PageRenderTime 57ms CodeModel.GetById 18ms 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
  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. else if (IS_IP_FAMILY(afamily_int)) {
  1477. id = rsock_intern_ipproto(rai->protocol);
  1478. if (id == 0)
  1479. rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
  1480. protocol = rb_id2str(id);
  1481. }
  1482. else {
  1483. rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
  1484. }
  1485. canonname = rai->canonname;
  1486. inspectname = rai->inspectname;
  1487. id = rsock_intern_family(afamily_int);
  1488. if (id == 0)
  1489. rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
  1490. afamily = rb_id2str(id);
  1491. switch(afamily_int) {
  1492. #ifdef HAVE_SYS_UN_H
  1493. case AF_UNIX:
  1494. {
  1495. sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai));
  1496. break;
  1497. }
  1498. #endif
  1499. default:
  1500. {
  1501. char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
  1502. int error;
  1503. error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
  1504. hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
  1505. NI_NUMERICHOST|NI_NUMERICSERV);
  1506. if (error) {
  1507. rsock_raise_socket_error("getnameinfo", error);
  1508. }
  1509. sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
  1510. break;
  1511. }
  1512. }
  1513. return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
  1514. }
  1515. /* :nodoc: */
  1516. static VALUE
  1517. addrinfo_mload(VALUE self, VALUE ary)
  1518. {
  1519. VALUE v;
  1520. VALUE canonname, inspectname;
  1521. int afamily, pfamily, socktype, protocol;
  1522. union_sockaddr ss;
  1523. socklen_t len;
  1524. rb_addrinfo_t *rai;
  1525. if (check_addrinfo(self))
  1526. rb_raise(rb_eTypeError, "already initialized socket address");
  1527. ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
  1528. v = rb_ary_entry(ary, 0);
  1529. StringValue(v);
  1530. if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
  1531. rb_raise(rb_eTypeError, "unexpected address family");
  1532. v = rb_ary_entry(ary, 2);
  1533. StringValue(v);
  1534. if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
  1535. rb_raise(rb_eTypeError, "unexpected protocol family");
  1536. v = rb_ary_entry(ary, 3);
  1537. if (v == INT2FIX(0))
  1538. socktype = 0;
  1539. else {
  1540. StringValue(v);
  1541. if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
  1542. rb_raise(rb_eTypeError, "unexpected socktype");
  1543. }
  1544. v = rb_ary_entry(ary, 4);
  1545. if (v == INT2FIX(0))
  1546. protocol = 0;
  1547. else {
  1548. StringValue(v);
  1549. if (IS_IP_FAMILY(afamily)) {
  1550. if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
  1551. rb_raise(rb_eTypeError, "unexpected protocol");
  1552. }
  1553. else {
  1554. rb_raise(rb_eTypeError, "unexpected protocol");
  1555. }
  1556. }
  1557. v = rb_ary_entry(ary, 5);
  1558. if (NIL_P(v))
  1559. canonname = Qnil;
  1560. else {
  1561. StringValue(v);
  1562. canonname = v;
  1563. }
  1564. v = rb_ary_entry(ary, 6);
  1565. if (NIL_P(v))
  1566. inspectname = Qnil;
  1567. else {
  1568. StringValue(v);
  1569. inspectname = v;
  1570. }
  1571. v = rb_ary_entry(ary, 1);
  1572. switch(afamily) {
  1573. #ifdef HAVE_SYS_UN_H
  1574. case AF_UNIX:
  1575. {
  1576. struct sockaddr_un uaddr;
  1577. INIT_SOCKADDR_UN(&uaddr, sizeof(struct sockaddr_un));
  1578. StringValue(v);
  1579. if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
  1580. rb_raise(rb_eSocket,
  1581. "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
  1582. (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
  1583. memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
  1584. len = (socklen_t)sizeof(uaddr);
  1585. memcpy(&ss, &uaddr, len);
  1586. break;
  1587. }
  1588. #endif
  1589. default:
  1590. {
  1591. VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
  1592. struct rb_addrinfo *res;
  1593. int flags = AI_NUMERICHOST;
  1594. #ifdef AI_NUMERICSERV
  1595. flags |= AI_NUMERICSERV;
  1596. #endif
  1597. res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
  1598. INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
  1599. INT2NUM(flags), 1, Qnil);
  1600. len = res->ai->ai_addrlen;
  1601. memcpy(&ss, res->ai->ai_addr, res->ai->ai_addrlen);
  1602. rb_freeaddrinfo(res);
  1603. break;
  1604. }
  1605. }
  1606. DATA_PTR(self) = rai = alloc_addrinfo();
  1607. init_addrinfo(rai, &ss.addr, len,
  1608. pfamily, socktype, protocol,
  1609. canonname, inspectname);
  1610. return self;
  1611. }
  1612. /*
  1613. * call-seq:
  1614. * addrinfo.afamily => integer
  1615. *
  1616. * returns the address family as an integer.
  1617. *
  1618. * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
  1619. *
  1620. */
  1621. static VALUE
  1622. addrinfo_afamily(VALUE self)
  1623. {
  1624. rb_addrinfo_t *rai = get_addrinfo(self);
  1625. return INT2NUM(ai_get_afamily(rai));
  1626. }
  1627. /*
  1628. * call-seq:
  1629. * addrinfo.pfamily => integer
  1630. *
  1631. * returns the protocol family as an integer.
  1632. *
  1633. * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
  1634. *
  1635. */
  1636. static VALUE
  1637. addrinfo_pfamily(VALUE self)
  1638. {
  1639. rb_addrinfo_t *rai = get_addrinfo(self);
  1640. return INT2NUM(rai->pfamily);
  1641. }
  1642. /*
  1643. * call-seq:
  1644. * addrinfo.socktype => integer
  1645. *
  1646. * returns the socket type as an integer.
  1647. *
  1648. * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
  1649. *
  1650. */
  1651. static VALUE
  1652. addrinfo_socktype(VALUE self)
  1653. {
  1654. rb_addrinfo_t *rai = get_addrinfo(self);
  1655. return INT2NUM(rai->socktype);
  1656. }
  1657. /*
  1658. * call-seq:
  1659. * addrinfo.protocol => integer
  1660. *
  1661. * returns the socket type as an integer.
  1662. *
  1663. * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
  1664. *
  1665. */
  1666. static VALUE
  1667. addrinfo_protocol(VALUE self)
  1668. {
  1669. rb_addrinfo_t *rai = get_addrinfo(self);
  1670. return INT2NUM(rai->protocol);
  1671. }
  1672. /*
  1673. * call-seq:
  1674. * addrinfo.to_sockaddr => string
  1675. * addrinfo.to_s => string
  1676. *
  1677. * returns the socket address as packed struct sockaddr string.
  1678. *
  1679. * Addrinfo.tcp("localhost", 80).to_sockaddr
  1680. * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
  1681. *
  1682. */
  1683. static VALUE
  1684. addrinfo_to_sockaddr(VALUE self)
  1685. {
  1686. rb_addrinfo_t *rai = get_addrinfo(self);
  1687. VALUE ret;
  1688. ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
  1689. return ret;
  1690. }
  1691. /*
  1692. * call-seq:
  1693. * addrinfo.canonname => string or nil
  1694. *
  1695. * returns the canonical name as a string.
  1696. *
  1697. * nil is returned if no canonical name.
  1698. *
  1699. * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
  1700. *
  1701. * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
  1702. * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)>
  1703. * p list[0].canonname #=> "carbon.ruby-lang.org"
  1704. *
  1705. */
  1706. static VALUE
  1707. addrinfo_canonname(VALUE self)
  1708. {
  1709. rb_addrinfo_t *rai = get_addrinfo(self);
  1710. return rai->canonname;
  1711. }
  1712. /*
  1713. * call-seq:
  1714. * addrinfo.ip? => true or false
  1715. *
  1716. * returns true if addrinfo is internet (IPv4/IPv6) address.
  1717. * returns false otherwise.
  1718. *
  1719. * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
  1720. * Addrinfo.tcp("::1", 80).ip? #=> true
  1721. * Addrinfo.unix("/tmp/sock").ip? #=> false
  1722. *
  1723. */
  1724. static VALUE
  1725. addrinfo_ip_p(VALUE self)
  1726. {
  1727. rb_addrinfo_t *rai = get_addrinfo(self);
  1728. int family = ai_get_afamily(rai);
  1729. return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
  1730. }
  1731. /*
  1732. * call-seq:
  1733. * addrinfo.ipv4? => true or false
  1734. *
  1735. * returns true if addrinfo is IPv4 address.
  1736. * returns false otherwise.
  1737. *
  1738. * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
  1739. * Addrinfo.tcp("::1", 80).ipv4? #=> false
  1740. * Addrinfo.unix("/tmp/sock").ipv4? #=> false
  1741. *
  1742. */
  1743. static VALUE
  1744. addrinfo_ipv4_p(VALUE self)
  1745. {
  1746. rb_addrinfo_t *rai = get_addrinfo(self);
  1747. return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
  1748. }
  1749. /*
  1750. * call-seq:
  1751. * addrinfo.ipv6? => true or false
  1752. *
  1753. * returns true if addrinfo is IPv6 address.
  1754. * returns false otherwise.
  1755. *
  1756. * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
  1757. * Addrinfo.tcp("::1", 80).ipv6? #=> true
  1758. * Addrinfo.unix("/tmp/sock").ipv6? #=> false
  1759. *
  1760. */
  1761. static VALUE
  1762. addrinfo_ipv6_p(VALUE self)
  1763. {
  1764. #ifdef AF_INET6
  1765. rb_addrinfo_t *rai = get_addrinfo(self);
  1766. return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
  1767. #else
  1768. return Qfalse;
  1769. #endif
  1770. }
  1771. /*
  1772. * call-seq:
  1773. * addrinfo.unix? => true or false
  1774. *
  1775. * returns true if addrinfo is UNIX address.
  1776. * returns false otherwise.
  1777. *
  1778. * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
  1779. * Addrinfo.tcp("::1", 80).unix? #=> false
  1780. * Addrinfo.unix("/tmp/sock").unix? #=> true
  1781. *
  1782. */
  1783. static VALUE
  1784. addrinfo_unix_p(VALUE self)
  1785. {
  1786. rb_addrinfo_t *rai = get_addrinfo(self);
  1787. #ifdef AF_UNIX
  1788. return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
  1789. #else
  1790. return Qfalse;
  1791. #endif
  1792. }
  1793. /*
  1794. * call-seq:
  1795. * addrinfo.getnameinfo => [nodename, service]
  1796. * addrinfo.getnameinfo(flags) => [nodename, service]
  1797. *
  1798. * returns nodename and service as a pair of strings.
  1799. * This converts struct sockaddr in addrinfo to textual representation.
  1800. *
  1801. * flags should be bitwise OR of Socket::NI_??? constants.
  1802. *
  1803. * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
  1804. *
  1805. * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
  1806. * #=> ["localhost", "80"]
  1807. */
  1808. static VALUE
  1809. addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
  1810. {
  1811. rb_addrinfo_t *rai = get_addrinfo(self);
  1812. VALUE vflags;
  1813. char hbuf[1024], pbuf[1024];
  1814. int flags, error;
  1815. rb_scan_args(argc, argv, "01", &vflags);
  1816. flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
  1817. if (rai->socktype == SOCK_DGRAM)
  1818. flags |= NI_DGRAM;
  1819. error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
  1820. hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
  1821. flags);
  1822. if (error) {
  1823. rsock_raise_socket_error("getnameinfo", error);
  1824. }
  1825. return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
  1826. }
  1827. /*
  1828. * call-seq:
  1829. * addrinfo.ip_unpack => [addr, port]
  1830. *
  1831. * Returns the IP address and port number as 2-element array.
  1832. *
  1833. * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
  1834. * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
  1835. */
  1836. static VALUE
  1837. addrinfo_ip_unpack(VALUE self)
  1838. {
  1839. rb_addrinfo_t *rai = get_addrinfo(self);
  1840. int family = ai_get_afamily(rai);
  1841. VALUE vflags;
  1842. VALUE ret, portstr;
  1843. if (!IS_IP_FAMILY(family))
  1844. rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
  1845. vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
  1846. ret = addrinfo_getnameinfo(1, &vflags, self);
  1847. portstr = rb_ary_entry(ret, 1);
  1848. rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
  1849. return ret;
  1850. }
  1851. /*
  1852. * call-seq:
  1853. * addrinfo.ip_address => string
  1854. *
  1855. * Returns the IP address as a string.
  1856. *
  1857. * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
  1858. * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
  1859. */
  1860. static VALUE
  1861. addrinfo_ip_address(VALUE self)
  1862. {
  1863. rb_addrinfo_t *rai = get_addrinfo(self);
  1864. int family = ai_get_afamily(rai);
  1865. VALUE vflags;
  1866. VALUE ret;
  1867. if (!IS_IP_FAMILY(family))
  1868. rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
  1869. vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
  1870. ret = addrinfo_getnameinfo(1, &vflags, self);
  1871. return rb_ary_entry(ret, 0);
  1872. }
  1873. /*
  1874. * call-seq:
  1875. * addrinfo.ip_port => port
  1876. *
  1877. * Returns the port number as an integer.
  1878. *
  1879. * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
  1880. * Addrinfo.tcp("::1", 80).ip_port #=> 80
  1881. */
  1882. static VALUE
  1883. addrinfo_ip_port(VALUE self)
  1884. {
  1885. rb_addrinfo_t *rai = get_addrinfo(self);
  1886. int family = ai_get_afamily(rai);
  1887. int port;
  1888. if (!IS_IP_FAMILY(family)) {
  1889. bad_family:
  1890. #ifdef AF_INET6
  1891. rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
  1892. #else
  1893. rb_raise(rb_eSocket, "need IPv4 address");
  1894. #endif
  1895. }
  1896. switch (family) {
  1897. case AF_INET:
  1898. if (rai->sockaddr_len != sizeof(struct sockaddr_in))
  1899. rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
  1900. port = ntohs(rai->addr.in.sin_port);
  1901. break;
  1902. #ifdef AF_INET6
  1903. case AF_INET6:
  1904. if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
  1905. rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
  1906. port = ntohs(rai->addr.in6.sin6_port);
  1907. break;
  1908. #endif
  1909. default:
  1910. goto bad_family;
  1911. }
  1912. return INT2NUM(port);
  1913. }
  1914. static int
  1915. extract_in_addr(VALUE self, uint32_t *addrp)
  1916. {
  1917. rb_addrinfo_t *rai = get_addrinfo(self);
  1918. int family = ai_get_afamily(rai);
  1919. if (family != AF_INET) return 0;
  1920. *addrp = ntohl(rai->addr.in.sin_addr.s_addr);
  1921. return 1;
  1922. }
  1923. /*
  1924. * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
  1925. * It returns false otherwise.
  1926. */
  1927. static VALUE
  1928. addrinfo_ipv4_private_p(VALUE self)
  1929. {
  1930. uint32_t a;
  1931. if (!extract_in_addr(self, &a)) return Qfalse;
  1932. if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
  1933. (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
  1934. (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
  1935. return Qtrue;
  1936. return Qfalse;
  1937. }
  1938. /*
  1939. * Returns true for IPv4 loopback address (127.0.0.0/8).
  1940. * It returns false otherwise.
  1941. */
  1942. static VALUE
  1943. addrinfo_ipv4_loopback_p(VALUE self)
  1944. {
  1945. uint32_t a;
  1946. if (!extract_in_addr(self, &a)) return Qfalse;
  1947. if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
  1948. return Qtrue;
  1949. return Qfalse;
  1950. }
  1951. /*
  1952. * Returns true for IPv4 multicast address (224.0.0.0/4).
  1953. * It returns false otherwise.
  1954. */
  1955. static VALUE
  1956. addrinfo_ipv4_multicast_p(VALUE self)
  1957. {
  1958. uint32_t a;
  1959. if (!extract_in_addr(self, &a)) return Qfalse;
  1960. if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
  1961. return Qtrue;
  1962. return Qfalse;
  1963. }
  1964. #ifdef INET6
  1965. static struct in6_addr *
  1966. extract_in6_addr(VALUE self)
  1967. {
  1968. rb_addrinfo_t *rai = get_addrinfo(self);
  1969. int family = ai_get_afamily(rai);
  1970. if (family != AF_INET6) return NULL;
  1971. return &rai->addr.in6.sin6_addr;
  1972. }
  1973. /*
  1974. * Returns true for IPv6 unspecified address (::).
  1975. * It returns false otherwise.
  1976. */
  1977. static VALUE
  1978. addrinfo_ipv6_unspecified_p(VALUE self)
  1979. {
  1980. struct in6_addr *addr = extract_in6_addr(self);
  1981. if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
  1982. return Qfalse;
  1983. }
  1984. /*
  1985. * Returns true for IPv6 loopback address (::1).
  1986. * It returns false otherwise.
  1987. */
  1988. static VALUE
  1989. addrinfo_ipv6_loopback_p(VALUE self)
  1990. {
  1991. struct in6_addr *addr = extract_in6_addr(self);
  1992. if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
  1993. return Qfalse;
  1994. }
  1995. /*
  1996. * Returns true for IPv6 multicast address (ff00::/8).
  1997. * It returns false otherwise.
  1998. */
  1999. static VALUE
  2000. addrinfo_ipv6_multicast_p(VALUE self)
  2001. {
  2002. struct in6_addr *addr = extract_in6_addr(self);
  2003. if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
  2004. return Qfalse;
  2005. }
  2006. /*
  2007. * Returns true for IPv6 link local address (ff80::/10).
  2008. * It returns false otherwise.
  2009. */
  2010. static VALUE
  2011. addrinfo_ipv6_linklocal_p(VALUE self)
  2012. {
  2013. struct in6_addr *addr = extract_in6_addr(self);
  2014. if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
  2015. return Qfalse;
  2016. }
  2017. /*
  2018. * Returns true for IPv6 site local address (ffc0::/10).
  2019. * It returns false otherwise.
  2020. */
  2021. static VALUE
  2022. addrinfo_ipv6_sitelocal_p(VALUE self)
  2023. {
  2024. struct in6_addr *addr = extract_in6_addr(self);
  2025. if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
  2026. return Qfalse;
  2027. }
  2028. /*
  2029. * Returns true for IPv6 unique local address (fc00::/7, RFC4193).
  2030. * It returns false otherwise.
  2031. */
  2032. static VALUE
  2033. addrinfo_ipv6_unique_local_p(VALUE self)
  2034. {
  2035. struct in6_addr *addr = extract_in6_addr(self);
  2036. if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue;
  2037. return Qfalse;
  2038. }
  2039. /*
  2040. * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
  2041. * It returns false otherwise.
  2042. */
  2043. static VALUE
  2044. addrinfo_ipv6_v4mapped_p(VALUE self)
  2045. {
  2046. struct in6_addr *addr = extract_in6_addr(self);
  2047. if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
  2048. return Qfalse;
  2049. }
  2050. /*
  2051. * Returns true for IPv4-compatible IPv6 address (::/80).
  2052. * It returns false otherwise.
  2053. */
  2054. static VALUE
  2055. addrinfo_ipv6_v4compat_p(VALUE self)
  2056. {
  2057. struct in6_addr *addr = extract_in6_addr(self);
  2058. if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
  2059. return Qfalse;
  2060. }
  2061. /*
  2062. * Returns true for IPv6 multicast node-local scope address.
  2063. * It returns false otherwise.
  2064. */
  2065. static VALUE
  2066. addrinfo_ipv6_mc_nodelocal_p(VALUE self)
  2067. {
  2068. struct in6_addr *addr = extract_in6_addr(self);
  2069. if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
  2070. return Qfalse;
  2071. }
  2072. /*
  2073. * Returns true for IPv6 multicast link-local scope address.
  2074. * It returns false otherwise.
  2075. */
  2076. static VALUE
  2077. addrinfo_ipv6_mc_linklocal_p(VALUE self)
  2078. {
  2079. struct in6_addr *addr = extract_in6_addr(self);
  2080. if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
  2081. return Qfalse;
  2082. }
  2083. /*
  2084. * Returns true for IPv6 multicast site-local scope address.
  2085. * It returns false otherwise.
  2086. */
  2087. static VALUE
  2088. addrinfo_ipv6_mc_sitelocal_p(VALUE self)
  2089. {
  2090. struct in6_addr *addr = extract_in6_addr(self);
  2091. if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
  2092. return Qfalse;
  2093. }
  2094. /*
  2095. * Returns true for IPv6 multicast organization-local scope address.
  2096. * It returns false otherwise.
  2097. */
  2098. static VALUE
  2099. addrinfo_ipv6_mc_orglocal_p(VALUE self)
  2100. {
  2101. struct in6_addr *addr = extract_in6_addr(self);
  2102. if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
  2103. return Qfalse;
  2104. }
  2105. /*
  2106. * Returns true for IPv6 multicast global scope address.
  2107. * It returns false otherwise.
  2108. */
  2109. static VALUE
  2110. addrinfo_ipv6_mc_global_p(VALUE self)
  2111. {
  2112. struct in6_addr *addr = extract_in6_addr(self);
  2113. if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
  2114. return Qfalse;
  2115. }
  2116. /*
  2117. * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
  2118. * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
  2119. *
  2120. * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
  2121. * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
  2122. * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
  2123. * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
  2124. * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
  2125. */
  2126. static VALUE
  2127. addrinfo_ipv6_to_ipv4(VALUE self)
  2128. {
  2129. rb_addrinfo_t *rai = get_addrinfo(self);
  2130. struct in6_addr *addr;
  2131. int family = ai_get_afamily(rai);
  2132. if (family != AF_INET6) return Qnil;
  2133. addr = &rai->addr.in6.sin6_addr;
  2134. if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
  2135. struct sockaddr_in sin4;
  2136. INIT_SOCKADDR_IN(&sin4, sizeof(sin4));
  2137. memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
  2138. return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
  2139. PF_INET, rai->socktype, rai->protocol,
  2140. rai->canonname, rai->inspectname);
  2141. }
  2142. else {
  2143. return Qnil;
  2144. }
  2145. }
  2146. #endif
  2147. #ifdef HAVE_SYS_UN_H
  2148. /*
  2149. * call-seq:
  2150. * addrinfo.unix_path => path
  2151. *
  2152. * Returns the socket path as a string.
  2153. *
  2154. * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
  2155. */
  2156. static VALUE
  2157. addrinfo_unix_path(VALUE self)
  2158. {
  2159. rb_addrinfo_t *rai = get_addrinfo(self);
  2160. int family = ai_get_afamily(rai);
  2161. struct sockaddr_un *addr;
  2162. long n;
  2163. if (family != AF_UNIX)
  2164. rb_raise(rb_eSocket, "need AF_UNIX address");
  2165. addr = &rai->addr.un;
  2166. n = rai_unixsocket_len(rai);
  2167. if (n < 0)
  2168. rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.",
  2169. (size_t)rai->sockaddr_len, offsetof(struct sockaddr_un, sun_path));
  2170. if ((long)sizeof(addr->sun_path) < n)
  2171. rb_raise(rb_eSocket,
  2172. "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
  2173. (size_t)n, sizeof(addr->sun_path));
  2174. return rb_str_new(addr->sun_path, n);
  2175. }
  2176. #endif
  2177. static ID id_timeout;
  2178. /*
  2179. * call-seq:
  2180. * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
  2181. * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
  2182. * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
  2183. * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
  2184. * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
  2185. *
  2186. * returns a list of addrinfo objects as an array.
  2187. *
  2188. * This method converts nodename (hostname) and service (port) to addrinfo.
  2189. * Since the conversion is not unique, the result is a list of addrinfo objects.
  2190. *
  2191. * nodename or service can be nil if no conversion intended.
  2192. *
  2193. * family, socktype and protocol are hint for preferred protocol.
  2194. * If the result will be used for a socket with SOCK_STREAM,
  2195. * SOCK_STREAM should be specified as socktype.
  2196. * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
  2197. * If they are omitted or nil is given, the result is not restricted.
  2198. *
  2199. * Similarly, PF_INET6 as family restricts for IPv6.
  2200. *
  2201. * flags should be bitwise OR of Socket::AI_??? constants such as follows.
  2202. * Note that the exact list of the constants depends on OS.
  2203. *
  2204. * AI_PASSIVE Get address to use with bind()
  2205. * AI_CANONNAME Fill in the canonical name
  2206. * AI_NUMERICHOST Prevent host name resolution
  2207. * AI_NUMERICSERV Prevent service name resolution
  2208. * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses
  2209. * AI_ALL Allow all addresses
  2210. * AI_ADDRCONFIG Accept only if any address is assigned
  2211. *
  2212. * Note that socktype should be specified whenever application knows the usage of the address.
  2213. * Some platform causes an error when socktype is omitted and servname is specified as an integer
  2214. * because some port numbers, 512 for example, are ambiguous without socktype.
  2215. *
  2216. * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
  2217. * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>,
  2218. * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>]
  2219. *
  2220. */
  2221. static VALUE
  2222. addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
  2223. {
  2224. VALUE node, service, family, socktype, protocol, flags, opts, timeout;
  2225. rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
  2226. &protocol, &flags, &opts);
  2227. rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
  2228. if (timeout == Qundef) {
  2229. timeout = Qnil;
  2230. }
  2231. return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
  2232. }
  2233. /*
  2234. * call-seq:
  2235. * Addrinfo.ip(host) => addrinfo
  2236. *
  2237. * returns an addrinfo object for IP address.
  2238. *
  2239. * The port, socktype, protocol of the result is filled by zero.
  2240. * So, it is not appropriate to create a socket.
  2241. *
  2242. * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
  2243. */
  2244. static VALUE
  2245. addrinfo_s_ip(VALUE self, VALUE host)
  2246. {
  2247. VALUE ret;
  2248. rb_addrinfo_t *rai;
  2249. ret = addrinfo_firstonly_new(host, Qnil,
  2250. INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
  2251. rai = get_addrinfo(ret);
  2252. rai->socktype = 0;
  2253. rai->protocol = 0;
  2254. return ret;
  2255. }
  2256. /*
  2257. * call-seq:
  2258. * Addrinfo.tcp(host, port) => addrinfo
  2259. *
  2260. * returns an addrinfo object for TCP address.
  2261. *
  2262. * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
  2263. */
  2264. static VALUE
  2265. addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
  2266. {
  2267. return addrinfo_firstonly_new(host, port,
  2268. INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
  2269. }
  2270. /*
  2271. * call-seq:
  2272. * Addrinfo.udp(host, port) => addrinfo
  2273. *
  2274. * returns an addrinfo object for UDP address.
  2275. *
  2276. * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
  2277. */
  2278. static VALUE
  2279. addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
  2280. {
  2281. return addrinfo_firstonly_new(host, port,
  2282. INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
  2283. }
  2284. #ifdef HAVE_SYS_UN_H
  2285. /*
  2286. * call-seq:
  2287. * Addrinfo.unix(path [, socktype]) => addrinfo
  2288. *
  2289. * returns an addrinfo object for UNIX socket address.
  2290. *
  2291. * _socktype_ specifies the socket type.
  2292. * If it is omitted, :STREAM is used.
  2293. *
  2294. * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
  2295. * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
  2296. */
  2297. static VALUE
  2298. addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
  2299. {
  2300. VALUE path, vsocktype, addr;
  2301. int socktype;
  2302. rb_addrinfo_t *rai;
  2303. rb_scan_args(argc, argv, "11", &path, &vsocktype);
  2304. if (NIL_P(vsocktype))
  2305. socktype = SOCK_STREAM;
  2306. else
  2307. socktype = rsock_socktype_arg(vsocktype);
  2308. addr = addrinfo_s_allocate(rb_cAddrinfo);
  2309. DATA_PTR(addr) = rai = alloc_addrinfo();
  2310. init_unix_addrinfo(rai, path, socktype);
  2311. return addr;
  2312. }
  2313. #endif
  2314. VALUE
  2315. rsock_sockaddr_string_value(volatile VALUE *v)
  2316. {
  2317. VALUE val = *v;
  2318. if (IS_ADDRINFO(val)) {
  2319. *v = addrinfo_to_sockaddr(val);
  2320. }
  2321. StringValue(*v);
  2322. return *v;
  2323. }
  2324. VALUE
  2325. rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *rai_ret)
  2326. {
  2327. VALUE val = *v;
  2328. *rai_ret = Qnil;
  2329. if (IS_ADDRINFO(val)) {
  2330. *v = addrinfo_to_sockaddr(val);
  2331. *rai_ret = val;
  2332. }
  2333. StringValue(*v);
  2334. return *v;
  2335. }
  2336. char *
  2337. rsock_sockaddr_string_value_ptr(volatile VALUE *v)
  2338. {
  2339. rsock_sockaddr_string_value(v);
  2340. return RSTRING_PTR(*v);
  2341. }
  2342. VALUE
  2343. rb_check_sockaddr_string_type(VALUE val)
  2344. {
  2345. if (IS_ADDRINFO(val))
  2346. return addrinfo_to_sockaddr(val);
  2347. return rb_check_string_type(val);
  2348. }
  2349. VALUE
  2350. rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
  2351. {
  2352. int family;
  2353. int socktype;
  2354. int ret;
  2355. socklen_t optlen = (socklen_t)sizeof(socktype);
  2356. /* assumes protocol family and address family are identical */
  2357. family = get_afamily(addr, len);
  2358. ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
  2359. if (ret == -1) {
  2360. rb_sys_fail("getsockopt(SO_TYPE)");
  2361. }
  2362. return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
  2363. }
  2364. VALUE
  2365. rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
  2366. {
  2367. rb_io_t *fptr;
  2368. switch (TYPE(io)) {
  2369. case T_FIXNUM:
  2370. return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
  2371. case T_BIGNUM:
  2372. return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
  2373. case T_FILE:
  2374. GetOpenFile(io, fptr);
  2375. return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
  2376. default:
  2377. rb_raise(rb_eTypeError, "neither IO nor file descriptor");
  2378. }
  2379. UNREACHABLE_RETURN(Qnil);
  2380. }
  2381. /*
  2382. * Addrinfo class
  2383. */
  2384. void
  2385. rsock_init_addrinfo(void)
  2386. {
  2387. /*
  2388. * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
  2389. * structure identifies an Internet host and a service.
  2390. */
  2391. id_timeout = rb_intern("timeout");
  2392. rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
  2393. rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
  2394. rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
  2395. rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0);
  2396. rb_define_method(rb_cAddrinfo, "inspect_sockaddr", rsock_addrinfo_inspect_sockaddr, 0);
  2397. rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1);
  2398. rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1);
  2399. rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2);
  2400. rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2);
  2401. #ifdef HAVE_SYS_UN_H
  2402. rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
  2403. #endif
  2404. rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0);
  2405. rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0);
  2406. rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0);
  2407. rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0);
  2408. rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0);
  2409. rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0);
  2410. rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0);
  2411. rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0);
  2412. rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0);
  2413. rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0);
  2414. rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0);
  2415. rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0);
  2416. rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0);
  2417. rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0);
  2418. rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0);
  2419. #ifdef INET6
  2420. rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
  2421. rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
  2422. rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
  2423. rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
  2424. rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
  2425. rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0);
  2426. rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
  2427. rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
  2428. rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
  2429. rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
  2430. rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
  2431. rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
  2432. rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
  2433. rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
  2434. #endif
  2435. #ifdef HAVE_SYS_UN_H
  2436. rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
  2437. #endif
  2438. rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0);
  2439. rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
  2440. rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
  2441. rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
  2442. rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
  2443. }