/Modules/getaddrinfo.c

http://unladen-swallow.googlecode.com/ · C · 638 lines · 522 code · 45 blank · 71 comment · 118 complexity · e94a071e4706b3edceb2a0d82f6b4de9 MD5 · raw file

  1. /*
  2. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * GAI_ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR GAI_ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON GAI_ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN GAI_ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
  31. *
  32. * Issues to be discussed:
  33. * - Thread safe-ness must be checked.
  34. * - Return values. There are nonstandard return values defined and used
  35. * in the source code. This is because RFC2133 is silent about which error
  36. * code must be returned for which situation.
  37. * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
  38. */
  39. #if 0
  40. #include <sys/types.h>
  41. #include <sys/param.h>
  42. #include <sys/sysctl.h>
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #include <arpa/nameser.h>
  47. #include <netdb.h>
  48. #include <resolv.h>
  49. #include <string.h>
  50. #include <stdlib.h>
  51. #include <stddef.h>
  52. #include <ctype.h>
  53. #include <unistd.h>
  54. #include "addrinfo.h"
  55. #endif
  56. #if defined(__KAME__) && defined(ENABLE_IPV6)
  57. # define FAITH
  58. #endif
  59. #define SUCCESS 0
  60. #define GAI_ANY 0
  61. #define YES 1
  62. #define NO 0
  63. #ifdef FAITH
  64. static int translate = NO;
  65. static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT;
  66. #endif
  67. static const char in_addrany[] = { 0, 0, 0, 0 };
  68. static const char in6_addrany[] = {
  69. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  70. };
  71. static const char in_loopback[] = { 127, 0, 0, 1 };
  72. static const char in6_loopback[] = {
  73. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
  74. };
  75. struct sockinet {
  76. u_char si_len;
  77. u_char si_family;
  78. u_short si_port;
  79. };
  80. static struct gai_afd {
  81. int a_af;
  82. int a_addrlen;
  83. int a_socklen;
  84. int a_off;
  85. const char *a_addrany;
  86. const char *a_loopback;
  87. } gai_afdl [] = {
  88. #ifdef ENABLE_IPV6
  89. #define N_INET6 0
  90. {PF_INET6, sizeof(struct in6_addr),
  91. sizeof(struct sockaddr_in6),
  92. offsetof(struct sockaddr_in6, sin6_addr),
  93. in6_addrany, in6_loopback},
  94. #define N_INET 1
  95. #else
  96. #define N_INET 0
  97. #endif
  98. {PF_INET, sizeof(struct in_addr),
  99. sizeof(struct sockaddr_in),
  100. offsetof(struct sockaddr_in, sin_addr),
  101. in_addrany, in_loopback},
  102. {0, 0, 0, 0, NULL, NULL},
  103. };
  104. #ifdef ENABLE_IPV6
  105. #define PTON_MAX 16
  106. #else
  107. #define PTON_MAX 4
  108. #endif
  109. #ifndef IN_MULTICAST
  110. #define IN_MULTICAST(i) (((i) & 0xf0000000U) == 0xe0000000U)
  111. #endif
  112. #ifndef IN_EXPERIMENTAL
  113. #define IN_EXPERIMENTAL(i) (((i) & 0xe0000000U) == 0xe0000000U)
  114. #endif
  115. #ifndef IN_LOOPBACKNET
  116. #define IN_LOOPBACKNET 127
  117. #endif
  118. static int get_name Py_PROTO((const char *, struct gai_afd *,
  119. struct addrinfo **, char *, struct addrinfo *,
  120. int));
  121. static int get_addr Py_PROTO((const char *, int, struct addrinfo **,
  122. struct addrinfo *, int));
  123. static int str_isnumber Py_PROTO((const char *));
  124. static char *ai_errlist[] = {
  125. "success.",
  126. "address family for hostname not supported.", /* EAI_ADDRFAMILY */
  127. "temporary failure in name resolution.", /* EAI_AGAIN */
  128. "invalid value for ai_flags.", /* EAI_BADFLAGS */
  129. "non-recoverable failure in name resolution.", /* EAI_FAIL */
  130. "ai_family not supported.", /* EAI_FAMILY */
  131. "memory allocation failure.", /* EAI_MEMORY */
  132. "no address associated with hostname.", /* EAI_NODATA */
  133. "hostname nor servname provided, or not known.",/* EAI_NONAME */
  134. "servname not supported for ai_socktype.", /* EAI_SERVICE */
  135. "ai_socktype not supported.", /* EAI_SOCKTYPE */
  136. "system error returned in errno.", /* EAI_SYSTEM */
  137. "invalid value for hints.", /* EAI_BADHINTS */
  138. "resolved protocol is unknown.", /* EAI_PROTOCOL */
  139. "unknown error.", /* EAI_MAX */
  140. };
  141. #define GET_CANONNAME(ai, str) \
  142. if (pai->ai_flags & AI_CANONNAME) {\
  143. if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
  144. strcpy((ai)->ai_canonname, (str));\
  145. } else {\
  146. error = EAI_MEMORY;\
  147. goto free;\
  148. }\
  149. }
  150. #ifdef HAVE_SOCKADDR_SA_LEN
  151. #define GET_AI(ai, gai_afd, addr, port) {\
  152. char *p;\
  153. if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
  154. ((gai_afd)->a_socklen)))\
  155. == NULL) goto free;\
  156. memcpy(ai, pai, sizeof(struct addrinfo));\
  157. (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
  158. memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
  159. (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\
  160. (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
  161. ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
  162. p = (char *)((ai)->ai_addr);\
  163. memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
  164. }
  165. #else
  166. #define GET_AI(ai, gai_afd, addr, port) {\
  167. char *p;\
  168. if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
  169. ((gai_afd)->a_socklen)))\
  170. == NULL) goto free;\
  171. memcpy(ai, pai, sizeof(struct addrinfo));\
  172. (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
  173. memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
  174. (ai)->ai_addrlen = (gai_afd)->a_socklen;\
  175. (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
  176. ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
  177. p = (char *)((ai)->ai_addr);\
  178. memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
  179. }
  180. #endif
  181. #define ERR(err) { error = (err); goto bad; }
  182. char *
  183. gai_strerror(int ecode)
  184. {
  185. if (ecode < 0 || ecode > EAI_MAX)
  186. ecode = EAI_MAX;
  187. return ai_errlist[ecode];
  188. }
  189. void
  190. freeaddrinfo(struct addrinfo *ai)
  191. {
  192. struct addrinfo *next;
  193. do {
  194. next = ai->ai_next;
  195. if (ai->ai_canonname)
  196. free(ai->ai_canonname);
  197. /* no need to free(ai->ai_addr) */
  198. free(ai);
  199. } while ((ai = next) != NULL);
  200. }
  201. static int
  202. str_isnumber(const char *p)
  203. {
  204. unsigned char *q = (unsigned char *)p;
  205. while (*q) {
  206. if (! isdigit(*q))
  207. return NO;
  208. q++;
  209. }
  210. return YES;
  211. }
  212. int
  213. getaddrinfo(const char*hostname, const char*servname,
  214. const struct addrinfo *hints, struct addrinfo **res)
  215. {
  216. struct addrinfo sentinel;
  217. struct addrinfo *top = NULL;
  218. struct addrinfo *cur;
  219. int i, error = 0;
  220. char pton[PTON_MAX];
  221. struct addrinfo ai;
  222. struct addrinfo *pai;
  223. u_short port;
  224. #ifdef FAITH
  225. static int firsttime = 1;
  226. if (firsttime) {
  227. /* translator hack */
  228. {
  229. char *q = getenv("GAI");
  230. if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
  231. translate = YES;
  232. }
  233. firsttime = 0;
  234. }
  235. #endif
  236. /* initialize file static vars */
  237. sentinel.ai_next = NULL;
  238. cur = &sentinel;
  239. pai = &ai;
  240. pai->ai_flags = 0;
  241. pai->ai_family = PF_UNSPEC;
  242. pai->ai_socktype = GAI_ANY;
  243. pai->ai_protocol = GAI_ANY;
  244. pai->ai_addrlen = 0;
  245. pai->ai_canonname = NULL;
  246. pai->ai_addr = NULL;
  247. pai->ai_next = NULL;
  248. port = GAI_ANY;
  249. if (hostname == NULL && servname == NULL)
  250. return EAI_NONAME;
  251. if (hints) {
  252. /* error check for hints */
  253. if (hints->ai_addrlen || hints->ai_canonname ||
  254. hints->ai_addr || hints->ai_next)
  255. ERR(EAI_BADHINTS); /* xxx */
  256. if (hints->ai_flags & ~AI_MASK)
  257. ERR(EAI_BADFLAGS);
  258. switch (hints->ai_family) {
  259. case PF_UNSPEC:
  260. case PF_INET:
  261. #ifdef ENABLE_IPV6
  262. case PF_INET6:
  263. #endif
  264. break;
  265. default:
  266. ERR(EAI_FAMILY);
  267. }
  268. memcpy(pai, hints, sizeof(*pai));
  269. switch (pai->ai_socktype) {
  270. case GAI_ANY:
  271. switch (pai->ai_protocol) {
  272. case GAI_ANY:
  273. break;
  274. case IPPROTO_UDP:
  275. pai->ai_socktype = SOCK_DGRAM;
  276. break;
  277. case IPPROTO_TCP:
  278. pai->ai_socktype = SOCK_STREAM;
  279. break;
  280. default:
  281. pai->ai_socktype = SOCK_RAW;
  282. break;
  283. }
  284. break;
  285. case SOCK_RAW:
  286. break;
  287. case SOCK_DGRAM:
  288. if (pai->ai_protocol != IPPROTO_UDP &&
  289. pai->ai_protocol != GAI_ANY)
  290. ERR(EAI_BADHINTS); /*xxx*/
  291. pai->ai_protocol = IPPROTO_UDP;
  292. break;
  293. case SOCK_STREAM:
  294. if (pai->ai_protocol != IPPROTO_TCP &&
  295. pai->ai_protocol != GAI_ANY)
  296. ERR(EAI_BADHINTS); /*xxx*/
  297. pai->ai_protocol = IPPROTO_TCP;
  298. break;
  299. default:
  300. ERR(EAI_SOCKTYPE);
  301. /* unreachable */
  302. }
  303. }
  304. /*
  305. * service port
  306. */
  307. if (servname) {
  308. if (str_isnumber(servname)) {
  309. if (pai->ai_socktype == GAI_ANY) {
  310. /* caller accept *GAI_ANY* socktype */
  311. pai->ai_socktype = SOCK_DGRAM;
  312. pai->ai_protocol = IPPROTO_UDP;
  313. }
  314. port = htons((u_short)atoi(servname));
  315. } else {
  316. struct servent *sp;
  317. char *proto;
  318. proto = NULL;
  319. switch (pai->ai_socktype) {
  320. case GAI_ANY:
  321. proto = NULL;
  322. break;
  323. case SOCK_DGRAM:
  324. proto = "udp";
  325. break;
  326. case SOCK_STREAM:
  327. proto = "tcp";
  328. break;
  329. default:
  330. fprintf(stderr, "panic!\n");
  331. break;
  332. }
  333. if ((sp = getservbyname(servname, proto)) == NULL)
  334. ERR(EAI_SERVICE);
  335. port = sp->s_port;
  336. if (pai->ai_socktype == GAI_ANY) {
  337. if (strcmp(sp->s_proto, "udp") == 0) {
  338. pai->ai_socktype = SOCK_DGRAM;
  339. pai->ai_protocol = IPPROTO_UDP;
  340. } else if (strcmp(sp->s_proto, "tcp") == 0) {
  341. pai->ai_socktype = SOCK_STREAM;
  342. pai->ai_protocol = IPPROTO_TCP;
  343. } else
  344. ERR(EAI_PROTOCOL); /*xxx*/
  345. }
  346. }
  347. }
  348. /*
  349. * hostname == NULL.
  350. * passive socket -> anyaddr (0.0.0.0 or ::)
  351. * non-passive socket -> localhost (127.0.0.1 or ::1)
  352. */
  353. if (hostname == NULL) {
  354. struct gai_afd *gai_afd;
  355. for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) {
  356. if (!(pai->ai_family == PF_UNSPEC
  357. || pai->ai_family == gai_afd->a_af)) {
  358. continue;
  359. }
  360. if (pai->ai_flags & AI_PASSIVE) {
  361. GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port);
  362. /* xxx meaningless?
  363. * GET_CANONNAME(cur->ai_next, "anyaddr");
  364. */
  365. } else {
  366. GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback,
  367. port);
  368. /* xxx meaningless?
  369. * GET_CANONNAME(cur->ai_next, "localhost");
  370. */
  371. }
  372. cur = cur->ai_next;
  373. }
  374. top = sentinel.ai_next;
  375. if (top)
  376. goto good;
  377. else
  378. ERR(EAI_FAMILY);
  379. }
  380. /* hostname as numeric name */
  381. for (i = 0; gai_afdl[i].a_af; i++) {
  382. if (inet_pton(gai_afdl[i].a_af, hostname, pton)) {
  383. u_long v4a;
  384. #ifdef ENABLE_IPV6
  385. u_char pfx;
  386. #endif
  387. switch (gai_afdl[i].a_af) {
  388. case AF_INET:
  389. v4a = ((struct in_addr *)pton)->s_addr;
  390. v4a = ntohl(v4a);
  391. if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
  392. pai->ai_flags &= ~AI_CANONNAME;
  393. v4a >>= IN_CLASSA_NSHIFT;
  394. if (v4a == 0 || v4a == IN_LOOPBACKNET)
  395. pai->ai_flags &= ~AI_CANONNAME;
  396. break;
  397. #ifdef ENABLE_IPV6
  398. case AF_INET6:
  399. pfx = ((struct in6_addr *)pton)->s6_addr8[0];
  400. if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
  401. pai->ai_flags &= ~AI_CANONNAME;
  402. break;
  403. #endif
  404. }
  405. if (pai->ai_family == gai_afdl[i].a_af ||
  406. pai->ai_family == PF_UNSPEC) {
  407. if (! (pai->ai_flags & AI_CANONNAME)) {
  408. GET_AI(top, &gai_afdl[i], pton, port);
  409. goto good;
  410. }
  411. /*
  412. * if AI_CANONNAME and if reverse lookup
  413. * fail, return ai anyway to pacify
  414. * calling application.
  415. *
  416. * XXX getaddrinfo() is a name->address
  417. * translation function, and it looks strange
  418. * that we do addr->name translation here.
  419. */
  420. get_name(pton, &gai_afdl[i], &top, pton, pai, port);
  421. goto good;
  422. } else
  423. ERR(EAI_FAMILY); /*xxx*/
  424. }
  425. }
  426. if (pai->ai_flags & AI_NUMERICHOST)
  427. ERR(EAI_NONAME);
  428. /* hostname as alphabetical name */
  429. error = get_addr(hostname, pai->ai_family, &top, pai, port);
  430. if (error == 0) {
  431. if (top) {
  432. good:
  433. *res = top;
  434. return SUCCESS;
  435. } else
  436. error = EAI_FAIL;
  437. }
  438. free:
  439. if (top)
  440. freeaddrinfo(top);
  441. bad:
  442. *res = NULL;
  443. return error;
  444. }
  445. static int
  446. get_name(addr, gai_afd, res, numaddr, pai, port0)
  447. const char *addr;
  448. struct gai_afd *gai_afd;
  449. struct addrinfo **res;
  450. char *numaddr;
  451. struct addrinfo *pai;
  452. int port0;
  453. {
  454. u_short port = port0 & 0xffff;
  455. struct hostent *hp;
  456. struct addrinfo *cur;
  457. int error = 0;
  458. #ifdef ENABLE_IPV6
  459. int h_error;
  460. #endif
  461. #ifdef ENABLE_IPV6
  462. hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error);
  463. #else
  464. hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET);
  465. #endif
  466. if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
  467. GET_AI(cur, gai_afd, hp->h_addr_list[0], port);
  468. GET_CANONNAME(cur, hp->h_name);
  469. } else
  470. GET_AI(cur, gai_afd, numaddr, port);
  471. #ifdef ENABLE_IPV6
  472. if (hp)
  473. freehostent(hp);
  474. #endif
  475. *res = cur;
  476. return SUCCESS;
  477. free:
  478. if (cur)
  479. freeaddrinfo(cur);
  480. #ifdef ENABLE_IPV6
  481. if (hp)
  482. freehostent(hp);
  483. #endif
  484. /* bad: */
  485. *res = NULL;
  486. return error;
  487. }
  488. static int
  489. get_addr(hostname, af, res, pai, port0)
  490. const char *hostname;
  491. int af;
  492. struct addrinfo **res;
  493. struct addrinfo *pai;
  494. int port0;
  495. {
  496. u_short port = port0 & 0xffff;
  497. struct addrinfo sentinel;
  498. struct hostent *hp;
  499. struct addrinfo *top, *cur;
  500. struct gai_afd *gai_afd;
  501. int i, error = 0, h_error;
  502. char *ap;
  503. top = NULL;
  504. sentinel.ai_next = NULL;
  505. cur = &sentinel;
  506. #ifdef ENABLE_IPV6
  507. if (af == AF_UNSPEC) {
  508. hp = getipnodebyname(hostname, AF_INET6,
  509. AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
  510. } else
  511. hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
  512. #else
  513. hp = gethostbyname(hostname);
  514. h_error = h_errno;
  515. #endif
  516. if (hp == NULL) {
  517. switch (h_error) {
  518. case HOST_NOT_FOUND:
  519. case NO_DATA:
  520. error = EAI_NODATA;
  521. break;
  522. case TRY_AGAIN:
  523. error = EAI_AGAIN;
  524. break;
  525. case NO_RECOVERY:
  526. default:
  527. error = EAI_FAIL;
  528. break;
  529. }
  530. goto free;
  531. }
  532. if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
  533. (hp->h_addr_list[0] == NULL)) {
  534. error = EAI_FAIL;
  535. goto free;
  536. }
  537. for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
  538. switch (af) {
  539. #ifdef ENABLE_IPV6
  540. case AF_INET6:
  541. gai_afd = &gai_afdl[N_INET6];
  542. break;
  543. #endif
  544. #ifndef ENABLE_IPV6
  545. default: /* AF_UNSPEC */
  546. #endif
  547. case AF_INET:
  548. gai_afd = &gai_afdl[N_INET];
  549. break;
  550. #ifdef ENABLE_IPV6
  551. default: /* AF_UNSPEC */
  552. if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
  553. ap += sizeof(struct in6_addr) -
  554. sizeof(struct in_addr);
  555. gai_afd = &gai_afdl[N_INET];
  556. } else
  557. gai_afd = &gai_afdl[N_INET6];
  558. break;
  559. #endif
  560. }
  561. #ifdef FAITH
  562. if (translate && gai_afd->a_af == AF_INET) {
  563. struct in6_addr *in6;
  564. GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port);
  565. in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
  566. memcpy(&in6->s6_addr32[0], &faith_prefix,
  567. sizeof(struct in6_addr) - sizeof(struct in_addr));
  568. memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
  569. } else
  570. #endif /* FAITH */
  571. GET_AI(cur->ai_next, gai_afd, ap, port);
  572. if (cur == &sentinel) {
  573. top = cur->ai_next;
  574. GET_CANONNAME(top, hp->h_name);
  575. }
  576. cur = cur->ai_next;
  577. }
  578. #ifdef ENABLE_IPV6
  579. freehostent(hp);
  580. #endif
  581. *res = top;
  582. return SUCCESS;
  583. free:
  584. if (top)
  585. freeaddrinfo(top);
  586. #ifdef ENABLE_IPV6
  587. if (hp)
  588. freehostent(hp);
  589. #endif
  590. /* bad: */
  591. *res = NULL;
  592. return error;
  593. }