Ruby  2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)
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) {
133  }
134  else if (r->ai_socktype == SOCK_STREAM) {
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 #ifdef HAVE_INET_PTON
149 static int
150 parse_numeric_port(const char *service, int *portp)
151 {
152  unsigned long u;
153 
154  if (!service) {
155  *portp = 0;
156  return 1;
157  }
158 
159  if (strspn(service, "0123456789") != strlen(service))
160  return 0;
161 
162  errno = 0;
163  u = STRTOUL(service, NULL, 10);
164  if (errno)
165  return 0;
166 
167  if (0x10000 <= u)
168  return 0;
169 
170  *portp = (int)u;
171 
172  return 1;
173 }
174 #endif
175 
176 #ifndef GETADDRINFO_EMU
178 {
179  const char *node;
180  const char *service;
181  const struct addrinfo *hints;
182  struct addrinfo **res;
183 };
184 
185 static void *
186 nogvl_getaddrinfo(void *arg)
187 {
188  int ret;
189  struct getaddrinfo_arg *ptr = arg;
190  ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
191 #ifdef __linux__
192  /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
193  * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
194  */
195  if (ret == EAI_SYSTEM && errno == ENOENT)
196  ret = EAI_NONAME;
197 #endif
198  return (void *)(VALUE)ret;
199 }
200 #endif
201 
202 #ifdef HAVE_GETADDRINFO_A
203 struct gai_suspend_arg
204 {
205  struct gaicb *req;
206  struct timespec *timeout;
207 };
208 
209 static void *
210 nogvl_gai_suspend(void *arg)
211 {
212  int ret;
213  struct gai_suspend_arg *ptr = arg;
214  struct gaicb const *wait_reqs[1];
215 
216  wait_reqs[0] = ptr->req;
217  ret = gai_suspend(wait_reqs, 1, ptr->timeout);
218 
219  return (void *)(VALUE)ret;
220 }
221 #endif
222 
223 static int
224 numeric_getaddrinfo(const char *node, const char *service,
225  const struct addrinfo *hints,
226  struct addrinfo **res)
227 {
228 #ifdef HAVE_INET_PTON
229 # if defined __MINGW64__
230 # define inet_pton(f,s,d) rb_w32_inet_pton(f,s,d)
231 # endif
232 
233  int port;
234 
235  if (node && parse_numeric_port(service, &port)) {
236  static const struct {
237  int socktype;
238  int protocol;
239  } list[] = {
240  { SOCK_STREAM, IPPROTO_TCP },
241  { SOCK_DGRAM, IPPROTO_UDP },
242  { SOCK_RAW, 0 }
243  };
244  struct addrinfo *ai = NULL;
245  int hint_family = hints ? hints->ai_family : PF_UNSPEC;
246  int hint_socktype = hints ? hints->ai_socktype : 0;
247  int hint_protocol = hints ? hints->ai_protocol : 0;
248  char ipv4addr[4];
249 #ifdef AF_INET6
250  char ipv6addr[16];
251  if ((hint_family == PF_UNSPEC || hint_family == PF_INET6) &&
252  strspn(node, "0123456789abcdefABCDEF.:") == strlen(node) &&
253  inet_pton(AF_INET6, node, ipv6addr)) {
254  int i;
255  for (i = numberof(list)-1; 0 <= i; i--) {
256  if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
257  (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
258  struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
259  struct sockaddr_in6 *sa = xmalloc(sizeof(struct sockaddr_in6));
260  INIT_SOCKADDR_IN6(sa, sizeof(struct sockaddr_in6));
261  memcpy(&sa->sin6_addr, ipv6addr, sizeof(ipv6addr));
262  sa->sin6_port = htons(port);
263  ai0->ai_family = PF_INET6;
264  ai0->ai_socktype = list[i].socktype;
265  ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
266  ai0->ai_addrlen = sizeof(struct sockaddr_in6);
267  ai0->ai_addr = (struct sockaddr *)sa;
268  ai0->ai_canonname = NULL;
269  ai0->ai_next = ai;
270  ai = ai0;
271  }
272  }
273  }
274  else
275 #endif
276  if ((hint_family == PF_UNSPEC || hint_family == PF_INET) &&
277  strspn(node, "0123456789.") == strlen(node) &&
278  inet_pton(AF_INET, node, ipv4addr)) {
279  int i;
280  for (i = numberof(list)-1; 0 <= i; i--) {
281  if ((hint_socktype == 0 || hint_socktype == list[i].socktype) &&
282  (hint_protocol == 0 || list[i].protocol == 0 || hint_protocol == list[i].protocol)) {
283  struct addrinfo *ai0 = xcalloc(1, sizeof(struct addrinfo));
284  struct sockaddr_in *sa = xmalloc(sizeof(struct sockaddr_in));
285  INIT_SOCKADDR_IN(sa, sizeof(struct sockaddr_in));
286  memcpy(&sa->sin_addr, ipv4addr, sizeof(ipv4addr));
287  sa->sin_port = htons(port);
288  ai0->ai_family = PF_INET;
289  ai0->ai_socktype = list[i].socktype;
290  ai0->ai_protocol = hint_protocol ? hint_protocol : list[i].protocol;
291  ai0->ai_addrlen = sizeof(struct sockaddr_in);
292  ai0->ai_addr = (struct sockaddr *)sa;
293  ai0->ai_canonname = NULL;
294  ai0->ai_next = ai;
295  ai = ai0;
296  }
297  }
298  }
299  if (ai) {
300  *res = ai;
301  return 0;
302  }
303  }
304 #endif
305  return EAI_FAIL;
306 }
307 
308 int
309 rb_getaddrinfo(const char *node, const char *service,
310  const struct addrinfo *hints,
311  struct rb_addrinfo **res)
312 {
313  struct addrinfo *ai;
314  int ret;
315  int allocated_by_malloc = 0;
316 
317  ret = numeric_getaddrinfo(node, service, hints, &ai);
318  if (ret == 0)
319  allocated_by_malloc = 1;
320  else {
321 #ifdef GETADDRINFO_EMU
322  ret = getaddrinfo(node, service, hints, &ai);
323 #else
324  struct getaddrinfo_arg arg;
325  MEMZERO(&arg, struct getaddrinfo_arg, 1);
326  arg.node = node;
327  arg.service = service;
328  arg.hints = hints;
329  arg.res = &ai;
330  ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
331 #endif
332  }
333 
334  if (ret == 0) {
335  *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
336  (*res)->allocated_by_malloc = allocated_by_malloc;
337  (*res)->ai = ai;
338  }
339  return ret;
340 }
341 
342 #ifdef HAVE_GETADDRINFO_A
343 int
344 rb_getaddrinfo_a(const char *node, const char *service,
345  const struct addrinfo *hints,
346  struct rb_addrinfo **res, struct timespec *timeout)
347 {
348  struct addrinfo *ai;
349  int ret;
350  int allocated_by_malloc = 0;
351 
352  ret = numeric_getaddrinfo(node, service, hints, &ai);
353  if (ret == 0)
354  allocated_by_malloc = 1;
355  else {
356  struct gai_suspend_arg arg;
357  struct gaicb *reqs[1];
358  struct gaicb req;
359 
360  req.ar_name = node;
361  req.ar_service = service;
362  req.ar_request = hints;
363 
364  reqs[0] = &req;
365  ret = getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL);
366  if (ret) return ret;
367 
368  arg.req = &req;
369  arg.timeout = timeout;
370 
371  ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_gai_suspend, &arg, RUBY_UBF_IO, 0);
372 
373  if (ret) {
374  /* on Ubuntu 18.04 (or other systems), gai_suspend(3) returns EAI_SYSTEM/ENOENT on timeout */
375  if (ret == EAI_SYSTEM && errno == ENOENT) {
376  return EAI_AGAIN;
377  } else {
378  return ret;
379  }
380  }
381 
382  ret = gai_error(reqs[0]);
383  ai = reqs[0]->ar_result;
384  }
385 
386  if (ret == 0) {
387  *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
388  (*res)->allocated_by_malloc = allocated_by_malloc;
389  (*res)->ai = ai;
390  }
391  return ret;
392 }
393 #endif
394 
395 void
397 {
398  if (!ai->allocated_by_malloc)
399  freeaddrinfo(ai->ai);
400  else {
401  struct addrinfo *ai1, *ai2;
402  ai1 = ai->ai;
403  while (ai1) {
404  ai2 = ai1->ai_next;
405  xfree(ai1->ai_addr);
406  xfree(ai1);
407  ai1 = ai2;
408  }
409  }
410  xfree(ai);
411 }
412 
413 #ifndef GETADDRINFO_EMU
415 {
416  const struct sockaddr *sa;
418  int flags;
419  char *host;
420  size_t hostlen;
421  char *serv;
422  size_t servlen;
423 };
424 
425 static void *
426 nogvl_getnameinfo(void *arg)
427 {
428  struct getnameinfo_arg *ptr = arg;
429  return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen,
430  ptr->host, (socklen_t)ptr->hostlen,
431  ptr->serv, (socklen_t)ptr->servlen,
432  ptr->flags);
433 }
434 #endif
435 
436 int
437 rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
438  char *host, size_t hostlen,
439  char *serv, size_t servlen, int flags)
440 {
441 #ifdef GETADDRINFO_EMU
443 #else
444  struct getnameinfo_arg arg;
445  int ret;
446  arg.sa = sa;
447  arg.salen = salen;
448  arg.host = host;
449  arg.hostlen = hostlen;
450  arg.serv = serv;
451  arg.servlen = servlen;
452  arg.flags = flags;
453  ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0);
454  return ret;
455 #endif
456 }
457 
458 static void
459 make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
460 {
461  int error;
462 
463  error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST);
464  if (error) {
465  rsock_raise_socket_error("getnameinfo", error);
466  }
467 }
468 
469 VALUE
470 rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
471 {
472  char hbuf[1024];
473 
474  make_ipaddr0(addr, addrlen, hbuf, sizeof(hbuf));
475  return rb_str_new2(hbuf);
476 }
477 
478 static void
479 make_inetaddr(unsigned int host, char *buf, size_t buflen)
480 {
481  struct sockaddr_in sin;
482 
483  INIT_SOCKADDR_IN(&sin, sizeof(sin));
484  sin.sin_addr.s_addr = host;
485  make_ipaddr0((struct sockaddr*)&sin, sizeof(sin), buf, buflen);
486 }
487 
488 static int
489 str_is_number(const char *p)
490 {
491  char *ep;
492 
493  if (!p || *p == '\0')
494  return 0;
495  ep = NULL;
496  (void)STRTOUL(p, &ep, 10);
497  if (ep && *ep == '\0')
498  return 1;
499  else
500  return 0;
501 }
502 
503 #define str_equal(ptr, len, name) \
504  ((ptr)[0] == name[0] && \
505  rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0)
506 
507 static char*
508 host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
509 {
510  if (NIL_P(host)) {
511  return NULL;
512  }
513  else if (rb_obj_is_kind_of(host, rb_cInteger)) {
514  unsigned int i = NUM2UINT(host);
515 
516  make_inetaddr(htonl(i), hbuf, hbuflen);
517  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
518  return hbuf;
519  }
520  else {
521  const char *name;
522  size_t len;
523 
524  StringValueCStr(host);
525  RSTRING_GETMEM(host, name, len);
526  if (!len || str_equal(name, len, "<any>")) {
527  make_inetaddr(INADDR_ANY, hbuf, hbuflen);
528  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
529  }
530  else if (str_equal(name, len, "<broadcast>")) {
531  make_inetaddr(INADDR_BROADCAST, hbuf, hbuflen);
532  if (flags_ptr) *flags_ptr |= AI_NUMERICHOST;
533  }
534  else if (len >= hbuflen) {
535  rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")",
536  len);
537  }
538  else {
539  memcpy(hbuf, name, len);
540  hbuf[len] = '\0';
541  }
542  return hbuf;
543  }
544 }
545 
546 static char*
547 port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
548 {
549  if (NIL_P(port)) {
550  return 0;
551  }
552  else if (FIXNUM_P(port)) {
553  snprintf(pbuf, pbuflen, "%ld", FIX2LONG(port));
554 #ifdef AI_NUMERICSERV
555  if (flags_ptr) *flags_ptr |= AI_NUMERICSERV;
556 #endif
557  return pbuf;
558  }
559  else {
560  const char *serv;
561  size_t len;
562 
563  StringValueCStr(port);
564  RSTRING_GETMEM(port, serv, len);
565  if (len >= pbuflen) {
566  rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")",
567  len);
568  }
569  memcpy(pbuf, serv, len);
570  pbuf[len] = '\0';
571  return pbuf;
572  }
573 }
574 
575 struct rb_addrinfo*
576 rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
577 {
578  struct rb_addrinfo* res = NULL;
579  char *hostp, *portp;
580  int error;
581  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
582  int additional_flags = 0;
583 
584  hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
585  portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
586 
587  if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
588  hints->ai_socktype = SOCK_DGRAM;
589  }
590  hints->ai_flags |= additional_flags;
591 
592  error = rb_getaddrinfo(hostp, portp, hints, &res);
593  if (error) {
594  if (hostp && hostp[strlen(hostp)-1] == '\n') {
595  rb_raise(rb_eSocket, "newline at the end of hostname");
596  }
597  rsock_raise_socket_error("getaddrinfo", error);
598  }
599 
600  return res;
601 }
602 
603 #ifdef HAVE_GETADDRINFO_A
604 static struct rb_addrinfo*
605 rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout)
606 {
607  struct rb_addrinfo* res = NULL;
608  char *hostp, *portp;
609  int error;
610  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
611  int additional_flags = 0;
612 
613  hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
614  portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
615 
616  if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
617  hints->ai_socktype = SOCK_DGRAM;
618  }
619  hints->ai_flags |= additional_flags;
620 
621  if (NIL_P(timeout)) {
622  error = rb_getaddrinfo(hostp, portp, hints, &res);
623  } else {
624  struct timespec _timeout = rb_time_timespec_interval(timeout);
625  error = rb_getaddrinfo_a(hostp, portp, hints, &res, &_timeout);
626  }
627 
628  if (error) {
629  if (hostp && hostp[strlen(hostp)-1] == '\n') {
630  rb_raise(rb_eSocket, "newline at the end of hostname");
631  }
632  rsock_raise_socket_error("getaddrinfo_a", error);
633  }
634 
635  return res;
636 }
637 #endif
638 
639 int
641 {
642  struct sockaddr sa = { 0 };
643  socklen_t sa_len = sizeof(sa);
644 
645  if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 ||
646  (size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) {
647  return AF_UNSPEC;
648  }
649  return sa.sa_family;
650 }
651 
652 struct rb_addrinfo*
653 rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
654 {
655  struct addrinfo hints;
656 
657  MEMZERO(&hints, struct addrinfo, 1);
658  hints.ai_family = family;
659  hints.ai_socktype = socktype;
660  hints.ai_flags = flags;
661  return rsock_getaddrinfo(host, port, &hints, 1);
662 }
663 
664 VALUE
665 rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
666 {
667  VALUE family, port, addr1, addr2;
668  VALUE ary;
669  int error;
670  char hbuf[1024], pbuf[1024];
671  ID id;
672 
673  id = rsock_intern_family(sockaddr->sa_family);
674  if (id) {
675  family = rb_str_dup(rb_id2str(id));
676  }
677  else {
678  sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
679  family = rb_str_new2(pbuf);
680  }
681 
682  addr1 = Qnil;
683  if (!norevlookup) {
684  error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
685  NULL, 0, 0);
686  if (! error) {
687  addr1 = rb_str_new2(hbuf);
688  }
689  }
690  error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
691  pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
692  if (error) {
693  rsock_raise_socket_error("getnameinfo", error);
694  }
695  addr2 = rb_str_new2(hbuf);
696  if (addr1 == Qnil) {
697  addr1 = addr2;
698  }
699  port = INT2FIX(atoi(pbuf));
700  ary = rb_ary_new3(4, family, port, addr1, addr2);
701 
702  return ary;
703 }
704 
705 #ifdef HAVE_SYS_UN_H
706 static long
707 unixsocket_len(const struct sockaddr_un *su, socklen_t socklen)
708 {
709  const char *s = su->sun_path, *e = (const char*)su + socklen;
710  while (s < e && *(e-1) == '\0')
711  e--;
712  return e - s;
713 }
714 
715 VALUE
716 rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len)
717 {
718  long n = unixsocket_len(sockaddr, len);
719  if (n >= 0)
720  return rb_str_new(sockaddr->sun_path, n);
721  else
722  return rb_str_new2("");
723 }
724 
725 VALUE
726 rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len)
727 {
728  return rb_assoc_new(rb_str_new2("AF_UNIX"),
729  rsock_unixpath_str(sockaddr, len));
730 }
731 
732 socklen_t
733 rsock_unix_sockaddr_len(VALUE path)
734 {
735 #ifdef __linux__
736  if (RSTRING_LEN(path) == 0) {
737  /* autobind; see unix(7) for details. */
738  return (socklen_t) sizeof(sa_family_t);
739  }
740  else if (RSTRING_PTR(path)[0] == '\0') {
741  /* abstract namespace; see unix(7) for details. */
742  if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path))
743  rb_raise(rb_eArgError, "Linux abstract socket too long");
744  return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
746  }
747  else {
748 #endif
749  return (socklen_t) sizeof(struct sockaddr_un);
750 #ifdef __linux__
751  }
752 #endif
753 }
754 #endif
755 
756 struct hostent_arg {
758  struct rb_addrinfo* addr;
759  VALUE (*ipaddr)(struct sockaddr*, socklen_t);
760 };
761 
762 static VALUE
763 make_hostent_internal(VALUE v)
764 {
765  struct hostent_arg *arg = (void *)v;
766  VALUE host = arg->host;
767  struct addrinfo* addr = arg->addr->ai;
768  VALUE (*ipaddr)(struct sockaddr*, socklen_t) = arg->ipaddr;
769 
770  struct addrinfo *ai;
771  struct hostent *h;
772  VALUE ary, names;
773  char **pch;
774  const char* hostp;
775  char hbuf[NI_MAXHOST];
776 
777  ary = rb_ary_new();
778  if (addr->ai_canonname) {
779  hostp = addr->ai_canonname;
780  }
781  else {
782  hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
783  }
784  rb_ary_push(ary, rb_str_new2(hostp));
785 
786  if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST &&
787  (h = gethostbyname(addr->ai_canonname))) {
788  names = rb_ary_new();
789  if (h->h_aliases != NULL) {
790  for (pch = h->h_aliases; *pch; pch++) {
791  rb_ary_push(names, rb_str_new2(*pch));
792  }
793  }
794  }
795  else {
796  names = rb_ary_new2(0);
797  }
798  rb_ary_push(ary, names);
799  rb_ary_push(ary, INT2NUM(addr->ai_family));
800  for (ai = addr; ai; ai = ai->ai_next) {
801  rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
802  }
803 
804  return ary;
805 }
806 
807 VALUE
809 {
810  struct rb_addrinfo *addr = (struct rb_addrinfo *)arg;
811  rb_freeaddrinfo(addr);
812  return Qnil;
813 }
814 
815 VALUE
816 rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t))
817 {
818  struct hostent_arg arg;
819 
820  arg.host = host;
821  arg.addr = addr;
822  arg.ipaddr = ipaddr;
823  return rb_ensure(make_hostent_internal, (VALUE)&arg,
825 }
826 
827 typedef struct {
830  int pfamily;
831  int socktype;
832  int protocol;
835 } rb_addrinfo_t;
836 
837 static void
838 addrinfo_mark(void *ptr)
839 {
840  rb_addrinfo_t *rai = ptr;
841  rb_gc_mark(rai->inspectname);
842  rb_gc_mark(rai->canonname);
843 }
844 
845 #define addrinfo_free RUBY_TYPED_DEFAULT_FREE
846 
847 static size_t
848 addrinfo_memsize(const void *ptr)
849 {
850  return sizeof(rb_addrinfo_t);
851 }
852 
853 static const rb_data_type_t addrinfo_type = {
854  "socket/addrinfo",
855  {addrinfo_mark, addrinfo_free, addrinfo_memsize,},
856 };
857 
858 static VALUE
859 addrinfo_s_allocate(VALUE klass)
860 {
861  return TypedData_Wrap_Struct(klass, &addrinfo_type, 0);
862 }
863 
864 #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
865 static inline rb_addrinfo_t *
866 check_addrinfo(VALUE self)
867 {
868  return rb_check_typeddata(self, &addrinfo_type);
869 }
870 
871 static rb_addrinfo_t *
872 get_addrinfo(VALUE self)
873 {
874  rb_addrinfo_t *rai = check_addrinfo(self);
875 
876  if (!rai) {
877  rb_raise(rb_eTypeError, "uninitialized socket address");
878  }
879  return rai;
880 }
881 
882 
883 static rb_addrinfo_t *
884 alloc_addrinfo(void)
885 {
887  rai->inspectname = Qnil;
888  rai->canonname = Qnil;
889  return rai;
890 }
891 
892 static void
893 init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
894  int pfamily, int socktype, int protocol,
895  VALUE canonname, VALUE inspectname)
896 {
897  if ((socklen_t)sizeof(rai->addr) < len)
898  rb_raise(rb_eArgError, "sockaddr string too big");
899  memcpy((void *)&rai->addr, (void *)sa, len);
900  rai->sockaddr_len = len;
901 
902  rai->pfamily = pfamily;
903  rai->socktype = socktype;
904  rai->protocol = protocol;
905  rai->canonname = canonname;
906  rai->inspectname = inspectname;
907 }
908 
909 VALUE
910 rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
911  int family, int socktype, int protocol,
912  VALUE canonname, VALUE inspectname)
913 {
914  VALUE a;
915  rb_addrinfo_t *rai;
916 
917  a = addrinfo_s_allocate(rb_cAddrinfo);
918  DATA_PTR(a) = rai = alloc_addrinfo();
919  init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
920  return a;
921 }
922 
923 static struct rb_addrinfo *
924 call_getaddrinfo(VALUE node, VALUE service,
925  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
926  int socktype_hack, VALUE timeout)
927 {
928  struct addrinfo hints;
929  struct rb_addrinfo *res;
930 
931  MEMZERO(&hints, struct addrinfo, 1);
932  hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
933 
934  if (!NIL_P(socktype)) {
935  hints.ai_socktype = rsock_socktype_arg(socktype);
936  }
937  if (!NIL_P(protocol)) {
938  hints.ai_protocol = NUM2INT(protocol);
939  }
940  if (!NIL_P(flags)) {
941  hints.ai_flags = NUM2INT(flags);
942  }
943 
944 #ifdef HAVE_GETADDRINFO_A
945  if (NIL_P(timeout)) {
946  res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
947  } else {
948  res = rsock_getaddrinfo_a(node, service, &hints, socktype_hack, timeout);
949  }
950 #else
951  res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
952 #endif
953 
954  if (res == NULL)
955  rb_raise(rb_eSocket, "host not found");
956  return res;
957 }
958 
959 static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
960 
961 static void
962 init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service,
963  VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
964  VALUE inspectnode, VALUE inspectservice)
965 {
966  struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1, Qnil);
967  VALUE canonname;
968  VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res->ai);
969 
970  canonname = Qnil;
971  if (res->ai->ai_canonname) {
972  canonname = rb_str_new_cstr(res->ai->ai_canonname);
973  OBJ_FREEZE(canonname);
974  }
975 
976  init_addrinfo(rai, res->ai->ai_addr, res->ai->ai_addrlen,
977  NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
978  canonname, inspectname);
979 
980  rb_freeaddrinfo(res);
981 }
982 
983 static VALUE
984 make_inspectname(VALUE node, VALUE service, struct addrinfo *res)
985 {
986  VALUE inspectname = Qnil;
987 
988  if (res) {
989  /* drop redundant information which also shown in address:port part. */
990  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
991  int ret;
992  ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
993  sizeof(hbuf), pbuf, sizeof(pbuf),
995  if (ret == 0) {
996  if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0)
997  node = Qnil;
998  if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0)
999  service = Qnil;
1000  else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service))
1001  service = Qnil;
1002  }
1003  }
1004 
1005  if (RB_TYPE_P(node, T_STRING)) {
1006  inspectname = rb_str_dup(node);
1007  }
1008  if (RB_TYPE_P(service, T_STRING)) {
1009  if (NIL_P(inspectname))
1010  inspectname = rb_sprintf(":%s", StringValueCStr(service));
1011  else
1012  rb_str_catf(inspectname, ":%s", StringValueCStr(service));
1013  }
1014  else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0)
1015  {
1016  if (NIL_P(inspectname))
1017  inspectname = rb_sprintf(":%d", FIX2INT(service));
1018  else
1019  rb_str_catf(inspectname, ":%d", FIX2INT(service));
1020  }
1021  if (!NIL_P(inspectname)) {
1022  OBJ_FREEZE(inspectname);
1023  }
1024  return inspectname;
1025 }
1026 
1027 static VALUE
1028 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags)
1029 {
1030  VALUE ret;
1031  VALUE canonname;
1032  VALUE inspectname;
1033 
1034  struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, Qnil);
1035 
1036  inspectname = make_inspectname(node, service, res->ai);
1037 
1038  canonname = Qnil;
1039  if (res->ai->ai_canonname) {
1040  canonname = rb_str_new_cstr(res->ai->ai_canonname);
1041  OBJ_FREEZE(canonname);
1042  }
1043 
1044  ret = rsock_addrinfo_new(res->ai->ai_addr, res->ai->ai_addrlen,
1045  res->ai->ai_family, res->ai->ai_socktype,
1046  res->ai->ai_protocol,
1047  canonname, inspectname);
1048 
1049  rb_freeaddrinfo(res);
1050  return ret;
1051 }
1052 
1053 static VALUE
1054 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE timeout)
1055 {
1056  VALUE ret;
1057  struct addrinfo *r;
1058  VALUE inspectname;
1059 
1060  struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, timeout);
1061 
1062  inspectname = make_inspectname(node, service, res->ai);
1063 
1064  ret = rb_ary_new();
1065  for (r = res->ai; r; r = r->ai_next) {
1066  VALUE addr;
1067  VALUE canonname = Qnil;
1068 
1069  if (r->ai_canonname) {
1070  canonname = rb_str_new_cstr(r->ai_canonname);
1071  OBJ_FREEZE(canonname);
1072  }
1073 
1074  addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen,
1075  r->ai_family, r->ai_socktype, r->ai_protocol,
1076  canonname, inspectname);
1077 
1078  rb_ary_push(ret, addr);
1079  }
1080 
1081  rb_freeaddrinfo(res);
1082  return ret;
1083 }
1084 
1085 
1086 #ifdef HAVE_SYS_UN_H
1087 static void
1088 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
1089 {
1090  struct sockaddr_un un;
1091  socklen_t len;
1092 
1093  StringValue(path);
1094 
1095  if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path))
1097  "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1098  (size_t)RSTRING_LEN(path), sizeof(un.sun_path));
1099 
1100  INIT_SOCKADDR_UN(&un, sizeof(struct sockaddr_un));
1101  memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
1102 
1103  len = rsock_unix_sockaddr_len(path);
1104  init_addrinfo(rai, (struct sockaddr *)&un, len,
1105  PF_UNIX, socktype, 0, Qnil, Qnil);
1106 }
1107 
1108 static long
1109 rai_unixsocket_len(const rb_addrinfo_t *rai)
1110 {
1111  return unixsocket_len(&rai->addr.un, rai->sockaddr_len);
1112 }
1113 #endif
1114 
1115 /*
1116  * call-seq:
1117  * Addrinfo.new(sockaddr) => addrinfo
1118  * Addrinfo.new(sockaddr, family) => addrinfo
1119  * Addrinfo.new(sockaddr, family, socktype) => addrinfo
1120  * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo
1121  *
1122  * returns a new instance of Addrinfo.
1123  * The instance contains sockaddr, family, socktype, protocol.
1124  * sockaddr means struct sockaddr which can be used for connect(2), etc.
1125  * family, socktype and protocol are integers which is used for arguments of socket(2).
1126  *
1127  * sockaddr is specified as an array or a string.
1128  * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr.
1129  * The string should be struct sockaddr as generated by
1130  * Socket.sockaddr_in or Socket.unpack_sockaddr_un.
1131  *
1132  * sockaddr examples:
1133  * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
1134  * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
1135  * - ["AF_UNIX", "/tmp/sock"]
1136  * - Socket.sockaddr_in("smtp", "2001:DB8::1")
1137  * - Socket.sockaddr_in(80, "172.18.22.42")
1138  * - Socket.sockaddr_in(80, "www.ruby-lang.org")
1139  * - Socket.sockaddr_un("/tmp/sock")
1140  *
1141  * In an AF_INET/AF_INET6 sockaddr array, the 4th element,
1142  * numeric IP address, is used to construct socket address in the Addrinfo instance.
1143  * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect.
1144  *
1145  * family is specified as an integer to specify the protocol family such as Socket::PF_INET.
1146  * It can be a symbol or a string which is the constant name
1147  * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc.
1148  * If omitted, PF_UNSPEC is assumed.
1149  *
1150  * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM.
1151  * It can be a symbol or a string which is the constant name
1152  * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc.
1153  * If omitted, 0 is assumed.
1154  *
1155  * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP.
1156  * It must be an integer, unlike family and socktype.
1157  * If omitted, 0 is assumed.
1158  * Note that 0 is reasonable value for most protocols, except raw socket.
1159  *
1160  */
1161 static VALUE
1162 addrinfo_initialize(int argc, VALUE *argv, VALUE self)
1163 {
1164  rb_addrinfo_t *rai;
1165  VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol;
1166  int i_pfamily, i_socktype, i_protocol;
1167  struct sockaddr *sockaddr_ptr;
1168  socklen_t sockaddr_len;
1169  VALUE canonname = Qnil, inspectname = Qnil;
1170 
1171  if (check_addrinfo(self))
1172  rb_raise(rb_eTypeError, "already initialized socket address");
1173  DATA_PTR(self) = rai = alloc_addrinfo();
1174 
1175  rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol);
1176 
1177  i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily);
1178  i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype);
1179  i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol);
1180 
1181  sockaddr_ary = rb_check_array_type(sockaddr_arg);
1182  if (!NIL_P(sockaddr_ary)) {
1183  VALUE afamily = rb_ary_entry(sockaddr_ary, 0);
1184  int af;
1185  StringValue(afamily);
1186  if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
1187  rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
1188  switch (af) {
1189  case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
1190 #ifdef INET6
1191  case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */
1192 #endif
1193  {
1194  VALUE service = rb_ary_entry(sockaddr_ary, 1);
1195  VALUE nodename = rb_ary_entry(sockaddr_ary, 2);
1196  VALUE numericnode = rb_ary_entry(sockaddr_ary, 3);
1197  int flags;
1198 
1199  service = INT2NUM(NUM2INT(service));
1200  if (!NIL_P(nodename))
1201  StringValue(nodename);
1202  StringValue(numericnode);
1203  flags = AI_NUMERICHOST;
1204 #ifdef AI_NUMERICSERV
1205  flags |= AI_NUMERICSERV;
1206 #endif
1207 
1208  init_addrinfo_getaddrinfo(rai, numericnode, service,
1209  INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
1210  INT2NUM(flags),
1211  nodename, service);
1212  break;
1213  }
1214 
1215 #ifdef HAVE_SYS_UN_H
1216  case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
1217  {
1218  VALUE path = rb_ary_entry(sockaddr_ary, 1);
1219  StringValue(path);
1220  init_unix_addrinfo(rai, path, SOCK_STREAM);
1221  break;
1222  }
1223 #endif
1224 
1225  default:
1226  rb_raise(rb_eSocket, "unexpected address family");
1227  }
1228  }
1229  else {
1230  StringValue(sockaddr_arg);
1231  sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
1232  sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg);
1233  init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
1234  i_pfamily, i_socktype, i_protocol,
1235  canonname, inspectname);
1236  }
1237 
1238  return self;
1239 }
1240 
1241 static int
1242 get_afamily(const struct sockaddr *addr, socklen_t len)
1243 {
1244  if ((socklen_t)((const char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len)
1245  return addr->sa_family;
1246  else
1247  return AF_UNSPEC;
1248 }
1249 
1250 static int
1251 ai_get_afamily(const rb_addrinfo_t *rai)
1252 {
1253  return get_afamily(&rai->addr.addr, rai->sockaddr_len);
1254 }
1255 
1256 static VALUE
1257 inspect_sockaddr(VALUE addrinfo, VALUE ret)
1258 {
1259  rb_addrinfo_t *rai = get_addrinfo(addrinfo);
1260  union_sockaddr *sockaddr = &rai->addr;
1261  socklen_t socklen = rai->sockaddr_len;
1262  return rsock_inspect_sockaddr((struct sockaddr *)sockaddr, socklen, ret);
1263 }
1264 
1265 VALUE
1266 rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
1267 {
1268  union_sockaddr *sockaddr = (union_sockaddr *)sockaddr_arg;
1269  if (socklen == 0) {
1270  rb_str_cat2(ret, "empty-sockaddr");
1271  }
1272  else if ((long)socklen < ((char*)&sockaddr->addr.sa_family + sizeof(sockaddr->addr.sa_family)) - (char*)sockaddr)
1273  rb_str_cat2(ret, "too-short-sockaddr");
1274  else {
1275  switch (sockaddr->addr.sa_family) {
1276  case AF_UNSPEC:
1277  {
1278  rb_str_cat2(ret, "UNSPEC");
1279  break;
1280  }
1281 
1282  case AF_INET:
1283  {
1284  struct sockaddr_in *addr;
1285  int port;
1286  addr = &sockaddr->in;
1287  if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
1288  rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
1289  else
1290  rb_str_cat2(ret, "?");
1291  if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
1292  rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
1293  else
1294  rb_str_cat2(ret, ".?");
1295  if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
1296  rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
1297  else
1298  rb_str_cat2(ret, ".?");
1299  if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
1300  rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
1301  else
1302  rb_str_cat2(ret, ".?");
1303 
1304  if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
1305  port = ntohs(addr->sin_port);
1306  if (port)
1307  rb_str_catf(ret, ":%d", port);
1308  }
1309  else {
1310  rb_str_cat2(ret, ":?");
1311  }
1312  if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
1313  rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
1314  (int)socklen,
1315  (int)sizeof(struct sockaddr_in));
1316  break;
1317  }
1318 
1319 #ifdef AF_INET6
1320  case AF_INET6:
1321  {
1322  struct sockaddr_in6 *addr;
1323  char hbuf[1024];
1324  int port;
1325  int error;
1326  if (socklen < (socklen_t)sizeof(struct sockaddr_in6)) {
1327  rb_str_catf(ret, "too-short-AF_INET6-sockaddr %d bytes", (int)socklen);
1328  }
1329  else {
1330  addr = &sockaddr->in6;
1331  /* use getnameinfo for scope_id.
1332  * RFC 4007: IPv6 Scoped Address Architecture
1333  * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API
1334  */
1335  error = getnameinfo(&sockaddr->addr, socklen,
1336  hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1338  if (error) {
1339  rsock_raise_socket_error("getnameinfo", error);
1340  }
1341  if (addr->sin6_port == 0) {
1342  rb_str_cat2(ret, hbuf);
1343  }
1344  else {
1345  port = ntohs(addr->sin6_port);
1346  rb_str_catf(ret, "[%s]:%d", hbuf, port);
1347  }
1348  if ((socklen_t)sizeof(struct sockaddr_in6) < socklen)
1349  rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(socklen - sizeof(struct sockaddr_in6)));
1350  }
1351  break;
1352  }
1353 #endif
1354 
1355 #ifdef HAVE_SYS_UN_H
1356  case AF_UNIX:
1357  {
1358  struct sockaddr_un *addr = &sockaddr->un;
1359  char *p, *s, *e;
1360  long len = unixsocket_len(addr, socklen);
1361  s = addr->sun_path;
1362  if (len < 0)
1363  rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr");
1364  else if (len == 0)
1365  rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr");
1366  else {
1367  int printable_only = 1;
1368  e = s + len;
1369  p = s;
1370  while (p < e) {
1371  printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p);
1372  p++;
1373  }
1374  if (printable_only) { /* only printable, no space */
1375  if (s[0] != '/') /* relative path */
1376  rb_str_cat2(ret, "UNIX ");
1377  rb_str_cat(ret, s, p - s);
1378  }
1379  else {
1380  rb_str_cat2(ret, "UNIX");
1381  while (s < e)
1382  rb_str_catf(ret, ":%02x", (unsigned char)*s++);
1383  }
1384  }
1385  break;
1386  }
1387 #endif
1388 
1389 #if defined(AF_PACKET) && defined(__linux__)
1390  /* GNU/Linux */
1391  case AF_PACKET:
1392  {
1393  struct sockaddr_ll *addr;
1394  const char *sep = "[";
1395 #define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
1396 
1397  addr = (struct sockaddr_ll *)sockaddr;
1398 
1399  rb_str_cat2(ret, "PACKET");
1400 
1401  if (offsetof(struct sockaddr_ll, sll_protocol) + sizeof(addr->sll_protocol) <= (size_t)socklen) {
1402  CATSEP;
1403  rb_str_catf(ret, "protocol=%d", ntohs(addr->sll_protocol));
1404  }
1405  if (offsetof(struct sockaddr_ll, sll_ifindex) + sizeof(addr->sll_ifindex) <= (size_t)socklen) {
1406  char buf[IFNAMSIZ];
1407  CATSEP;
1408  if (if_indextoname(addr->sll_ifindex, buf) == NULL)
1409  rb_str_catf(ret, "ifindex=%d", addr->sll_ifindex);
1410  else
1411  rb_str_catf(ret, "%s", buf);
1412  }
1413  if (offsetof(struct sockaddr_ll, sll_hatype) + sizeof(addr->sll_hatype) <= (size_t)socklen) {
1414  CATSEP;
1415  rb_str_catf(ret, "hatype=%d", addr->sll_hatype);
1416  }
1417  if (offsetof(struct sockaddr_ll, sll_pkttype) + sizeof(addr->sll_pkttype) <= (size_t)socklen) {
1418  CATSEP;
1419  if (addr->sll_pkttype == PACKET_HOST)
1420  rb_str_cat2(ret, "HOST");
1421  else if (addr->sll_pkttype == PACKET_BROADCAST)
1422  rb_str_cat2(ret, "BROADCAST");
1423  else if (addr->sll_pkttype == PACKET_MULTICAST)
1424  rb_str_cat2(ret, "MULTICAST");
1425  else if (addr->sll_pkttype == PACKET_OTHERHOST)
1426  rb_str_cat2(ret, "OTHERHOST");
1427  else if (addr->sll_pkttype == PACKET_OUTGOING)
1428  rb_str_cat2(ret, "OUTGOING");
1429  else
1430  rb_str_catf(ret, "pkttype=%d", addr->sll_pkttype);
1431  }
1432  if (socklen != (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen)) {
1433  CATSEP;
1434  if (offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen) <= (size_t)socklen) {
1435  rb_str_catf(ret, "halen=%d", addr->sll_halen);
1436  }
1437  }
1438  if (offsetof(struct sockaddr_ll, sll_addr) < (size_t)socklen) {
1439  socklen_t len, i;
1440  CATSEP;
1441  rb_str_cat2(ret, "hwaddr");
1442  len = addr->sll_halen;
1443  if ((size_t)socklen < offsetof(struct sockaddr_ll, sll_addr) + len)
1444  len = socklen - offsetof(struct sockaddr_ll, sll_addr);
1445  for (i = 0; i < len; i++) {
1446  rb_str_cat2(ret, i == 0 ? "=" : ":");
1447  rb_str_catf(ret, "%02x", addr->sll_addr[i]);
1448  }
1449  }
1450 
1451  if (socklen < (socklen_t)(offsetof(struct sockaddr_ll, sll_halen) + sizeof(addr->sll_halen)) ||
1452  (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + addr->sll_halen) != socklen) {
1453  CATSEP;
1454  rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_ll)",
1455  (int)socklen, (int)sizeof(struct sockaddr_ll));
1456  }
1457 
1458  rb_str_cat2(ret, "]");
1459 #undef CATSEP
1460 
1461  break;
1462  }
1463 #endif
1464 
1465 #if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL)
1466  /* AF_LINK is defined in 4.4BSD derivations since Net2.
1467  link_ntoa is also defined at Net2.
1468  However Debian GNU/kFreeBSD defines AF_LINK but
1469  don't have link_ntoa. */
1470  case AF_LINK:
1471  {
1472  /*
1473  * Simple implementation using link_ntoa():
1474  * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
1475  * Also, the format is bit different.
1476  *
1477  * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
1478  * break;
1479  */
1480  struct sockaddr_dl *addr = &sockaddr->dl;
1481  char *np = NULL, *ap = NULL, *endp;
1482  int nlen = 0, alen = 0;
1483  int i, off;
1484  const char *sep = "[";
1485 #define CATSEP do { rb_str_cat2(ret, sep); sep = " "; } while (0);
1486 
1487  rb_str_cat2(ret, "LINK");
1488 
1489  endp = ((char *)addr) + socklen;
1490 
1491  if (offsetof(struct sockaddr_dl, sdl_data) < socklen) {
1492  np = addr->sdl_data;
1493  nlen = addr->sdl_nlen;
1494  if (endp - np < nlen)
1495  nlen = (int)(endp - np);
1496  }
1497  off = addr->sdl_nlen;
1498 
1499  if (offsetof(struct sockaddr_dl, sdl_data) + off < socklen) {
1500  ap = addr->sdl_data + off;
1501  alen = addr->sdl_alen;
1502  if (endp - ap < alen)
1503  alen = (int)(endp - ap);
1504  }
1505 
1506  CATSEP;
1507  if (np)
1508  rb_str_catf(ret, "%.*s", nlen, np);
1509  else
1510  rb_str_cat2(ret, "?");
1511 
1512  if (ap && 0 < alen) {
1513  CATSEP;
1514  for (i = 0; i < alen; i++)
1515  rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]);
1516  }
1517 
1518  if (socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_nlen) + sizeof(addr->sdl_nlen)) ||
1519  socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_alen) + sizeof(addr->sdl_alen)) ||
1520  socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_slen) + sizeof(addr->sdl_slen)) ||
1521  /* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field.
1522  * cf. Net2:/usr/src/sys/net/if_dl.h. */
1523  socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) {
1524  CATSEP;
1525  rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)",
1526  (int)socklen, (int)sizeof(struct sockaddr_dl));
1527  }
1528 
1529  rb_str_cat2(ret, "]");
1530 #undef CATSEP
1531  break;
1532  }
1533 #endif
1534 
1535  default:
1536  {
1537  ID id = rsock_intern_family(sockaddr->addr.sa_family);
1538  if (id == 0)
1539  rb_str_catf(ret, "unknown address family %d", sockaddr->addr.sa_family);
1540  else
1541  rb_str_catf(ret, "%s address format unknown", rb_id2name(id));
1542  break;
1543  }
1544  }
1545  }
1546 
1547  return ret;
1548 }
1549 
1550 /*
1551  * call-seq:
1552  * addrinfo.inspect => string
1553  *
1554  * returns a string which shows addrinfo in human-readable form.
1555  *
1556  * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>"
1557  * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>"
1558  *
1559  */
1560 static VALUE
1561 addrinfo_inspect(VALUE self)
1562 {
1563  rb_addrinfo_t *rai = get_addrinfo(self);
1564  int internet_p;
1565  VALUE ret;
1566 
1567  ret = rb_sprintf("#<%s: ", rb_obj_classname(self));
1568 
1569  inspect_sockaddr(self, ret);
1570 
1571  if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) {
1573  if (id)
1574  rb_str_catf(ret, " %s", rb_id2name(id));
1575  else
1576  rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily);
1577  }
1578 
1579  internet_p = rai->pfamily == PF_INET;
1580 #ifdef INET6
1581  internet_p = internet_p || rai->pfamily == PF_INET6;
1582 #endif
1583  if (internet_p && rai->socktype == SOCK_STREAM &&
1584  (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) {
1585  rb_str_cat2(ret, " TCP");
1586  }
1587  else if (internet_p && rai->socktype == SOCK_DGRAM &&
1588  (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) {
1589  rb_str_cat2(ret, " UDP");
1590  }
1591  else {
1592  if (rai->socktype) {
1593  ID id = rsock_intern_socktype(rai->socktype);
1594  if (id)
1595  rb_str_catf(ret, " %s", rb_id2name(id));
1596  else
1597  rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype);
1598  }
1599 
1600  if (rai->protocol) {
1601  if (internet_p) {
1602  ID id = rsock_intern_ipproto(rai->protocol);
1603  if (id)
1604  rb_str_catf(ret, " %s", rb_id2name(id));
1605  else
1606  goto unknown_protocol;
1607  }
1608  else {
1609  unknown_protocol:
1610  rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol);
1611  }
1612  }
1613  }
1614 
1615  if (!NIL_P(rai->canonname)) {
1616  VALUE name = rai->canonname;
1617  rb_str_catf(ret, " %s", StringValueCStr(name));
1618  }
1619 
1620  if (!NIL_P(rai->inspectname)) {
1621  VALUE name = rai->inspectname;
1622  rb_str_catf(ret, " (%s)", StringValueCStr(name));
1623  }
1624 
1625  rb_str_buf_cat2(ret, ">");
1626  return ret;
1627 }
1628 
1629 /*
1630  * call-seq:
1631  * addrinfo.inspect_sockaddr => string
1632  *
1633  * returns a string which shows the sockaddr in _addrinfo_ with human-readable form.
1634  *
1635  * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80"
1636  * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80"
1637  * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock"
1638  *
1639  */
1640 VALUE
1642 {
1643  return inspect_sockaddr(self, rb_str_new("", 0));
1644 }
1645 
1646 /* :nodoc: */
1647 static VALUE
1648 addrinfo_mdump(VALUE self)
1649 {
1650  rb_addrinfo_t *rai = get_addrinfo(self);
1651  VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname;
1652  int afamily_int = ai_get_afamily(rai);
1653  ID id;
1654 
1656  if (id == 0)
1657  rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily);
1658  pfamily = rb_id2str(id);
1659 
1660  if (rai->socktype == 0)
1661  socktype = INT2FIX(0);
1662  else {
1663  id = rsock_intern_socktype(rai->socktype);
1664  if (id == 0)
1665  rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype);
1666  socktype = rb_id2str(id);
1667  }
1668 
1669  if (rai->protocol == 0)
1670  protocol = INT2FIX(0);
1671  else if (IS_IP_FAMILY(afamily_int)) {
1672  id = rsock_intern_ipproto(rai->protocol);
1673  if (id == 0)
1674  rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol);
1675  protocol = rb_id2str(id);
1676  }
1677  else {
1678  rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol);
1679  }
1680 
1681  canonname = rai->canonname;
1682 
1683  inspectname = rai->inspectname;
1684 
1685  id = rsock_intern_family(afamily_int);
1686  if (id == 0)
1687  rb_raise(rb_eSocket, "unknown address family: %d", afamily_int);
1688  afamily = rb_id2str(id);
1689 
1690  switch(afamily_int) {
1691 #ifdef HAVE_SYS_UN_H
1692  case AF_UNIX:
1693  {
1694  sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai));
1695  break;
1696  }
1697 #endif
1698 
1699  default:
1700  {
1701  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1702  int error;
1703  error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
1704  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
1706  if (error) {
1707  rsock_raise_socket_error("getnameinfo", error);
1708  }
1709  sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
1710  break;
1711  }
1712  }
1713 
1714  return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname);
1715 }
1716 
1717 /* :nodoc: */
1718 static VALUE
1719 addrinfo_mload(VALUE self, VALUE ary)
1720 {
1721  VALUE v;
1722  VALUE canonname, inspectname;
1723  int afamily, pfamily, socktype, protocol;
1724  union_sockaddr ss;
1725  socklen_t len;
1726  rb_addrinfo_t *rai;
1727 
1728  if (check_addrinfo(self))
1729  rb_raise(rb_eTypeError, "already initialized socket address");
1730 
1731  ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1732 
1733  v = rb_ary_entry(ary, 0);
1734  StringValue(v);
1735  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1)
1736  rb_raise(rb_eTypeError, "unexpected address family");
1737 
1738  v = rb_ary_entry(ary, 2);
1739  StringValue(v);
1740  if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1)
1741  rb_raise(rb_eTypeError, "unexpected protocol family");
1742 
1743  v = rb_ary_entry(ary, 3);
1744  if (v == INT2FIX(0))
1745  socktype = 0;
1746  else {
1747  StringValue(v);
1748  if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1)
1749  rb_raise(rb_eTypeError, "unexpected socktype");
1750  }
1751 
1752  v = rb_ary_entry(ary, 4);
1753  if (v == INT2FIX(0))
1754  protocol = 0;
1755  else {
1756  StringValue(v);
1757  if (IS_IP_FAMILY(afamily)) {
1758  if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1)
1759  rb_raise(rb_eTypeError, "unexpected protocol");
1760  }
1761  else {
1762  rb_raise(rb_eTypeError, "unexpected protocol");
1763  }
1764  }
1765 
1766  v = rb_ary_entry(ary, 5);
1767  if (NIL_P(v))
1768  canonname = Qnil;
1769  else {
1770  StringValue(v);
1771  canonname = v;
1772  }
1773 
1774  v = rb_ary_entry(ary, 6);
1775  if (NIL_P(v))
1776  inspectname = Qnil;
1777  else {
1778  StringValue(v);
1779  inspectname = v;
1780  }
1781 
1782  v = rb_ary_entry(ary, 1);
1783  switch(afamily) {
1784 #ifdef HAVE_SYS_UN_H
1785  case AF_UNIX:
1786  {
1787  struct sockaddr_un uaddr;
1788  INIT_SOCKADDR_UN(&uaddr, sizeof(struct sockaddr_un));
1789 
1790  StringValue(v);
1791  if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v))
1793  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
1794  (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path));
1795  memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v));
1796  len = (socklen_t)sizeof(uaddr);
1797  memcpy(&ss, &uaddr, len);
1798  break;
1799  }
1800 #endif
1801 
1802  default:
1803  {
1804  VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
1805  struct rb_addrinfo *res;
1806  int flags = AI_NUMERICHOST;
1807 #ifdef AI_NUMERICSERV
1808  flags |= AI_NUMERICSERV;
1809 #endif
1810  res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1),
1811  INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol),
1812  INT2NUM(flags), 1, Qnil);
1813 
1814  len = res->ai->ai_addrlen;
1815  memcpy(&ss, res->ai->ai_addr, res->ai->ai_addrlen);
1816  rb_freeaddrinfo(res);
1817  break;
1818  }
1819  }
1820 
1821  DATA_PTR(self) = rai = alloc_addrinfo();
1822  init_addrinfo(rai, &ss.addr, len,
1823  pfamily, socktype, protocol,
1824  canonname, inspectname);
1825  return self;
1826 }
1827 
1828 /*
1829  * call-seq:
1830  * addrinfo.afamily => integer
1831  *
1832  * returns the address family as an integer.
1833  *
1834  * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true
1835  *
1836  */
1837 static VALUE
1838 addrinfo_afamily(VALUE self)
1839 {
1840  rb_addrinfo_t *rai = get_addrinfo(self);
1841  return INT2NUM(ai_get_afamily(rai));
1842 }
1843 
1844 /*
1845  * call-seq:
1846  * addrinfo.pfamily => integer
1847  *
1848  * returns the protocol family as an integer.
1849  *
1850  * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true
1851  *
1852  */
1853 static VALUE
1854 addrinfo_pfamily(VALUE self)
1855 {
1856  rb_addrinfo_t *rai = get_addrinfo(self);
1857  return INT2NUM(rai->pfamily);
1858 }
1859 
1860 /*
1861  * call-seq:
1862  * addrinfo.socktype => integer
1863  *
1864  * returns the socket type as an integer.
1865  *
1866  * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true
1867  *
1868  */
1869 static VALUE
1870 addrinfo_socktype(VALUE self)
1871 {
1872  rb_addrinfo_t *rai = get_addrinfo(self);
1873  return INT2NUM(rai->socktype);
1874 }
1875 
1876 /*
1877  * call-seq:
1878  * addrinfo.protocol => integer
1879  *
1880  * returns the socket type as an integer.
1881  *
1882  * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true
1883  *
1884  */
1885 static VALUE
1886 addrinfo_protocol(VALUE self)
1887 {
1888  rb_addrinfo_t *rai = get_addrinfo(self);
1889  return INT2NUM(rai->protocol);
1890 }
1891 
1892 /*
1893  * call-seq:
1894  * addrinfo.to_sockaddr => string
1895  * addrinfo.to_s => string
1896  *
1897  * returns the socket address as packed struct sockaddr string.
1898  *
1899  * Addrinfo.tcp("localhost", 80).to_sockaddr
1900  * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
1901  *
1902  */
1903 static VALUE
1904 addrinfo_to_sockaddr(VALUE self)
1905 {
1906  rb_addrinfo_t *rai = get_addrinfo(self);
1907  VALUE ret;
1908  ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len);
1909  return ret;
1910 }
1911 
1912 /*
1913  * call-seq:
1914  * addrinfo.canonname => string or nil
1915  *
1916  * returns the canonical name as an string.
1917  *
1918  * nil is returned if no canonical name.
1919  *
1920  * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified.
1921  *
1922  * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
1923  * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)>
1924  * p list[0].canonname #=> "carbon.ruby-lang.org"
1925  *
1926  */
1927 static VALUE
1928 addrinfo_canonname(VALUE self)
1929 {
1930  rb_addrinfo_t *rai = get_addrinfo(self);
1931  return rai->canonname;
1932 }
1933 
1934 /*
1935  * call-seq:
1936  * addrinfo.ip? => true or false
1937  *
1938  * returns true if addrinfo is internet (IPv4/IPv6) address.
1939  * returns false otherwise.
1940  *
1941  * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true
1942  * Addrinfo.tcp("::1", 80).ip? #=> true
1943  * Addrinfo.unix("/tmp/sock").ip? #=> false
1944  *
1945  */
1946 static VALUE
1947 addrinfo_ip_p(VALUE self)
1948 {
1949  rb_addrinfo_t *rai = get_addrinfo(self);
1950  int family = ai_get_afamily(rai);
1951  return IS_IP_FAMILY(family) ? Qtrue : Qfalse;
1952 }
1953 
1954 /*
1955  * call-seq:
1956  * addrinfo.ipv4? => true or false
1957  *
1958  * returns true if addrinfo is IPv4 address.
1959  * returns false otherwise.
1960  *
1961  * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true
1962  * Addrinfo.tcp("::1", 80).ipv4? #=> false
1963  * Addrinfo.unix("/tmp/sock").ipv4? #=> false
1964  *
1965  */
1966 static VALUE
1967 addrinfo_ipv4_p(VALUE self)
1968 {
1969  rb_addrinfo_t *rai = get_addrinfo(self);
1970  return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse;
1971 }
1972 
1973 /*
1974  * call-seq:
1975  * addrinfo.ipv6? => true or false
1976  *
1977  * returns true if addrinfo is IPv6 address.
1978  * returns false otherwise.
1979  *
1980  * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false
1981  * Addrinfo.tcp("::1", 80).ipv6? #=> true
1982  * Addrinfo.unix("/tmp/sock").ipv6? #=> false
1983  *
1984  */
1985 static VALUE
1986 addrinfo_ipv6_p(VALUE self)
1987 {
1988 #ifdef AF_INET6
1989  rb_addrinfo_t *rai = get_addrinfo(self);
1990  return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse;
1991 #else
1992  return Qfalse;
1993 #endif
1994 }
1995 
1996 /*
1997  * call-seq:
1998  * addrinfo.unix? => true or false
1999  *
2000  * returns true if addrinfo is UNIX address.
2001  * returns false otherwise.
2002  *
2003  * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false
2004  * Addrinfo.tcp("::1", 80).unix? #=> false
2005  * Addrinfo.unix("/tmp/sock").unix? #=> true
2006  *
2007  */
2008 static VALUE
2009 addrinfo_unix_p(VALUE self)
2010 {
2011  rb_addrinfo_t *rai = get_addrinfo(self);
2012 #ifdef AF_UNIX
2013  return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse;
2014 #else
2015  return Qfalse;
2016 #endif
2017 }
2018 
2019 /*
2020  * call-seq:
2021  * addrinfo.getnameinfo => [nodename, service]
2022  * addrinfo.getnameinfo(flags) => [nodename, service]
2023  *
2024  * returns nodename and service as a pair of strings.
2025  * This converts struct sockaddr in addrinfo to textual representation.
2026  *
2027  * flags should be bitwise OR of Socket::NI_??? constants.
2028  *
2029  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"]
2030  *
2031  * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV)
2032  * #=> ["localhost", "80"]
2033  */
2034 static VALUE
2035 addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
2036 {
2037  rb_addrinfo_t *rai = get_addrinfo(self);
2038  VALUE vflags;
2039  char hbuf[1024], pbuf[1024];
2040  int flags, error;
2041 
2042  rb_scan_args(argc, argv, "01", &vflags);
2043 
2044  flags = NIL_P(vflags) ? 0 : NUM2INT(vflags);
2045 
2046  if (rai->socktype == SOCK_DGRAM)
2047  flags |= NI_DGRAM;
2048 
2049  error = getnameinfo(&rai->addr.addr, rai->sockaddr_len,
2050  hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
2051  flags);
2052  if (error) {
2053  rsock_raise_socket_error("getnameinfo", error);
2054  }
2055 
2056  return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
2057 }
2058 
2059 /*
2060  * call-seq:
2061  * addrinfo.ip_unpack => [addr, port]
2062  *
2063  * Returns the IP address and port number as 2-element array.
2064  *
2065  * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80]
2066  * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80]
2067  */
2068 static VALUE
2069 addrinfo_ip_unpack(VALUE self)
2070 {
2071  rb_addrinfo_t *rai = get_addrinfo(self);
2072  int family = ai_get_afamily(rai);
2073  VALUE vflags;
2074  VALUE ret, portstr;
2075 
2076  if (!IS_IP_FAMILY(family))
2077  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
2078 
2080  ret = addrinfo_getnameinfo(1, &vflags, self);
2081  portstr = rb_ary_entry(ret, 1);
2082  rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr))));
2083  return ret;
2084 }
2085 
2086 /*
2087  * call-seq:
2088  * addrinfo.ip_address => string
2089  *
2090  * Returns the IP address as a string.
2091  *
2092  * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1"
2093  * Addrinfo.tcp("::1", 80).ip_address #=> "::1"
2094  */
2095 static VALUE
2096 addrinfo_ip_address(VALUE self)
2097 {
2098  rb_addrinfo_t *rai = get_addrinfo(self);
2099  int family = ai_get_afamily(rai);
2100  VALUE vflags;
2101  VALUE ret;
2102 
2103  if (!IS_IP_FAMILY(family))
2104  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
2105 
2107  ret = addrinfo_getnameinfo(1, &vflags, self);
2108  return rb_ary_entry(ret, 0);
2109 }
2110 
2111 /*
2112  * call-seq:
2113  * addrinfo.ip_port => port
2114  *
2115  * Returns the port number as an integer.
2116  *
2117  * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80
2118  * Addrinfo.tcp("::1", 80).ip_port #=> 80
2119  */
2120 static VALUE
2121 addrinfo_ip_port(VALUE self)
2122 {
2123  rb_addrinfo_t *rai = get_addrinfo(self);
2124  int family = ai_get_afamily(rai);
2125  int port;
2126 
2127  if (!IS_IP_FAMILY(family)) {
2128  bad_family:
2129 #ifdef AF_INET6
2130  rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
2131 #else
2132  rb_raise(rb_eSocket, "need IPv4 address");
2133 #endif
2134  }
2135 
2136  switch (family) {
2137  case AF_INET:
2138  if (rai->sockaddr_len != sizeof(struct sockaddr_in))
2139  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4");
2140  port = ntohs(rai->addr.in.sin_port);
2141  break;
2142 
2143 #ifdef AF_INET6
2144  case AF_INET6:
2145  if (rai->sockaddr_len != sizeof(struct sockaddr_in6))
2146  rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6");
2147  port = ntohs(rai->addr.in6.sin6_port);
2148  break;
2149 #endif
2150 
2151  default:
2152  goto bad_family;
2153  }
2154 
2155  return INT2NUM(port);
2156 }
2157 
2158 static int
2159 extract_in_addr(VALUE self, uint32_t *addrp)
2160 {
2161  rb_addrinfo_t *rai = get_addrinfo(self);
2162  int family = ai_get_afamily(rai);
2163  if (family != AF_INET) return 0;
2164  *addrp = ntohl(rai->addr.in.sin_addr.s_addr);
2165  return 1;
2166 }
2167 
2168 /*
2169  * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
2170  * It returns false otherwise.
2171  */
2172 static VALUE
2173 addrinfo_ipv4_private_p(VALUE self)
2174 {
2175  uint32_t a;
2176  if (!extract_in_addr(self, &a)) return Qfalse;
2177  if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
2178  (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
2179  (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */
2180  return Qtrue;
2181  return Qfalse;
2182 }
2183 
2184 /*
2185  * Returns true for IPv4 loopback address (127.0.0.0/8).
2186  * It returns false otherwise.
2187  */
2188 static VALUE
2189 addrinfo_ipv4_loopback_p(VALUE self)
2190 {
2191  uint32_t a;
2192  if (!extract_in_addr(self, &a)) return Qfalse;
2193  if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */
2194  return Qtrue;
2195  return Qfalse;
2196 }
2197 
2198 /*
2199  * Returns true for IPv4 multicast address (224.0.0.0/4).
2200  * It returns false otherwise.
2201  */
2202 static VALUE
2203 addrinfo_ipv4_multicast_p(VALUE self)
2204 {
2205  uint32_t a;
2206  if (!extract_in_addr(self, &a)) return Qfalse;
2207  if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */
2208  return Qtrue;
2209  return Qfalse;
2210 }
2211 
2212 #ifdef INET6
2213 
2214 static struct in6_addr *
2215 extract_in6_addr(VALUE self)
2216 {
2217  rb_addrinfo_t *rai = get_addrinfo(self);
2218  int family = ai_get_afamily(rai);
2219  if (family != AF_INET6) return NULL;
2220  return &rai->addr.in6.sin6_addr;
2221 }
2222 
2223 /*
2224  * Returns true for IPv6 unspecified address (::).
2225  * It returns false otherwise.
2226  */
2227 static VALUE
2228 addrinfo_ipv6_unspecified_p(VALUE self)
2229 {
2230  struct in6_addr *addr = extract_in6_addr(self);
2231  if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue;
2232  return Qfalse;
2233 }
2234 
2235 /*
2236  * Returns true for IPv6 loopback address (::1).
2237  * It returns false otherwise.
2238  */
2239 static VALUE
2240 addrinfo_ipv6_loopback_p(VALUE self)
2241 {
2242  struct in6_addr *addr = extract_in6_addr(self);
2243  if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue;
2244  return Qfalse;
2245 }
2246 
2247 /*
2248  * Returns true for IPv6 multicast address (ff00::/8).
2249  * It returns false otherwise.
2250  */
2251 static VALUE
2252 addrinfo_ipv6_multicast_p(VALUE self)
2253 {
2254  struct in6_addr *addr = extract_in6_addr(self);
2255  if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue;
2256  return Qfalse;
2257 }
2258 
2259 /*
2260  * Returns true for IPv6 link local address (ff80::/10).
2261  * It returns false otherwise.
2262  */
2263 static VALUE
2264 addrinfo_ipv6_linklocal_p(VALUE self)
2265 {
2266  struct in6_addr *addr = extract_in6_addr(self);
2267  if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue;
2268  return Qfalse;
2269 }
2270 
2271 /*
2272  * Returns true for IPv6 site local address (ffc0::/10).
2273  * It returns false otherwise.
2274  */
2275 static VALUE
2276 addrinfo_ipv6_sitelocal_p(VALUE self)
2277 {
2278  struct in6_addr *addr = extract_in6_addr(self);
2279  if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue;
2280  return Qfalse;
2281 }
2282 
2283 /*
2284  * Returns true for IPv6 unique local address (fc00::/7, RFC4193).
2285  * It returns false otherwise.
2286  */
2287 static VALUE
2288 addrinfo_ipv6_unique_local_p(VALUE self)
2289 {
2290  struct in6_addr *addr = extract_in6_addr(self);
2291  if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue;
2292  return Qfalse;
2293 }
2294 
2295 /*
2296  * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80).
2297  * It returns false otherwise.
2298  */
2299 static VALUE
2300 addrinfo_ipv6_v4mapped_p(VALUE self)
2301 {
2302  struct in6_addr *addr = extract_in6_addr(self);
2303  if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue;
2304  return Qfalse;
2305 }
2306 
2307 /*
2308  * Returns true for IPv4-compatible IPv6 address (::/80).
2309  * It returns false otherwise.
2310  */
2311 static VALUE
2312 addrinfo_ipv6_v4compat_p(VALUE self)
2313 {
2314  struct in6_addr *addr = extract_in6_addr(self);
2315  if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue;
2316  return Qfalse;
2317 }
2318 
2319 /*
2320  * Returns true for IPv6 multicast node-local scope address.
2321  * It returns false otherwise.
2322  */
2323 static VALUE
2324 addrinfo_ipv6_mc_nodelocal_p(VALUE self)
2325 {
2326  struct in6_addr *addr = extract_in6_addr(self);
2327  if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue;
2328  return Qfalse;
2329 }
2330 
2331 /*
2332  * Returns true for IPv6 multicast link-local scope address.
2333  * It returns false otherwise.
2334  */
2335 static VALUE
2336 addrinfo_ipv6_mc_linklocal_p(VALUE self)
2337 {
2338  struct in6_addr *addr = extract_in6_addr(self);
2339  if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue;
2340  return Qfalse;
2341 }
2342 
2343 /*
2344  * Returns true for IPv6 multicast site-local scope address.
2345  * It returns false otherwise.
2346  */
2347 static VALUE
2348 addrinfo_ipv6_mc_sitelocal_p(VALUE self)
2349 {
2350  struct in6_addr *addr = extract_in6_addr(self);
2351  if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue;
2352  return Qfalse;
2353 }
2354 
2355 /*
2356  * Returns true for IPv6 multicast organization-local scope address.
2357  * It returns false otherwise.
2358  */
2359 static VALUE
2360 addrinfo_ipv6_mc_orglocal_p(VALUE self)
2361 {
2362  struct in6_addr *addr = extract_in6_addr(self);
2363  if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue;
2364  return Qfalse;
2365 }
2366 
2367 /*
2368  * Returns true for IPv6 multicast global scope address.
2369  * It returns false otherwise.
2370  */
2371 static VALUE
2372 addrinfo_ipv6_mc_global_p(VALUE self)
2373 {
2374  struct in6_addr *addr = extract_in6_addr(self);
2375  if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue;
2376  return Qfalse;
2377 }
2378 
2379 /*
2380  * Returns IPv4 address of IPv4 mapped/compatible IPv6 address.
2381  * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address.
2382  *
2383  * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
2384  * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3>
2385  * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil
2386  * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil
2387  * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil
2388  */
2389 static VALUE
2390 addrinfo_ipv6_to_ipv4(VALUE self)
2391 {
2392  rb_addrinfo_t *rai = get_addrinfo(self);
2393  struct in6_addr *addr;
2394  int family = ai_get_afamily(rai);
2395  if (family != AF_INET6) return Qnil;
2396  addr = &rai->addr.in6.sin6_addr;
2397  if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) {
2398  struct sockaddr_in sin4;
2399  INIT_SOCKADDR_IN(&sin4, sizeof(sin4));
2400  memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr));
2401  return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4),
2402  PF_INET, rai->socktype, rai->protocol,
2403  rai->canonname, rai->inspectname);
2404  }
2405  else {
2406  return Qnil;
2407  }
2408 }
2409 
2410 #endif
2411 
2412 #ifdef HAVE_SYS_UN_H
2413 /*
2414  * call-seq:
2415  * addrinfo.unix_path => path
2416  *
2417  * Returns the socket path as a string.
2418  *
2419  * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock"
2420  */
2421 static VALUE
2422 addrinfo_unix_path(VALUE self)
2423 {
2424  rb_addrinfo_t *rai = get_addrinfo(self);
2425  int family = ai_get_afamily(rai);
2426  struct sockaddr_un *addr;
2427  long n;
2428 
2429  if (family != AF_UNIX)
2430  rb_raise(rb_eSocket, "need AF_UNIX address");
2431 
2432  addr = &rai->addr.un;
2433 
2434  n = rai_unixsocket_len(rai);
2435  if (n < 0)
2436  rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.",
2437  (size_t)rai->sockaddr_len, offsetof(struct sockaddr_un, sun_path));
2438  if ((long)sizeof(addr->sun_path) < n)
2440  "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
2441  (size_t)n, sizeof(addr->sun_path));
2442  return rb_str_new(addr->sun_path, n);
2443 }
2444 #endif
2445 
2446 static ID id_timeout;
2447 
2448 /*
2449  * call-seq:
2450  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...]
2451  * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...]
2452  * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...]
2453  * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...]
2454  * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...]
2455  *
2456  * returns a list of addrinfo objects as an array.
2457  *
2458  * This method converts nodename (hostname) and service (port) to addrinfo.
2459  * Since the conversion is not unique, the result is a list of addrinfo objects.
2460  *
2461  * nodename or service can be nil if no conversion intended.
2462  *
2463  * family, socktype and protocol are hint for preferred protocol.
2464  * If the result will be used for a socket with SOCK_STREAM,
2465  * SOCK_STREAM should be specified as socktype.
2466  * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM.
2467  * If they are omitted or nil is given, the result is not restricted.
2468  *
2469  * Similarly, PF_INET6 as family restricts for IPv6.
2470  *
2471  * flags should be bitwise OR of Socket::AI_??? constants such as follows.
2472  * Note that the exact list of the constants depends on OS.
2473  *
2474  * AI_PASSIVE Get address to use with bind()
2475  * AI_CANONNAME Fill in the canonical name
2476  * AI_NUMERICHOST Prevent host name resolution
2477  * AI_NUMERICSERV Prevent service name resolution
2478  * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses
2479  * AI_ALL Allow all addresses
2480  * AI_ADDRCONFIG Accept only if any address is assigned
2481  *
2482  * Note that socktype should be specified whenever application knows the usage of the address.
2483  * Some platform causes an error when socktype is omitted and servname is specified as an integer
2484  * because some port numbers, 512 for example, are ambiguous without socktype.
2485  *
2486  * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM)
2487  * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>,
2488  * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>]
2489  *
2490  */
2491 static VALUE
2492 addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
2493 {
2494  VALUE node, service, family, socktype, protocol, flags, opts, timeout;
2495 
2496  rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
2497  &protocol, &flags, &opts);
2498  rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
2499  if (timeout == Qundef) {
2500  timeout = Qnil;
2501  }
2502 
2503  return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
2504 }
2505 
2506 /*
2507  * call-seq:
2508  * Addrinfo.ip(host) => addrinfo
2509  *
2510  * returns an addrinfo object for IP address.
2511  *
2512  * The port, socktype, protocol of the result is filled by zero.
2513  * So, it is not appropriate to create a socket.
2514  *
2515  * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)>
2516  */
2517 static VALUE
2518 addrinfo_s_ip(VALUE self, VALUE host)
2519 {
2520  VALUE ret;
2521  rb_addrinfo_t *rai;
2522  ret = addrinfo_firstonly_new(host, Qnil,
2523  INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0));
2524  rai = get_addrinfo(ret);
2525  rai->socktype = 0;
2526  rai->protocol = 0;
2527  return ret;
2528 }
2529 
2530 /*
2531  * call-seq:
2532  * Addrinfo.tcp(host, port) => addrinfo
2533  *
2534  * returns an addrinfo object for TCP address.
2535  *
2536  * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)>
2537  */
2538 static VALUE
2539 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port)
2540 {
2541  return addrinfo_firstonly_new(host, port,
2542  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0));
2543 }
2544 
2545 /*
2546  * call-seq:
2547  * Addrinfo.udp(host, port) => addrinfo
2548  *
2549  * returns an addrinfo object for UDP address.
2550  *
2551  * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)>
2552  */
2553 static VALUE
2554 addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
2555 {
2556  return addrinfo_firstonly_new(host, port,
2557  INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
2558 }
2559 
2560 #ifdef HAVE_SYS_UN_H
2561 
2562 /*
2563  * call-seq:
2564  * Addrinfo.unix(path [, socktype]) => addrinfo
2565  *
2566  * returns an addrinfo object for UNIX socket address.
2567  *
2568  * _socktype_ specifies the socket type.
2569  * If it is omitted, :STREAM is used.
2570  *
2571  * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM>
2572  * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM>
2573  */
2574 static VALUE
2575 addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
2576 {
2577  VALUE path, vsocktype, addr;
2578  int socktype;
2579  rb_addrinfo_t *rai;
2580 
2581  rb_scan_args(argc, argv, "11", &path, &vsocktype);
2582 
2583  if (NIL_P(vsocktype))
2584  socktype = SOCK_STREAM;
2585  else
2586  socktype = rsock_socktype_arg(vsocktype);
2587 
2588  addr = addrinfo_s_allocate(rb_cAddrinfo);
2589  DATA_PTR(addr) = rai = alloc_addrinfo();
2590  init_unix_addrinfo(rai, path, socktype);
2591  return addr;
2592 }
2593 
2594 #endif
2595 
2596 VALUE
2598 {
2599  VALUE val = *v;
2600  if (IS_ADDRINFO(val)) {
2601  *v = addrinfo_to_sockaddr(val);
2602  }
2603  StringValue(*v);
2604  return *v;
2605 }
2606 
2607 VALUE
2609 {
2610  VALUE val = *v;
2611  *rai_ret = Qnil;
2612  if (IS_ADDRINFO(val)) {
2613  *v = addrinfo_to_sockaddr(val);
2614  *rai_ret = val;
2615  }
2616  StringValue(*v);
2617  return *v;
2618 }
2619 
2620 char *
2622 {
2624  return RSTRING_PTR(*v);
2625 }
2626 
2627 VALUE
2629 {
2630  if (IS_ADDRINFO(val))
2631  return addrinfo_to_sockaddr(val);
2632  return rb_check_string_type(val);
2633 }
2634 
2635 VALUE
2636 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
2637 {
2638  int family;
2639  int socktype;
2640  int ret;
2641  socklen_t optlen = (socklen_t)sizeof(socktype);
2642 
2643  /* assumes protocol family and address family are identical */
2644  family = get_afamily(addr, len);
2645 
2646  ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen);
2647  if (ret == -1) {
2648  rb_sys_fail("getsockopt(SO_TYPE)");
2649  }
2650 
2651  return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil);
2652 }
2653 
2654 VALUE
2655 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
2656 {
2657  rb_io_t *fptr;
2658 
2659  switch (TYPE(io)) {
2660  case T_FIXNUM:
2661  return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len);
2662 
2663  case T_BIGNUM:
2664  return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len);
2665 
2666  case T_FILE:
2667  GetOpenFile(io, fptr);
2668  return rsock_fd_socket_addrinfo(fptr->fd, addr, len);
2669 
2670  default:
2671  rb_raise(rb_eTypeError, "neither IO nor file descriptor");
2672  }
2673 
2675 }
2676 
2677 /*
2678  * Addrinfo class
2679  */
2680 void
2682 {
2683  /*
2684  * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
2685  * structure identifies an Internet host and a service.
2686  */
2687  id_timeout = rb_intern("timeout");
2688 
2689  rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
2690  rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
2691  rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
2692  rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0);
2694  rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1);
2695  rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1);
2696  rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2);
2697  rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2);
2698 #ifdef HAVE_SYS_UN_H
2699  rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
2700 #endif
2701 
2702  rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0);
2703  rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0);
2704  rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0);
2705  rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0);
2706  rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0);
2707 
2708  rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0);
2709  rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0);
2710  rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0);
2711 
2712  rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0);
2713  rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0);
2714  rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0);
2715  rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0);
2716 
2717  rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0);
2718  rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0);
2719  rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0);
2720 
2721 #ifdef INET6
2722  rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0);
2723  rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0);
2724  rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0);
2725  rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0);
2726  rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0);
2727  rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0);
2728  rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0);
2729  rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0);
2730  rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0);
2731  rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0);
2732  rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0);
2733  rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0);
2734  rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0);
2735 
2736  rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
2737 #endif
2738 
2739 #ifdef HAVE_SYS_UN_H
2740  rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
2741 #endif
2742 
2743  rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0);
2744  rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */
2745 
2746  rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1);
2747 
2748  rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0);
2749  rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1);
2750 }
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
AF_UNSPEC
#define AF_UNSPEC
Definition: sockport.h:101
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
strncpy
char * strncpy(char *__restrict, const char *__restrict, size_t)
rb_id2name
const char * rb_id2name(ID)
Definition: symbol.c:801
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:1018
xcalloc
#define xcalloc
Definition: defines.h:213
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_cData
RUBY_EXTERN VALUE rb_cData
Definition: ruby.h:2018
id
const int id
Definition: nkf.c:209
rsock_sockaddr_string_value_with_addrinfo
VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *rai_ret)
Definition: raddrinfo.c:2608
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rsock_fd_socket_addrinfo
VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2636
getaddrinfo_arg::node
const char * node
Definition: raddrinfo.c:179
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
IS_ADDRINFO
#define IS_ADDRINFO(obj)
Definition: raddrinfo.c:864
rb_str_buf_cat2
#define rb_str_buf_cat2
Definition: intern.h:911
str_equal
#define str_equal(ptr, len, name)
Definition: raddrinfo.c:503
IPPROTO_UDP
#define IPPROTO_UDP
Definition: constdefs.h:627
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.0.h:666
getaddrinfo_arg::service
const char * service
Definition: raddrinfo.c:180
IPPROTO_TCP
#define IPPROTO_TCP
Definition: constdefs.h:610
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
getnameinfo_arg::servlen
size_t servlen
Definition: raddrinfo.c:422
rb_check_sockaddr_string_type
VALUE rb_check_sockaddr_string_type(VALUE val)
Definition: raddrinfo.c:2628
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_addrinfo_t::sockaddr_len
socklen_t sockaddr_len
Definition: raddrinfo.c:833
rb_addrinfo_t::pfamily
int pfamily
Definition: raddrinfo.c:830
NI_MAXSERV
#define NI_MAXSERV
Definition: addrinfo.h:118
hostent_arg::addr
struct rb_addrinfo * addr
Definition: raddrinfo.c:758
addrinfo_free
#define addrinfo_free
Definition: raddrinfo.c:845
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
addrinfo::ai_addrlen
size_t ai_addrlen
Definition: addrinfo.h:136
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
rb_intern
#define rb_intern(str)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
union_sockaddr
Definition: rubysocket.h:192
TYPE
#define TYPE(x)
Definition: ruby.h:554
getnameinfo_arg::serv
char * serv
Definition: raddrinfo.c:421
getnameinfo_arg::host
char * host
Definition: raddrinfo.c:419
hostent_arg
Definition: raddrinfo.c:756
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
INADDR_ANY
#define INADDR_ANY
Definition: constdefs.h:740
getnameinfo_arg::sa
const struct sockaddr * sa
Definition: raddrinfo.c:416
getaddrinfo_arg::hints
const struct addrinfo * hints
Definition: raddrinfo.c:181
sin
double sin(double)
StringValue
use StringValue() instead")))
rsock_socktype_to_int
int rsock_socktype_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4863
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_addrinfo::ai
struct addrinfo * ai
Definition: rubysocket.h:291
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
atoi
int atoi(const char *__nptr)
ptr
struct RIMemo * ptr
Definition: debug.c:74
Qfalse
#define Qfalse
Definition: ruby.h:467
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: addrinfo.h:98
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
u_int32_t
__uint32_t u_int32_t
Definition: rb_mjit_min_header-2.7.0.h:1159
rb_cInteger
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:2031
rb_addrinfo
Definition: rubysocket.h:290
rb_io_t::fd
int fd
Definition: io.h:68
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:104
RIMemo::flags
VALUE flags
Definition: internal.h:1125
NULL
#define NULL
Definition: _sdbm.c:101
IS_IP_FAMILY
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:162
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
socklen_t
int socklen_t
Definition: getaddrinfo.c:83
rb_addrinfo_t
Definition: raddrinfo.c:827
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
error
const rb_iseq_t const char * error
Definition: rb_mjit_min_header-2.7.0.h:13506
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rsock_inspect_sockaddr
VALUE rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE ret)
Definition: raddrinfo.c:1266
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
EAI_SYSTEM
#define EAI_SYSTEM
Definition: addrinfo.h:88
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
const
#define const
Definition: strftime.c:103
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
T_FILE
#define T_FILE
Definition: ruby.h:534
rsock_family_to_int
int rsock_family_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4468
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:716
EAI_AGAIN
#define EAI_AGAIN
Definition: addrinfo.h:79
rsock_make_ipaddr
VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen)
Definition: raddrinfo.c:470
INIT_SOCKADDR_IN
#define INIT_SOCKADDR_IN(addr, len)
Definition: sockport.h:47
PRIuSIZE
#define PRIuSIZE
Definition: ruby.h:208
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
RSTRING_SOCKLEN
#define RSTRING_SOCKLEN
Definition: rubysocket.h:130
rsock_addrinfo_inspect_sockaddr
VALUE rsock_addrinfo_inspect_sockaddr(VALUE self)
Definition: raddrinfo.c:1641
NI_NUMERICHOST
#define NI_NUMERICHOST
Definition: addrinfo.h:125
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
rsock_freeaddrinfo
VALUE rsock_freeaddrinfo(VALUE arg)
Definition: raddrinfo.c:808
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rsock_addrinfo_new
VALUE rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, int family, int socktype, int protocol, VALUE canonname, VALUE inspectname)
Definition: raddrinfo.c:910
getnameinfo_arg::salen
socklen_t salen
Definition: raddrinfo.c:417
addrinfo::ai_canonname
char * ai_canonname
Definition: addrinfo.h:137
rb_time_timespec_interval
struct timespec rb_time_timespec_interval(VALUE num)
Definition: time.c:2706
rsock_sockaddr_string_value
VALUE rsock_sockaddr_string_value(volatile VALUE *v)
Definition: raddrinfo.c:2597
rb_str_equal
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:3267
addrinfo::ai_addr
struct sockaddr * ai_addr
Definition: addrinfo.h:138
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rsock_ipproto_to_int
int rsock_ipproto_to_int(const char *str, long len, int *valp)
Definition: constdefs.c:4934
IFNAMSIZ
#define IFNAMSIZ
sprintf
int sprintf(char *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: intern.h:945
rsock_intern_socktype
ID rsock_intern_socktype(int val)
Definition: constdefs.c:6775
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
addrinfo::ai_family
int ai_family
Definition: addrinfo.h:133
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
rb_eSocket
VALUE rb_eSocket
Definition: init.c:29
rsock_init_addrinfo
void rsock_init_addrinfo(void)
Definition: raddrinfo.c:2681
rsock_getaddrinfo
struct rb_addrinfo * rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
Definition: raddrinfo.c:576
AI_NUMERICSERV
#define AI_NUMERICSERV
Definition: addrinfo.h:99
NI_MAXHOST
#define NI_MAXHOST
Definition: addrinfo.h:117
rsock_ipaddr
VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
Definition: raddrinfo.c:665
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
STRTOUL
#define STRTOUL(str, endptr, base)
Definition: ruby.h:2327
hostent_arg::ipaddr
VALUE(* ipaddr)(struct sockaddr *, socklen_t)
Definition: raddrinfo.c:759
PF_INET
#define PF_INET
Definition: sockport.h:109
list
struct rb_encoding_entry * list
Definition: encoding.c:56
addrinfo::ai_protocol
int ai_protocol
Definition: addrinfo.h:135
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
rb_getnameinfo
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:437
ISSPACE
#define ISSPACE(c)
Definition: ruby.h:2307
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
hostent_arg::host
VALUE host
Definition: raddrinfo.c:757
NI_NUMERICSERV
#define NI_NUMERICSERV
Definition: addrinfo.h:127
rb_freeaddrinfo
void rb_freeaddrinfo(struct rb_addrinfo *ai)
Definition: raddrinfo.c:396
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
PF_UNSPEC
#define PF_UNSPEC
Definition: sockport.h:105
union_sockaddr::in
struct sockaddr_in in
Definition: rubysocket.h:194
INIT_SOCKADDR_IN6
#define INIT_SOCKADDR_IN6(addr, len)
Definition: sockport.h:56
strcmp
int strcmp(const char *, const char *)
rsock_socktype_arg
int rsock_socktype_arg(VALUE type)
Definition: constants.c:49
strspn
size_t strspn(const char *, const char *)
addrinfo::ai_next
struct addrinfo * ai_next
Definition: addrinfo.h:139
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
ISPRINT
#define ISPRINT(c)
Definition: ruby.h:2305
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
xmalloc
#define xmalloc
Definition: defines.h:211
freeaddrinfo
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:216
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
names
st_table * names
Definition: encoding.c:59
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
rsock_intern_ipproto
ID rsock_intern_ipproto(int val)
Definition: constdefs.c:6784
rb_addrinfo_t::protocol
int protocol
Definition: raddrinfo.c:832
rb_cAddrinfo
VALUE rb_cAddrinfo
Definition: init.c:27
getnameinfo
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
Definition: getnameinfo.c:122
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
Definition: object.c:2900
rb_addrinfo_t::addr
union_sockaddr addr
Definition: raddrinfo.c:834
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rsock_intern_family
ID rsock_intern_family(int val)
Definition: constdefs.c:6748
rb_addrinfo_t::inspectname
VALUE inspectname
Definition: raddrinfo.c:828
ENOENT
#define ENOENT
Definition: rb_mjit_min_header-2.7.0.h:10939
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_addrinfo_t::socktype
int socktype
Definition: raddrinfo.c:831
addrinfo::ai_socktype
int ai_socktype
Definition: addrinfo.h:134
argc
int argc
Definition: ruby.c:222
INADDR_BROADCAST
#define INADDR_BROADCAST
Definition: constdefs.h:747
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
rsock_io_socket_addrinfo
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
Definition: raddrinfo.c:2655
getaddrinfo_arg::res
struct addrinfo ** res
Definition: raddrinfo.c:182
rsock_fd_family
int rsock_fd_family(int fd)
Definition: raddrinfo.c:640
rb_data_type_struct
Definition: ruby.h:1148
xfree
#define xfree
Definition: defines.h:216
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:127
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
addrinfo::ai_flags
int ai_flags
Definition: addrinfo.h:132
getnameinfo_arg::hostlen
size_t hostlen
Definition: raddrinfo.c:420
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
rsock_make_hostent
VALUE rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE(*ipaddr)(struct sockaddr *, socklen_t))
Definition: raddrinfo.c:816
getnameinfo_arg
Definition: raddrinfo.c:414
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:889
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
errno
int errno
rsock_raise_socket_error
void rsock_raise_socket_error(const char *reason, int error)
Definition: init.c:39
rsock_sockaddr_string_value_ptr
char * rsock_sockaddr_string_value_ptr(volatile VALUE *v)
Definition: raddrinfo.c:2621
len
uint8_t len
Definition: escape.c:17
rsock_addrinfo
struct rb_addrinfo * rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
Definition: raddrinfo.c:653
EAI_NONAME
#define EAI_NONAME
Definition: addrinfo.h:85
rb_addrinfo_t::canonname
VALUE canonname
Definition: raddrinfo.c:829
timespec
Definition: missing.h:60
rubysocket.h
T_STRING
#define T_STRING
Definition: ruby.h:528
NI_DGRAM
#define NI_DGRAM
Definition: addrinfo.h:128
rb_getaddrinfo
int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res)
Definition: raddrinfo.c:309
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1114
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
rsock_family_arg
int rsock_family_arg(VALUE domain)
Definition: constants.c:42
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.0.h:5462
IN6_IS_ADDR_UNIQUE_LOCAL
#define IN6_IS_ADDR_UNIQUE_LOCAL(a)
Definition: rubysocket.h:166
rb_io_t
Definition: io.h:66
union_sockaddr::addr
struct sockaddr addr
Definition: rubysocket.h:193
SOCKLEN_MAX
#define SOCKLEN_MAX
Definition: rubysocket.h:124
getaddrinfo
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
Definition: getaddrinfo.c:272
getaddrinfo_arg
Definition: raddrinfo.c:177
numberof
#define numberof(array)
Definition: etc.c:618
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN(val)
Definition: ruby.h:59
rb_addrinfo::allocated_by_malloc
int allocated_by_malloc
Definition: rubysocket.h:292
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
addrinfo
Definition: addrinfo.h:131
getnameinfo_arg::flags
int flags
Definition: raddrinfo.c:418
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
EAI_FAIL
#define EAI_FAIL
Definition: addrinfo.h:81
rsock_intern_protocol_family
ID rsock_intern_protocol_family(int val)
Definition: constdefs.c:6766
name
const char * name
Definition: nkf.c:208