getaddrinfo.lc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* include ga1 */
  2. #include "gai_hdr.h"## 1 ##src/libgai/getaddrinfo.c##
  3. #include <arpa/nameser.h> /* needed for <resolv.h> */## 2 ##src/libgai/getaddrinfo.c##
  4. #include <resolv.h> /* res_init, _res */## 3 ##src/libgai/getaddrinfo.c##
  5. int## 4 ##src/libgai/getaddrinfo.c##
  6. getaddrinfo(const char *hostname, const char *servname,## 5 ##src/libgai/getaddrinfo.c##
  7. const struct addrinfo *hintsp, struct addrinfo **result)## 6 ##src/libgai/getaddrinfo.c##
  8. {## 7 ##src/libgai/getaddrinfo.c##
  9. int rc, error, nsearch;## 8 ##src/libgai/getaddrinfo.c##
  10. char **ap, *canon;## 9 ##src/libgai/getaddrinfo.c##
  11. struct hostent *hptr;## 10 ##src/libgai/getaddrinfo.c##
  12. struct search search[3], *sptr;## 11 ##src/libgai/getaddrinfo.c##
  13. struct addrinfo hints, *aihead, **aipnext;## 12 ##src/libgai/getaddrinfo.c##
  14. /* ## 13 ##src/libgai/getaddrinfo.c##
  15. * If we encounter an error we want to free() any dynamic memory## 14 ##src/libgai/getaddrinfo.c##
  16. * that we've allocated. This is our hack to simplify the code.## 15 ##src/libgai/getaddrinfo.c##
  17. */## 16 ##src/libgai/getaddrinfo.c##
  18. #define error(e) { error = (e); goto bad; }## 17 ##src/libgai/getaddrinfo.c##
  19. aihead = NULL; /* initialize automatic variables */## 18 ##src/libgai/getaddrinfo.c##
  20. aipnext = &aihead;## 19 ##src/libgai/getaddrinfo.c##
  21. canon = NULL;## 20 ##src/libgai/getaddrinfo.c##
  22. if (hintsp == NULL) {## 21 ##src/libgai/getaddrinfo.c##
  23. bzero(&hints, sizeof(hints));## 22 ##src/libgai/getaddrinfo.c##
  24. hints.ai_family = AF_UNSPEC;## 23 ##src/libgai/getaddrinfo.c##
  25. } else## 24 ##src/libgai/getaddrinfo.c##
  26. hints = *hintsp; /* struct copy */## 25 ##src/libgai/getaddrinfo.c##
  27. /* 4first some basic error checking */## 26 ##src/libgai/getaddrinfo.c##
  28. if ((rc = ga_echeck(hostname, servname, hints.ai_flags, hints.ai_family,## 27 ##src/libgai/getaddrinfo.c##
  29. hints.ai_socktype, hints.ai_protocol)) != 0)## 28 ##src/libgai/getaddrinfo.c##
  30. error(rc);## 29 ##src/libgai/getaddrinfo.c##
  31. /* 4special case Unix domain first */## 30 ##src/libgai/getaddrinfo.c##
  32. if (hostname != NULL &&## 31 ##src/libgai/getaddrinfo.c##
  33. (strcmp(hostname, "/local") == 0 || strcmp(hostname, "/unix") == 0)## 32 ##src/libgai/getaddrinfo.c##
  34. && (servname != NULL && servname[0] == '/'))## 33 ##src/libgai/getaddrinfo.c##
  35. return (ga_unix(servname, &hints, result));## 34 ##src/libgai/getaddrinfo.c##
  36. /* end ga1 */
  37. /* include ga3 */
  38. /* 4remainder of function for IPv4/IPv6 */## 35 ##src/libgai/getaddrinfo.c##
  39. nsearch = ga_nsearch(hostname, &hints, &search[0]);## 36 ##src/libgai/getaddrinfo.c##
  40. for (sptr = &search[0]; sptr < &search[nsearch]; sptr++) {## 37 ##src/libgai/getaddrinfo.c##
  41. /* 4check for an IPv4 dotted-decimal string */## 38 ##src/libgai/getaddrinfo.c##
  42. if (isdigit(sptr->host[0])) {## 39 ##src/libgai/getaddrinfo.c##
  43. struct in_addr inaddr;## 40 ##src/libgai/getaddrinfo.c##
  44. if (inet_pton(AF_INET, sptr->host, &inaddr) == 1) {## 41 ##src/libgai/getaddrinfo.c##
  45. if (hints.ai_family != AF_UNSPEC &&## 42 ##src/libgai/getaddrinfo.c##
  46. hints.ai_family != AF_INET)## 43 ##src/libgai/getaddrinfo.c##
  47. error(EAI_ADDRFAMILY);## 44 ##src/libgai/getaddrinfo.c##
  48. if (sptr->family != AF_INET)## 45 ##src/libgai/getaddrinfo.c##
  49. continue; /* ignore */## 46 ##src/libgai/getaddrinfo.c##
  50. rc = ga_aistruct(&aipnext, &hints, &inaddr, AF_INET);## 47 ##src/libgai/getaddrinfo.c##
  51. if (rc != 0)## 48 ##src/libgai/getaddrinfo.c##
  52. error(rc);## 49 ##src/libgai/getaddrinfo.c##
  53. continue;## 50 ##src/libgai/getaddrinfo.c##
  54. }## 51 ##src/libgai/getaddrinfo.c##
  55. }## 52 ##src/libgai/getaddrinfo.c##
  56. /* 4check for an IPv6 hex string */## 53 ##src/libgai/getaddrinfo.c##
  57. if ((isxdigit(sptr->host[0]) || sptr->host[0] == ':') &&## 54 ##src/libgai/getaddrinfo.c##
  58. (strchr(sptr->host, ':') != NULL)) {## 55 ##src/libgai/getaddrinfo.c##
  59. struct in6_addr in6addr;## 56 ##src/libgai/getaddrinfo.c##
  60. if (inet_pton(AF_INET6, sptr->host, &in6addr) == 1) {## 57 ##src/libgai/getaddrinfo.c##
  61. if (hints.ai_family != AF_UNSPEC &&## 58 ##src/libgai/getaddrinfo.c##
  62. hints.ai_family != AF_INET6)## 59 ##src/libgai/getaddrinfo.c##
  63. error(EAI_ADDRFAMILY);## 60 ##src/libgai/getaddrinfo.c##
  64. if (sptr->family != AF_INET6)## 61 ##src/libgai/getaddrinfo.c##
  65. continue; /* ignore */## 62 ##src/libgai/getaddrinfo.c##
  66. rc = ga_aistruct(&aipnext, &hints, &in6addr, AF_INET6);## 63 ##src/libgai/getaddrinfo.c##
  67. if (rc != 0)## 64 ##src/libgai/getaddrinfo.c##
  68. error(rc);## 65 ##src/libgai/getaddrinfo.c##
  69. continue;## 66 ##src/libgai/getaddrinfo.c##
  70. }## 67 ##src/libgai/getaddrinfo.c##
  71. }## 68 ##src/libgai/getaddrinfo.c##
  72. /* end ga3 */
  73. /* include ga4 */
  74. /* 4remainder of for() to look up hostname */## 69 ##src/libgai/getaddrinfo.c##
  75. if ((_res.options & RES_INIT) == 0)## 70 ##src/libgai/getaddrinfo.c##
  76. res_init(); /* need this to set _res.options */## 71 ##src/libgai/getaddrinfo.c##
  77. if (nsearch == 2) {## 72 ##src/libgai/getaddrinfo.c##
  78. _res.options &= ~RES_USE_INET6;## 73 ##src/libgai/getaddrinfo.c##
  79. hptr = gethostbyname2(sptr->host, sptr->family);## 74 ##src/libgai/getaddrinfo.c##
  80. } else {## 75 ##src/libgai/getaddrinfo.c##
  81. if (sptr->family == AF_INET6)## 76 ##src/libgai/getaddrinfo.c##
  82. _res.options |= RES_USE_INET6;## 77 ##src/libgai/getaddrinfo.c##
  83. else## 78 ##src/libgai/getaddrinfo.c##
  84. _res.options &= ~RES_USE_INET6;## 79 ##src/libgai/getaddrinfo.c##
  85. hptr = gethostbyname(sptr->host);## 80 ##src/libgai/getaddrinfo.c##
  86. }## 81 ##src/libgai/getaddrinfo.c##
  87. if (hptr == NULL) {## 82 ##src/libgai/getaddrinfo.c##
  88. if (nsearch == 2)## 83 ##src/libgai/getaddrinfo.c##
  89. continue; /* failure OK if multiple searches */## 84 ##src/libgai/getaddrinfo.c##
  90. switch (h_errno) {## 85 ##src/libgai/getaddrinfo.c##
  91. case HOST_NOT_FOUND:## 86 ##src/libgai/getaddrinfo.c##
  92. error(EAI_NONAME);## 87 ##src/libgai/getaddrinfo.c##
  93. case TRY_AGAIN:## 88 ##src/libgai/getaddrinfo.c##
  94. error(EAI_AGAIN);## 89 ##src/libgai/getaddrinfo.c##
  95. case NO_RECOVERY:## 90 ##src/libgai/getaddrinfo.c##
  96. error(EAI_FAIL);## 91 ##src/libgai/getaddrinfo.c##
  97. case NO_DATA:## 92 ##src/libgai/getaddrinfo.c##
  98. error(EAI_NODATA);## 93 ##src/libgai/getaddrinfo.c##
  99. default:## 94 ##src/libgai/getaddrinfo.c##
  100. error(EAI_NONAME);## 95 ##src/libgai/getaddrinfo.c##
  101. }## 96 ##src/libgai/getaddrinfo.c##
  102. }## 97 ##src/libgai/getaddrinfo.c##
  103. /* 4check for address family mismatch if one specified */## 98 ##src/libgai/getaddrinfo.c##
  104. if (hints.ai_family != AF_UNSPEC## 99 ##src/libgai/getaddrinfo.c##
  105. && hints.ai_family != hptr->h_addrtype)##100 ##src/libgai/getaddrinfo.c##
  106. error(EAI_ADDRFAMILY);##101 ##src/libgai/getaddrinfo.c##
  107. /* 4save canonical name first time */##102 ##src/libgai/getaddrinfo.c##
  108. if (hostname != NULL && hostname[0] != '\0' &&##103 ##src/libgai/getaddrinfo.c##
  109. (hints.ai_flags & AI_CANONNAME) && canon == NULL) {##104 ##src/libgai/getaddrinfo.c##
  110. if ((canon = strdup(hptr->h_name)) == NULL)##105 ##src/libgai/getaddrinfo.c##
  111. error(EAI_MEMORY);##106 ##src/libgai/getaddrinfo.c##
  112. }##107 ##src/libgai/getaddrinfo.c##
  113. /* 4create one addrinfo{} for each returned address */##108 ##src/libgai/getaddrinfo.c##
  114. for (ap = hptr->h_addr_list; *ap != NULL; ap++) {##109 ##src/libgai/getaddrinfo.c##
  115. rc = ga_aistruct(&aipnext, &hints, *ap, hptr->h_addrtype);##110 ##src/libgai/getaddrinfo.c##
  116. if (rc != 0)##111 ##src/libgai/getaddrinfo.c##
  117. error(rc);##112 ##src/libgai/getaddrinfo.c##
  118. }##113 ##src/libgai/getaddrinfo.c##
  119. }##114 ##src/libgai/getaddrinfo.c##
  120. if (aihead == NULL)##115 ##src/libgai/getaddrinfo.c##
  121. error(EAI_NONAME); /* nothing found */##116 ##src/libgai/getaddrinfo.c##
  122. /* end ga4 */
  123. /* include ga5 */
  124. /* 4return canonical name */##117 ##src/libgai/getaddrinfo.c##
  125. if (hostname != NULL && hostname[0] != '\0' &&##118 ##src/libgai/getaddrinfo.c##
  126. hints.ai_flags & AI_CANONNAME) {##119 ##src/libgai/getaddrinfo.c##
  127. if (canon != NULL)##120 ##src/libgai/getaddrinfo.c##
  128. aihead->ai_canonname = canon; /* strdup'ed earlier */##121 ##src/libgai/getaddrinfo.c##
  129. else {##122 ##src/libgai/getaddrinfo.c##
  130. if ((aihead->ai_canonname = strdup(search[0].host)) == NULL)##123 ##src/libgai/getaddrinfo.c##
  131. error(EAI_MEMORY);##124 ##src/libgai/getaddrinfo.c##
  132. }##125 ##src/libgai/getaddrinfo.c##
  133. }##126 ##src/libgai/getaddrinfo.c##
  134. /* 4now process the service name */##127 ##src/libgai/getaddrinfo.c##
  135. if (servname != NULL && servname[0] != '\0') {##128 ##src/libgai/getaddrinfo.c##
  136. if ((rc = ga_serv(aihead, &hints, servname)) != 0)##129 ##src/libgai/getaddrinfo.c##
  137. error(rc);##130 ##src/libgai/getaddrinfo.c##
  138. }##131 ##src/libgai/getaddrinfo.c##
  139. *result = aihead; /* pointer to first structure in linked list */##132 ##src/libgai/getaddrinfo.c##
  140. return (0);##133 ##src/libgai/getaddrinfo.c##
  141. bad:##134 ##src/libgai/getaddrinfo.c##
  142. freeaddrinfo(aihead); /* free any alloc'ed memory */##135 ##src/libgai/getaddrinfo.c##
  143. return (error);##136 ##src/libgai/getaddrinfo.c##
  144. }##137 ##src/libgai/getaddrinfo.c##
  145. /* end ga5 */