getnameinfo.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright (c) 1996 W. Richard Stevens. All rights reserved.
  3. *
  4. * Permission to use or modify this software for educational or
  5. * for commercial purposes, and without fee, is hereby granted,
  6. * provided that the above copyright notice appears in connection
  7. * with any and all uses, with clear indication as to any
  8. * modifications made. The author RESERVES the sole rights of
  9. * reproduction, publication and distribution and hence permission
  10. * to print this source code in any book, reference manual,
  11. * magazine, or other type of publication, including any digital
  12. * medium, must be granted in writing by W. Richard Stevens.
  13. *
  14. * The author makes no representations about the suitability of this
  15. * software for any purpose. It is provided "as is" without express
  16. * or implied warranty.
  17. */
  18. /* tabs set for 4 spaces, not 8 */
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <netdb.h> /* hostent{}, servent{}, etc. */
  23. #include <string.h> /* strncpy() */
  24. /* We need a way to determine if the compiling host supports IPv4/IPv6.
  25. Cannot test for AF_INET6, as some vendors #define it, even though
  26. they don't support it. */
  27. #ifdef AF_INET
  28. #define IPV4 /* this is tested throughout the code that follows */
  29. #endif
  30. #ifdef IPV6ADDR_ANY_INIT
  31. #define IPV6 /* this is tested throughout the code that follows */
  32. #endif
  33. /* Define following if the reentrant versions of get{host|serv}byaddr
  34. are to be used.
  35. Note that getaddrinfo{} must be reentrant if the underlying
  36. get{host|serv}byaddr_r functions are provided. */
  37. /* #define REENTRANT */
  38. #define HENTBUFSIZ 8*1024
  39. /* function prototypes for our own internal functions */
  40. static int do_ipv46(char *, size_t, char *, size_t,
  41. void *, size_t, int, int);
  42. int
  43. getnameinfo(const struct sockaddr *sa, size_t salen,
  44. char *host, size_t hostlen, char *serv, size_t servlen)
  45. {
  46. switch (sa->sa_family) {
  47. #ifdef IPV4
  48. case AF_INET: {
  49. struct sockaddr_in *sain = (struct sockaddr_in *) sa;
  50. return(do_ipv46(host, hostlen, serv, servlen,
  51. &sain->sin_addr, sizeof(struct in_addr), AF_INET,
  52. sain->sin_port));
  53. }
  54. #endif /* IPV4 */
  55. #ifdef IPV6
  56. case AF_INET6: {
  57. struct sockaddr_in6 *sain = (struct sockaddr_in6 *) sa;
  58. return(do_ipv46(host, hostlen, serv, servlen,
  59. &sain->sin6_addr, sizeof(struct in6_addr), AF_INET6,
  60. sain->sin6_port));
  61. }
  62. #endif /* IPV6 */
  63. default:
  64. return(1);
  65. }
  66. }
  67. /*
  68. * Handle either an IPv4 or an IPv6 address and port.
  69. */
  70. static int
  71. do_ipv46(char *host, size_t hostlen, char *serv, size_t servlen,
  72. void *aptr, size_t alen, int family, int port)
  73. {
  74. struct hostent *hptr, hent;
  75. struct servent *sptr, sent;
  76. char hentbuf[HENTBUFSIZ];
  77. if (hostlen > 0) {
  78. #ifdef REENTRANT
  79. hptr = gethostbyaddr_r(aptr, alen, family,
  80. &hent, hentbuf, HENTBUFSIZ, &h_errno);
  81. #else
  82. hptr = gethostbyaddr(aptr, alen, family);
  83. #endif
  84. if (hptr != NULL && hptr->h_name != NULL)
  85. strncpy(host, hptr->h_name, hostlen);
  86. else
  87. return(1);
  88. }
  89. if (servlen > 0) {
  90. /*
  91. * Notice that we do not have enough information to pass a
  92. * "protocol" argument to getservbyport(), so the assumption
  93. * is that the protocol (TCP or UDP) does not matter.
  94. */
  95. #ifdef REENTRANT
  96. sptr = getservbyport_r(port, NULL,
  97. &sent, hentbuf, HENTBUFSIZ);
  98. #else
  99. sptr = getservbyport(port, NULL);
  100. #endif
  101. if (sptr != NULL && sptr->s_name != NULL)
  102. strncpy(serv, sptr->s_name, servlen);
  103. else
  104. return(1);
  105. }
  106. return(0);
  107. }