Ruby  1.9.3p551(2014-11-13revision48407)
raddrinfo.c
Go to the documentation of this file.
1 /************************************************
2 
3  ainfo.c -
4 
5  created at: Thu Mar 31 12:21:29 JST 1994
6 
7  Copyright (C) 1993-2007 Yukihiro Matsumoto
8 
9 ************************************************/
10 
11 #include "rubysocket.h"
12 
13 #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
14 #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0]))
15 static const int lookup_order_table[] = {
16 #if defined(LOOKUP_ORDER_HACK_INET)
17  PF_INET, PF_INET6, PF_UNSPEC,
18 #elif defined(LOOKUP_ORDER_HACK_INET6)
19  PF_INET6, PF_INET, PF_UNSPEC,
20 #else
21  /* should not happen */
22 #endif
23 };
24 
25 static int
26 ruby_getaddrinfo(const char *nodename, const char *servname,
27  const struct addrinfo *hints, struct addrinfo **res)
28 {
29  struct addrinfo tmp_hints;
30  int i, af, error;
31 
32  if (hints->ai_family != PF_UNSPEC) {
33  return getaddrinfo(nodename, servname, hints, res);
34  }
35 
36  for (i = 0; i < LOOKUP_ORDERS; i++) {
37  af = lookup_order_table[i];
38  MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
39  tmp_hints.ai_family = af;
40  error = getaddrinfo(nodename, servname, &tmp_hints, res);
41  if (error) {
42  if (tmp_hints.ai_family == PF_UNSPEC) {
43  break;
44  }
45  }
46  else {
47  break;
48  }
49  }
50 
51  return error;
52 }
53 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
54 #endif
55 
56 #if defined(_AIX)
57 static int
58 ruby_getaddrinfo__aix(const char *nodename, const char *servname,
59  const struct addrinfo *hints, struct addrinfo **res)
60 {
61  int error = getaddrinfo(nodename, servname, hints, res);
62  struct addrinfo *r;
63  if (error)
64  return error;
65  for (r = *res; r != NULL; r = r->ai_next) {
66  if (r->ai_addr->sa_family == 0)
67  r->ai_addr->sa_family = r->ai_family;
68  if (r->ai_addr->sa_len == 0)
69  r->ai_addr->sa_len = r->ai_addrlen;
70  }
71  return 0;
72 }
73 #undef getaddrinfo
74 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
75 static int
76 ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
77  char *host, size_t hostlen,
78  char *serv, size_t servlen, int flags)
79 {
80  struct sockaddr_in6 *sa6;
81  u_int32_t *a6;
82 
83  if (sa->sa_family == AF_INET6) {
84  sa6 = (struct sockaddr_in6 *)sa;
85  a6 = sa6->sin6_addr.u6_addr.u6_addr32;
86 
87  if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
88  strncpy(host, "::", hostlen);
89  snprintf(serv, servlen, "%d", sa6->sin6_port);
90  return 0;
91  }
92  }
93  return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
94 }
95 #undef getnameinfo
96 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
97  ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
98 #endif
99 
100 static int str_is_number(const char *);
101 
102 #if defined(__APPLE__)
103 static int
104 ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
105  const struct addrinfo *hints, struct addrinfo **res)
106 {
107  /* fix [ruby-core:29427] */
108  const char *tmp_servname;
109  struct addrinfo tmp_hints;
110  int error;
111 
112  tmp_servname = servname;
113  MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
114  if (nodename && servname) {
115  if (str_is_number(tmp_servname) && atoi(servname) == 0) {
116  tmp_servname = NULL;
117 #ifdef AI_NUMERICSERV
118  if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
119 #endif
120  }
121  }
122 
123  error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
124  if (error == 0) {
125  /* [ruby-dev:23164] */
126  struct addrinfo *r;
127  r = *res;
128  while (r) {
129  if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype;
130  if (! r->ai_protocol) {
131  if (r->ai_socktype == SOCK_DGRAM) {
132  r->ai_protocol = IPPROTO_UDP;
133  }
134  else if (r->ai_socktype == SOCK_STREAM) {
135  r->ai_protocol = IPPROTO_TCP;
136  }
137  }
138  r = r->ai_next;
139  }
140  }
141 
142  return error;
143 }
144 #undef getaddrinfo
145 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
146 #endif
147 
148 #ifndef GETADDRINFO_EMU
150 {
151  const char *node;
152  const char *service;
153  const struct addrinfo *hints;
154  struct addrinfo **res;
155 };
156 
157 static VALUE
159 {
160  int ret;
161  struct getaddrinfo_arg *ptr = arg;
162  ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
163 #ifdef __linux__
164  /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
165  * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
166  */
167  if (ret == EAI_SYSTEM && errno == ENOENT)
168  ret = EAI_NONAME;
169 #endif
170  return (VALUE)ret;
171 }
172 #endif
173 
174 int
175 rb_getaddrinfo(const char *node, const char *service,
176  const struct addrinfo *hints,
177  struct addrinfo **res)
178 {
179 #ifdef GETADDRINFO_EMU
180  return getaddrinfo(node, service, hints, res);
181 #else
182  struct getaddrinfo_arg arg;
183  int ret;
184  MEMZERO(&arg, sizeof arg, 1);
185  arg.node = node;
186  arg.service = service;
187  arg.hints = hints;
188  arg.res = res;
189  ret = (int)BLOCKING_REGION(nogvl_getaddrinfo, &arg);
190  return ret;
191 #endif
192 }
193 
194 #ifndef GETADDRINFO_EMU
196 {
197  const struct sockaddr *sa;
198  socklen_t salen;
199  char *host;
200  size_t hostlen;
201  char *serv;
202  size_t servlen;
203  int flags;
204 };
205 
206 static VALUE
208 {
209  struct getnameinfo_arg *ptr = arg;
210  return getnameinfo(ptr->sa, ptr->salen,
211  ptr->host, (socklen_t)ptr->hostlen,
212  ptr->serv, (socklen_t)ptr->servlen,
213  ptr->flags);
214 }
215 #endif
216 
217 int
218 rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
219  char *host, size_t hostlen,
220  char *serv, size_t servlen, int flags)
221 {
222 #ifdef GETADDRINFO_EMU
223  return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
224 #else
225  struct getnameinfo_arg arg;
226  int ret;
227  arg.sa = sa;
228  arg.salen = salen;
229  arg.host = host;
230  arg.hostlen = hostlen;
231  arg.serv = serv;
232  arg.servlen = servlen;
233  arg.flags = flags;
234  ret = (int)BLOCKING_REGION(nogvl_getnameinfo, &arg);
235  return ret;
236 #endif
237 }
238 
239 static void
240 make_ipaddr0(struct sockaddr *addr, char *buf, size_t len)
241 {
242  int error;
243 
244  error = rb_getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
245  if (error) {
246  rsock_raise_socket_error("getnameinfo", error);
247  }
248 }
249 
250 VALUE
251 rsock_make_ipaddr(struct sockaddr *addr)
252 {
253  char hbuf[1024];
254 
255  make_ipaddr0(addr, hbuf, sizeof(hbuf));
256  return rb_str_new2(hbuf);
257 }
258 
259 static void
260 make_inetaddr(unsigned int host, char *buf, size_t len)
261 {
262  struct sockaddr_in sin;
263 
264  MEMZERO(&sin, struct sockaddr_in, 1);
265  sin.sin_family = AF_INET;
266  SET_SIN_LEN(&sin, sizeof(sin));
267  sin.sin_addr.s_addr = host;
268  make_ipaddr0((struct sockaddr*)&sin, buf, len);
269 }
270 
271 static int
272 str_is_number(const char *p)
273 {
274  char *ep;
275 
276  if (!p || *p == '\0')
277  return 0;
278  ep = NULL;
279  (void)STRTOUL(p, &ep, 10);
280  if (ep && *ep == '\0')
281  return 1;
282  else
283  return 0;
284 }
285 
286 static char*
287 host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr)
288 {
289  if (NIL_P(host)) {
290  return NULL;
291  }
292  else if (rb_obj_is_kind_of(host, rb_cInteger)) {
293  unsigned int i = NUM2UINT(host);
294 
295  make_inetaddr(htonl(i), hbuf, len);
296  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
297  return hbuf;
298  }
299  else {
300  char *name;
301 
302  SafeStringValue(host);
303  name = RSTRING_PTR(host);
304  if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) {
305  make_inetaddr(INADDR_ANY, hbuf, len);
306  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
307  }
308  else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
309  make_inetaddr(INADDR_BROADCAST, hbuf, len);
310  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
311  }
312  else if (strlen(name) >= len) {
313  rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
314  strlen(name));
315  }
316  else {
317  strcpy(hbuf, name);
318  }
319  return hbuf;
320  }
321 }
322 
323 static char*
324 port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr)
325 {
326  if (NIL_P(port)) {
327  return 0;
328  }
329  else if (FIXNUM_P(port)) {
330  snprintf(pbuf, len, "%ld", FIX2LONG(port));
331 #ifdef AI_NUMERICSERV
332  if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
333 #endif
334  return pbuf;
335  }
336  else {
337  char *serv;
338 
339  SafeStringValue(port);
340  serv = RSTRING_PTR(port);
341  if (strlen(serv) >= len) {
342  rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
343  strlen(serv));
344  }
345  strcpy(pbuf, serv);
346  return pbuf;
347  }
348 }
349 
350 struct addrinfo*
351 rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
352 {
353  struct addrinfo* res = NULL;
354  char *hostp, *portp;
355  int error;
356  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
357  int additional_flags = 0;
358 
359  hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
360  portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
361 
362  if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
363  hints->ai_socktype = SOCK_DGRAM;
364  }
365  hints->ai_flags |= additional_flags;
366 
367  error = rb_getaddrinfo(hostp, portp, hints, &res);
368  if (error) {
369  if (hostp && hostp[strlen(hostp)-1] == '\n') {
370  rb_raise(rb_eSocket, "newline at the end of hostname");
371  }
372  rsock_raise_socket_error("getaddrinfo", error);
373  }
374 
375  return res;
376 }
377 
378 struct addrinfo*
379 rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
380 {
381  struct addrinfo hints;
382 
383  MEMZERO(&hints, struct addrinfo, 1);
384  hints.ai_family = AF_UNSPEC;
385  hints.ai_socktype = socktype;
386  hints.ai_flags = flags;
387  return rsock_getaddrinfo(host, port, &hints, 1);
388 }
389 
390 VALUE
391 rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
392 {
393  VALUE family, port, addr1, addr2;
394  VALUE ary;
395  int error;
396  char hbuf[1024], pbuf[1024];
397  ID id;
398 
399  id = rsock_intern_family(sockaddr->sa_family);
400  if (id) {
401  family = rb_str_dup(rb_id2str(id));
402  }
403  else {
404  sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
405  family = rb_str_new2(pbuf);
406  }
407 
408  addr1 = Qnil;
409  if (!norevlookup) {
410  error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
411  NULL, 0, 0);
412  if (! error) {
413  addr1 = rb_str_new2(hbuf);
414  }
415  }
416  error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
417  pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
418  if (error) {
419  rsock_raise_socket_error("getnameinfo", error);
420  }
421  addr2 = rb_str_new2(hbuf);
422  if (addr1 == Qnil) {
423  addr1 = addr2;
424  }
425  port = INT2FIX(atoi(pbuf));
426  ary = rb_ary_new3(4, family, port, addr1, addr2);
427 
428  return ary;
429 }
430 
431 #ifdef HAVE_SYS_UN_H
432 VALUE
433 rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
434 {
435  char *s, *e;
436  s = sockaddr->sun_path;
437  e = (char *)sockaddr + len;
438  while (s < e && *(e-1) == '\0')
439  e--;
440  if (s <= e)
441  return rb_str_new(s, e-s);
442  else
443  return rb_str_new2("");
444 }
445 
446 VALUE
447 rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
448 {
449  return rb_assoc_new(rb_str_new2("AF_UNIX"),
450  rsock_unixpath_str(sockaddr, len));
451 }
452 
453 socklen_t
454 rsock_unix_sockaddr_len(VALUE path)
455 {
456 #ifdef __linux__
457  if (RSTRING_LEN(path) == 0) {
458  /* autobind; see unix(7) for details. */
459  return (socklen_t) sizeof(sa_family_t);
460  }
461  else if (RSTRING_PTR(path)[0] == '\0') {
462  /* abstract namespace; see unix(7) for details. */
463  return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
464  RSTRING_LEN(path);
465  }
466  else {
467 #endif
468  return (socklen_t) sizeof(struct sockaddr_un);
469 #ifdef __linux__
470  }
471 #endif
472 }
473 #endif
474 
475 struct hostent_arg {
477  struct addrinfo* addr;
478  VALUE (*ipaddr)(struct sockaddr*, size_t);
479 };
480 
481 static VALUE
483 {
484  VALUE host = arg->host;
485  struct addrinfo* addr = arg->addr;
486  VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr;
487 
488  struct addrinfo *ai;
489  struct hostent *h;
490  VALUE ary, names;
491  char **pch;
492  const char* hostp;
493  char hbuf[NI_MAXHOST];
494 
495  ary = rb_ary_new();
496  if (addr->ai_canonname) {
497  hostp = addr->ai_canonname;
498  }
499  else {
500  hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
501  }
502  rb_ary_push(ary, rb_str_new2(hostp));
503 
504  if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
505  names = rb_ary_new();
506  if (h->h_aliases != NULL) {
507  for (pch = h->h_aliases; *pch; pch++) {
508  rb_ary_push(names, rb_str_new2(*pch));
509  }
510  }
511  }
512  else {
513  names = rb_ary_new2(0);
514  }
515  rb_ary_push(ary, names);
516  rb_ary_push(ary, INT2NUM(addr->ai_family));
517  for (ai = addr; ai; ai = ai->ai_next) {
518  rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
519  }
520 
521  return ary;
522 }
523 
524 VALUE
526 {
527  freeaddrinfo(addr);
528  return Qnil;
529 }
530 
531 VALUE
532 rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t))
533 {
534  struct hostent_arg arg;
535 
536  arg.host = host;
537  arg.addr = addr;
538  arg.ipaddr = ipaddr;
539  return rb_ensure(make_hostent_internal, (VALUE)&arg,
540  rsock_freeaddrinfo, (VALUE)addr);
541 }
542 
543 typedef struct {
546  int pfamily;
547  int socktype;
548  int protocol;
549  socklen_t sockaddr_len;
550  struct sockaddr_storage addr;
551 } rb_addrinfo_t;
552 
553 static void
555 {
556  rb_addrinfo_t *rai = ptr;
557  if (rai) {
558  rb_gc_mark(rai->inspectname);
559  rb_gc_mark(rai->canonname);
560  }
561 }
562 
563 #define addrinfo_free RUBY_TYPED_DEFAULT_FREE
564 
565 static size_t
566 addrinfo_memsize(const void *ptr)
567 {
568  return ptr ? sizeof(rb_addrinfo_t) : 0;
569 }
570 
572  "socket/addrinfo",
574 };
575 
576 static VALUE
578 {
579  return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
580 }
581 
582 #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
583 static inline rb_addrinfo_t *
585 {
586  return rb_check_typeddata(self, &addrinfo_type);
587 }
588 
589 static rb_addrinfo_t *
591 {
592  rb_addrinfo_t *rai = check_addrinfo(self);
593 
594  if (!rai) {
595  rb_raise(rb_eTypeError, "uninitialized socket address");
596  }
597  return rai;
598 }
599 
600 
601 static rb_addrinfo_t *
603 {
605  memset(rai, 0, sizeof(rb_addrinfo_t));
606  rai->inspectname = Qnil;
607  rai->canonname = Qnil;
608  return rai;
609 }
610 
611 static void
612 init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
613  int pfamily, int socktype, int protocol,
614  VALUE canonname, VALUE inspectname)
615 {
616  if ((socklen_t)sizeof(rai->addr) < len)
617  rb_raise(rb_eArgError, "sockaddr string too big");
618  memcpy((void *)&rai->addr, (void *)sa, len);
619  rai->sockaddr_len = len;
620 
621  rai->pfamily = pfamily;
622  rai->socktype = socktype;
623  rai->protocol = protocol;
624  rai->canonname = canonname;
625  rai->inspectname = inspectname;
626 }
627 
628 VALUE
629 rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
630  int family, int socktype, int protocol,
631  VALUE canonname, VALUE inspectname)
632 {
633  VALUE a;
634  rb_addrinfo_t *rai;
635 
637  DATA_PTR(a) = rai = alloc_addrinfo();
638  init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
639  return a;
640 }
641 
642 static struct addrinfo *
644  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
645  int socktype_hack)
646 {
647  struct addrinfo hints, *res;
648 
649  MEMZERO(&hints, struct addrinfo, 1);
650  hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
651 
652  if (!NIL_P(socktype)) {
653  hints.ai_socktype = rsock_socktype_arg(socktype);
654  }
655  if (!NIL_P(protocol)) {
656  hints.ai_protocol = NUM2INT(protocol);
657  }
658  if (!NIL_P(flags)) {
659  hints.ai_flags = NUM2INT(flags);
660  }
661  res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
662 
663  if (res == NULL)
664  rb_raise(rb_eSocket, "host not found");
665  return res;
666 }
667 
668 static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
669 
670 static void
672  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
673  VALUE inspectnode, VALUE inspectservice)
674 {
675  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1);
676  VALUE canonname;
677  VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res);
678 
679  canonname = Qnil;
680  if (res->ai_canonname) {
681  canonname = rb_tainted_str_new_cstr(res->ai_canonname);
682  OBJ_FREEZE(canonname);
683  }
684 
685  init_addrinfo(rai, res->ai_addr, res->ai_addrlen,
686  NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
687  canonname, inspectname);
688 
689  freeaddrinfo(res);
690 }
691 
692 static VALUE
693 make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
694 {
695  VALUE inspectname = Qnil;
696 
697  if (res) {
698  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
699  int ret;
700  ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
701  sizeof(hbuf), pbuf, sizeof(pbuf),
703  if (ret == 0) {
704  if (TYPE(node) == T_STRING && strcmp(hbuf, RSTRING_PTR(node)) == 0)
705  node = Qnil;
706  if (TYPE(service) == T_STRING && strcmp(pbuf, RSTRING_PTR(service)) == 0)
707  service = Qnil;
708  else if (TYPE(service) == T_FIXNUM && atoi(pbuf) == FIX2INT(service))
709  service = Qnil;
710  }
711  }
712 
713  if (TYPE(node) == T_STRING) {
714  inspectname = rb_str_dup(node);
715  }
716  if (TYPE(service) == T_STRING) {
717  if (NIL_P(inspectname))
718  inspectname = rb_sprintf(":%s", StringValueCStr(service));
719  else
720  rb_str_catf(inspectname, ":%s", StringValueCStr(service));
721  }
722  else if (TYPE(service) == T_FIXNUM && FIX2INT(service) != 0)
723  {
724  if (NIL_P(inspectname))
725  inspectname = rb_sprintf(":%d", FIX2INT(service));
726  else
727  rb_str_catf(inspectname, ":%d", FIX2INT(service));
728  }
729  if (!NIL_P(inspectname)) {
730  OBJ_INFECT(inspectname, node);
731  OBJ_INFECT(inspectname, service);
732  OBJ_FREEZE(inspectname);
733  }
734  return inspectname;
735 }
736 
737 static VALUE
738 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
739 {
740  VALUE ret;
741  VALUE canonname;
742  VALUE inspectname;
743 
744  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
745 
746  inspectname = make_inspectname(node, service, res);
747 
748  canonname = Qnil;
749  if (res->ai_canonname) {
750  canonname = rb_tainted_str_new_cstr(res->ai_canonname);
751  OBJ_FREEZE(canonname);
752  }
753 
754  ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen,
755  res->ai_family, res->ai_socktype, res->ai_protocol,
756  canonname, inspectname);
757 
758  freeaddrinfo(res);
759  return ret;
760 }
761 
762 static VALUE
763 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
764 {
765  VALUE ret;
766  struct addrinfo *r;
767  VALUE inspectname;
768 
769  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
770 
771  inspectname = make_inspectname(node, service, res);
772 
773  ret = rb_ary_new();
774  for (r = res; r; r = r->ai_next) {
775  VALUE addr;
776  VALUE canonname = Qnil;
777 
778  if (r->ai_canonname) {
779  canonname = rb_tainted_str_new_cstr(r->ai_canonname);
780  OBJ_FREEZE(canonname);
781  }
782 
783  addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
784  r->ai_family, r->ai_socktype, r->ai_protocol,
785  canonname, inspectname);
786 
787  rb_ary_push(ret, addr);
788  }
789 
790  freeaddrinfo(res);
791  return ret;
792 }
793 
794 
795 #ifdef HAVE_SYS_UN_H
796 static void
797 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
798 {
799  struct sockaddr_un un;
800  socklen_t len;
801 
802  StringValue(path);
803 
804  if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
806  "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
807  (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
808 
809  MEMZERO(&un, struct sockaddr_un, 1);
810 
811  un.sun_family = AF_UNIX;
812  memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
813 
814  len = rsock_unix_sockaddr_len(path);
815  init_addrinfo(rai, (struct sockaddr *)&un, len,
816  PF_UNIX, socktype, 0, Qnil, Qnil);
817 }
818 #endif
819 
820 /*
821  * call-seq:
822  * Addrinfo.new(sockaddr) => addrinfo
823  * Addrinfo.new(sockaddr, family) => addrinfo
824  * Addrinfo.new(sockaddr, family, socktype) => addrinfo
825  * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
826  *
827  * returns a new instance of Addrinfo.
828  * The instance contains sockaddr, family, socktype, protocol.
829  * sockaddr means struct sockaddr which can be used for connect(2), etc.
830  * family, socktype and protocol are integers which is used for arguments of socket(2).
831  *
832  * sockaddr is specified as an array or a string.
833  * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
834  * The string should be struct sockaddr as generated by
835  * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
836  *
837  * sockaddr examples:
838  * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
839  * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
840  * - ["AF_UNIX", "/tmp/sock"]
841  * - Socket.sockaddr_in("smtp", "2001:DB8::1")
842  * - Socket.sockaddr_in(80, "172.18.22.42")
843  * - Socket.sockaddr_in(80, "www.ruby-lang.org")
844  * - Socket.sockaddr_un("/tmp/sock")
845  *
846  * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
847  * numeric IP address, is used to construct socket address in the Addrinfo instance.
848  * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
849  *
850  * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
851  * It can be a symbol or a string which is the constant name
852  * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
853  * If omitted, PF_UNSPEC is assumed.
854  *
855  * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
856  * It can be a symbol or a string which is the constant name
857  * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
858  * If omitted, 0 is assumed.
859  *
860  * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
861  * It must be an integer, unlike family and socktype.
862  * If omitted, 0 is assumed.
863  * Note that 0 is reasonable value for most protocols, except raw socket.
864  *
865  */
866 static VALUE
868 {
869  rb_addrinfo_t *rai;
870  VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
871  int i_pfamily, i_socktype, i_protocol;
872  struct sockaddr *sockaddr_ptr;
873  socklen_t sockaddr_len;
874  VALUE canonname = Qnil, inspectname = Qnil;
875 
876  if (check_addrinfo(self))
877  rb_raise(rb_eTypeError, "already initialized socket address");
878  DATA_PTR(self) = rai = alloc_addrinfo();
879 
880  rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
881 
882  i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
883  i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
884  i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
885 
886  sockaddr_ary = rb_check_array_type(sockaddr_arg);
887  if (!NIL_P(sockaddr_ary)) {
888  VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
889  int af;
890  StringValue(afamily);
891  if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
892  rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
893  switch (af) {
894  case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
895 #ifdef INET6
896  case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
897 #endif
898  {
899  VALUE service = rb_ary_entry(sockaddr_ary, 1);
900  VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
901  VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
902  int flags;
903 
904  service = INT2NUM(NUM2INT(service));
905  if (!NIL_P(nodename))
906  StringValue(nodename);
907  StringValue(numericnode);
908  flags = AI_NUMERICHOST;
909 #ifdef AI_NUMERICSERV
910  flags |= AI_NUMERICSERV;
911 #endif
912 
913  init_addrinfo_getaddrinfo(rai, numericnode, service,
914  INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
915  INT2NUM(flags),
916  nodename, service);
917  break;
918  }
919 
920 #ifdef HAVE_SYS_UN_H
921  case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
922  {
923  VALUE path = rb_ary_entry(sockaddr_ary, 1);
924  StringValue(path);
925  init_unix_addrinfo(rai, path, SOCK_STREAM);
926  break;
927  }
928 #endif
929 
930  default:
931  rb_raise(rb_eSocket, "unexpected address family");
932  }
933  }
934  else {
935  StringValue(sockaddr_arg);
936  sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
937  sockaddr_len = RSTRING_LENINT(sockaddr_arg);
938  init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
939  i_pfamily, i_socktype, i_protocol,
940  canonname, inspectname);
941  }
942 
943  return self;
944 }
945 
946 static int
947 get_afamily(struct sockaddr *addr, socklen_t len)
948 {
949  if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
950  return addr->sa_family;
951  else
952  return AF_UNSPEC;
953 }
954 
955 static int
957 {
958  return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len);
959 }
960 
961 static VALUE
963 {
964  rb_addrinfo_t *rai = get_addrinfo(addrinfo);
965 
966  if (rai->sockaddr_len == 0) {
967  rb_str_cat2(ret, "empty-sockaddr");
968  }
969  else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr)
970  rb_str_cat2(ret, "too-short-sockaddr");
971  else {
972  switch (rai->addr.ss_family) {
973  case AF_INET:
974  {
975  struct sockaddr_in *addr;
976  int port;
977  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) {
978  rb_str_cat2(ret, "too-short-AF_INET-sockaddr");
979  }
980  else {
981  addr = (struct sockaddr_in *)&rai->addr;
982  rb_str_catf(ret, "%d.%d.%d.%d",
983  ((unsigned char*)&addr->sin_addr)[0],
984  ((unsigned char*)&addr->sin_addr)[1],
985  ((unsigned char*)&addr->sin_addr)[2],
986  ((unsigned char*)&addr->sin_addr)[3]);
987  port = ntohs(addr->sin_port);
988  if (port)
989  rb_str_catf(ret, ":%d", port);
990  if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len)
991  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in)));
992  }
993  break;
994  }
995 
996 #ifdef AF_INET6
997  case AF_INET6:
998  {
999  struct sockaddr_in6 *addr;
1000  char hbuf[1024];
1001  int port;
1002  int error;
1003  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) {
1004  rb_str_cat2(ret, "too-short-AF_INET6-sockaddr");
1005  }
1006  else {
1007  addr = (struct sockaddr_in6 *)&rai->addr;
1008  /* use getnameinfo for scope_id.
1009  * RFC 4007: IPv6 Scoped Address Architecture
1010  * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
1011  */
1012  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1013  hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1015  if (error) {
1016  rsock_raise_socket_error("getnameinfo", error);
1017  }
1018  if (addr->sin6_port == 0) {
1019  rb_str_cat2(ret, hbuf);
1020  }
1021  else {
1022  port = ntohs(addr->sin6_port);
1023  rb_str_catf(ret, "[%s]:%d", hbuf, port);
1024  }
1025  if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len)
1026  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6)));
1027  }
1028  break;
1029  }
1030 #endif
1031 
1032 #ifdef HAVE_SYS_UN_H
1033  case AF_UNIX:
1034  {
1035  struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr;
1036  char *p, *s, *e;
1037  s = addr->sun_path;
1038  e = (char*)addr + rai->sockaddr_len;
1039  while (s < e && *(e-1) == '\0')
1040  e--;
1041  if (e < s)
1042  rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
1043  else if (s == e)
1044  rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
1045  else {
1046  int printable_only = 1;
1047  p = s;
1048  while (p < e) {
1049  printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
1050  p++;
1051  }
1052  if (printable_only) { /* only printable, no space */
1053  if (s[0] != '/') /* relative path */
1054  rb_str_cat2(ret, "AF_UNIX ");
1055  rb_str_cat(ret, s, p - s);
1056  }
1057  else {
1058  rb_str_cat2(ret, "AF_UNIX");
1059  while (s < e)
1060  rb_str_catf(ret, ":%02x", (unsigned char)*s++);
1061  }
1062  if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len)
1063  rb_str_catf(ret, "(sockaddr %d bytes too long)",
1064  (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr)));
1065  }
1066  break;
1067  }
1068 #endif
1069 
1070  default:
1071  {
1072  ID id = rsock_intern_family(rai->addr.ss_family);
1073  if (id == 0)
1074  rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family);
1075  else
1076  rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
1077  break;
1078  }
1079  }
1080  }
1081 
1082  return ret;
1083 }
1084 
1085 /*
1086  * call-seq:
1087  * addrinfo.inspect => string
1088  *
1089  * returns a string which shows addrinfo in human-readable form.
1090  *
1091  * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost:80)>"
1092  * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
1093  *
1094  */
1095 static VALUE
1097 {
1098  rb_addrinfo_t *rai = get_addrinfo(self);
1099  int internet_p;
1100  VALUE ret;
1101 
1102  ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
1103 
1104  inspect_sockaddr(self, ret);
1105 
1106  if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
1107  ID id = rsock_intern_protocol_family(rai->pfamily);
1108  if (id)
1109  rb_str_catf(ret, " %s", rb_id2name(id));
1110  else
1111  rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
1112  }
1113 
1114  internet_p = rai->pfamily == PF_INET;
1115 #ifdef INET6
1116  internet_p = internet_p || rai->pfamily == PF_INET6;
1117 #endif
1118  if (internet_p && rai->socktype == SOCK_STREAM &&
1119  (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
1120  rb_str_cat2(ret, " TCP");
1121  }
1122  else if (internet_p && rai->socktype == SOCK_DGRAM &&
1123  (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
1124  rb_str_cat2(ret, " UDP");
1125  }
1126  else {
1127  if (rai->socktype) {
1128  ID id = rsock_intern_socktype(rai->socktype);
1129  if (id)
1130  rb_str_catf(ret, " %s", rb_id2name(id));
1131  else
1132  rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
1133  }
1134 
1135  if (rai->protocol) {
1136  if (internet_p) {
1137  ID id = rsock_intern_ipproto(rai->protocol);
1138  if (id)
1139  rb_str_catf(ret, " %s", rb_id2name(id));
1140  else
1141  goto unknown_protocol;
1142  }
1143  else {
1144  unknown_protocol:
1145  rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
1146  }
1147  }
1148  }
1149 
1150  if (!NIL_P(rai->canonname)) {
1151  VALUE name = rai->canonname;
1152  rb_str_catf(ret, " %s", StringValueCStr(name));
1153  }
1154 
1155  if (!NIL_P(rai->inspectname)) {
1156  VALUE name = rai->inspectname;
1157  rb_str_catf(ret, " (%s)", StringValueCStr(name));
1158  }
1159 
1160  rb_str_buf_cat2(ret, ">");
1161  return ret;
1162 }
1163 
1164 /*
1165  * call-seq:
1166  * addrinfo.inspect_sockaddr => string
1167  *
1168  * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
1169  *
1170  * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
1171  * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
1172  * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
1173  *
1174  */
1175 static VALUE
1177 {
1178  return inspect_sockaddr(self, rb_str_new("", 0));
1179 }
1180 
1181 /* :nodoc: */
1182 static VALUE
1184 {
1185  rb_addrinfo_t *rai = get_addrinfo(self);
1186  VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
1187  int afamily_int = ai_get_afamily(rai);
1188  ID id;
1189 
1190  id = rsock_intern_protocol_family(rai->pfamily);
1191  if (id == 0)
1192  rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
1193  pfamily = rb_id2str(id);
1194 
1195  if (rai->socktype == 0)
1196  socktype = INT2FIX(0);
1197  else {
1198  id = rsock_intern_socktype(rai->socktype);
1199  if (id == 0)
1200  rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
1201  socktype = rb_id2str(id);
1202  }
1203 
1204  if (rai->protocol == 0)
1205  protocol = INT2FIX(0);
1206  else if (IS_IP_FAMILY(afamily_int)) {
1207  id = rsock_intern_ipproto(rai->protocol);
1208  if (id == 0)
1209  rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
1210  protocol = rb_id2str(id);
1211  }
1212  else {
1213  rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
1214  }
1215 
1216  canonname = rai->canonname;
1217 
1218  inspectname = rai->inspectname;
1219 
1220  id = rsock_intern_family(afamily_int);
1221  if (id == 0)
1222  rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
1223  afamily = rb_id2str(id);
1224 
1225  switch(afamily_int) {
1226 #ifdef HAVE_SYS_UN_H
1227  case AF_UNIX:
1228  {
1229  struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr;
1230  char *s, *e;
1231  s = su->sun_path;
1232  e = (char*)su + rai->sockaddr_len;
1233  while (s < e && *(e-1) == '\0')
1234  e--;
1235  sockaddr = rb_str_new(s, e-s);
1236  break;
1237  }
1238 #endif
1239 
1240  default:
1241  {
1242  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1243  int error;
1244  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1245  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1247  if (error) {
1248  rsock_raise_socket_error("getnameinfo", error);
1249  }
1250  sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
1251  break;
1252  }
1253  }
1254 
1255  return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
1256 }
1257 
1258 /* :nodoc: */
1259 static VALUE
1261 {
1262  VALUE v;
1263  VALUE canonname, inspectname;
1264  int afamily, pfamily, socktype, protocol;
1265  struct sockaddr_storage ss;
1266  socklen_t len;
1267  rb_addrinfo_t *rai;
1268 
1269  if (check_addrinfo(self))
1270  rb_raise(rb_eTypeError, "already initialized socket address");
1271 
1272  ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1273 
1274  v = rb_ary_entry(ary, 0);
1275  StringValue(v);
1276  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
1277  rb_raise(rb_eTypeError, "unexpected address family");
1278 
1279  v = rb_ary_entry(ary, 2);
1280  StringValue(v);
1281  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
1282  rb_raise(rb_eTypeError, "unexpected protocol family");
1283 
1284  v = rb_ary_entry(ary, 3);
1285  if (v == INT2FIX(0))
1286  socktype = 0;
1287  else {
1288  StringValue(v);
1289  if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
1290  rb_raise(rb_eTypeError, "unexpected socktype");
1291  }
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 
1307  v = rb_ary_entry(ary, 5);
1308  if (NIL_P(v))
1309  canonname = Qnil;
1310  else {
1311  StringValue(v);
1312  canonname = v;
1313  }
1314 
1315  v = rb_ary_entry(ary, 6);
1316  if (NIL_P(v))
1317  inspectname = Qnil;
1318  else {
1319  StringValue(v);
1320  inspectname = v;
1321  }
1322 
1323  v = rb_ary_entry(ary, 1);
1324  switch(afamily) {
1325 #ifdef HAVE_SYS_UN_H
1326  case AF_UNIX:
1327  {
1328  struct sockaddr_un uaddr;
1329  MEMZERO(&uaddr, struct sockaddr_un, 1);
1330  uaddr.sun_family = AF_UNIX;
1331 
1332  StringValue(v);
1333  if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
1335  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1336  (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
1337  memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
1338  len = (socklen_t)sizeof(uaddr);
1339  memcpy(&ss, &uaddr, len);
1340  break;
1341  }
1342 #endif
1343 
1344  default:
1345  {
1346  VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
1347  struct addrinfo *res;
1348  int flags = AI_NUMERICHOST;
1349 #ifdef AI_NUMERICSERV
1350  flags |= AI_NUMERICSERV;
1351 #endif
1352  res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
1353  INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
1354  INT2NUM(flags), 1);
1355 
1356  len = res->ai_addrlen;
1357  memcpy(&ss, res->ai_addr, res->ai_addrlen);
1358  break;
1359  }
1360  }
1361 
1362  DATA_PTR(self) = rai = alloc_addrinfo();
1363  init_addrinfo(rai, (struct sockaddr *)&ss, len,
1364  pfamily, socktype, protocol,
1365  canonname, inspectname);
1366  return self;
1367 }
1368 
1369 /*
1370  * call-seq:
1371  * addrinfo.afamily => integer
1372  *
1373  * returns the address family as an integer.
1374  *
1375  * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
1376  *
1377  */
1378 static VALUE
1380 {
1381  rb_addrinfo_t *rai = get_addrinfo(self);
1382  return INT2NUM(ai_get_afamily(rai));
1383 }
1384 
1385 /*
1386  * call-seq:
1387  * addrinfo.pfamily => integer
1388  *
1389  * returns the protocol family as an integer.
1390  *
1391  * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
1392  *
1393  */
1394 static VALUE
1396 {
1397  rb_addrinfo_t *rai = get_addrinfo(self);
1398  return INT2NUM(rai->pfamily);
1399 }
1400 
1401 /*
1402  * call-seq:
1403  * addrinfo.socktype => integer
1404  *
1405  * returns the socket type as an integer.
1406  *
1407  * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
1408  *
1409  */
1410 static VALUE
1412 {
1413  rb_addrinfo_t *rai = get_addrinfo(self);
1414  return INT2NUM(rai->socktype);
1415 }
1416 
1417 /*
1418  * call-seq:
1419  * addrinfo.protocol => integer
1420  *
1421  * returns the socket type as an integer.
1422  *
1423  * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
1424  *
1425  */
1426 static VALUE
1428 {
1429  rb_addrinfo_t *rai = get_addrinfo(self);
1430  return INT2NUM(rai->protocol);
1431 }
1432 
1433 /*
1434  * call-seq:
1435  * addrinfo.to_sockaddr => string
1436  * addrinfo.to_s => string
1437  *
1438  * returns the socket address as packed struct sockaddr string.
1439  *
1440  * Addrinfo.tcp("localhost", 80).to_sockaddr
1441  * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1442  *
1443  */
1444 static VALUE
1446 {
1447  rb_addrinfo_t *rai = get_addrinfo(self);
1448  VALUE ret;
1449  ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
1450  OBJ_INFECT(ret, self);
1451  return ret;
1452 }
1453 
1454 /*
1455  * call-seq:
1456  * addrinfo.canonname => string or nil
1457  *
1458  * returns the canonical name as an string.
1459  *
1460  * nil is returned if no canonical name.
1461  *
1462  * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
1463  *
1464  * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
1465  * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org:80)>
1466  * p list[0].canonname #=> "carbon.ruby-lang.org"
1467  *
1468  */
1469 static VALUE
1471 {
1472  rb_addrinfo_t *rai = get_addrinfo(self);
1473  return rai->canonname;
1474 }
1475 
1476 /*
1477  * call-seq:
1478  * addrinfo.ip? => true or false
1479  *
1480  * returns true if addrinfo is internet (IPv4/IPv6) address.
1481  * returns false otherwise.
1482  *
1483  * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
1484  * Addrinfo.tcp("::1", 80).ip? #=> true
1485  * Addrinfo.unix("/tmp/sock").ip? #=> false
1486  *
1487  */
1488 static VALUE
1490 {
1491  rb_addrinfo_t *rai = get_addrinfo(self);
1492  int family = ai_get_afamily(rai);
1493  return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
1494 }
1495 
1496 /*
1497  * call-seq:
1498  * addrinfo.ipv4? => true or false
1499  *
1500  * returns true if addrinfo is IPv4 address.
1501  * returns false otherwise.
1502  *
1503  * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
1504  * Addrinfo.tcp("::1", 80).ipv4? #=> false
1505  * Addrinfo.unix("/tmp/sock").ipv4? #=> false
1506  *
1507  */
1508 static VALUE
1510 {
1511  rb_addrinfo_t *rai = get_addrinfo(self);
1512  return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
1513 }
1514 
1515 /*
1516  * call-seq:
1517  * addrinfo.ipv6? => true or false
1518  *
1519  * returns true if addrinfo is IPv6 address.
1520  * returns false otherwise.
1521  *
1522  * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
1523  * Addrinfo.tcp("::1", 80).ipv6? #=> true
1524  * Addrinfo.unix("/tmp/sock").ipv6? #=> false
1525  *
1526  */
1527 static VALUE
1529 {
1530 #ifdef AF_INET6
1531  rb_addrinfo_t *rai = get_addrinfo(self);
1532  return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
1533 #else
1534  return Qfalse;
1535 #endif
1536 }
1537 
1538 /*
1539  * call-seq:
1540  * addrinfo.unix? => true or false
1541  *
1542  * returns true if addrinfo is UNIX address.
1543  * returns false otherwise.
1544  *
1545  * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
1546  * Addrinfo.tcp("::1", 80).unix? #=> false
1547  * Addrinfo.unix("/tmp/sock").unix? #=> true
1548  *
1549  */
1550 static VALUE
1552 {
1553  rb_addrinfo_t *rai = get_addrinfo(self);
1554 #ifdef AF_UNIX
1555  return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
1556 #else
1557  return Qfalse;
1558 #endif
1559 }
1560 
1561 /*
1562  * call-seq:
1563  * addrinfo.getnameinfo => [nodename, service]
1564  * addrinfo.getnameinfo(flags) => [nodename, service]
1565  *
1566  * returns nodename and service as a pair of strings.
1567  * This converts struct sockaddr in addrinfo to textual representation.
1568  *
1569  * flags should be bitwise OR of Socket::NI_??? constants.
1570  *
1571  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
1572  *
1573  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
1574  * #=> ["localhost", "80"]
1575  */
1576 static VALUE
1578 {
1579  rb_addrinfo_t *rai = get_addrinfo(self);
1580  VALUE vflags;
1581  char hbuf[1024], pbuf[1024];
1582  int flags, error;
1583 
1584  rb_scan_args(argc, argv, "01", &vflags);
1585 
1586  flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
1587 
1588  if (rai->socktype == SOCK_DGRAM)
1589  flags |= NI_DGRAM;
1590 
1591  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1592  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1593  flags);
1594  if (error) {
1595  rsock_raise_socket_error("getnameinfo", error);
1596  }
1597 
1598  return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1599 }
1600 
1601 /*
1602  * call-seq:
1603  * addrinfo.ip_unpack => [addr, port]
1604  *
1605  * Returns the IP address and port number as 2-element array.
1606  *
1607  * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
1608  * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
1609  */
1610 static VALUE
1612 {
1613  rb_addrinfo_t *rai = get_addrinfo(self);
1614  int family = ai_get_afamily(rai);
1615  VALUE vflags;
1616  VALUE ret, portstr;
1617 
1618  if (!IS_IP_FAMILY(family))
1619  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1620 
1622  ret = addrinfo_getnameinfo(1, &vflags, self);
1623  portstr = rb_ary_entry(ret, 1);
1624  rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
1625  return ret;
1626 }
1627 
1628 /*
1629  * call-seq:
1630  * addrinfo.ip_address => string
1631  *
1632  * Returns the IP address as a string.
1633  *
1634  * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
1635  * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
1636  */
1637 static VALUE
1639 {
1640  rb_addrinfo_t *rai = get_addrinfo(self);
1641  int family = ai_get_afamily(rai);
1642  VALUE vflags;
1643  VALUE ret;
1644 
1645  if (!IS_IP_FAMILY(family))
1646  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1647 
1649  ret = addrinfo_getnameinfo(1, &vflags, self);
1650  return rb_ary_entry(ret, 0);
1651 }
1652 
1653 /*
1654  * call-seq:
1655  * addrinfo.ip_port => port
1656  *
1657  * Returns the port number as an integer.
1658  *
1659  * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
1660  * Addrinfo.tcp("::1", 80).ip_port #=> 80
1661  */
1662 static VALUE
1664 {
1665  rb_addrinfo_t *rai = get_addrinfo(self);
1666  int family = ai_get_afamily(rai);
1667  int port;
1668 
1669  if (!IS_IP_FAMILY(family)) {
1670  bad_family:
1671 #ifdef AF_INET6
1672  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1673 #else
1674  rb_raise(rb_eSocket, "need IPv4 address");
1675 #endif
1676  }
1677 
1678  switch (family) {
1679  case AF_INET:
1680  if (rai->sockaddr_len != sizeof(struct sockaddr_in))
1681  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
1682  port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port);
1683  break;
1684 
1685 #ifdef AF_INET6
1686  case AF_INET6:
1687  if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
1688  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
1689  port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port);
1690  break;
1691 #endif
1692 
1693  default:
1694  goto bad_family;
1695  }
1696 
1697  return INT2NUM(port);
1698 }
1699 
1700 static int
1702 {
1703  rb_addrinfo_t *rai = get_addrinfo(self);
1704  int family = ai_get_afamily(rai);
1705  if (family != AF_INET) return 0;
1706  *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr);
1707  return 1;
1708 }
1709 
1710 /*
1711  * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
1712  * It returns false otherwise.
1713  */
1714 static VALUE
1716 {
1717  uint32_t a;
1718  if (!extract_in_addr(self, &a)) return Qfalse;
1719  if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
1720  (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
1721  (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
1722  return Qtrue;
1723  return Qfalse;
1724 }
1725 
1726 /*
1727  * Returns true for IPv4 loopback address (127.0.0.0/8).
1728  * It returns false otherwise.
1729  */
1730 static VALUE
1732 {
1733  uint32_t a;
1734  if (!extract_in_addr(self, &a)) return Qfalse;
1735  if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
1736  return Qtrue;
1737  return Qfalse;
1738 }
1739 
1740 /*
1741  * Returns true for IPv4 multicast address (224.0.0.0/4).
1742  * It returns false otherwise.
1743  */
1744 static VALUE
1746 {
1747  uint32_t a;
1748  if (!extract_in_addr(self, &a)) return Qfalse;
1749  if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
1750  return Qtrue;
1751  return Qfalse;
1752 }
1753 
1754 #ifdef INET6
1755 
1756 static struct in6_addr *
1757 extract_in6_addr(VALUE self)
1758 {
1759  rb_addrinfo_t *rai = get_addrinfo(self);
1760  int family = ai_get_afamily(rai);
1761  if (family != AF_INET6) return NULL;
1762  return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1763 }
1764 
1765 /*
1766  * Returns true for IPv6 unspecified address (::).
1767  * It returns false otherwise.
1768  */
1769 static VALUE
1770 addrinfo_ipv6_unspecified_p(VALUE self)
1771 {
1772  struct in6_addr *addr = extract_in6_addr(self);
1773  if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
1774  return Qfalse;
1775 }
1776 
1777 /*
1778  * Returns true for IPv6 loopback address (::1).
1779  * It returns false otherwise.
1780  */
1781 static VALUE
1782 addrinfo_ipv6_loopback_p(VALUE self)
1783 {
1784  struct in6_addr *addr = extract_in6_addr(self);
1785  if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
1786  return Qfalse;
1787 }
1788 
1789 /*
1790  * Returns true for IPv6 multicast address (ff00::/8).
1791  * It returns false otherwise.
1792  */
1793 static VALUE
1794 addrinfo_ipv6_multicast_p(VALUE self)
1795 {
1796  struct in6_addr *addr = extract_in6_addr(self);
1797  if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
1798  return Qfalse;
1799 }
1800 
1801 /*
1802  * Returns true for IPv6 link local address (ff80::/10).
1803  * It returns false otherwise.
1804  */
1805 static VALUE
1806 addrinfo_ipv6_linklocal_p(VALUE self)
1807 {
1808  struct in6_addr *addr = extract_in6_addr(self);
1809  if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
1810  return Qfalse;
1811 }
1812 
1813 /*
1814  * Returns true for IPv6 site local address (ffc0::/10).
1815  * It returns false otherwise.
1816  */
1817 static VALUE
1818 addrinfo_ipv6_sitelocal_p(VALUE self)
1819 {
1820  struct in6_addr *addr = extract_in6_addr(self);
1821  if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
1822  return Qfalse;
1823 }
1824 
1825 /*
1826  * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
1827  * It returns false otherwise.
1828  */
1829 static VALUE
1830 addrinfo_ipv6_v4mapped_p(VALUE self)
1831 {
1832  struct in6_addr *addr = extract_in6_addr(self);
1833  if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
1834  return Qfalse;
1835 }
1836 
1837 /*
1838  * Returns true for IPv4-compatible IPv6 address (::/80).
1839  * It returns false otherwise.
1840  */
1841 static VALUE
1842 addrinfo_ipv6_v4compat_p(VALUE self)
1843 {
1844  struct in6_addr *addr = extract_in6_addr(self);
1845  if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
1846  return Qfalse;
1847 }
1848 
1849 /*
1850  * Returns true for IPv6 multicast node-local scope address.
1851  * It returns false otherwise.
1852  */
1853 static VALUE
1854 addrinfo_ipv6_mc_nodelocal_p(VALUE self)
1855 {
1856  struct in6_addr *addr = extract_in6_addr(self);
1857  if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
1858  return Qfalse;
1859 }
1860 
1861 /*
1862  * Returns true for IPv6 multicast link-local scope address.
1863  * It returns false otherwise.
1864  */
1865 static VALUE
1866 addrinfo_ipv6_mc_linklocal_p(VALUE self)
1867 {
1868  struct in6_addr *addr = extract_in6_addr(self);
1869  if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
1870  return Qfalse;
1871 }
1872 
1873 /*
1874  * Returns true for IPv6 multicast site-local scope address.
1875  * It returns false otherwise.
1876  */
1877 static VALUE
1878 addrinfo_ipv6_mc_sitelocal_p(VALUE self)
1879 {
1880  struct in6_addr *addr = extract_in6_addr(self);
1881  if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
1882  return Qfalse;
1883 }
1884 
1885 /*
1886  * Returns true for IPv6 multicast organization-local scope address.
1887  * It returns false otherwise.
1888  */
1889 static VALUE
1890 addrinfo_ipv6_mc_orglocal_p(VALUE self)
1891 {
1892  struct in6_addr *addr = extract_in6_addr(self);
1893  if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
1894  return Qfalse;
1895 }
1896 
1897 /*
1898  * Returns true for IPv6 multicast global scope address.
1899  * It returns false otherwise.
1900  */
1901 static VALUE
1902 addrinfo_ipv6_mc_global_p(VALUE self)
1903 {
1904  struct in6_addr *addr = extract_in6_addr(self);
1905  if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
1906  return Qfalse;
1907 }
1908 
1909 /*
1910  * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
1911  * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
1912  *
1913  * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1914  * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1915  * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
1916  * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
1917  * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
1918  */
1919 static VALUE
1920 addrinfo_ipv6_to_ipv4(VALUE self)
1921 {
1922  rb_addrinfo_t *rai = get_addrinfo(self);
1923  struct in6_addr *addr;
1924  int family = ai_get_afamily(rai);
1925  if (family != AF_INET6) return Qnil;
1926  addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1927  if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
1928  struct sockaddr_in sin4;
1929  MEMZERO(&sin4, struct sockaddr_in, 1);
1930  sin4.sin_family = AF_INET;
1931  SET_SIN_LEN(&sin4, sizeof(sin4));
1932  memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
1933  return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
1934  PF_INET, rai->socktype, rai->protocol,
1935  rai->canonname, rai->inspectname);
1936  }
1937  else {
1938  return Qnil;
1939  }
1940 }
1941 
1942 #endif
1943 
1944 #ifdef HAVE_SYS_UN_H
1945 /*
1946  * call-seq:
1947  * addrinfo.unix_path => path
1948  *
1949  * Returns the socket path as a string.
1950  *
1951  * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
1952  */
1953 static VALUE
1954 addrinfo_unix_path(VALUE self)
1955 {
1956  rb_addrinfo_t *rai = get_addrinfo(self);
1957  int family = ai_get_afamily(rai);
1958  struct sockaddr_un *addr;
1959  char *s, *e;
1960 
1961  if (family != AF_UNIX)
1962  rb_raise(rb_eSocket, "need AF_UNIX address");
1963 
1964  addr = (struct sockaddr_un *)&rai->addr;
1965 
1966  s = addr->sun_path;
1967  e = (char*)addr + rai->sockaddr_len;
1968  if (e < s)
1969  rb_raise(rb_eSocket, "too short AF_UNIX address");
1970  if (addr->sun_path + sizeof(addr->sun_path) < e)
1971  rb_raise(rb_eSocket, "too long AF_UNIX address");
1972  while (s < e && *(e-1) == '\0')
1973  e--;
1974  return rb_str_new(s, e-s);
1975 }
1976 #endif
1977 
1978 /*
1979  * call-seq:
1980  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
1981  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
1982  * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
1983  * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
1984  * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
1985  *
1986  * returns a list of addrinfo objects as an array.
1987  *
1988  * This method converts nodename (hostname) and service (port) to addrinfo.
1989  * Since the conversion is not unique, the result is a list of addrinfo objects.
1990  *
1991  * nodename or service can be nil if no conversion intended.
1992  *
1993  * family, socktype and protocol are hint for preferred protocol.
1994  * If the result will be used for a socket with SOCK_STREAM,
1995  * SOCK_STREAM should be specified as socktype.
1996  * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
1997  * If they are omitted or nil is given, the result is not restricted.
1998  *
1999  * Similarly, PF_INET6 as family restricts for IPv6.
2000  *
2001  * flags should be bitwise OR of Socket::AI_??? constants.
2002  *
2003  * Note that socktype should be specified whenever application knows the usage of the address.
2004  * Some platform causes an error when socktype is omitted and servname is specified as an integer
2005  * because some port numbers, 512 for example, are ambiguous without socktype.
2006  *
2007  * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
2008  * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net:80)>,
2009  * # #<Addrinfo: [2001:200:0:8002:203:47ff:fea5:3085]:80 TCP (www.kame.net:80)>]
2010  *
2011  */
2012 static VALUE
2014 {
2015  VALUE node, service, family, socktype, protocol, flags;
2016 
2017  rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags);
2018  return addrinfo_list_new(node, service, family, socktype, protocol, flags);
2019 }
2020 
2021 /*
2022  * call-seq:
2023  * Addrinfo.ip(host) => addrinfo
2024  *
2025  * returns an addrinfo object for IP address.
2026  *
2027  * The port, socktype, protocol of the result is filled by zero.
2028  * So, it is not appropriate to create a socket.
2029  *
2030  * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
2031  */
2032 static VALUE
2034 {
2035  VALUE ret;
2036  rb_addrinfo_t *rai;
2037  ret = addrinfo_firstonly_new(host, Qnil,
2038  INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
2039  rai = get_addrinfo(ret);
2040  rai->socktype = 0;
2041  rai->protocol = 0;
2042  return ret;
2043 }
2044 
2045 /*
2046  * call-seq:
2047  * Addrinfo.tcp(host, port) => addrinfo
2048  *
2049  * returns an addrinfo object for TCP address.
2050  *
2051  * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
2052  */
2053 static VALUE
2054 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
2055 {
2056  return addrinfo_firstonly_new(host, port,
2057  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
2058 }
2059 
2060 /*
2061  * call-seq:
2062  * Addrinfo.udp(host, port) => addrinfo
2063  *
2064  * returns an addrinfo object for UDP address.
2065  *
2066  * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
2067  */
2068 static VALUE
2069 addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
2070 {
2071  return addrinfo_firstonly_new(host, port,
2072  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
2073 }
2074 
2075 #ifdef HAVE_SYS_UN_H
2076 
2077 /*
2078  * call-seq:
2079  * Addrinfo.unix(path [, socktype]) => addrinfo
2080  *
2081  * returns an addrinfo object for UNIX socket address.
2082  *
2083  * _socktype_ specifies the socket type.
2084  * If it is omitted, :STREAM is used.
2085  *
2086  * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
2087  * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
2088  */
2089 static VALUE
2090 addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
2091 {
2092  VALUE path, vsocktype, addr;
2093  int socktype;
2094  rb_addrinfo_t *rai;
2095 
2096  rb_scan_args(argc, argv, "11", &path, &vsocktype);
2097 
2098  if (NIL_P(vsocktype))
2099  socktype = SOCK_STREAM;
2100  else
2101  socktype = rsock_socktype_arg(vsocktype);
2102 
2104  DATA_PTR(addr) = rai = alloc_addrinfo();
2105  init_unix_addrinfo(rai, path, socktype);
2106  OBJ_INFECT(addr, path);
2107  return addr;
2108 }
2109 
2110 #endif
2111 
2112 VALUE
2114 {
2115  VALUE val = *v;
2116  if (IS_ADDRINFO(val)) {
2117  *v = addrinfo_to_sockaddr(val);
2118  }
2119  StringValue(*v);
2120  return *v;
2121 }
2122 
2123 char *
2125 {
2127  return RSTRING_PTR(*v);
2128 }
2129 
2130 VALUE
2132 {
2133  if (IS_ADDRINFO(val))
2134  return addrinfo_to_sockaddr(val);
2135  return rb_check_string_type(val);
2136 }
2137 
2138 VALUE
2139 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
2140 {
2141  int family;
2142  int socktype;
2143  int ret;
2144  socklen_t optlen = (socklen_t)sizeof(socktype);
2145 
2146  /* assumes protocol family and address family are identical */
2147  family = get_afamily(addr, len);
2148 
2149  ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
2150  if (ret == -1) {
2151  rb_sys_fail("getsockopt(SO_TYPE)");
2152  }
2153 
2154  return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
2155 }
2156 
2157 VALUE
2158 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
2159 {
2160  rb_io_t *fptr;
2161 
2162  switch (TYPE(io)) {
2163  case T_FIXNUM:
2164  return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
2165 
2166  case T_BIGNUM:
2167  return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
2168 
2169  case T_FILE:
2170  GetOpenFile(io, fptr);
2171  return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
2172 
2173  default:
2174  rb_raise(rb_eTypeError, "neither IO nor file descriptor");
2175  }
2176 }
2177 
2178 /*
2179  * Addrinfo class
2180  */
2181 void
2183 {
2184  /*
2185  * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
2186  * structure identifies an Internet host and a service.
2187  */
2188  rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
2192  rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0);
2197 #ifdef HAVE_SYS_UN_H
2198  rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
2199 #endif
2200 
2206 
2210 
2215 
2219 
2220 #ifdef INET6
2221  rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
2222  rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
2223  rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
2224  rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
2225  rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
2226  rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
2227  rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
2228  rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
2229  rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
2230  rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
2231  rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
2232  rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
2233 
2234  rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
2235 #endif
2236 
2237 #ifdef HAVE_SYS_UN_H
2238  rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
2239 #endif
2240 
2242  rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
2243 
2244  rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
2245 
2246  rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
2247  rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
2248 }
#define RSTRING_LEN(string)
Definition: generator.h:45
VALUE inspectname
Definition: raddrinfo.c:544
RUBY_EXTERN VALUE rb_cData
Definition: ruby.h:1253
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:379
static void make_ipaddr0(struct sockaddr *addr, char *buf, size_t len)
Definition: raddrinfo.c:240
volatile VALUE ary
Definition: tcltklib.c:9700
VP_EXPORT int
Definition: bigdecimal.c:4911
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:956
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:2284
static int str_is_number(const char *)
Definition: raddrinfo.c:272
size_t strlen(const char *)
#define T_FIXNUM
Definition: ruby.h:425
#define PF_INET
Definition: sockport.h:77
size_t servlen
Definition: raddrinfo.c:202
VALUE rb_id2str(ID id)
Definition: ripper.c:16301
#define NUM2INT(x)
Definition: ruby.h:536
#define NUM2UINT(x)
Definition: ruby.h:537
volatile VALUE pair
Definition: tkutil.c:553
parser parser_yylval val
Definition: ripper.c:14289
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1343
static rb_addrinfo_t * check_addrinfo(VALUE self)
Definition: raddrinfo.c:584
static VALUE nogvl_getaddrinfo(void *arg)
Definition: raddrinfo.c:158
#define SA_LEN(sa)
Definition: sockport.h:29
static struct addrinfo * call_getaddrinfo(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, int socktype_hack)
Definition: raddrinfo.c:643
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1889
#define NI_DGRAM
Definition: addrinfo.h:128
struct sockaddr_storage addr
Definition: raddrinfo.c:550
static VALUE addrinfo_ipv6_p(VALUE self)
Definition: raddrinfo.c:1528
#define SET_SIN_LEN(si, len)
Definition: sockport.h:48
Definition: io.h:53
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:826
int rsock_socktype_arg(VALUE type)
Definition: constants.c:50
static VALUE addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
Definition: raddrinfo.c:763
int ret
Definition: tcltklib.c:276
SYMID SyckParser * p
Definition: yaml2byte.c:119
VALUE rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
Definition: raddrinfo.c:391
VALUE rb_eTypeError
Definition: error.c:467
st_table * names
Definition: encoding.c:52
unsigned long VALUE
Definition: ruby.h:88
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:740
gz path
Definition: zlib.c:2040
static VALUE INT2NUM(int v)
Definition: ruby.h:981
#define RSTRING_PTR(string)
Definition: generator.h:42
static VALUE addrinfo_ipv4_loopback_p(VALUE self)
Definition: raddrinfo.c:1731
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
return Qtrue
Definition: tcltklib.c:9597
static VALUE addrinfo_protocol(VALUE self)
Definition: raddrinfo.c:1427
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2079
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:525
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2131
VALUE rb_ary_new3(long n,...)
Definition: array.c:347
static VALUE addrinfo_ipv4_p(VALUE self)
Definition: raddrinfo.c:1509
#define T_ARRAY
Definition: ruby.h:420
r
Definition: bigdecimal.c:1154
VALUE rb_tainted_str_new_cstr(const char *)
Definition: string.c:464
const char * service
Definition: raddrinfo.c:152
static size_t addrinfo_memsize(const void *ptr)
Definition: raddrinfo.c:566
#define FIXNUM_P(f)
Definition: ruby.h:338
#define GetOpenFile(obj, fp)
Definition: io.h:110
void rsock_init_addrinfo(void)
Definition: raddrinfo.c:2182
static char * host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr)
Definition: raddrinfo.c:287
VALUE rsock_make_ipaddr(struct sockaddr *addr)
Definition: raddrinfo.c:251
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2158
const char * rb_obj_classname(VALUE)
Definition: variable.c:318
static VALUE addrinfo_ipv4_multicast_p(VALUE self)
Definition: raddrinfo.c:1745
#define NI_MAXSERV
Definition: addrinfo.h:118
static VALUE addrinfo_inspect_sockaddr(VALUE self)
Definition: raddrinfo.c:1176
VALUE rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE(*ipaddr)(struct sockaddr *, size_t))
Definition: raddrinfo.c:532
static VALUE addrinfo_to_sockaddr(VALUE self)
Definition: raddrinfo.c:1445
#define Qnil
Definition: ruby.h:367
#define IS_ADDRINFO(obj)
Definition: raddrinfo.c:582
strcpy(cmd2, cmd)
VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:629
#define MEMZERO(p, type, n)
Definition: ruby.h:1052
n NULL
Definition: yaml2byte.c:134
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
return Qfalse
Definition: tcltklib.c:6768
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
socklen_t salen
Definition: raddrinfo.c:198
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1908
VALUE rb_ary_new(void)
Definition: array.c:339
static int ai_get_afamily(rb_addrinfo_t *rai)
Definition: raddrinfo.c:956
VALUE rb_str_buf_cat2(VALUE, const char *)
Definition: string.c:1883
int flags
Definition: tcltklib.c:3012
static VALUE addrinfo_initialize(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:867
#define STRTOUL(str, endptr, base)
Definition: ruby.h:1470
#define NI_NUMERICSERV
Definition: addrinfo.h:127
#define snprintf
Definition: subst.h:6
#define NIL_P(v)
Definition: ruby.h:374
static VALUE addrinfo_ip_unpack(VALUE self)
Definition: raddrinfo.c:1611
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:469
static VALUE addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:1577
int fd
Definition: io.h:54
char * ai_canonname
Definition: addrinfo.h:137
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:635
#define offsetof(p_type, field)
Definition: addrinfo.h:186
static const rb_data_type_t addrinfo_type
Definition: raddrinfo.c:571
#define TYPE(x)
Definition: ruby.h:441
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
Definition: getaddrinfo.c:267
static char * port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr)
Definition: raddrinfo.c:324
#define T_BIGNUM
Definition: ruby.h:423
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:3913
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1053
#define EAI_SYSTEM
Definition: addrinfo.h:88
#define OBJ_FREEZE(x)
Definition: ruby.h:970
unsigned short ss_family
Definition: rubysocket.h:134
static VALUE addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
Definition: raddrinfo.c:2069
static int get_afamily(struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:947
#define ALLOC(type)
Definition: ruby.h:1035
static VALUE addrinfo_unix_p(VALUE self)
Definition: raddrinfo.c:1551
static void init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE inspectnode, VALUE inspectservice)
Definition: raddrinfo.c:671
VALUE * argv
Definition: tcltklib.c:1962
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:116
memcpy(buf+1, str, len)
const int id
Definition: nkf.c:209
char * rsock_sockaddr_string_value_ptr(volatile VALUE *v)
Definition: raddrinfo.c:2124
int errno
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1203
VALUE rsock_freeaddrinfo(struct addrinfo *addr)
Definition: raddrinfo.c:525
static VALUE addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
Definition: raddrinfo.c:738
register char * s
Definition: os2.c:56
static VALUE addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:2013
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:211
#define NI_NUMERICHOST
Definition: addrinfo.h:125
static rb_addrinfo_t * alloc_addrinfo()
Definition: raddrinfo.c:602
VP_EXPORT void
Definition: bigdecimal.c:4944
VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2139
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1416
static VALUE addrinfo_mload(VALUE self, VALUE ary)
Definition: raddrinfo.c:1260
static VALUE nogvl_getnameinfo(void *arg)
Definition: raddrinfo.c:207
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:460
unsigned long ID
Definition: ruby.h:89
static VALUE addrinfo_pfamily(VALUE self)
Definition: raddrinfo.c:1395
socklen_t sockaddr_len
Definition: raddrinfo.c:549
static VALUE addrinfo_ip_address(VALUE self)
Definition: raddrinfo.c:1638
static VALUE addrinfo_s_ip(VALUE self, VALUE host)
Definition: raddrinfo.c:2033
VALUE host
Definition: raddrinfo.c:476
int argc
Definition: tcltklib.c:1961
struct sockaddr * sa
Definition: raddrinfo.c:197
#define AI_NUMERICHOST
Definition: addrinfo.h:98
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1261
#define FIX2INT(x)
Definition: ruby.h:538
#define addrinfo_free
Definition: raddrinfo.c:563
register unsigned int len
Definition: name2ctype.h:22210
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:737
VALUE rb_str_new_cstr(const char *)
Definition: string.c:432
static VALUE addrinfo_ip_p(VALUE self)
Definition: raddrinfo.c:1489
void rb_sys_fail(const char *mesg)
Definition: error.c:1671
VALUE rb_str_dup(VALUE)
Definition: string.c:905
static VALUE addrinfo_s_allocate(VALUE klass)
Definition: raddrinfo.c:577
return ptr
Definition: tcltklib.c:780
static void init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, int pfamily, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:612
static void make_inetaddr(unsigned int host, char *buf, size_t len)
Definition: raddrinfo.c:260
static VALUE make_hostent_internal(struct hostent_arg *arg)
Definition: raddrinfo.c:482
unsigned int uint32_t
Definition: sha2.h:101
int ai_protocol
Definition: addrinfo.h:135
static VALUE addrinfo_afamily(VALUE self)
Definition: raddrinfo.c:1379
#define StringValueCStr(v)
Definition: ruby.h:468
int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
Definition: raddrinfo.c:218
VALUE rb_eSocket
Definition: init.c:25
#define AI_NUMERICSERV
Definition: addrinfo.h:99
arg
Definition: ripper.y:1287
static VALUE inspect_sockaddr(VALUE addrinfo, VALUE ret)
Definition: raddrinfo.c:962
static VALUE addrinfo_canonname(VALUE self)
Definition: raddrinfo.c:1470
#define INT2FIX(i)
Definition: ruby.h:225
static VALUE addrinfo_ipv4_private_p(VALUE self)
Definition: raddrinfo.c:1715
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:440
#define PF_UNSPEC
Definition: sockport.h:73
int ai_socktype
Definition: addrinfo.h:134
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:472
DATA_PTR(self)
void rsock_raise_socket_error(const char *reason, int error)
Definition: init.c:34
VALUE canonname
Definition: raddrinfo.c:545
size_t hostlen
Definition: raddrinfo.c:200
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1239
VALUE rb_check_string_type(VALUE)
Definition: string.c:1450
static VALUE addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
Definition: raddrinfo.c:2054
VALUE rb_cAddrinfo
Definition: init.c:23
struct addrinfo * addr
Definition: raddrinfo.c:477
#define T_STRING
Definition: ruby.h:418
#define AF_UNSPEC
Definition: sockport.h:69
struct addrinfo * rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
Definition: raddrinfo.c:351
klass
Definition: tcltklib.c:3493
#define PRIuSIZE
Definition: ruby.h:173
#define OBJ_INFECT(x, s)
Definition: ruby.h:967
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
Definition: getnameinfo.c:136
#define T_FILE
Definition: ruby.h:424
struct addrinfo * hints
Definition: raddrinfo.c:153
#define BLOCKING_REGION(func, arg)
Definition: rubysocket.h:200
#define ISPRINT(c)
Definition: ruby.h:1452
gz io
Definition: zlib.c:2024
struct addrinfo ** res
Definition: raddrinfo.c:154
struct addrinfo * ai_next
Definition: addrinfo.h:139
#define SafeStringValue(v)
Definition: ruby.h:472
static VALUE addrinfo_socktype(VALUE self)
Definition: raddrinfo.c:1411
VALUE rb_ary_new2(long capa)
Definition: array.c:332
Real * res
Definition: bigdecimal.c:1189
const char * rb_id2name(ID id)
Definition: ripper.c:16362
static void addrinfo_mark(void *ptr)
Definition: raddrinfo.c:554
BDIGIT e
Definition: bigdecimal.c:4946
#define EAI_NONAME
Definition: addrinfo.h:85
VALUE(* ipaddr)(struct sockaddr *, size_t)
Definition: raddrinfo.c:478
#define RSTRING_LENINT(str)
Definition: ruby.h:684
size_t ai_addrlen
Definition: addrinfo.h:136
static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
Definition: raddrinfo.c:693
ssize_t i
Definition: bigdecimal.c:5519
int ai_flags
Definition: addrinfo.h:132
BDIGIT v
Definition: bigdecimal.c:5520
static VALUE addrinfo_ip_port(VALUE self)
Definition: raddrinfo.c:1663
rb_gc_mark(ptr->aliases)
const char * name
Definition: nkf.c:208
#define FIX2LONG(x)
Definition: ruby.h:336
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
Definition: raddrinfo.c:175
#define NI_MAXHOST
Definition: addrinfo.h:117
const char * node
Definition: raddrinfo.c:151
static VALUE addrinfo_mdump(VALUE self)
Definition: raddrinfo.c:1183
static rb_addrinfo_t * get_addrinfo(VALUE self)
Definition: raddrinfo.c:590
Real * a
Definition: bigdecimal.c:1140
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1210
static VALUE addrinfo_inspect(VALUE self)
Definition: raddrinfo.c:1096
VALUE rb_str_new2(const char *)
struct sockaddr * ai_addr
Definition: addrinfo.h:138
VALUE rb_eArgError
Definition: error.c:468
static int extract_in_addr(VALUE self, uint32_t *addrp)
Definition: raddrinfo.c:1701
VALUE rsock_sockaddr_string_value(volatile VALUE *v)
Definition: raddrinfo.c:2113
#define ISSPACE(c)
Definition: ruby.h:1453
#define StringValue(v)
Definition: ruby.h:466
VALUE rb_str_new(const char *, long)
Definition: string.c:410
int ai_family
Definition: addrinfo.h:133