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) {
132 r->ai_protocol = IPPROTO_UDP;
133 }
134 else if (r->ai_socktype == SOCK_STREAM) {
135 r->ai_protocol = IPPROTO_TCP;
136 }
137 }
138 r = r->ai_next;
139 }
140 }
141
142 return error;
143 }
144 #undef getaddrinfo
145 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res))
146 #endif
147
148 #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
177 struct getaddrinfo_arg
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
396 rb_freeaddrinfo(struct rb_addrinfo *ai)
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
414 struct getnameinfo_arg
415 {
416 const struct sockaddr *sa;
417 socklen_t salen;
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
442 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
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
640 rsock_fd_family(int fd)
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) +
745 RSTRING_SOCKLEN(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 {
757 VALUE host;
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
808 rsock_freeaddrinfo(VALUE arg)
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,
824 rsock_freeaddrinfo, (VALUE)addr);
825 }
826
827 typedef struct {
828 VALUE inspectname;
829 VALUE canonname;
830 int pfamily;
831 int socktype;
832 int protocol;
833 socklen_t sockaddr_len;
834 union_sockaddr addr;
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 {
886 rb_addrinfo_t *rai = ZALLOC(rb_addrinfo_t);
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),
994 NI_NUMERICHOST|NI_NUMERICSERV);
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))
1096 rb_raise(rb_eArgError,
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,
1337 NI_NUMERICHOST|NI_NUMERICSERV);
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) {
1572 ID id = rsock_intern_protocol_family(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
1641 rsock_addrinfo_inspect_sockaddr(VALUE self)
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
1655 id = rsock_intern_protocol_family(rai->pfamily);
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),
1705 NI_NUMERICHOST|NI_NUMERICSERV);
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))
1792 rb_raise(rb_eSocket,
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
2079 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
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
2106 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
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)
2439 rb_raise(rb_eSocket,
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
2597 rsock_sockaddr_string_value(volatile VALUE *v)
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
2608 rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *rai_ret)
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 *
2621 rsock_sockaddr_string_value_ptr(volatile VALUE *v)
2622 {
2623 rsock_sockaddr_string_value(v);
2624 return RSTRING_PTR(*v);
2625 }
2626
2627 VALUE
2628 rb_check_sockaddr_string_type(VALUE val)
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
2674 UNREACHABLE_RETURN(Qnil);
2675 }
2676
2677 /*
2678 * Addrinfo class
2679 */
2680 void
2681 rsock_init_addrinfo(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);
2693 rb_define_method(rb_cAddrinfo, "inspect_sockaddr", rsock_addrinfo_inspect_sockaddr, 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