Ruby  2.0.0p598(2014-11-13revision48408)
raddrinfo.c
Go to the documentation of this file.
1 /************************************************
2 
3  raddrinfo.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 void *
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 (void *)(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;
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 void *
208 {
209  struct getnameinfo_arg *ptr = arg;
210  return (void *)(VALUE)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;
235  return ret;
236 #endif
237 }
238 
239 static void
240 make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
241 {
242  int error;
243 
244  error = rb_getnameinfo(addr, addrlen, buf, buflen, 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, socklen_t addrlen)
252 {
253  char hbuf[1024];
254 
255  make_ipaddr0(addr, addrlen, hbuf, sizeof(hbuf));
256  return rb_str_new2(hbuf);
257 }
258 
259 static void
260 make_inetaddr(unsigned int host, char *buf, size_t buflen)
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, sizeof(sin), buf, buflen);
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 hbuflen, 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, hbuflen);
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, hbuflen);
306  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
307  }
308  else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
309  make_inetaddr(INADDR_BROADCAST, hbuf, hbuflen);
310  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
311  }
312  else if (strlen(name) >= hbuflen) {
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 pbuflen, int *flags_ptr)
325 {
326  if (NIL_P(port)) {
327  return 0;
328  }
329  else if (FIXNUM_P(port)) {
330  snprintf(pbuf, pbuflen, "%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) >= pbuflen) {
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, socklen_t sockaddrlen, 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, sockaddrlen, hbuf, sizeof(hbuf),
411  NULL, 0, 0);
412  if (! error) {
413  addr1 = rb_str_new2(hbuf);
414  }
415  }
416  error = rb_getnameinfo(sockaddr, sockaddrlen, 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  /* drop redundant information which also shown in address:port part. */
699  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
700  int ret;
701  ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
702  sizeof(hbuf), pbuf, sizeof(pbuf),
704  if (ret == 0) {
705  if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0)
706  node = Qnil;
707  if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0)
708  service = Qnil;
709  else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service))
710  service = Qnil;
711  }
712  }
713 
714  if (RB_TYPE_P(node, T_STRING)) {
715  inspectname = rb_str_dup(node);
716  }
717  if (RB_TYPE_P(service, T_STRING)) {
718  if (NIL_P(inspectname))
719  inspectname = rb_sprintf(":%s", StringValueCStr(service));
720  else
721  rb_str_catf(inspectname, ":%s", StringValueCStr(service));
722  }
723  else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0)
724  {
725  if (NIL_P(inspectname))
726  inspectname = rb_sprintf(":%d", FIX2INT(service));
727  else
728  rb_str_catf(inspectname, ":%d", FIX2INT(service));
729  }
730  if (!NIL_P(inspectname)) {
731  OBJ_INFECT(inspectname, node);
732  OBJ_INFECT(inspectname, service);
733  OBJ_FREEZE(inspectname);
734  }
735  return inspectname;
736 }
737 
738 static VALUE
739 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
740 {
741  VALUE ret;
742  VALUE canonname;
743  VALUE inspectname;
744 
745  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
746 
747  inspectname = make_inspectname(node, service, res);
748 
749  canonname = Qnil;
750  if (res->ai_canonname) {
751  canonname = rb_tainted_str_new_cstr(res->ai_canonname);
752  OBJ_FREEZE(canonname);
753  }
754 
755  ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen,
756  res->ai_family, res->ai_socktype, res->ai_protocol,
757  canonname, inspectname);
758 
759  freeaddrinfo(res);
760  return ret;
761 }
762 
763 static VALUE
764 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
765 {
766  VALUE ret;
767  struct addrinfo *r;
768  VALUE inspectname;
769 
770  struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0);
771 
772  inspectname = make_inspectname(node, service, res);
773 
774  ret = rb_ary_new();
775  for (r = res; r; r = r->ai_next) {
776  VALUE addr;
777  VALUE canonname = Qnil;
778 
779  if (r->ai_canonname) {
780  canonname = rb_tainted_str_new_cstr(r->ai_canonname);
781  OBJ_FREEZE(canonname);
782  }
783 
784  addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
785  r->ai_family, r->ai_socktype, r->ai_protocol,
786  canonname, inspectname);
787 
788  rb_ary_push(ret, addr);
789  }
790 
791  freeaddrinfo(res);
792  return ret;
793 }
794 
795 
796 #ifdef HAVE_SYS_UN_H
797 static void
798 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
799 {
800  struct sockaddr_un un;
801  socklen_t len;
802 
803  StringValue(path);
804 
805  if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
807  "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
808  (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
809 
810  MEMZERO(&un, struct sockaddr_un, 1);
811 
812  un.sun_family = AF_UNIX;
813  memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
814 
815  len = rsock_unix_sockaddr_len(path);
816  init_addrinfo(rai, (struct sockaddr *)&un, len,
817  PF_UNIX, socktype, 0, Qnil, Qnil);
818 }
819 #endif
820 
821 /*
822  * call-seq:
823  * Addrinfo.new(sockaddr) => addrinfo
824  * Addrinfo.new(sockaddr, family) => addrinfo
825  * Addrinfo.new(sockaddr, family, socktype) => addrinfo
826  * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
827  *
828  * returns a new instance of Addrinfo.
829  * The instance contains sockaddr, family, socktype, protocol.
830  * sockaddr means struct sockaddr which can be used for connect(2), etc.
831  * family, socktype and protocol are integers which is used for arguments of socket(2).
832  *
833  * sockaddr is specified as an array or a string.
834  * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
835  * The string should be struct sockaddr as generated by
836  * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
837  *
838  * sockaddr examples:
839  * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
840  * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
841  * - ["AF_UNIX", "/tmp/sock"]
842  * - Socket.sockaddr_in("smtp", "2001:DB8::1")
843  * - Socket.sockaddr_in(80, "172.18.22.42")
844  * - Socket.sockaddr_in(80, "www.ruby-lang.org")
845  * - Socket.sockaddr_un("/tmp/sock")
846  *
847  * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
848  * numeric IP address, is used to construct socket address in the Addrinfo instance.
849  * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
850  *
851  * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
852  * It can be a symbol or a string which is the constant name
853  * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
854  * If omitted, PF_UNSPEC is assumed.
855  *
856  * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
857  * It can be a symbol or a string which is the constant name
858  * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
859  * If omitted, 0 is assumed.
860  *
861  * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
862  * It must be an integer, unlike family and socktype.
863  * If omitted, 0 is assumed.
864  * Note that 0 is reasonable value for most protocols, except raw socket.
865  *
866  */
867 static VALUE
869 {
870  rb_addrinfo_t *rai;
871  VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
872  int i_pfamily, i_socktype, i_protocol;
873  struct sockaddr *sockaddr_ptr;
874  socklen_t sockaddr_len;
875  VALUE canonname = Qnil, inspectname = Qnil;
876 
877  if (check_addrinfo(self))
878  rb_raise(rb_eTypeError, "already initialized socket address");
879  DATA_PTR(self) = rai = alloc_addrinfo();
880 
881  rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
882 
883  i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
884  i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
885  i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
886 
887  sockaddr_ary = rb_check_array_type(sockaddr_arg);
888  if (!NIL_P(sockaddr_ary)) {
889  VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
890  int af;
891  StringValue(afamily);
892  if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
893  rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
894  switch (af) {
895  case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
896 #ifdef INET6
897  case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
898 #endif
899  {
900  VALUE service = rb_ary_entry(sockaddr_ary, 1);
901  VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
902  VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
903  int flags;
904 
905  service = INT2NUM(NUM2INT(service));
906  if (!NIL_P(nodename))
907  StringValue(nodename);
908  StringValue(numericnode);
909  flags = AI_NUMERICHOST;
910 #ifdef AI_NUMERICSERV
911  flags |= AI_NUMERICSERV;
912 #endif
913 
914  init_addrinfo_getaddrinfo(rai, numericnode, service,
915  INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
916  INT2NUM(flags),
917  nodename, service);
918  break;
919  }
920 
921 #ifdef HAVE_SYS_UN_H
922  case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
923  {
924  VALUE path = rb_ary_entry(sockaddr_ary, 1);
925  StringValue(path);
926  init_unix_addrinfo(rai, path, SOCK_STREAM);
927  break;
928  }
929 #endif
930 
931  default:
932  rb_raise(rb_eSocket, "unexpected address family");
933  }
934  }
935  else {
936  StringValue(sockaddr_arg);
937  sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
938  sockaddr_len = RSTRING_LENINT(sockaddr_arg);
939  init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
940  i_pfamily, i_socktype, i_protocol,
941  canonname, inspectname);
942  }
943 
944  return self;
945 }
946 
947 static int
948 get_afamily(struct sockaddr *addr, socklen_t len)
949 {
950  if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
951  return addr->sa_family;
952  else
953  return AF_UNSPEC;
954 }
955 
956 static int
958 {
959  return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len);
960 }
961 
962 static VALUE
964 {
965  rb_addrinfo_t *rai = get_addrinfo(addrinfo);
966 
967  if (rai->sockaddr_len == 0) {
968  rb_str_cat2(ret, "empty-sockaddr");
969  }
970  else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr)
971  rb_str_cat2(ret, "too-short-sockaddr");
972  else {
973  switch (rai->addr.ss_family) {
974  case AF_INET:
975  {
976  struct sockaddr_in *addr;
977  int port;
978  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) {
979  rb_str_cat2(ret, "too-short-AF_INET-sockaddr");
980  }
981  else {
982  addr = (struct sockaddr_in *)&rai->addr;
983  rb_str_catf(ret, "%d.%d.%d.%d",
984  ((unsigned char*)&addr->sin_addr)[0],
985  ((unsigned char*)&addr->sin_addr)[1],
986  ((unsigned char*)&addr->sin_addr)[2],
987  ((unsigned char*)&addr->sin_addr)[3]);
988  port = ntohs(addr->sin_port);
989  if (port)
990  rb_str_catf(ret, ":%d", port);
991  if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len)
992  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in)));
993  }
994  break;
995  }
996 
997 #ifdef AF_INET6
998  case AF_INET6:
999  {
1000  struct sockaddr_in6 *addr;
1001  char hbuf[1024];
1002  int port;
1003  int error;
1004  if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) {
1005  rb_str_cat2(ret, "too-short-AF_INET6-sockaddr");
1006  }
1007  else {
1008  addr = (struct sockaddr_in6 *)&rai->addr;
1009  /* use getnameinfo for scope_id.
1010  * RFC 4007: IPv6 Scoped Address Architecture
1011  * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
1012  */
1013  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1014  hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1016  if (error) {
1017  rsock_raise_socket_error("getnameinfo", error);
1018  }
1019  if (addr->sin6_port == 0) {
1020  rb_str_cat2(ret, hbuf);
1021  }
1022  else {
1023  port = ntohs(addr->sin6_port);
1024  rb_str_catf(ret, "[%s]:%d", hbuf, port);
1025  }
1026  if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len)
1027  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6)));
1028  }
1029  break;
1030  }
1031 #endif
1032 
1033 #ifdef HAVE_SYS_UN_H
1034  case AF_UNIX:
1035  {
1036  struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr;
1037  char *p, *s, *e;
1038  s = addr->sun_path;
1039  e = (char*)addr + rai->sockaddr_len;
1040  while (s < e && *(e-1) == '\0')
1041  e--;
1042  if (e < s)
1043  rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
1044  else if (s == e)
1045  rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
1046  else {
1047  int printable_only = 1;
1048  p = s;
1049  while (p < e) {
1050  printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
1051  p++;
1052  }
1053  if (printable_only) { /* only printable, no space */
1054  if (s[0] != '/') /* relative path */
1055  rb_str_cat2(ret, "AF_UNIX ");
1056  rb_str_cat(ret, s, p - s);
1057  }
1058  else {
1059  rb_str_cat2(ret, "AF_UNIX");
1060  while (s < e)
1061  rb_str_catf(ret, ":%02x", (unsigned char)*s++);
1062  }
1063  if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len)
1064  rb_str_catf(ret, "(sockaddr %d bytes too long)",
1065  (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr)));
1066  }
1067  break;
1068  }
1069 #endif
1070 
1071  default:
1072  {
1073  ID id = rsock_intern_family(rai->addr.ss_family);
1074  if (id == 0)
1075  rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family);
1076  else
1077  rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
1078  break;
1079  }
1080  }
1081  }
1082 
1083  return ret;
1084 }
1085 
1086 /*
1087  * call-seq:
1088  * addrinfo.inspect => string
1089  *
1090  * returns a string which shows addrinfo in human-readable form.
1091  *
1092  * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>"
1093  * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
1094  *
1095  */
1096 static VALUE
1098 {
1099  rb_addrinfo_t *rai = get_addrinfo(self);
1100  int internet_p;
1101  VALUE ret;
1102 
1103  ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
1104 
1105  inspect_sockaddr(self, ret);
1106 
1107  if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
1108  ID id = rsock_intern_protocol_family(rai->pfamily);
1109  if (id)
1110  rb_str_catf(ret, " %s", rb_id2name(id));
1111  else
1112  rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
1113  }
1114 
1115  internet_p = rai->pfamily == PF_INET;
1116 #ifdef INET6
1117  internet_p = internet_p || rai->pfamily == PF_INET6;
1118 #endif
1119  if (internet_p && rai->socktype == SOCK_STREAM &&
1120  (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
1121  rb_str_cat2(ret, " TCP");
1122  }
1123  else if (internet_p && rai->socktype == SOCK_DGRAM &&
1124  (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
1125  rb_str_cat2(ret, " UDP");
1126  }
1127  else {
1128  if (rai->socktype) {
1129  ID id = rsock_intern_socktype(rai->socktype);
1130  if (id)
1131  rb_str_catf(ret, " %s", rb_id2name(id));
1132  else
1133  rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
1134  }
1135 
1136  if (rai->protocol) {
1137  if (internet_p) {
1138  ID id = rsock_intern_ipproto(rai->protocol);
1139  if (id)
1140  rb_str_catf(ret, " %s", rb_id2name(id));
1141  else
1142  goto unknown_protocol;
1143  }
1144  else {
1145  unknown_protocol:
1146  rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
1147  }
1148  }
1149  }
1150 
1151  if (!NIL_P(rai->canonname)) {
1152  VALUE name = rai->canonname;
1153  rb_str_catf(ret, " %s", StringValueCStr(name));
1154  }
1155 
1156  if (!NIL_P(rai->inspectname)) {
1157  VALUE name = rai->inspectname;
1158  rb_str_catf(ret, " (%s)", StringValueCStr(name));
1159  }
1160 
1161  rb_str_buf_cat2(ret, ">");
1162  return ret;
1163 }
1164 
1165 /*
1166  * call-seq:
1167  * addrinfo.inspect_sockaddr => string
1168  *
1169  * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
1170  *
1171  * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
1172  * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
1173  * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
1174  *
1175  */
1176 static VALUE
1178 {
1179  return inspect_sockaddr(self, rb_str_new("", 0));
1180 }
1181 
1182 /* :nodoc: */
1183 static VALUE
1185 {
1186  rb_addrinfo_t *rai = get_addrinfo(self);
1187  VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
1188  int afamily_int = ai_get_afamily(rai);
1189  ID id;
1190 
1191  id = rsock_intern_protocol_family(rai->pfamily);
1192  if (id == 0)
1193  rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
1194  pfamily = rb_id2str(id);
1195 
1196  if (rai->socktype == 0)
1197  socktype = INT2FIX(0);
1198  else {
1199  id = rsock_intern_socktype(rai->socktype);
1200  if (id == 0)
1201  rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
1202  socktype = rb_id2str(id);
1203  }
1204 
1205  if (rai->protocol == 0)
1206  protocol = INT2FIX(0);
1207  else if (IS_IP_FAMILY(afamily_int)) {
1208  id = rsock_intern_ipproto(rai->protocol);
1209  if (id == 0)
1210  rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
1211  protocol = rb_id2str(id);
1212  }
1213  else {
1214  rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
1215  }
1216 
1217  canonname = rai->canonname;
1218 
1219  inspectname = rai->inspectname;
1220 
1221  id = rsock_intern_family(afamily_int);
1222  if (id == 0)
1223  rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
1224  afamily = rb_id2str(id);
1225 
1226  switch(afamily_int) {
1227 #ifdef HAVE_SYS_UN_H
1228  case AF_UNIX:
1229  {
1230  struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr;
1231  char *s, *e;
1232  s = su->sun_path;
1233  e = (char*)su + rai->sockaddr_len;
1234  while (s < e && *(e-1) == '\0')
1235  e--;
1236  sockaddr = rb_str_new(s, e-s);
1237  break;
1238  }
1239 #endif
1240 
1241  default:
1242  {
1243  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1244  int error;
1245  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1246  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1248  if (error) {
1249  rsock_raise_socket_error("getnameinfo", error);
1250  }
1251  sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
1252  break;
1253  }
1254  }
1255 
1256  return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
1257 }
1258 
1259 /* :nodoc: */
1260 static VALUE
1262 {
1263  VALUE v;
1264  VALUE canonname, inspectname;
1265  int afamily, pfamily, socktype, protocol;
1266  struct sockaddr_storage ss;
1267  socklen_t len;
1268  rb_addrinfo_t *rai;
1269 
1270  if (check_addrinfo(self))
1271  rb_raise(rb_eTypeError, "already initialized socket address");
1272 
1273  ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1274 
1275  v = rb_ary_entry(ary, 0);
1276  StringValue(v);
1277  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
1278  rb_raise(rb_eTypeError, "unexpected address family");
1279 
1280  v = rb_ary_entry(ary, 2);
1281  StringValue(v);
1282  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
1283  rb_raise(rb_eTypeError, "unexpected protocol family");
1284 
1285  v = rb_ary_entry(ary, 3);
1286  if (v == INT2FIX(0))
1287  socktype = 0;
1288  else {
1289  StringValue(v);
1290  if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
1291  rb_raise(rb_eTypeError, "unexpected socktype");
1292  }
1293 
1294  v = rb_ary_entry(ary, 4);
1295  if (v == INT2FIX(0))
1296  protocol = 0;
1297  else {
1298  StringValue(v);
1299  if (IS_IP_FAMILY(afamily)) {
1300  if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
1301  rb_raise(rb_eTypeError, "unexpected protocol");
1302  }
1303  else {
1304  rb_raise(rb_eTypeError, "unexpected protocol");
1305  }
1306  }
1307 
1308  v = rb_ary_entry(ary, 5);
1309  if (NIL_P(v))
1310  canonname = Qnil;
1311  else {
1312  StringValue(v);
1313  canonname = v;
1314  }
1315 
1316  v = rb_ary_entry(ary, 6);
1317  if (NIL_P(v))
1318  inspectname = Qnil;
1319  else {
1320  StringValue(v);
1321  inspectname = v;
1322  }
1323 
1324  v = rb_ary_entry(ary, 1);
1325  switch(afamily) {
1326 #ifdef HAVE_SYS_UN_H
1327  case AF_UNIX:
1328  {
1329  struct sockaddr_un uaddr;
1330  MEMZERO(&uaddr, struct sockaddr_un, 1);
1331  uaddr.sun_family = AF_UNIX;
1332 
1333  StringValue(v);
1334  if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
1336  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1337  (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
1338  memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
1339  len = (socklen_t)sizeof(uaddr);
1340  memcpy(&ss, &uaddr, len);
1341  break;
1342  }
1343 #endif
1344 
1345  default:
1346  {
1347  VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
1348  struct addrinfo *res;
1349  int flags = AI_NUMERICHOST;
1350 #ifdef AI_NUMERICSERV
1351  flags |= AI_NUMERICSERV;
1352 #endif
1353  res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
1354  INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
1355  INT2NUM(flags), 1);
1356 
1357  len = res->ai_addrlen;
1358  memcpy(&ss, res->ai_addr, res->ai_addrlen);
1359  break;
1360  }
1361  }
1362 
1363  DATA_PTR(self) = rai = alloc_addrinfo();
1364  init_addrinfo(rai, (struct sockaddr *)&ss, len,
1365  pfamily, socktype, protocol,
1366  canonname, inspectname);
1367  return self;
1368 }
1369 
1370 /*
1371  * call-seq:
1372  * addrinfo.afamily => integer
1373  *
1374  * returns the address family as an integer.
1375  *
1376  * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
1377  *
1378  */
1379 static VALUE
1381 {
1382  rb_addrinfo_t *rai = get_addrinfo(self);
1383  return INT2NUM(ai_get_afamily(rai));
1384 }
1385 
1386 /*
1387  * call-seq:
1388  * addrinfo.pfamily => integer
1389  *
1390  * returns the protocol family as an integer.
1391  *
1392  * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
1393  *
1394  */
1395 static VALUE
1397 {
1398  rb_addrinfo_t *rai = get_addrinfo(self);
1399  return INT2NUM(rai->pfamily);
1400 }
1401 
1402 /*
1403  * call-seq:
1404  * addrinfo.socktype => integer
1405  *
1406  * returns the socket type as an integer.
1407  *
1408  * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
1409  *
1410  */
1411 static VALUE
1413 {
1414  rb_addrinfo_t *rai = get_addrinfo(self);
1415  return INT2NUM(rai->socktype);
1416 }
1417 
1418 /*
1419  * call-seq:
1420  * addrinfo.protocol => integer
1421  *
1422  * returns the socket type as an integer.
1423  *
1424  * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
1425  *
1426  */
1427 static VALUE
1429 {
1430  rb_addrinfo_t *rai = get_addrinfo(self);
1431  return INT2NUM(rai->protocol);
1432 }
1433 
1434 /*
1435  * call-seq:
1436  * addrinfo.to_sockaddr => string
1437  * addrinfo.to_s => string
1438  *
1439  * returns the socket address as packed struct sockaddr string.
1440  *
1441  * Addrinfo.tcp("localhost", 80).to_sockaddr
1442  * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1443  *
1444  */
1445 static VALUE
1447 {
1448  rb_addrinfo_t *rai = get_addrinfo(self);
1449  VALUE ret;
1450  ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
1451  OBJ_INFECT(ret, self);
1452  return ret;
1453 }
1454 
1455 /*
1456  * call-seq:
1457  * addrinfo.canonname => string or nil
1458  *
1459  * returns the canonical name as an string.
1460  *
1461  * nil is returned if no canonical name.
1462  *
1463  * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
1464  *
1465  * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
1466  * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)>
1467  * p list[0].canonname #=> "carbon.ruby-lang.org"
1468  *
1469  */
1470 static VALUE
1472 {
1473  rb_addrinfo_t *rai = get_addrinfo(self);
1474  return rai->canonname;
1475 }
1476 
1477 /*
1478  * call-seq:
1479  * addrinfo.ip? => true or false
1480  *
1481  * returns true if addrinfo is internet (IPv4/IPv6) address.
1482  * returns false otherwise.
1483  *
1484  * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
1485  * Addrinfo.tcp("::1", 80).ip? #=> true
1486  * Addrinfo.unix("/tmp/sock").ip? #=> false
1487  *
1488  */
1489 static VALUE
1491 {
1492  rb_addrinfo_t *rai = get_addrinfo(self);
1493  int family = ai_get_afamily(rai);
1494  return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
1495 }
1496 
1497 /*
1498  * call-seq:
1499  * addrinfo.ipv4? => true or false
1500  *
1501  * returns true if addrinfo is IPv4 address.
1502  * returns false otherwise.
1503  *
1504  * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
1505  * Addrinfo.tcp("::1", 80).ipv4? #=> false
1506  * Addrinfo.unix("/tmp/sock").ipv4? #=> false
1507  *
1508  */
1509 static VALUE
1511 {
1512  rb_addrinfo_t *rai = get_addrinfo(self);
1513  return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
1514 }
1515 
1516 /*
1517  * call-seq:
1518  * addrinfo.ipv6? => true or false
1519  *
1520  * returns true if addrinfo is IPv6 address.
1521  * returns false otherwise.
1522  *
1523  * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
1524  * Addrinfo.tcp("::1", 80).ipv6? #=> true
1525  * Addrinfo.unix("/tmp/sock").ipv6? #=> false
1526  *
1527  */
1528 static VALUE
1530 {
1531 #ifdef AF_INET6
1532  rb_addrinfo_t *rai = get_addrinfo(self);
1533  return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
1534 #else
1535  return Qfalse;
1536 #endif
1537 }
1538 
1539 /*
1540  * call-seq:
1541  * addrinfo.unix? => true or false
1542  *
1543  * returns true if addrinfo is UNIX address.
1544  * returns false otherwise.
1545  *
1546  * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
1547  * Addrinfo.tcp("::1", 80).unix? #=> false
1548  * Addrinfo.unix("/tmp/sock").unix? #=> true
1549  *
1550  */
1551 static VALUE
1553 {
1554  rb_addrinfo_t *rai = get_addrinfo(self);
1555 #ifdef AF_UNIX
1556  return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
1557 #else
1558  return Qfalse;
1559 #endif
1560 }
1561 
1562 /*
1563  * call-seq:
1564  * addrinfo.getnameinfo => [nodename, service]
1565  * addrinfo.getnameinfo(flags) => [nodename, service]
1566  *
1567  * returns nodename and service as a pair of strings.
1568  * This converts struct sockaddr in addrinfo to textual representation.
1569  *
1570  * flags should be bitwise OR of Socket::NI_??? constants.
1571  *
1572  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
1573  *
1574  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
1575  * #=> ["localhost", "80"]
1576  */
1577 static VALUE
1579 {
1580  rb_addrinfo_t *rai = get_addrinfo(self);
1581  VALUE vflags;
1582  char hbuf[1024], pbuf[1024];
1583  int flags, error;
1584 
1585  rb_scan_args(argc, argv, "01", &vflags);
1586 
1587  flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
1588 
1589  if (rai->socktype == SOCK_DGRAM)
1590  flags |= NI_DGRAM;
1591 
1592  error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len,
1593  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1594  flags);
1595  if (error) {
1596  rsock_raise_socket_error("getnameinfo", error);
1597  }
1598 
1599  return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
1600 }
1601 
1602 /*
1603  * call-seq:
1604  * addrinfo.ip_unpack => [addr, port]
1605  *
1606  * Returns the IP address and port number as 2-element array.
1607  *
1608  * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
1609  * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
1610  */
1611 static VALUE
1613 {
1614  rb_addrinfo_t *rai = get_addrinfo(self);
1615  int family = ai_get_afamily(rai);
1616  VALUE vflags;
1617  VALUE ret, portstr;
1618 
1619  if (!IS_IP_FAMILY(family))
1620  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1621 
1623  ret = addrinfo_getnameinfo(1, &vflags, self);
1624  portstr = rb_ary_entry(ret, 1);
1625  rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
1626  return ret;
1627 }
1628 
1629 /*
1630  * call-seq:
1631  * addrinfo.ip_address => string
1632  *
1633  * Returns the IP address as a string.
1634  *
1635  * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
1636  * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
1637  */
1638 static VALUE
1640 {
1641  rb_addrinfo_t *rai = get_addrinfo(self);
1642  int family = ai_get_afamily(rai);
1643  VALUE vflags;
1644  VALUE ret;
1645 
1646  if (!IS_IP_FAMILY(family))
1647  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1648 
1650  ret = addrinfo_getnameinfo(1, &vflags, self);
1651  return rb_ary_entry(ret, 0);
1652 }
1653 
1654 /*
1655  * call-seq:
1656  * addrinfo.ip_port => port
1657  *
1658  * Returns the port number as an integer.
1659  *
1660  * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
1661  * Addrinfo.tcp("::1", 80).ip_port #=> 80
1662  */
1663 static VALUE
1665 {
1666  rb_addrinfo_t *rai = get_addrinfo(self);
1667  int family = ai_get_afamily(rai);
1668  int port;
1669 
1670  if (!IS_IP_FAMILY(family)) {
1671  bad_family:
1672 #ifdef AF_INET6
1673  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
1674 #else
1675  rb_raise(rb_eSocket, "need IPv4 address");
1676 #endif
1677  }
1678 
1679  switch (family) {
1680  case AF_INET:
1681  if (rai->sockaddr_len != sizeof(struct sockaddr_in))
1682  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
1683  port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port);
1684  break;
1685 
1686 #ifdef AF_INET6
1687  case AF_INET6:
1688  if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
1689  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
1690  port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port);
1691  break;
1692 #endif
1693 
1694  default:
1695  goto bad_family;
1696  }
1697 
1698  return INT2NUM(port);
1699 }
1700 
1701 static int
1703 {
1704  rb_addrinfo_t *rai = get_addrinfo(self);
1705  int family = ai_get_afamily(rai);
1706  if (family != AF_INET) return 0;
1707  *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr);
1708  return 1;
1709 }
1710 
1711 /*
1712  * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
1713  * It returns false otherwise.
1714  */
1715 static VALUE
1717 {
1718  uint32_t a;
1719  if (!extract_in_addr(self, &a)) return Qfalse;
1720  if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
1721  (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
1722  (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
1723  return Qtrue;
1724  return Qfalse;
1725 }
1726 
1727 /*
1728  * Returns true for IPv4 loopback address (127.0.0.0/8).
1729  * It returns false otherwise.
1730  */
1731 static VALUE
1733 {
1734  uint32_t a;
1735  if (!extract_in_addr(self, &a)) return Qfalse;
1736  if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
1737  return Qtrue;
1738  return Qfalse;
1739 }
1740 
1741 /*
1742  * Returns true for IPv4 multicast address (224.0.0.0/4).
1743  * It returns false otherwise.
1744  */
1745 static VALUE
1747 {
1748  uint32_t a;
1749  if (!extract_in_addr(self, &a)) return Qfalse;
1750  if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
1751  return Qtrue;
1752  return Qfalse;
1753 }
1754 
1755 #ifdef INET6
1756 
1757 static struct in6_addr *
1758 extract_in6_addr(VALUE self)
1759 {
1760  rb_addrinfo_t *rai = get_addrinfo(self);
1761  int family = ai_get_afamily(rai);
1762  if (family != AF_INET6) return NULL;
1763  return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1764 }
1765 
1766 /*
1767  * Returns true for IPv6 unspecified address (::).
1768  * It returns false otherwise.
1769  */
1770 static VALUE
1771 addrinfo_ipv6_unspecified_p(VALUE self)
1772 {
1773  struct in6_addr *addr = extract_in6_addr(self);
1774  if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
1775  return Qfalse;
1776 }
1777 
1778 /*
1779  * Returns true for IPv6 loopback address (::1).
1780  * It returns false otherwise.
1781  */
1782 static VALUE
1783 addrinfo_ipv6_loopback_p(VALUE self)
1784 {
1785  struct in6_addr *addr = extract_in6_addr(self);
1786  if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
1787  return Qfalse;
1788 }
1789 
1790 /*
1791  * Returns true for IPv6 multicast address (ff00::/8).
1792  * It returns false otherwise.
1793  */
1794 static VALUE
1795 addrinfo_ipv6_multicast_p(VALUE self)
1796 {
1797  struct in6_addr *addr = extract_in6_addr(self);
1798  if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
1799  return Qfalse;
1800 }
1801 
1802 /*
1803  * Returns true for IPv6 link local address (ff80::/10).
1804  * It returns false otherwise.
1805  */
1806 static VALUE
1807 addrinfo_ipv6_linklocal_p(VALUE self)
1808 {
1809  struct in6_addr *addr = extract_in6_addr(self);
1810  if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
1811  return Qfalse;
1812 }
1813 
1814 /*
1815  * Returns true for IPv6 site local address (ffc0::/10).
1816  * It returns false otherwise.
1817  */
1818 static VALUE
1819 addrinfo_ipv6_sitelocal_p(VALUE self)
1820 {
1821  struct in6_addr *addr = extract_in6_addr(self);
1822  if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
1823  return Qfalse;
1824 }
1825 
1826 /*
1827  * Returns true for IPv6 unique local address (fc00::/7, RFC4193).
1828  * It returns false otherwise.
1829  */
1830 static VALUE
1831 addrinfo_ipv6_unique_local_p(VALUE self)
1832 {
1833  struct in6_addr *addr = extract_in6_addr(self);
1834  if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue;
1835  return Qfalse;
1836 }
1837 
1838 /*
1839  * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
1840  * It returns false otherwise.
1841  */
1842 static VALUE
1843 addrinfo_ipv6_v4mapped_p(VALUE self)
1844 {
1845  struct in6_addr *addr = extract_in6_addr(self);
1846  if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
1847  return Qfalse;
1848 }
1849 
1850 /*
1851  * Returns true for IPv4-compatible IPv6 address (::/80).
1852  * It returns false otherwise.
1853  */
1854 static VALUE
1855 addrinfo_ipv6_v4compat_p(VALUE self)
1856 {
1857  struct in6_addr *addr = extract_in6_addr(self);
1858  if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
1859  return Qfalse;
1860 }
1861 
1862 /*
1863  * Returns true for IPv6 multicast node-local scope address.
1864  * It returns false otherwise.
1865  */
1866 static VALUE
1867 addrinfo_ipv6_mc_nodelocal_p(VALUE self)
1868 {
1869  struct in6_addr *addr = extract_in6_addr(self);
1870  if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
1871  return Qfalse;
1872 }
1873 
1874 /*
1875  * Returns true for IPv6 multicast link-local scope address.
1876  * It returns false otherwise.
1877  */
1878 static VALUE
1879 addrinfo_ipv6_mc_linklocal_p(VALUE self)
1880 {
1881  struct in6_addr *addr = extract_in6_addr(self);
1882  if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
1883  return Qfalse;
1884 }
1885 
1886 /*
1887  * Returns true for IPv6 multicast site-local scope address.
1888  * It returns false otherwise.
1889  */
1890 static VALUE
1891 addrinfo_ipv6_mc_sitelocal_p(VALUE self)
1892 {
1893  struct in6_addr *addr = extract_in6_addr(self);
1894  if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
1895  return Qfalse;
1896 }
1897 
1898 /*
1899  * Returns true for IPv6 multicast organization-local scope address.
1900  * It returns false otherwise.
1901  */
1902 static VALUE
1903 addrinfo_ipv6_mc_orglocal_p(VALUE self)
1904 {
1905  struct in6_addr *addr = extract_in6_addr(self);
1906  if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
1907  return Qfalse;
1908 }
1909 
1910 /*
1911  * Returns true for IPv6 multicast global scope address.
1912  * It returns false otherwise.
1913  */
1914 static VALUE
1915 addrinfo_ipv6_mc_global_p(VALUE self)
1916 {
1917  struct in6_addr *addr = extract_in6_addr(self);
1918  if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
1919  return Qfalse;
1920 }
1921 
1922 /*
1923  * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
1924  * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
1925  *
1926  * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1927  * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
1928  * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
1929  * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
1930  * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
1931  */
1932 static VALUE
1933 addrinfo_ipv6_to_ipv4(VALUE self)
1934 {
1935  rb_addrinfo_t *rai = get_addrinfo(self);
1936  struct in6_addr *addr;
1937  int family = ai_get_afamily(rai);
1938  if (family != AF_INET6) return Qnil;
1939  addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr;
1940  if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
1941  struct sockaddr_in sin4;
1942  MEMZERO(&sin4, struct sockaddr_in, 1);
1943  sin4.sin_family = AF_INET;
1944  SET_SIN_LEN(&sin4, sizeof(sin4));
1945  memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
1946  return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
1947  PF_INET, rai->socktype, rai->protocol,
1948  rai->canonname, rai->inspectname);
1949  }
1950  else {
1951  return Qnil;
1952  }
1953 }
1954 
1955 #endif
1956 
1957 #ifdef HAVE_SYS_UN_H
1958 /*
1959  * call-seq:
1960  * addrinfo.unix_path => path
1961  *
1962  * Returns the socket path as a string.
1963  *
1964  * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
1965  */
1966 static VALUE
1967 addrinfo_unix_path(VALUE self)
1968 {
1969  rb_addrinfo_t *rai = get_addrinfo(self);
1970  int family = ai_get_afamily(rai);
1971  struct sockaddr_un *addr;
1972  char *s, *e;
1973 
1974  if (family != AF_UNIX)
1975  rb_raise(rb_eSocket, "need AF_UNIX address");
1976 
1977  addr = (struct sockaddr_un *)&rai->addr;
1978 
1979  s = addr->sun_path;
1980  e = (char*)addr + rai->sockaddr_len;
1981  if (e < s)
1982  rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.",
1983  (size_t)rai->sockaddr_len, (size_t)(s - (char *)addr));
1984  if (addr->sun_path + sizeof(addr->sun_path) < e)
1986  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1987  (size_t)(e - addr->sun_path), sizeof(addr->sun_path));
1988  while (s < e && *(e-1) == '\0')
1989  e--;
1990  return rb_str_new(s, e-s);
1991 }
1992 #endif
1993 
1994 /*
1995  * call-seq:
1996  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
1997  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
1998  * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
1999  * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
2000  * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
2001  *
2002  * returns a list of addrinfo objects as an array.
2003  *
2004  * This method converts nodename (hostname) and service (port) to addrinfo.
2005  * Since the conversion is not unique, the result is a list of addrinfo objects.
2006  *
2007  * nodename or service can be nil if no conversion intended.
2008  *
2009  * family, socktype and protocol are hint for preferred protocol.
2010  * If the result will be used for a socket with SOCK_STREAM,
2011  * SOCK_STREAM should be specified as socktype.
2012  * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
2013  * If they are omitted or nil is given, the result is not restricted.
2014  *
2015  * Similarly, PF_INET6 as family restricts for IPv6.
2016  *
2017  * flags should be bitwise OR of Socket::AI_??? constants such as follows.
2018  * Note that the exact list of the constants depends on OS.
2019  *
2020  * AI_PASSIVE Get address to use with bind()
2021  * AI_CANONNAME Fill in the canonical name
2022  * AI_NUMERICHOST Prevent host name resolution
2023  * AI_NUMERICSERV Prevent service name resolution
2024  * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses
2025  * AI_ALL Allow all addresses
2026  * AI_ADDRCONFIG Accept only if any address is assigned
2027  *
2028  * Note that socktype should be specified whenever application knows the usage of the address.
2029  * Some platform causes an error when socktype is omitted and servname is specified as an integer
2030  * because some port numbers, 512 for example, are ambiguous without socktype.
2031  *
2032  * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
2033  * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>,
2034  * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>]
2035  *
2036  */
2037 static VALUE
2039 {
2040  VALUE node, service, family, socktype, protocol, flags;
2041 
2042  rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags);
2043  return addrinfo_list_new(node, service, family, socktype, protocol, flags);
2044 }
2045 
2046 /*
2047  * call-seq:
2048  * Addrinfo.ip(host) => addrinfo
2049  *
2050  * returns an addrinfo object for IP address.
2051  *
2052  * The port, socktype, protocol of the result is filled by zero.
2053  * So, it is not appropriate to create a socket.
2054  *
2055  * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
2056  */
2057 static VALUE
2059 {
2060  VALUE ret;
2061  rb_addrinfo_t *rai;
2062  ret = addrinfo_firstonly_new(host, Qnil,
2063  INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
2064  rai = get_addrinfo(ret);
2065  rai->socktype = 0;
2066  rai->protocol = 0;
2067  return ret;
2068 }
2069 
2070 /*
2071  * call-seq:
2072  * Addrinfo.tcp(host, port) => addrinfo
2073  *
2074  * returns an addrinfo object for TCP address.
2075  *
2076  * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
2077  */
2078 static VALUE
2079 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
2080 {
2081  return addrinfo_firstonly_new(host, port,
2082  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
2083 }
2084 
2085 /*
2086  * call-seq:
2087  * Addrinfo.udp(host, port) => addrinfo
2088  *
2089  * returns an addrinfo object for UDP address.
2090  *
2091  * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
2092  */
2093 static VALUE
2094 addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
2095 {
2096  return addrinfo_firstonly_new(host, port,
2097  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
2098 }
2099 
2100 #ifdef HAVE_SYS_UN_H
2101 
2102 /*
2103  * call-seq:
2104  * Addrinfo.unix(path [, socktype]) => addrinfo
2105  *
2106  * returns an addrinfo object for UNIX socket address.
2107  *
2108  * _socktype_ specifies the socket type.
2109  * If it is omitted, :STREAM is used.
2110  *
2111  * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
2112  * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
2113  */
2114 static VALUE
2115 addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
2116 {
2117  VALUE path, vsocktype, addr;
2118  int socktype;
2119  rb_addrinfo_t *rai;
2120 
2121  rb_scan_args(argc, argv, "11", &path, &vsocktype);
2122 
2123  if (NIL_P(vsocktype))
2124  socktype = SOCK_STREAM;
2125  else
2126  socktype = rsock_socktype_arg(vsocktype);
2127 
2129  DATA_PTR(addr) = rai = alloc_addrinfo();
2130  init_unix_addrinfo(rai, path, socktype);
2131  OBJ_INFECT(addr, path);
2132  return addr;
2133 }
2134 
2135 #endif
2136 
2137 VALUE
2139 {
2140  VALUE val = *v;
2141  if (IS_ADDRINFO(val)) {
2142  *v = addrinfo_to_sockaddr(val);
2143  }
2144  StringValue(*v);
2145  return *v;
2146 }
2147 
2148 char *
2150 {
2152  return RSTRING_PTR(*v);
2153 }
2154 
2155 VALUE
2157 {
2158  if (IS_ADDRINFO(val))
2159  return addrinfo_to_sockaddr(val);
2160  return rb_check_string_type(val);
2161 }
2162 
2163 VALUE
2164 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
2165 {
2166  int family;
2167  int socktype;
2168  int ret;
2169  socklen_t optlen = (socklen_t)sizeof(socktype);
2170 
2171  /* assumes protocol family and address family are identical */
2172  family = get_afamily(addr, len);
2173 
2174  ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
2175  if (ret == -1) {
2176  rb_sys_fail("getsockopt(SO_TYPE)");
2177  }
2178 
2179  return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
2180 }
2181 
2182 VALUE
2183 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
2184 {
2185  rb_io_t *fptr;
2186 
2187  switch (TYPE(io)) {
2188  case T_FIXNUM:
2189  return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
2190 
2191  case T_BIGNUM:
2192  return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
2193 
2194  case T_FILE:
2195  GetOpenFile(io, fptr);
2196  return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
2197 
2198  default:
2199  rb_raise(rb_eTypeError, "neither IO nor file descriptor");
2200  }
2201 
2202  UNREACHABLE;
2203 }
2204 
2205 /*
2206  * Addrinfo class
2207  */
2208 void
2210 {
2211  /*
2212  * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
2213  * structure identifies an Internet host and a service.
2214  */
2215  rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
2219  rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0);
2224 #ifdef HAVE_SYS_UN_H
2225  rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
2226 #endif
2227 
2233 
2237 
2242 
2246 
2247 #ifdef INET6
2248  rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
2249  rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
2250  rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
2251  rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
2252  rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
2253  rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0);
2254  rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
2255  rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
2256  rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
2257  rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
2258  rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
2259  rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
2260  rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
2261 
2262  rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
2263 #endif
2264 
2265 #ifdef HAVE_SYS_UN_H
2266  rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
2267 #endif
2268 
2270  rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
2271 
2272  rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
2273 
2274  rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
2275  rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
2276 }
#define RB_TYPE_P(obj, type)
VALUE inspectname
Definition: raddrinfo.c:544
#define ALLOC(type)
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:379
volatile VALUE ary
Definition: tcltklib.c:9712
VP_EXPORT int
Definition: bigdecimal.c:5071
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1088
static int str_is_number(const char *)
Definition: raddrinfo.c:272
size_t strlen(const char *)
#define OBJ_INFECT(x, s)
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
#define PF_INET
Definition: sockport.h:77
size_t servlen
Definition: raddrinfo.c:202
VALUE rb_id2str(ID id)
Definition: ripper.c:16940
Win32OLEIDispatch * p
Definition: win32ole.c:786
volatile VALUE pair
Definition: tkutil.c:554
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1501
static rb_addrinfo_t * check_addrinfo(VALUE self)
Definition: raddrinfo.c:584
static struct addrinfo * call_getaddrinfo(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, int socktype_hack)
Definition: raddrinfo.c:643
#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:1529
#define SET_SIN_LEN(si, len)
Definition: sockport.h:48
VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
Definition: raddrinfo.c:251
ssize_t i
Definition: bigdecimal.c:5676
Definition: io.h:63
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:764
VALUE rb_str_new_cstr(const char *)
Definition: string.c:447
int ret
Definition: tcltklib.c:280
Real * a
Definition: bigdecimal.c:1196
VALUE rb_eTypeError
Definition: error.c:516
#define OBJ_FREEZE(x)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define UNREACHABLE
Definition: ruby.h:40
st_table * names
Definition: encoding.c:53
#define RUBY_UBF_IO
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
static void * nogvl_getaddrinfo(void *arg)
Definition: raddrinfo.c:158
gz path
Definition: zlib.c:2277
#define TYPE(x)
#define RSTRING_PTR(str)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4067
#define T_ARRAY
VALUE rb_str_buf_cat2(VALUE, const char *)
Definition: string.c:1961
static VALUE addrinfo_ipv4_loopback_p(VALUE self)
Definition: raddrinfo.c:1732
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1788
#define IN6_IS_ADDR_UNIQUE_LOCAL(a)
Definition: rubysocket.h:121
return Qtrue
Definition: tcltklib.c:9609
static VALUE addrinfo_protocol(VALUE self)
Definition: raddrinfo.c:1428
static void make_inetaddr(unsigned int host, char *buf, size_t buflen)
Definition: raddrinfo.c:260
#define T_FILE
#define SafeStringValue(v)
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2156
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
static VALUE addrinfo_ipv4_p(VALUE self)
Definition: raddrinfo.c:1510
r
Definition: bigdecimal.c:1210
#define rb_str_new2
const char * service
Definition: raddrinfo.c:152
static size_t addrinfo_memsize(const void *ptr)
Definition: raddrinfo.c:566
VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
Definition: raddrinfo.c:391
#define STRTOUL(str, endptr, base)
#define GetOpenFile(obj, fp)
Definition: io.h:120
void rsock_init_addrinfo(void)
Definition: raddrinfo.c:2209
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2183
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:2363
static VALUE addrinfo_ipv4_multicast_p(VALUE self)
Definition: raddrinfo.c:1746
#define NI_MAXSERV
Definition: addrinfo.h:118
static VALUE addrinfo_inspect_sockaddr(VALUE self)
Definition: raddrinfo.c:1177
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:1446
#define MEMZERO(p, type, n)
#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
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
return Qfalse
Definition: tcltklib.c:6778
#define FIXNUM_P(f)
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
#define Qnil
Definition: tcltklib.c:1895
#define val
Definition: tcltklib.c:1948
socklen_t salen
Definition: raddrinfo.c:198
VALUE rb_ary_new(void)
Definition: array.c:424
static int ai_get_afamily(rb_addrinfo_t *rai)
Definition: raddrinfo.c:957
#define StringValueCStr(v)
int flags
Definition: tcltklib.c:3022
unsigned long ID
Definition: ripper.y:105
#define PRIuSIZE
static VALUE addrinfo_initialize(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:868
#define NI_NUMERICSERV
Definition: addrinfo.h:127
void rb_gc_mark(VALUE)
Definition: gc.c:2600
static VALUE addrinfo_ip_unpack(VALUE self)
Definition: raddrinfo.c:1612
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1986
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:503
#define RSTRING_LEN(str)
#define FIX2INT(x)
static VALUE addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:1578
#define INT2FIX(i)
static char * host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
Definition: raddrinfo.c:287
int fd
Definition: io.h:64
char * ai_canonname
Definition: addrinfo.h:137
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:719
#define FIX2LONG(x)
#define offsetof(p_type, field)
Definition: addrinfo.h:186
static const rb_data_type_t addrinfo_type
Definition: raddrinfo.c:571
#define T_STRING
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
Definition: getaddrinfo.c:267
#define TypedData_Wrap_Struct(klass, data_type, sval)
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
#define EAI_SYSTEM
Definition: addrinfo.h:88
unsigned short ss_family
Definition: rubysocket.h:139
static VALUE addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
Definition: raddrinfo.c:2094
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
static int get_afamily(struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:948
static VALUE addrinfo_unix_p(VALUE self)
Definition: raddrinfo.c:1552
VALUE rb_str_dup(VALUE)
Definition: string.c:946
VALUE rb_tainted_str_new_cstr(const char *)
Definition: string.c:479
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:1970
RUBY_EXTERN VALUE rb_cInteger
Definition: ripper.y:1441
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:117
memcpy(buf+1, str, len)
const int id
Definition: nkf.c:209
char * rsock_sockaddr_string_value_ptr(volatile VALUE *v)
Definition: raddrinfo.c:2149
int errno
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1275
#define StringValue(v)
static void * nogvl_getnameinfo(void *arg)
Definition: raddrinfo.c:207
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:739
register char * s
Definition: os2.c:56
static VALUE addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
Definition: raddrinfo.c:2038
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:5104
VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2164
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1574
static VALUE addrinfo_mload(VALUE self, VALUE ary)
Definition: raddrinfo.c:1261
#define NUM2UINT(x)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
static VALUE addrinfo_pfamily(VALUE self)
Definition: raddrinfo.c:1396
socklen_t sockaddr_len
Definition: raddrinfo.c:549
static VALUE addrinfo_ip_address(VALUE self)
Definition: raddrinfo.c:1639
static VALUE addrinfo_s_ip(VALUE self, VALUE host)
Definition: raddrinfo.c:2058
static char * port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
Definition: raddrinfo.c:324
VALUE host
Definition: raddrinfo.c:476
#define T_FIXNUM
int argc
Definition: tcltklib.c:1969
struct sockaddr * sa
Definition: raddrinfo.c:197
#define AI_NUMERICHOST
Definition: addrinfo.h:98
#define addrinfo_free
Definition: raddrinfo.c:563
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
static VALUE addrinfo_ip_p(VALUE self)
Definition: raddrinfo.c:1490
void rb_sys_fail(const char *mesg)
Definition: error.c:1907
static VALUE addrinfo_s_allocate(VALUE klass)
Definition: raddrinfo.c:577
return ptr
Definition: tcltklib.c:784
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_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
Definition: raddrinfo.c:240
#define T_BIGNUM
static VALUE make_hostent_internal(struct hostent_arg *arg)
Definition: raddrinfo.c:482
unsigned int uint32_t
Definition: sha2.h:101
#define MEMCPY(p1, p2, type, n)
int ai_protocol
Definition: addrinfo.h:135
static VALUE addrinfo_afamily(VALUE self)
Definition: raddrinfo.c:1380
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:1317
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1967
static VALUE inspect_sockaddr(VALUE addrinfo, VALUE ret)
Definition: raddrinfo.c:963
static VALUE addrinfo_canonname(VALUE self)
Definition: raddrinfo.c:1471
static VALUE addrinfo_ipv4_private_p(VALUE self)
Definition: raddrinfo.c:1716
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:488
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:593
#define PF_UNSPEC
Definition: sockport.h:73
int ai_socktype
Definition: addrinfo.h:134
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
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:1315
static VALUE addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
Definition: raddrinfo.c:2079
VALUE rb_cAddrinfo
Definition: init.c:23
struct addrinfo * addr
Definition: raddrinfo.c:477
#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:3503
#define INT2NUM(x)
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
struct addrinfo * hints
Definition: raddrinfo.c:153
#define ISPRINT(c)
Definition: ruby.h:1631
gz io
Definition: zlib.c:2261
struct addrinfo ** res
Definition: raddrinfo.c:154
struct addrinfo * ai_next
Definition: addrinfo.h:139
#define RSTRING_LENINT(str)
static VALUE addrinfo_socktype(VALUE self)
Definition: raddrinfo.c:1412
VALUE rb_ary_new2(long capa)
Definition: array.c:417
VALUE rb_str_new(const char *, long)
Definition: string.c:425
Real * res
Definition: bigdecimal.c:1247
#define NUM2INT(x)
const char * rb_id2name(ID id)
Definition: ripper.c:17006
static void addrinfo_mark(void *ptr)
Definition: raddrinfo.c:554
BDIGIT e
Definition: bigdecimal.c:5106
#define EAI_NONAME
Definition: addrinfo.h:85
unsigned long VALUE
Definition: ripper.y:104
VALUE(* ipaddr)(struct sockaddr *, size_t)
Definition: raddrinfo.c:478
size_t ai_addrlen
Definition: addrinfo.h:136
static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
Definition: raddrinfo.c:693
#define snprintf
int ai_flags
Definition: addrinfo.h:132
BDIGIT v
Definition: bigdecimal.c:5677
static VALUE addrinfo_ip_port(VALUE self)
Definition: raddrinfo.c:1664
RUBY_EXTERN VALUE rb_cData
Definition: ripper.y:1433
#define NULL
Definition: _sdbm.c:103
const char * name
Definition: nkf.c:208
VALUE rb_check_string_type(VALUE)
Definition: string.c:1509
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:1184
static rb_addrinfo_t * get_addrinfo(VALUE self)
Definition: raddrinfo.c:590
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1348
static VALUE addrinfo_inspect(VALUE self)
Definition: raddrinfo.c:1097
struct sockaddr * ai_addr
Definition: addrinfo.h:138
VALUE rb_eArgError
Definition: error.c:517
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2400
static int extract_in_addr(VALUE self, uint32_t *addrp)
Definition: raddrinfo.c:1702
VALUE rsock_sockaddr_string_value(volatile VALUE *v)
Definition: raddrinfo.c:2138
#define ISSPACE(c)
Definition: ruby.h:1632
size_t len
Definition: tcltklib.c:3567
int ai_family
Definition: addrinfo.h:133