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

/benchmarks/rdoc/ruby_trunk/ext/socket/raddrinfo.c

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

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