PageRenderTime 58ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/socket/raddrinfo.c

http://github.com/ruby/ruby
C | 2750 lines | 2016 code | 303 blank | 431 comment | 452 complexity | 3ad6cc4207b8782abdb35f077acb46e8 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /************************************************
  2. raddrinfo.c -
  3. created at: Thu Mar 31 12:21:29 JST 1994
  4. Copyright (C) 1993-2007 Yukihiro Matsumoto
  5. ************************************************/
  6. #include "rubysocket.h"
  7. #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
  8. #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0]))
  9. static const int lookup_order_table[] = {
  10. #if defined(LOOKUP_ORDER_HACK_INET)
  11. PF_INET, PF_INET6, PF_UNSPEC,
  12. #elif defined(LOOKUP_ORDER_HACK_INET6)
  13. PF_INET6, PF_INET, PF_UNSPEC,
  14. #else
  15. /* should not happen */
  16. #endif
  17. };
  18. static int
  19. ruby_getaddrinfo(const char *nodename, const char *servname,
  20. const struct addrinfo *hints, struct addrinfo **res)
  21. {
  22. struct addrinfo tmp_hints;
  23. int i, af, error;
  24. if (hints->ai_family != PF_UNSPEC) {
  25. return getaddrinfo(nodename, servname, hints, res);
  26. }
  27. for (i = 0; i < LOOKUP_ORDERS; i++) {
  28. af = lookup_order_table[i];
  29. MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
  30. tmp_hints.ai_family = af;
  31. error = getaddrinfo(nodename, servname, &tmp_hints, res);
  32. if (error) {
  33. if (tmp_hints.ai_family == PF_UNSPEC) {
  34. break;
  35. }
  36. }
  37. else {
  38. break;
  39. }
  40. }
  41. return error;
  42. }
  43. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
  44. #endif
  45. #if defined(_AIX)
  46. static int
  47. ruby_getaddrinfo__aix(const char *nodename, const char *servname,
  48. const struct addrinfo *hints, struct addrinfo **res)
  49. {
  50. int error = getaddrinfo(nodename, servname, hints, res);
  51. struct addrinfo *r;
  52. if (error)
  53. return error;
  54. for (r = *res; r != NULL; r = r->ai_next) {
  55. if (r->ai_addr->sa_family == 0)
  56. r->ai_addr->sa_family = r->ai_family;
  57. if (r->ai_addr->sa_len == 0)
  58. r->ai_addr->sa_len = r->ai_addrlen;
  59. }
  60. return 0;
  61. }
  62. #undef getaddrinfo
  63. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
  64. static int
  65. ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
  66. char *host, size_t hostlen,
  67. char *serv, size_t servlen, int flags)
  68. {
  69. struct sockaddr_in6 *sa6;
  70. u_int32_t *a6;
  71. if (sa->sa_family == AF_INET6) {
  72. sa6 = (struct sockaddr_in6 *)sa;
  73. a6 = sa6->sin6_addr.u6_addr.u6_addr32;
  74. if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
  75. strncpy(host, "::", hostlen);
  76. snprintf(serv, servlen, "%d", sa6->sin6_port);
  77. return 0;
  78. }
  79. }
  80. return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
  81. }
  82. #undef getnameinfo
  83. #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
  84. ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
  85. #endif
  86. static int str_is_number(const char *);
  87. #if defined(__APPLE__)
  88. static int
  89. ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
  90. const struct addrinfo *hints, struct addrinfo **res)
  91. {
  92. /* fix [ruby-core:29427] */
  93. const char *tmp_servname;
  94. struct addrinfo tmp_hints;
  95. int error;
  96. tmp_servname = servname;
  97. MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
  98. if (nodename && servname) {
  99. if (str_is_number(tmp_servname) && atoi(servname) == 0) {
  100. tmp_servname = NULL;
  101. #ifdef AI_NUMERICSERV
  102. if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
  103. #endif
  104. }
  105. }
  106. error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
  107. if (error == 0) {
  108. /* [ruby-dev:23164] */
  109. struct addrinfo *r;
  110. r = *res;
  111. while (r) {
  112. if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype;
  113. if (! r->ai_protocol) {
  114. if (r->ai_socktype == SOCK_DGRAM) {
  115. r->ai_protocol = IPPROTO_UDP;
  116. }
  117. else if (r->ai_socktype == SOCK_STREAM) {
  118. r->ai_protocol = IPPROTO_TCP;
  119. }
  120. }
  121. r = r->ai_next;
  122. }
  123. }
  124. return error;
  125. }
  126. #undef getaddrinfo
  127. #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
  128. #endif
  129. #ifdef HAVE_INET_PTON
  130. static int
  131. parse_numeric_port(const char *service, int *portp)
  132. {
  133. unsigned long u;
  134. if (!service) {
  135. *portp = 0;
  136. return 1;
  137. }
  138. if (strspn(service, "0123456789") != strlen(service))
  139. return 0;
  140. errno = 0;
  141. u = STRTOUL(service, NULL, 10);
  142. if (errno)
  143. return 0;
  144. if (0x10000 <= u)
  145. return 0;
  146. *portp = (int)u;
  147. return 1;
  148. }
  149. #endif
  150. #ifndef GETADDRINFO_EMU
  151. struct getaddrinfo_arg
  152. {
  153. const char *node;
  154. const char *service;
  155. const struct addrinfo *hints;
  156. struct addrinfo **res;
  157. };
  158. static void *
  159. nogvl_getaddrinfo(void *arg)
  160. {
  161. int ret;
  162. struct getaddrinfo_arg *ptr = arg;
  163. ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
  164. #ifdef __linux__
  165. /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
  166. * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
  167. */
  168. if (ret == EAI_SYSTEM && errno == ENOENT)
  169. ret = EAI_NONAME;
  170. #endif
  171. return (void *)(VALUE)ret;
  172. }
  173. #endif
  174. #ifdef HAVE_GETADDRINFO_A
  175. struct gai_suspend_arg
  176. {
  177. struct gaicb *req;
  178. struct timespec *timeout;
  179. };
  180. static void *
  181. nogvl_gai_suspend(void *arg)
  182. {
  183. int ret;
  184. struct gai_suspend_arg *ptr = arg;
  185. struct gaicb const *wait_reqs[1];
  186. wait_reqs[0] = ptr->req;
  187. ret = gai_suspend(wait_reqs, 1, ptr->timeout);
  188. return (void *)(VALUE)ret;
  189. }
  190. #endif
  191. static int
  192. numeric_getaddrinfo(const char *node, const char *service,
  193. const struct addrinfo *hints,
  194. struct addrinfo **res)
  195. {
  196. #ifdef HAVE_INET_PTON
  197. # if defined __MINGW64__
  198. # define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
  199. # endif
  200. int port;
  201. if (node && parse_numeric_port(service, &port)) {
  202. static const struct {
  203. int socktype;
  204. int protocol;
  205. } list[] = {
  206. { SOCK_STREAM, IPPROTO_TCP },
  207. { SOCK_DGRAM, IPPROTO_UDP },
  208. { SOCK_RAW, 0 }
  209. };
  210. struct addrinfo *ai = NULL;
  211. int hint_family = hints ? hints->ai_family : PF_UNSPEC;
  212. int hint_socktype = hints ? hints->ai_socktype : 0;
  213. int hint_protocol = hints ? hints->ai_protocol : 0;
  214. char ipv4addr[4];
  215. #ifdef AF_INET6
  216. char ipv6addr[16];
  217. if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) &&
  218. strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) &&
  219. inet_pton(AF_INET6, node, ipv6addr)) {
  220. int i;
  221. for (i = numberof(list)-1; 0 <= i; i--) {
  222. if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
  223. (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
  224. struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
  225. struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6));
  226. INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6));
  227. memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr));
  228. sa->sin6_port = htons(port);
  229. ai0->ai_family = PF_INET6;
  230. ai0->ai_socktype = list[i].socktype;
  231. ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
  232. ai0->ai_addrlen = sizeof(struct sockaddr_in6);
  233. ai0->ai_addr = (struct sockaddr *)sa;
  234. ai0->ai_canonname = NULL;
  235. ai0->ai_next = ai;
  236. ai = ai0;
  237. }
  238. }
  239. }
  240. else
  241. #endif
  242. if ((hint_family == PF_UNSPEC || hint_family == PF_INET) &&
  243. strspn(node, "0123456789.") == strlen(node) &&
  244. inet_pton(AF_INET, node, ipv4addr)) {
  245. int i;
  246. for (i = numberof(list)-1; 0 <= i; i--) {
  247. if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
  248. (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
  249. struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
  250. struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in));
  251. INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in));
  252. memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr));
  253. sa->sin_port = htons(port);
  254. ai0->ai_family = PF_INET;
  255. ai0->ai_socktype = list[i].socktype;
  256. ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
  257. ai0->ai_addrlen = sizeof(struct sockaddr_in);
  258. ai0->ai_addr = (struct sockaddr *)sa;
  259. ai0->ai_canonname = NULL;
  260. ai0->ai_next = ai;
  261. ai = ai0;
  262. }
  263. }
  264. }
  265. if (ai) {
  266. *res = ai;
  267. return 0;
  268. }
  269. }
  270. #endif
  271. return EAI_FAIL;
  272. }
  273. int
  274. rb_getaddrinfo(const char *node, const char *service,
  275. const struct addrinfo *hints,
  276. struct rb_addrinfo **res)
  277. {
  278. struct addrinfo *ai;
  279. int ret;
  280. int allocated_by_malloc = 0;
  281. ret = numeric_getaddrinfo(node, service, hints, &ai);
  282. if (ret == 0)
  283. allocated_by_malloc = 1;
  284. else {
  285. #ifdef GETADDRINFO_EMU
  286. ret = getaddrinfo(node, service, hints, &ai);
  287. #else
  288. struct getaddrinfo_arg arg;
  289. MEMZERO(&arg, struct getaddrinfo_arg, 1);
  290. arg.node = node;
  291. arg.service = service;
  292. arg.hints = hints;
  293. arg.res = &ai;
  294. ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
  295. #endif
  296. }
  297. if (ret == 0) {
  298. *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
  299. (*res)->allocated_by_malloc = allocated_by_malloc;
  300. (*res)->ai = ai;
  301. }
  302. return ret;
  303. }
  304. #ifdef HAVE_GETADDRINFO_A
  305. int
  306. rb_getaddrinfo_a(const char *node, const char *service,
  307. const struct addrinfo *hints,
  308. struct rb_addrinfo **res, struct timespec *timeout)
  309. {
  310. struct addrinfo *ai;
  311. int ret;
  312. int allocated_by_malloc = 0;
  313. ret = numeric_getaddrinfo(node, service, hints, &ai);
  314. if (ret == 0)
  315. allocated_by_malloc = 1;
  316. else {
  317. struct gai_suspend_arg arg;
  318. struct gaicb *reqs[1];
  319. struct gaicb req;
  320. req.ar_name = node;
  321. req.ar_service = service;
  322. req.ar_request = hints;
  323. reqs[0] = &req;
  324. ret = getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL);
  325. if (ret) return ret;
  326. arg.req = &req;
  327. arg.timeout = timeout;
  328. ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_gai_suspend, &arg, RUBY_UBF_IO, 0);
  329. if (ret) {
  330. /* on Ubuntu 18.04 (or other systems), gai_suspend(3) returns EAI_SYSTEM/ENOENT on timeout */
  331. if (ret == EAI_SYSTEM && errno == ENOENT) {
  332. return EAI_AGAIN;
  333. } else {
  334. return ret;
  335. }
  336. }
  337. ret = gai_error(reqs[0]);
  338. ai = reqs[0]->ar_result;
  339. }
  340. if (ret == 0) {
  341. *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
  342. (*res)->allocated_by_malloc = allocated_by_malloc;
  343. (*res)->ai = ai;
  344. }
  345. return ret;
  346. }
  347. #endif
  348. void
  349. rb_freeaddrinfo(struct rb_addrinfo *ai)
  350. {
  351. if (!ai->allocated_by_malloc)
  352. freeaddrinfo(ai->ai);
  353. else {
  354. struct addrinfo *ai1, *ai2;
  355. ai1 = ai->ai;
  356. while (ai1) {
  357. ai2 = ai1->ai_next;
  358. xfree(ai1->ai_addr);
  359. xfree(ai1);
  360. ai1 = ai2;
  361. }
  362. }
  363. xfree(ai);
  364. }
  365. #ifndef GETADDRINFO_EMU
  366. struct getnameinfo_arg
  367. {
  368. const struct sockaddr *sa;
  369. socklen_t salen;
  370. int flags;
  371. char *host;
  372. size_t hostlen;
  373. char *serv;
  374. size_t servlen;
  375. };
  376. static void *
  377. nogvl_getnameinfo(void *arg)
  378. {
  379. struct getnameinfo_arg *ptr = arg;
  380. return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen,
  381. ptr->host, (socklen_t)ptr->hostlen,
  382. ptr->serv, (socklen_t)ptr->servlen,
  383. ptr->flags);
  384. }
  385. #endif
  386. int
  387. rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
  388. char *host, size_t hostlen,
  389. char *serv, size_t servlen, int flags)
  390. {
  391. #ifdef GETADDRINFO_EMU
  392. return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
  393. #else
  394. struct getnameinfo_arg arg;
  395. int ret;
  396. arg.sa = sa;
  397. arg.salen = salen;
  398. arg.host = host;
  399. arg.hostlen = hostlen;
  400. arg.serv = serv;
  401. arg.servlen = servlen;
  402. arg.flags = flags;
  403. ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0);
  404. return ret;
  405. #endif
  406. }
  407. static void
  408. make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
  409. {
  410. int error;
  411. error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST);
  412. if (error) {
  413. rsock_raise_socket_error("getnameinfo", error);
  414. }
  415. }
  416. VALUE
  417. rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
  418. {
  419. char hbuf[1024];
  420. make_ipaddr0(addr, addrlen, hbuf, sizeof(hbuf));
  421. return rb_str_new2(hbuf);
  422. }
  423. static void
  424. make_inetaddr(unsigned int host, char *buf, size_t buflen)
  425. {
  426. struct sockaddr_in sin;
  427. INIT_SOCKADDR_IN(&sin, sizeof(sin));
  428. sin.sin_addr.s_addr = host;
  429. make_ipaddr0((struct sockaddr*)&sin, sizeof(sin), buf, buflen);
  430. }
  431. static int
  432. str_is_number(const char *p)
  433. {
  434. char *ep;
  435. if (!p || *p == '\0')
  436. return 0;
  437. ep = NULL;
  438. (void)STRTOUL(p, &ep, 10);
  439. if (ep && *ep == '\0')
  440. return 1;
  441. else
  442. return 0;
  443. }
  444. #define str_equal(ptr, len, name) \
  445. ((ptr)[0] == name[0] && \
  446. rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0)
  447. static char*
  448. host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
  449. {
  450. if (NIL_P(host)) {
  451. return NULL;
  452. }
  453. else if (rb_obj_is_kind_of(host, rb_cInteger)) {
  454. unsigned int i = NUM2UINT(host);
  455. make_inetaddr(htonl(i), hbuf, hbuflen);
  456. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  457. return hbuf;
  458. }
  459. else {
  460. const char *name;
  461. size_t len;
  462. StringValueCStr(host);
  463. RSTRING_GETMEM(host, name, len);
  464. if (!len || str_equal(name, len, "<any>")) {
  465. make_inetaddr(INADDR_ANY, hbuf, hbuflen);
  466. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  467. }
  468. else if (str_equal(name, len, "<broadcast>")) {
  469. make_inetaddr(INADDR_BROADCAST, hbuf, hbuflen);
  470. if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
  471. }
  472. else if (len >= hbuflen) {
  473. rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
  474. len);
  475. }
  476. else {
  477. memcpy(hbuf, name, len);
  478. hbuf[len] = '\0';
  479. }
  480. return hbuf;
  481. }
  482. }
  483. static char*
  484. port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
  485. {
  486. if (NIL_P(port)) {
  487. return 0;
  488. }
  489. else if (FIXNUM_P(port)) {
  490. snprintf(pbuf, pbuflen, "%ld", FIX2LONG(port));
  491. #ifdef AI_NUMERICSERV
  492. if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
  493. #endif
  494. return pbuf;
  495. }
  496. else {
  497. const char *serv;
  498. size_t len;
  499. StringValueCStr(port);
  500. RSTRING_GETMEM(port, serv, len);
  501. if (len >= pbuflen) {
  502. rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
  503. len);
  504. }
  505. memcpy(pbuf, serv, len);
  506. pbuf[len] = '\0';
  507. return pbuf;
  508. }
  509. }
  510. struct rb_addrinfo*
  511. rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
  512. {
  513. struct rb_addrinfo* res = NULL;
  514. char *hostp, *portp;
  515. int error;
  516. char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
  517. int additional_flags = 0;
  518. hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
  519. portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
  520. if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
  521. hints->ai_socktype = SOCK_DGRAM;
  522. }
  523. hints->ai_flags |= additional_flags;
  524. error = rb_getaddrinfo(hostp, portp, hints, &res);
  525. if (error) {
  526. if (hostp && hostp[strlen(hostp)-1] == '\n') {
  527. rb_raise(rb_eSocket, "newline at the end of hostname");
  528. }
  529. rsock_raise_socket_error("getaddrinfo", error);
  530. }
  531. return res;
  532. }
  533. #ifdef HAVE_GETADDRINFO_A
  534. static struct rb_addrinfo*
  535. rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout)
  536. {
  537. struct rb_addrinfo* res = NULL;
  538. char *hostp, *portp;
  539. int error;
  540. char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
  541. int additional_flags = 0;
  542. hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
  543. portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
  544. if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
  545. hints->ai_socktype = SOCK_DGRAM;
  546. }
  547. hints->ai_flags |= additional_flags;
  548. if (NIL_P(timeout)) {
  549. error = rb_getaddrinfo(hostp, portp, hints, &res);
  550. } else {
  551. struct timespec _timeout = rb_time_timespec_interval(timeout);
  552. error = rb_getaddrinfo_a(hostp, portp, hints, &res, &_timeout);
  553. }
  554. if (error) {
  555. if (hostp && hostp[strlen(hostp)-1] == '\n') {
  556. rb_raise(rb_eSocket, "newline at the end of hostname");
  557. }
  558. rsock_raise_socket_error("getaddrinfo_a", error);
  559. }
  560. return res;
  561. }
  562. #endif
  563. int
  564. rsock_fd_family(int fd)
  565. {
  566. struct sockaddr sa = { 0 };
  567. socklen_t sa_len = sizeof(sa);
  568. if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 ||
  569. (size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) {
  570. return AF_UNSPEC;
  571. }
  572. return sa.sa_family;
  573. }
  574. struct rb_addrinfo*
  575. rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
  576. {
  577. struct addrinfo hints;
  578. MEMZERO(&hints, struct addrinfo, 1);
  579. hints.ai_family = family;
  580. hints.ai_socktype = socktype;
  581. hints.ai_flags = flags;
  582. return rsock_getaddrinfo(host, port, &hints, 1);
  583. }
  584. VALUE
  585. rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
  586. {
  587. VALUE family, port, addr1, addr2;
  588. VALUE ary;
  589. int error;
  590. char hbuf[1024], pbuf[1024];
  591. ID id;
  592. id = rsock_intern_family(sockaddr->sa_family);
  593. if (id) {
  594. family = rb_str_dup(rb_id2str(id));
  595. }
  596. else {
  597. sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
  598. family = rb_str_new2(pbuf);
  599. }
  600. addr1 = Qnil;
  601. if (!norevlookup) {
  602. error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
  603. NULL, 0, 0);
  604. if (! error) {
  605. addr1 = rb_str_new2(hbuf);
  606. }
  607. }
  608. error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
  609. pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
  610. if (error) {
  611. rsock_raise_socket_error("getnameinfo", error);
  612. }
  613. addr2 = rb_str_new2(hbuf);
  614. if (addr1 == Qnil) {
  615. addr1 = addr2;
  616. }
  617. port = INT2FIX(atoi(pbuf));
  618. ary = rb_ary_new3(4, family, port, addr1, addr2);
  619. return ary;
  620. }
  621. #ifdef HAVE_SYS_UN_H
  622. static long
  623. unixsocket_len(const struct sockaddr_un *su, socklen_t socklen)
  624. {
  625. const char *s = su->sun_path, *e = (const char*)su + socklen;
  626. while (s < e && *(e-1) == '\0')
  627. e--;
  628. return e - s;
  629. }
  630. VALUE
  631. rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
  632. {
  633. long n = unixsocket_len(sockaddr, len);
  634. if (n >= 0)
  635. return rb_str_new(sockaddr->sun_path, n);
  636. else
  637. return rb_str_new2("");
  638. }
  639. VALUE
  640. rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
  641. {
  642. return rb_assoc_new(rb_str_new2("AF_UNIX"),
  643. rsock_unixpath_str(sockaddr, len));
  644. }
  645. socklen_t
  646. rsock_unix_sockaddr_len(VALUE path)
  647. {
  648. #ifdef __linux__
  649. if (RSTRING_LEN(path) == 0) {
  650. /* autobind; see unix(7) for details. */
  651. return (socklen_t) sizeof(sa_family_t);
  652. }
  653. else if (RSTRING_PTR(path)[0] == '\0') {
  654. /* abstract namespace; see unix(7) for details. */
  655. if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path))
  656. rb_raise(rb_eArgError, "Linux abstract socket too long");
  657. return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
  658. RSTRING_SOCKLEN(path);
  659. }
  660. else {
  661. #endif
  662. return (socklen_t) sizeof(struct sockaddr_un);
  663. #ifdef __linux__
  664. }
  665. #endif
  666. }
  667. #endif
  668. struct hostent_arg {
  669. VALUE host;
  670. struct rb_addrinfo* addr;
  671. VALUE (*ipaddr)(struct sockaddr*, socklen_t);
  672. };
  673. static VALUE
  674. make_hostent_internal(VALUE v)
  675. {
  676. struct hostent_arg *arg = (void *)v;
  677. VALUE host = arg->host;
  678. struct addrinfo* addr = arg->addr->ai;
  679. VALUE (*ipaddr)(struct sockaddr*, socklen_t) = arg->ipaddr;
  680. struct addrinfo *ai;
  681. struct hostent *h;
  682. VALUE ary, names;
  683. char **pch;
  684. const char* hostp;
  685. char hbuf[NI_MAXHOST];
  686. ary = rb_ary_new();
  687. if (addr->ai_canonname) {
  688. hostp = addr->ai_canonname;
  689. }
  690. else {
  691. hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
  692. }
  693. rb_ary_push(ary, rb_str_new2(hostp));
  694. if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST &&
  695. (h = gethostbyname(addr->ai_canonname))) {
  696. names = rb_ary_new();
  697. if (h->h_aliases != NULL) {
  698. for (pch = h->h_aliases; *pch; pch++) {
  699. rb_ary_push(names, rb_str_new2(*pch));
  700. }
  701. }
  702. }
  703. else {
  704. names = rb_ary_new2(0);
  705. }
  706. rb_ary_push(ary, names);
  707. rb_ary_push(ary, INT2NUM(addr->ai_family));
  708. for (ai = addr; ai; ai = ai->ai_next) {
  709. rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
  710. }
  711. return ary;
  712. }
  713. VALUE
  714. rsock_freeaddrinfo(VALUE arg)
  715. {
  716. struct rb_addrinfo *addr = (struct rb_addrinfo *)arg;
  717. rb_freeaddrinfo(addr);
  718. return Qnil;
  719. }
  720. VALUE
  721. rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t))
  722. {
  723. struct hostent_arg arg;
  724. arg.host = host;
  725. arg.addr = addr;
  726. arg.ipaddr = ipaddr;
  727. return rb_ensure(make_hostent_internal, (VALUE)&arg,
  728. rsock_freeaddrinfo, (VALUE)addr);
  729. }
  730. typedef struct {
  731. VALUE inspectname;
  732. VALUE canonname;
  733. int pfamily;
  734. int socktype;
  735. int protocol;
  736. socklen_t sockaddr_len;
  737. union_sockaddr addr;
  738. } rb_addrinfo_t;
  739. static void
  740. addrinfo_mark(void *ptr)
  741. {
  742. rb_addrinfo_t *rai = ptr;
  743. rb_gc_mark(rai->inspectname);
  744. rb_gc_mark(rai->canonname);
  745. }
  746. #define addrinfo_free RUBY_TYPED_DEFAULT_FREE
  747. static size_t
  748. addrinfo_memsize(const void *ptr)
  749. {
  750. return sizeof(rb_addrinfo_t);
  751. }
  752. static const rb_data_type_t addrinfo_type = {
  753. "socket/addrinfo",
  754. {addrinfo_mark, addrinfo_free, addrinfo_memsize,},
  755. };
  756. static VALUE
  757. addrinfo_s_allocate(VALUE klass)
  758. {
  759. return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
  760. }
  761. #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
  762. static inline rb_addrinfo_t *
  763. check_addrinfo(VALUE self)
  764. {
  765. return rb_check_typeddata(self, &addrinfo_type);
  766. }
  767. static rb_addrinfo_t *
  768. get_addrinfo(VALUE self)
  769. {
  770. rb_addrinfo_t *rai = check_addrinfo(self);
  771. if (!rai) {
  772. rb_raise(rb_eTypeError, "uninitialized socket address");
  773. }
  774. return rai;
  775. }
  776. static rb_addrinfo_t *
  777. alloc_addrinfo(void)
  778. {
  779. rb_addrinfo_t *rai = ZALLOC(rb_addrinfo_t);
  780. rai->inspectname = Qnil;
  781. rai->canonname = Qnil;
  782. return rai;
  783. }
  784. static void
  785. init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
  786. int pfamily, int socktype, int protocol,
  787. VALUE canonname, VALUE inspectname)
  788. {
  789. if ((socklen_t)sizeof(rai->addr) < len)
  790. rb_raise(rb_eArgError, "sockaddr string too big");
  791. memcpy((void *)&rai->addr, (void *)sa, len);
  792. rai->sockaddr_len = len;
  793. rai->pfamily = pfamily;
  794. rai->socktype = socktype;
  795. rai->protocol = protocol;
  796. rai->canonname = canonname;
  797. rai->inspectname = inspectname;
  798. }
  799. VALUE
  800. rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
  801. int family, int socktype, int protocol,
  802. VALUE canonname, VALUE inspectname)
  803. {
  804. VALUE a;
  805. rb_addrinfo_t *rai;
  806. a = addrinfo_s_allocate(rb_cAddrinfo);
  807. DATA_PTR(a) = rai = alloc_addrinfo();
  808. init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
  809. return a;
  810. }
  811. static struct rb_addrinfo *
  812. call_getaddrinfo(VALUE node, VALUE service,
  813. VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
  814. int socktype_hack, VALUE timeout)
  815. {
  816. struct addrinfo hints;
  817. struct rb_addrinfo *res;
  818. MEMZERO(&hints, struct addrinfo, 1);
  819. hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
  820. if (!NIL_P(socktype)) {
  821. hints.ai_socktype = rsock_socktype_arg(socktype);
  822. }
  823. if (!NIL_P(protocol)) {
  824. hints.ai_protocol = NUM2INT(protocol);
  825. }
  826. if (!NIL_P(flags)) {
  827. hints.ai_flags = NUM2INT(flags);
  828. }
  829. #ifdef HAVE_GETADDRINFO_A
  830. if (NIL_P(timeout)) {
  831. res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
  832. } else {
  833. res = rsock_getaddrinfo_a(node, service, &hints, socktype_hack, timeout);
  834. }
  835. #else
  836. res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
  837. #endif
  838. if (res == NULL)
  839. rb_raise(rb_eSocket, "host not found");
  840. return res;
  841. }
  842. static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
  843. static void
  844. init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service,
  845. VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
  846. VALUE inspectnode, VALUE inspectservice)
  847. {
  848. struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1, Qnil);
  849. VALUE canonname;
  850. VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res->ai);
  851. canonname = Qnil;
  852. if (res->ai->ai_canonname) {
  853. canonname = rb_str_new_cstr(res->ai->ai_canonname);
  854. OBJ_FREEZE(canonname);
  855. }
  856. init_addrinfo(rai, res->ai->ai_addr, res->ai->ai_addrlen,
  857. NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
  858. canonname, inspectname);
  859. rb_freeaddrinfo(res);
  860. }
  861. static VALUE
  862. make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
  863. {
  864. VALUE inspectname = Qnil;
  865. if (res) {
  866. /* drop redundant information which also shown in address:port part. */
  867. char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
  868. int ret;
  869. ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
  870. sizeof(hbuf), pbuf, sizeof(pbuf),
  871. NI_NUMERICHOST|NI_NUMERICSERV);
  872. if (ret == 0) {
  873. if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0)
  874. node = Qnil;
  875. if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0)
  876. service = Qnil;
  877. else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service))
  878. service = Qnil;
  879. }
  880. }
  881. if (RB_TYPE_P(node, T_STRING)) {
  882. inspectname = rb_str_dup(node);
  883. }
  884. if (RB_TYPE_P(service, T_STRING)) {
  885. if (NIL_P(inspectname))
  886. inspectname = rb_sprintf(":%s", StringValueCStr(service));
  887. else
  888. rb_str_catf(inspectname, ":%s", StringValueCStr(service));
  889. }
  890. else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0)
  891. {
  892. if (NIL_P(inspectname))
  893. inspectname = rb_sprintf(":%d", FIX2INT(service));
  894. else
  895. rb_str_catf(inspectname, ":%d", FIX2INT(service));
  896. }
  897. if (!NIL_P(inspectname)) {
  898. OBJ_FREEZE(inspectname);
  899. }
  900. return inspectname;
  901. }
  902. static VALUE
  903. addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
  904. {
  905. VALUE ret;
  906. VALUE canonname;
  907. VALUE inspectname;
  908. struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, Qnil);
  909. inspectname = make_inspectname(node, service, res->ai);
  910. canonname = Qnil;
  911. if (res->ai->ai_canonname) {
  912. canonname = rb_str_new_cstr(res->ai->ai_canonname);
  913. OBJ_FREEZE(canonname);
  914. }
  915. ret = rsock_addrinfo_new(res->ai->ai_addr, res->ai->ai_addrlen,
  916. res->ai->ai_family, res->ai->ai_socktype,
  917. res->ai->ai_protocol,
  918. canonname, inspectname);
  919. rb_freeaddrinfo(res);
  920. return ret;
  921. }
  922. static VALUE
  923. addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE timeout)
  924. {
  925. VALUE ret;
  926. struct addrinfo *r;
  927. VALUE inspectname;
  928. struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, timeout);
  929. inspectname = make_inspectname(node, service, res->ai);
  930. ret = rb_ary_new();
  931. for (r = res->ai; r; r = r->ai_next) {
  932. VALUE addr;
  933. VALUE canonname = Qnil;
  934. if (r->ai_canonname) {
  935. canonname = rb_str_new_cstr(r->ai_canonname);
  936. OBJ_FREEZE(canonname);
  937. }
  938. addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
  939. r->ai_family, r->ai_socktype, r->ai_protocol,
  940. canonname, inspectname);
  941. rb_ary_push(ret, addr);
  942. }
  943. rb_freeaddrinfo(res);
  944. return ret;
  945. }
  946. #ifdef HAVE_SYS_UN_H
  947. static void
  948. init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
  949. {
  950. struct sockaddr_un un;
  951. socklen_t len;
  952. StringValue(path);
  953. if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
  954. rb_raise(rb_eArgError,
  955. "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
  956. (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
  957. INIT_SOCKADDR_UN(&un, sizeof(struct sockaddr_un));
  958. memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
  959. len = rsock_unix_sockaddr_len(path);
  960. init_addrinfo(rai, (struct sockaddr *)&un, len,
  961. PF_UNIX, socktype, 0, Qnil, Qnil);
  962. }
  963. static long
  964. rai_unixsocket_len(const rb_addrinfo_t *rai)
  965. {
  966. return unixsocket_len(&rai->addr.un, rai->sockaddr_len);
  967. }
  968. #endif
  969. /*
  970. * call-seq:
  971. * Addrinfo.new(sockaddr) => addrinfo
  972. * Addrinfo.new(sockaddr, family) => addrinfo
  973. * Addrinfo.new(sockaddr, family, socktype) => addrinfo
  974. * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
  975. *
  976. * returns a new instance of Addrinfo.
  977. * The instance contains sockaddr, family, socktype, protocol.
  978. * sockaddr means struct sockaddr which can be used for connect(2), etc.
  979. * family, socktype and protocol are integers which is used for arguments of socket(2).
  980. *
  981. * sockaddr is specified as an array or a string.
  982. * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
  983. * The string should be struct sockaddr as generated by
  984. * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
  985. *
  986. * sockaddr examples:
  987. * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
  988. * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
  989. * - ["AF_UNIX", "/tmp/sock"]
  990. * - Socket.sockaddr_in("smtp", "2001:DB8::1")
  991. * - Socket.sockaddr_in(80, "172.18.22.42")
  992. * - Socket.sockaddr_in(80, "www.ruby-lang.org")
  993. * - Socket.sockaddr_un("/tmp/sock")
  994. *
  995. * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
  996. * numeric IP address, is used to construct socket address in the Addrinfo instance.
  997. * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
  998. *
  999. * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
  1000. * It can be a symbol or a string which is the constant name
  1001. * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
  1002. * If omitted, PF_UNSPEC is assumed.
  1003. *
  1004. * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
  1005. * It can be a symbol or a string which is the constant name
  1006. * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
  1007. * If omitted, 0 is assumed.
  1008. *
  1009. * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
  1010. * It must be an integer, unlike family and socktype.
  1011. * If omitted, 0 is assumed.
  1012. * Note that 0 is reasonable value for most protocols, except raw socket.
  1013. *
  1014. */
  1015. static VALUE
  1016. addrinfo_initialize(int argc, VALUE *argv, VALUE self)
  1017. {
  1018. rb_addrinfo_t *rai;
  1019. VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
  1020. int i_pfamily, i_socktype, i_protocol;
  1021. struct sockaddr *sockaddr_ptr;
  1022. socklen_t sockaddr_len;
  1023. VALUE canonname = Qnil, inspectname = Qnil;
  1024. if (check_addrinfo(self))
  1025. rb_raise(rb_eTypeError, "already initialized socket address");
  1026. DATA_PTR(self) = rai = alloc_addrinfo();
  1027. rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
  1028. i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
  1029. i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
  1030. i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
  1031. sockaddr_ary = rb_check_array_type(sockaddr_arg);
  1032. if (!NIL_P(sockaddr_ary)) {
  1033. VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
  1034. int af;
  1035. StringValue(afamily);
  1036. if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
  1037. rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
  1038. switch (af) {
  1039. case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
  1040. #ifdef INET6
  1041. case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
  1042. #endif
  1043. {
  1044. VALUE service = rb_ary_entry(sockaddr_ary, 1);
  1045. VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
  1046. VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
  1047. int flags;
  1048. service = INT2NUM(NUM2INT(service));
  1049. if (!NIL_P(nodename))
  1050. StringValue(nodename);
  1051. StringValue(numericnode);
  1052. flags = AI_NUMERICHOST;
  1053. #ifdef AI_NUMERICSERV
  1054. flags |= AI_NUMERICSERV;
  1055. #endif
  1056. init_addrinfo_getaddrinfo(rai, numericnode, service,
  1057. INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
  1058. INT2NUM(flags),
  1059. nodename, service);
  1060. break;
  1061. }
  1062. #ifdef HAVE_SYS_UN_H
  1063. case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
  1064. {
  1065. VALUE path = rb_ary_entry(sockaddr_ary, 1);
  1066. StringValue(path);
  1067. init_unix_addrinfo(rai, path, SOCK_STREAM);
  1068. break;
  1069. }
  1070. #endif
  1071. default:
  1072. rb_raise(rb_eSocket, "unexpected address family");
  1073. }
  1074. }
  1075. else {
  1076. StringValue(sockaddr_arg);
  1077. sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
  1078. sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg);
  1079. init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
  1080. i_pfamily, i_socktype, i_protocol,
  1081. canonname, inspectname);
  1082. }
  1083. return self;
  1084. }
  1085. static int
  1086. get_afamily(const struct sockaddr *addr, socklen_t len)
  1087. {
  1088. if ((socklen_t)((const char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
  1089. return addr->sa_family;
  1090. else
  1091. return AF_UNSPEC;
  1092. }
  1093. static int
  1094. ai_get_afamily(const rb_addrinfo_t *rai)
  1095. {
  1096. return get_afamily(&rai->addr.addr, rai->sockaddr_len);
  1097. }
  1098. static VALUE
  1099. inspect_sockaddr(VALUE addrinfo, VALUE ret)
  1100. {
  1101. rb_addrinfo_t *rai = get_addrinfo(addrinfo);
  1102. union_sockaddr *sockaddr = &rai->addr;
  1103. socklen_t socklen = rai->sockaddr_len;
  1104. return rsock_inspect_sockaddr((struct sockaddr *)sockaddr, socklen, ret);
  1105. }
  1106. VALUE
  1107. rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
  1108. {
  1109. union_sockaddr *sockaddr = (union_sockaddr *)sockaddr_arg;
  1110. if (socklen == 0) {
  1111. rb_str_cat2(ret, "empty-sockaddr");
  1112. }
  1113. else if ((long)socklen < ((char*)&sockaddr->addr.sa_family + sizeof(sockaddr->addr.sa_family)) - (char*)sockaddr)
  1114. rb_str_cat2(ret, "too-short-sockaddr");
  1115. else {
  1116. switch (sockaddr->addr.sa_family) {
  1117. case AF_UNSPEC:
  1118. {
  1119. rb_str_cat2(ret, "UNSPEC");
  1120. break;
  1121. }
  1122. case AF_INET:
  1123. {
  1124. struct sockaddr_in *addr;
  1125. int port;
  1126. addr = &sockaddr->in;
  1127. if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
  1128. rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
  1129. else
  1130. rb_str_cat2(ret, "?");
  1131. if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
  1132. rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
  1133. else
  1134. rb_str_cat2(ret, ".?");
  1135. if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
  1136. rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
  1137. else
  1138. rb_str_cat2(ret, ".?");
  1139. if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
  1140. rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
  1141. else
  1142. rb_str_cat2(ret, ".?");
  1143. if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
  1144. port = ntohs(addr->sin_port);
  1145. if (port)
  1146. rb_str_catf(ret, ":%d", port);
  1147. }
  1148. else {
  1149. rb_str_cat2(ret, ":?");
  1150. }
  1151. if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
  1152. rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
  1153. (int)socklen,
  1154. (int)sizeof(struct sockaddr_in));
  1155. break;
  1156. }
  1157. #ifdef AF_INET6
  1158. case AF_INET6:
  1159. {
  1160. struct sockaddr_in6 *addr;
  1161. char hbuf[1024];
  1162. int port;
  1163. int error;
  1164. if (socklen < (socklen_t)sizeof(struct sockaddr_in6)) {
  1165. rb_str_catf(ret, "too-short-AF_INET6-sockaddr %d bytes", (int)socklen);
  1166. }
  1167. else {
  1168. addr = &sockaddr->in6;
  1169. /* use getnameinfo for scope_id.
  1170. * RFC 4007: IPv6 Scoped Address Architecture
  1171. * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
  1172. */
  1173. error = getnameinfo(&sockaddr->addr, socklen,
  1174. hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
  1175. NI_NUMERICHOST|NI_NUMERICSERV);
  1176. if (error) {
  1177. rsock_raise_socket_error("getnameinfo", error);
  1178. }
  1179. if (addr->sin6_port == 0) {
  1180. rb_str_cat2(ret, hbuf);
  1181. }
  1182. else {
  1183. port = ntohs(addr->sin6_port);
  1184. rb_str_catf(ret, "[%s]:%d", hbuf, port);
  1185. }
  1186. if ((socklen_t)sizeof(struct sockaddr_in6) < socklen)
  1187. rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(socklen - sizeof(struct sockaddr_in6)));
  1188. }
  1189. break;
  1190. }
  1191. #endif
  1192. #ifdef HAVE_SYS_UN_H
  1193. case AF_UNIX:
  1194. {
  1195. struct sockaddr_un *addr = &sockaddr->un;
  1196. char *p, *s, *e;
  1197. long len = unixsocket_len(addr, socklen);
  1198. s = addr->sun_path;
  1199. if (len < 0)
  1200. rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
  1201. else if (len == 0)
  1202. rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
  1203. else {
  1204. int printable_only = 1;
  1205. e = s + len;
  1206. p = s;
  1207. while (p < e) {
  1208. printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
  1209. p++;
  1210. }
  1211. if (printable_only) { /* only printable, no space */
  1212. if (s[0] != '/') /* relative path */
  1213. rb_str_cat2(ret, "UNIX ");
  1214. rb_str_cat(ret, s, p - s);
  1215. }
  1216. else {
  1217. rb_str_cat2(ret, "UNIX");
  1218. while (s < e)
  1219. rb_str_catf(ret, ":%02x", (unsigned char)*s++);
  1220. }
  1221. }
  1222. break;
  1223. }
  1224. #endif
  1225. #if defined(AF_PACKET) && defined(__linux__)
  1226. /* GNU/Linux */
  1227. case AF_PACKET:
  1228. {
  1229. struct sockaddr_ll *addr;
  1230. const char *sep = "[";
  1231. #define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
  1232. addr = (struct sockaddr_ll *)sockaddr;
  1233. rb_str_cat2(ret, "PACKET");
  1234. if (offsetof(struct sockaddr_ll, sll_protocol) + sizeof(addr->sll_protocol) <= (size_t)socklen) {
  1235. CATSEP;
  1236. rb_str_catf(ret, "protocol=%d", ntohs(addr->sll_protocol));
  1237. }
  1238. if (offsetof(struct sockaddr_ll, sll_ifindex) + sizeof(addr->sll_ifindex) <= (size_t)socklen) {
  1239. char buf[IFNAMSIZ];
  1240. CATSEP;
  1241. if (if_indextoname(addr->sll_ifindex, buf) == NULL)
  1242. rb_str_catf(ret, "ifindex=%d", addr->sll_ifindex);
  1243. else
  1244. rb_str_catf(ret, "%s", buf);
  1245. }
  1246. if (offsetof(struct sockaddr_ll, sll_hatype) + sizeof(addr->sll_hatype) <= (size_t)socklen) {
  1247. CATSEP;
  1248. rb_str_catf(ret, "hatype=%d", addr->sll_hatype);
  1249. }
  1250. if (offsetof(struct sockaddr_ll, sll_pkttype) + sizeof(addr->sll_pkttype) <= (size_t)socklen) {
  1251. CATSEP;
  1252. if (addr->sll_pkttype == PACKET_HOST)
  1253. rb_str_cat2(ret, "HOST");
  1254. else if (addr->sll_pkttype == PACKET_BROADCAST)
  1255. rb_str_cat2(ret, "BROADCAST");
  1256. else if (addr->sll_pkttype == PACKET_MULTICAST)
  1257. rb_str_cat2(ret, "MULTICAST");
  1258. else if (addr->sll_pkttype == PACKET_OTHERHOST)
  1259. rb_str_cat2(ret, "OTHERHOST");
  1260. else if (addr->sll_pkttype == PACKET_OUTGOING)
  1261. rb_str_cat2(ret, "OUTGOING");
  1262. else
  1263. rb_str_catf(ret, "pkttype=%d", addr->sll_pkttype);
  1264. }
  1265. if (socklen != (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen)) {
  1266. CATSEP;
  1267. if (offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen) <= (size_t)socklen) {
  1268. rb_str_catf(ret, "halen=%d", addr->sll_halen);
  1269. }
  1270. }
  1271. if (offsetof(struct sockaddr_ll, sll_addr) < (size_t)socklen) {
  1272. socklen_t len, i;
  1273. CATSEP;
  1274. rb_str_cat2(ret, "hwaddr");
  1275. len = addr->sll_halen;
  1276. if ((size_t)socklen < offsetof(struct sockaddr_ll, sll_addr) + len)
  1277. len = socklen - offsetof(struct sockaddr_ll, sll_addr);
  1278. for (i = 0; i < len; i++) {
  1279. rb_str_cat2(ret, i == 0 ? "=" : ":");
  1280. rb_str_catf(ret, "%02x", addr->sll_addr[i]);
  1281. }
  1282. }
  1283. if (socklen < (socklen_t)(offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen)) ||
  1284. (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen) != socklen) {
  1285. CATSEP;
  1286. rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_ll)",
  1287. (int)socklen, (int)sizeof(struct sockaddr_ll));
  1288. }
  1289. rb_str_cat2(ret, "]");
  1290. #undef CATSEP
  1291. break;
  1292. }
  1293. #endif
  1294. #if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL)
  1295. /* AF_LINK is defined in 4.4BSD derivations since Net2.
  1296. link_ntoa is also defined at Net2.
  1297. However Debian GNU/kFreeBSD defines AF_LINK but
  1298. don't have link_ntoa. */
  1299. case AF_LINK:
  1300. {
  1301. /*
  1302. * Simple implementation using link_ntoa():
  1303. * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
  1304. * Also, the format is bit different.
  1305. *
  1306. * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
  1307. * break;
  1308. */
  1309. struct sockaddr_dl *addr = &sockaddr->dl;
  1310. char *np = NULL, *ap = NULL, *endp;
  1311. int nlen = 0, alen = 0;
  1312. int i, off;
  1313. const char *sep = "[";
  1314. #define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
  1315. rb_str_cat2(ret, "LINK");
  1316. endp = ((char *)addr) + socklen;
  1317. if (offsetof(struct sockaddr_dl, sdl_data) < socklen) {
  1318. np = addr->sdl_data;
  1319. nlen = addr->sdl_nlen;
  1320. if (endp - np < nlen)
  1321. nlen = (int)(endp - np);
  1322. }
  1323. off = addr->sdl_nlen;
  1324. if (offsetof(struct sockaddr_dl, sdl_data) + off < socklen) {
  1325. ap = addr->sdl_data + off;
  1326. alen = addr->sdl_alen;
  1327. if (endp - ap < alen)
  1328. alen = (int)(endp - ap);
  1329. }
  1330. CATSEP;
  1331. if (np)
  1332. rb_str_catf(ret, "%.*s", nlen, np);
  1333. else
  1334. rb_str_cat2(ret, "?");
  1335. if (ap && 0 < alen) {
  1336. CATSEP;
  1337. for (i = 0; i < alen; i++)
  1338. rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]);
  1339. }
  1340. if (socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_nlen) + sizeof(addr->sdl_nlen)) ||
  1341. socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_alen) + sizeof(addr->sdl_alen)) ||
  1342. socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_slen) + sizeof(addr->sdl_slen)) ||
  1343. /* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field.
  1344. * cf. Net2:/usr/src/sys/net/if_dl.h. */
  1345. socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) {
  1346. CATSEP;
  1347. rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)",
  1348. (int)socklen, (int)sizeof(struct sockaddr_dl));
  1349. }
  1350. rb_str_cat2(ret, "]");
  1351. #undef CATSEP
  1352. break;
  1353. }
  1354. #endif
  1355. default:
  1356. {
  1357. ID id = rsock_intern_family(sockaddr->addr.sa_family);
  1358. if (id == 0)
  1359. rb_str_catf(ret, "unknown address family %d", sockaddr->addr.sa_family);
  1360. else
  1361. rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
  1362. break;
  1363. }
  1364. }
  1365. }
  1366. return ret;
  1367. }
  1368. /*
  1369. * call-seq:
  1370. * addrinfo.inspect => string
  1371. *
  1372. * returns a string which shows addrinfo in human-readable form.
  1373. *
  1374. * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>"
  1375. * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
  1376. *
  1377. */
  1378. static VALUE
  1379. addrinfo_inspect(VALUE self)
  1380. {
  1381. rb_addrinfo_t *rai = get_addrinfo(self);
  1382. int internet_p;
  1383. VALUE ret;
  1384. ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
  1385. inspect_sockaddr(self, ret);
  1386. if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
  1387. ID id = rsock_intern_protocol_family(rai->pfamily);
  1388. if (id)
  1389. rb_str_catf(ret, " %s", rb_id2name(id));
  1390. else
  1391. rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
  1392. }
  1393. internet_p = rai->pfamily == PF_INET;
  1394. #ifdef INET6
  1395. internet_p = internet_p || rai->pfamily == PF_INET6;
  1396. #endif
  1397. if (internet_p && rai->socktype == SOCK_STREAM &&
  1398. (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
  1399. rb_str_cat2(ret, " TCP");
  1400. }
  1401. else if (internet_p && rai->socktype == SOCK_DGRAM &&
  1402. (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
  1403. rb_str_cat2(ret, " UDP");
  1404. }
  1405. else {
  1406. if (rai->socktype) {
  1407. ID id = rsock_intern_socktype(rai->socktype);
  1408. if (id)
  1409. rb_str_catf(ret, " %s", rb_id2name(id));
  1410. else
  1411. rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
  1412. }
  1413. if (rai->protocol) {
  1414. if (internet_p) {
  1415. ID id = rsock_intern_ipproto(rai->protocol);
  1416. if (id)
  1417. rb_str_catf(ret, " %s", rb_id2name(id));
  1418. else
  1419. goto unknown_protocol;
  1420. }
  1421. else {
  1422. unknown_protocol:
  1423. rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
  1424. }
  1425. }
  1426. }
  1427. if (!NIL_P(rai->canonname)) {
  1428. VALUE name = rai->canonname;
  1429. rb_str_catf(ret, " %s", StringValueCStr(name));
  1430. }
  1431. if (!NIL_P(rai->inspectname)) {
  1432. VALUE name = rai->inspectname;
  1433. rb_str_catf(ret, " (%s)", StringValueCStr(name));
  1434. }
  1435. rb_str_buf_cat2(ret, ">");
  1436. return ret;
  1437. }
  1438. /*
  1439. * call-seq:
  1440. * addrinfo.inspect_sockaddr => string
  1441. *
  1442. * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
  1443. *
  1444. * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
  1445. * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
  1446. * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
  1447. *
  1448. */
  1449. VALUE
  1450. rsock_addrinfo_inspect_sockaddr(VALUE self)
  1451. {
  1452. return inspect_sockaddr(self, rb_str_new("", 0));
  1453. }
  1454. /* :nodoc: */
  1455. static VALUE
  1456. addrinfo_mdump(VALUE self)
  1457. {
  1458. rb_addrinfo_t *rai = get_addrinfo(self);
  1459. VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
  1460. int afamily_int = ai_get_afamily(rai);
  1461. ID id;
  1462. id = rsock_intern_protocol_family(rai->pfamily);
  1463. if (id == 0)
  1464. rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
  1465. pfamily = rb_id2str(id);
  1466. if (rai->socktype == 0)
  1467. socktype = INT2FIX(0);
  1468. else {
  1469. id = rsock_intern_socktype(rai->socktype);
  1470. if (id == 0)
  1471. rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
  1472. socktype = rb_id2str(id);
  1473. }
  1474. if (rai->protocol == 0)
  1475. protocol = INT2FIX(0);
  1476. el

Large files files are truncated, but you can click here to view the full file