PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/components/ruby-2.1.0/ext/socket/raddrinfo.c

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

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