Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 ainfo.c - 00004 00005 created at: Thu Mar 31 12:21:29 JST 1994 00006 00007 Copyright (C) 1993-2007 Yukihiro Matsumoto 00008 00009 ************************************************/ 00010 00011 #include "rubysocket.h" 00012 00013 #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6)) 00014 #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0])) 00015 static const int lookup_order_table[] = { 00016 #if defined(LOOKUP_ORDER_HACK_INET) 00017 PF_INET, PF_INET6, PF_UNSPEC, 00018 #elif defined(LOOKUP_ORDER_HACK_INET6) 00019 PF_INET6, PF_INET, PF_UNSPEC, 00020 #else 00021 /* should not happen */ 00022 #endif 00023 }; 00024 00025 static int 00026 ruby_getaddrinfo(const char *nodename, const char *servname, 00027 const struct addrinfo *hints, struct addrinfo **res) 00028 { 00029 struct addrinfo tmp_hints; 00030 int i, af, error; 00031 00032 if (hints->ai_family != PF_UNSPEC) { 00033 return getaddrinfo(nodename, servname, hints, res); 00034 } 00035 00036 for (i = 0; i < LOOKUP_ORDERS; i++) { 00037 af = lookup_order_table[i]; 00038 MEMCPY(&tmp_hints, hints, struct addrinfo, 1); 00039 tmp_hints.ai_family = af; 00040 error = getaddrinfo(nodename, servname, &tmp_hints, res); 00041 if (error) { 00042 if (tmp_hints.ai_family == PF_UNSPEC) { 00043 break; 00044 } 00045 } 00046 else { 00047 break; 00048 } 00049 } 00050 00051 return error; 00052 } 00053 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res)) 00054 #endif 00055 00056 #if defined(_AIX) 00057 static int 00058 ruby_getaddrinfo__aix(const char *nodename, const char *servname, 00059 const struct addrinfo *hints, struct addrinfo **res) 00060 { 00061 int error = getaddrinfo(nodename, servname, hints, res); 00062 struct addrinfo *r; 00063 if (error) 00064 return error; 00065 for (r = *res; r != NULL; r = r->ai_next) { 00066 if (r->ai_addr->sa_family == 0) 00067 r->ai_addr->sa_family = r->ai_family; 00068 if (r->ai_addr->sa_len == 0) 00069 r->ai_addr->sa_len = r->ai_addrlen; 00070 } 00071 return 0; 00072 } 00073 #undef getaddrinfo 00074 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res)) 00075 static int 00076 ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen, 00077 char *host, size_t hostlen, 00078 char *serv, size_t servlen, int flags) 00079 { 00080 struct sockaddr_in6 *sa6; 00081 u_int32_t *a6; 00082 00083 if (sa->sa_family == AF_INET6) { 00084 sa6 = (struct sockaddr_in6 *)sa; 00085 a6 = sa6->sin6_addr.u6_addr.u6_addr32; 00086 00087 if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { 00088 strncpy(host, "::", hostlen); 00089 snprintf(serv, servlen, "%d", sa6->sin6_port); 00090 return 0; 00091 } 00092 } 00093 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 00094 } 00095 #undef getnameinfo 00096 #define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \ 00097 ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags)) 00098 #endif 00099 00100 static int str_is_number(const char *); 00101 00102 #if defined(__APPLE__) 00103 static int 00104 ruby_getaddrinfo__darwin(const char *nodename, const char *servname, 00105 const struct addrinfo *hints, struct addrinfo **res) 00106 { 00107 /* fix [ruby-core:29427] */ 00108 const char *tmp_servname; 00109 struct addrinfo tmp_hints; 00110 int error; 00111 00112 tmp_servname = servname; 00113 MEMCPY(&tmp_hints, hints, struct addrinfo, 1); 00114 if (nodename && servname) { 00115 if (str_is_number(tmp_servname) && atoi(servname) == 0) { 00116 tmp_servname = NULL; 00117 #ifdef AI_NUMERICSERV 00118 if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV; 00119 #endif 00120 } 00121 } 00122 00123 error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res); 00124 if (error == 0) { 00125 /* [ruby-dev:23164] */ 00126 struct addrinfo *r; 00127 r = *res; 00128 while (r) { 00129 if (! r->ai_socktype) r->ai_socktype = hints->ai_socktype; 00130 if (! r->ai_protocol) { 00131 if (r->ai_socktype == SOCK_DGRAM) { 00132 r->ai_protocol = IPPROTO_UDP; 00133 } 00134 else if (r->ai_socktype == SOCK_STREAM) { 00135 r->ai_protocol = IPPROTO_TCP; 00136 } 00137 } 00138 r = r->ai_next; 00139 } 00140 } 00141 00142 return error; 00143 } 00144 #undef getaddrinfo 00145 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__darwin((node),(serv),(hints),(res)) 00146 #endif 00147 00148 #ifndef GETADDRINFO_EMU 00149 struct getaddrinfo_arg 00150 { 00151 const char *node; 00152 const char *service; 00153 const struct addrinfo *hints; 00154 struct addrinfo **res; 00155 }; 00156 00157 static void * 00158 nogvl_getaddrinfo(void *arg) 00159 { 00160 struct getaddrinfo_arg *ptr = arg; 00161 return (void *)(VALUE)getaddrinfo(ptr->node, ptr->service, 00162 ptr->hints, ptr->res); 00163 } 00164 #endif 00165 00166 int 00167 rb_getaddrinfo(const char *node, const char *service, 00168 const struct addrinfo *hints, 00169 struct addrinfo **res) 00170 { 00171 #ifdef GETADDRINFO_EMU 00172 return getaddrinfo(node, service, hints, res); 00173 #else 00174 struct getaddrinfo_arg arg; 00175 int ret; 00176 MEMZERO(&arg, sizeof arg, 1); 00177 arg.node = node; 00178 arg.service = service; 00179 arg.hints = hints; 00180 arg.res = res; 00181 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); 00182 return ret; 00183 #endif 00184 } 00185 00186 #ifndef GETADDRINFO_EMU 00187 struct getnameinfo_arg 00188 { 00189 const struct sockaddr *sa; 00190 socklen_t salen; 00191 char *host; 00192 size_t hostlen; 00193 char *serv; 00194 size_t servlen; 00195 int flags; 00196 }; 00197 00198 static void * 00199 nogvl_getnameinfo(void *arg) 00200 { 00201 struct getnameinfo_arg *ptr = arg; 00202 return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen, 00203 ptr->host, (socklen_t)ptr->hostlen, 00204 ptr->serv, (socklen_t)ptr->servlen, 00205 ptr->flags); 00206 } 00207 #endif 00208 00209 int 00210 rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, 00211 char *host, size_t hostlen, 00212 char *serv, size_t servlen, int flags) 00213 { 00214 #ifdef GETADDRINFO_EMU 00215 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 00216 #else 00217 struct getnameinfo_arg arg; 00218 int ret; 00219 arg.sa = sa; 00220 arg.salen = salen; 00221 arg.host = host; 00222 arg.hostlen = hostlen; 00223 arg.serv = serv; 00224 arg.servlen = servlen; 00225 arg.flags = flags; 00226 ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0); 00227 return ret; 00228 #endif 00229 } 00230 00231 static void 00232 make_ipaddr0(struct sockaddr *addr, char *buf, size_t len) 00233 { 00234 int error; 00235 00236 error = rb_getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST); 00237 if (error) { 00238 rsock_raise_socket_error("getnameinfo", error); 00239 } 00240 } 00241 00242 VALUE 00243 rsock_make_ipaddr(struct sockaddr *addr) 00244 { 00245 char hbuf[1024]; 00246 00247 make_ipaddr0(addr, hbuf, sizeof(hbuf)); 00248 return rb_str_new2(hbuf); 00249 } 00250 00251 static void 00252 make_inetaddr(unsigned int host, char *buf, size_t len) 00253 { 00254 struct sockaddr_in sin; 00255 00256 MEMZERO(&sin, struct sockaddr_in, 1); 00257 sin.sin_family = AF_INET; 00258 SET_SIN_LEN(&sin, sizeof(sin)); 00259 sin.sin_addr.s_addr = host; 00260 make_ipaddr0((struct sockaddr*)&sin, buf, len); 00261 } 00262 00263 static int 00264 str_is_number(const char *p) 00265 { 00266 char *ep; 00267 00268 if (!p || *p == '\0') 00269 return 0; 00270 ep = NULL; 00271 (void)STRTOUL(p, &ep, 10); 00272 if (ep && *ep == '\0') 00273 return 1; 00274 else 00275 return 0; 00276 } 00277 00278 static char* 00279 host_str(VALUE host, char *hbuf, size_t len, int *flags_ptr) 00280 { 00281 if (NIL_P(host)) { 00282 return NULL; 00283 } 00284 else if (rb_obj_is_kind_of(host, rb_cInteger)) { 00285 unsigned int i = NUM2UINT(host); 00286 00287 make_inetaddr(htonl(i), hbuf, len); 00288 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00289 return hbuf; 00290 } 00291 else { 00292 char *name; 00293 00294 SafeStringValue(host); 00295 name = RSTRING_PTR(host); 00296 if (!name || *name == 0 || (name[0] == '<' && strcmp(name, "<any>") == 0)) { 00297 make_inetaddr(INADDR_ANY, hbuf, len); 00298 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00299 } 00300 else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { 00301 make_inetaddr(INADDR_BROADCAST, hbuf, len); 00302 if (flags_ptr) *flags_ptr |= AI_NUMERICHOST; 00303 } 00304 else if (strlen(name) >= len) { 00305 rb_raise(rb_eArgError, "hostname too long (%"PRIuSIZE")", 00306 strlen(name)); 00307 } 00308 else { 00309 strcpy(hbuf, name); 00310 } 00311 return hbuf; 00312 } 00313 } 00314 00315 static char* 00316 port_str(VALUE port, char *pbuf, size_t len, int *flags_ptr) 00317 { 00318 if (NIL_P(port)) { 00319 return 0; 00320 } 00321 else if (FIXNUM_P(port)) { 00322 snprintf(pbuf, len, "%ld", FIX2LONG(port)); 00323 #ifdef AI_NUMERICSERV 00324 if (flags_ptr) *flags_ptr |= AI_NUMERICSERV; 00325 #endif 00326 return pbuf; 00327 } 00328 else { 00329 char *serv; 00330 00331 SafeStringValue(port); 00332 serv = RSTRING_PTR(port); 00333 if (strlen(serv) >= len) { 00334 rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")", 00335 strlen(serv)); 00336 } 00337 strcpy(pbuf, serv); 00338 return pbuf; 00339 } 00340 } 00341 00342 struct addrinfo* 00343 rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack) 00344 { 00345 struct addrinfo* res = NULL; 00346 char *hostp, *portp; 00347 int error; 00348 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00349 int additional_flags = 0; 00350 00351 hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags); 00352 portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); 00353 00354 if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { 00355 hints->ai_socktype = SOCK_DGRAM; 00356 } 00357 hints->ai_flags |= additional_flags; 00358 00359 error = rb_getaddrinfo(hostp, portp, hints, &res); 00360 if (error) { 00361 if (hostp && hostp[strlen(hostp)-1] == '\n') { 00362 rb_raise(rb_eSocket, "newline at the end of hostname"); 00363 } 00364 rsock_raise_socket_error("getaddrinfo", error); 00365 } 00366 00367 return res; 00368 } 00369 00370 struct addrinfo* 00371 rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags) 00372 { 00373 struct addrinfo hints; 00374 00375 MEMZERO(&hints, struct addrinfo, 1); 00376 hints.ai_family = AF_UNSPEC; 00377 hints.ai_socktype = socktype; 00378 hints.ai_flags = flags; 00379 return rsock_getaddrinfo(host, port, &hints, 1); 00380 } 00381 00382 VALUE 00383 rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup) 00384 { 00385 VALUE family, port, addr1, addr2; 00386 VALUE ary; 00387 int error; 00388 char hbuf[1024], pbuf[1024]; 00389 ID id; 00390 00391 id = rsock_intern_family(sockaddr->sa_family); 00392 if (id) { 00393 family = rb_str_dup(rb_id2str(id)); 00394 } 00395 else { 00396 sprintf(pbuf, "unknown:%d", sockaddr->sa_family); 00397 family = rb_str_new2(pbuf); 00398 } 00399 00400 addr1 = Qnil; 00401 if (!norevlookup) { 00402 error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf), 00403 NULL, 0, 0); 00404 if (! error) { 00405 addr1 = rb_str_new2(hbuf); 00406 } 00407 } 00408 error = rb_getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf), 00409 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV); 00410 if (error) { 00411 rsock_raise_socket_error("getnameinfo", error); 00412 } 00413 addr2 = rb_str_new2(hbuf); 00414 if (addr1 == Qnil) { 00415 addr1 = addr2; 00416 } 00417 port = INT2FIX(atoi(pbuf)); 00418 ary = rb_ary_new3(4, family, port, addr1, addr2); 00419 00420 return ary; 00421 } 00422 00423 #ifdef HAVE_SYS_UN_H 00424 VALUE 00425 rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len) 00426 { 00427 char *s, *e; 00428 s = sockaddr->sun_path; 00429 e = (char *)sockaddr + len; 00430 while (s < e && *(e-1) == '\0') 00431 e--; 00432 if (s <= e) 00433 return rb_str_new(s, e-s); 00434 else 00435 return rb_str_new2(""); 00436 } 00437 00438 VALUE 00439 rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len) 00440 { 00441 return rb_assoc_new(rb_str_new2("AF_UNIX"), 00442 rsock_unixpath_str(sockaddr, len)); 00443 } 00444 00445 socklen_t 00446 rsock_unix_sockaddr_len(VALUE path) 00447 { 00448 #ifdef __linux__ 00449 if (RSTRING_LEN(path) == 0) { 00450 /* autobind; see unix(7) for details. */ 00451 return (socklen_t) sizeof(sa_family_t); 00452 } 00453 else if (RSTRING_PTR(path)[0] == '\0') { 00454 /* abstract namespace; see unix(7) for details. */ 00455 return (socklen_t) offsetof(struct sockaddr_un, sun_path) + 00456 RSTRING_LEN(path); 00457 } 00458 else { 00459 #endif 00460 return (socklen_t) sizeof(struct sockaddr_un); 00461 #ifdef __linux__ 00462 } 00463 #endif 00464 } 00465 #endif 00466 00467 struct hostent_arg { 00468 VALUE host; 00469 struct addrinfo* addr; 00470 VALUE (*ipaddr)(struct sockaddr*, size_t); 00471 }; 00472 00473 static VALUE 00474 make_hostent_internal(struct hostent_arg *arg) 00475 { 00476 VALUE host = arg->host; 00477 struct addrinfo* addr = arg->addr; 00478 VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr; 00479 00480 struct addrinfo *ai; 00481 struct hostent *h; 00482 VALUE ary, names; 00483 char **pch; 00484 const char* hostp; 00485 char hbuf[NI_MAXHOST]; 00486 00487 ary = rb_ary_new(); 00488 if (addr->ai_canonname) { 00489 hostp = addr->ai_canonname; 00490 } 00491 else { 00492 hostp = host_str(host, hbuf, sizeof(hbuf), NULL); 00493 } 00494 rb_ary_push(ary, rb_str_new2(hostp)); 00495 00496 if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) { 00497 names = rb_ary_new(); 00498 if (h->h_aliases != NULL) { 00499 for (pch = h->h_aliases; *pch; pch++) { 00500 rb_ary_push(names, rb_str_new2(*pch)); 00501 } 00502 } 00503 } 00504 else { 00505 names = rb_ary_new2(0); 00506 } 00507 rb_ary_push(ary, names); 00508 rb_ary_push(ary, INT2NUM(addr->ai_family)); 00509 for (ai = addr; ai; ai = ai->ai_next) { 00510 rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen)); 00511 } 00512 00513 return ary; 00514 } 00515 00516 VALUE 00517 rsock_freeaddrinfo(struct addrinfo *addr) 00518 { 00519 freeaddrinfo(addr); 00520 return Qnil; 00521 } 00522 00523 VALUE 00524 rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t)) 00525 { 00526 struct hostent_arg arg; 00527 00528 arg.host = host; 00529 arg.addr = addr; 00530 arg.ipaddr = ipaddr; 00531 return rb_ensure(make_hostent_internal, (VALUE)&arg, 00532 rsock_freeaddrinfo, (VALUE)addr); 00533 } 00534 00535 typedef struct { 00536 VALUE inspectname; 00537 VALUE canonname; 00538 int pfamily; 00539 int socktype; 00540 int protocol; 00541 socklen_t sockaddr_len; 00542 struct sockaddr_storage addr; 00543 } rb_addrinfo_t; 00544 00545 static void 00546 addrinfo_mark(void *ptr) 00547 { 00548 rb_addrinfo_t *rai = ptr; 00549 if (rai) { 00550 rb_gc_mark(rai->inspectname); 00551 rb_gc_mark(rai->canonname); 00552 } 00553 } 00554 00555 #define addrinfo_free RUBY_TYPED_DEFAULT_FREE 00556 00557 static size_t 00558 addrinfo_memsize(const void *ptr) 00559 { 00560 return ptr ? sizeof(rb_addrinfo_t) : 0; 00561 } 00562 00563 static const rb_data_type_t addrinfo_type = { 00564 "socket/addrinfo", 00565 {addrinfo_mark, addrinfo_free, addrinfo_memsize,}, 00566 }; 00567 00568 static VALUE 00569 addrinfo_s_allocate(VALUE klass) 00570 { 00571 return TypedData_Wrap_Struct(klass, &addrinfo_type, 0); 00572 } 00573 00574 #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type) 00575 static inline rb_addrinfo_t * 00576 check_addrinfo(VALUE self) 00577 { 00578 return rb_check_typeddata(self, &addrinfo_type); 00579 } 00580 00581 static rb_addrinfo_t * 00582 get_addrinfo(VALUE self) 00583 { 00584 rb_addrinfo_t *rai = check_addrinfo(self); 00585 00586 if (!rai) { 00587 rb_raise(rb_eTypeError, "uninitialized socket address"); 00588 } 00589 return rai; 00590 } 00591 00592 00593 static rb_addrinfo_t * 00594 alloc_addrinfo() 00595 { 00596 rb_addrinfo_t *rai = ALLOC(rb_addrinfo_t); 00597 memset(rai, 0, sizeof(rb_addrinfo_t)); 00598 rai->inspectname = Qnil; 00599 rai->canonname = Qnil; 00600 return rai; 00601 } 00602 00603 static void 00604 init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, 00605 int pfamily, int socktype, int protocol, 00606 VALUE canonname, VALUE inspectname) 00607 { 00608 if ((socklen_t)sizeof(rai->addr) < len) 00609 rb_raise(rb_eArgError, "sockaddr string too big"); 00610 memcpy((void *)&rai->addr, (void *)sa, len); 00611 rai->sockaddr_len = len; 00612 00613 rai->pfamily = pfamily; 00614 rai->socktype = socktype; 00615 rai->protocol = protocol; 00616 rai->canonname = canonname; 00617 rai->inspectname = inspectname; 00618 } 00619 00620 VALUE 00621 rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, 00622 int family, int socktype, int protocol, 00623 VALUE canonname, VALUE inspectname) 00624 { 00625 VALUE a; 00626 rb_addrinfo_t *rai; 00627 00628 a = addrinfo_s_allocate(rb_cAddrinfo); 00629 DATA_PTR(a) = rai = alloc_addrinfo(); 00630 init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname); 00631 return a; 00632 } 00633 00634 static struct addrinfo * 00635 call_getaddrinfo(VALUE node, VALUE service, 00636 VALUE family, VALUE socktype, VALUE protocol, VALUE flags, 00637 int socktype_hack) 00638 { 00639 struct addrinfo hints, *res; 00640 00641 MEMZERO(&hints, struct addrinfo, 1); 00642 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family); 00643 00644 if (!NIL_P(socktype)) { 00645 hints.ai_socktype = rsock_socktype_arg(socktype); 00646 } 00647 if (!NIL_P(protocol)) { 00648 hints.ai_protocol = NUM2INT(protocol); 00649 } 00650 if (!NIL_P(flags)) { 00651 hints.ai_flags = NUM2INT(flags); 00652 } 00653 res = rsock_getaddrinfo(node, service, &hints, socktype_hack); 00654 00655 if (res == NULL) 00656 rb_raise(rb_eSocket, "host not found"); 00657 return res; 00658 } 00659 00660 static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res); 00661 00662 static void 00663 init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service, 00664 VALUE family, VALUE socktype, VALUE protocol, VALUE flags, 00665 VALUE inspectnode, VALUE inspectservice) 00666 { 00667 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1); 00668 VALUE canonname; 00669 VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res); 00670 00671 canonname = Qnil; 00672 if (res->ai_canonname) { 00673 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00674 OBJ_FREEZE(canonname); 00675 } 00676 00677 init_addrinfo(rai, res->ai_addr, res->ai_addrlen, 00678 NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol), 00679 canonname, inspectname); 00680 00681 freeaddrinfo(res); 00682 } 00683 00684 static VALUE 00685 make_inspectname(VALUE node, VALUE service, struct addrinfo *res) 00686 { 00687 VALUE inspectname = Qnil; 00688 00689 if (res) { 00690 /* drop redundant information which also shown in address:port part. */ 00691 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00692 int ret; 00693 ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 00694 sizeof(hbuf), pbuf, sizeof(pbuf), 00695 NI_NUMERICHOST|NI_NUMERICSERV); 00696 if (ret == 0) { 00697 if (RB_TYPE_P(node, T_STRING) && strcmp(hbuf, RSTRING_PTR(node)) == 0) 00698 node = Qnil; 00699 if (RB_TYPE_P(service, T_STRING) && strcmp(pbuf, RSTRING_PTR(service)) == 0) 00700 service = Qnil; 00701 else if (RB_TYPE_P(service, T_FIXNUM) && atoi(pbuf) == FIX2INT(service)) 00702 service = Qnil; 00703 } 00704 } 00705 00706 if (RB_TYPE_P(node, T_STRING)) { 00707 inspectname = rb_str_dup(node); 00708 } 00709 if (RB_TYPE_P(service, T_STRING)) { 00710 if (NIL_P(inspectname)) 00711 inspectname = rb_sprintf(":%s", StringValueCStr(service)); 00712 else 00713 rb_str_catf(inspectname, ":%s", StringValueCStr(service)); 00714 } 00715 else if (RB_TYPE_P(service, T_FIXNUM) && FIX2INT(service) != 0) 00716 { 00717 if (NIL_P(inspectname)) 00718 inspectname = rb_sprintf(":%d", FIX2INT(service)); 00719 else 00720 rb_str_catf(inspectname, ":%d", FIX2INT(service)); 00721 } 00722 if (!NIL_P(inspectname)) { 00723 OBJ_INFECT(inspectname, node); 00724 OBJ_INFECT(inspectname, service); 00725 OBJ_FREEZE(inspectname); 00726 } 00727 return inspectname; 00728 } 00729 00730 static VALUE 00731 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00732 { 00733 VALUE ret; 00734 VALUE canonname; 00735 VALUE inspectname; 00736 00737 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00738 00739 inspectname = make_inspectname(node, service, res); 00740 00741 canonname = Qnil; 00742 if (res->ai_canonname) { 00743 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00744 OBJ_FREEZE(canonname); 00745 } 00746 00747 ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen, 00748 res->ai_family, res->ai_socktype, res->ai_protocol, 00749 canonname, inspectname); 00750 00751 freeaddrinfo(res); 00752 return ret; 00753 } 00754 00755 static VALUE 00756 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00757 { 00758 VALUE ret; 00759 struct addrinfo *r; 00760 VALUE inspectname; 00761 00762 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00763 00764 inspectname = make_inspectname(node, service, res); 00765 00766 ret = rb_ary_new(); 00767 for (r = res; r; r = r->ai_next) { 00768 VALUE addr; 00769 VALUE canonname = Qnil; 00770 00771 if (r->ai_canonname) { 00772 canonname = rb_tainted_str_new_cstr(r->ai_canonname); 00773 OBJ_FREEZE(canonname); 00774 } 00775 00776 addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen, 00777 r->ai_family, r->ai_socktype, r->ai_protocol, 00778 canonname, inspectname); 00779 00780 rb_ary_push(ret, addr); 00781 } 00782 00783 freeaddrinfo(res); 00784 return ret; 00785 } 00786 00787 00788 #ifdef HAVE_SYS_UN_H 00789 static void 00790 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) 00791 { 00792 struct sockaddr_un un; 00793 socklen_t len; 00794 00795 StringValue(path); 00796 00797 if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path)) 00798 rb_raise(rb_eArgError, 00799 "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 00800 (size_t)RSTRING_LEN(path), sizeof(un.sun_path)); 00801 00802 MEMZERO(&un, struct sockaddr_un, 1); 00803 00804 un.sun_family = AF_UNIX; 00805 memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); 00806 00807 len = rsock_unix_sockaddr_len(path); 00808 init_addrinfo(rai, (struct sockaddr *)&un, len, 00809 PF_UNIX, socktype, 0, Qnil, Qnil); 00810 } 00811 #endif 00812 00813 /* 00814 * call-seq: 00815 * Addrinfo.new(sockaddr) => addrinfo 00816 * Addrinfo.new(sockaddr, family) => addrinfo 00817 * Addrinfo.new(sockaddr, family, socktype) => addrinfo 00818 * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo 00819 * 00820 * returns a new instance of Addrinfo. 00821 * The instance contains sockaddr, family, socktype, protocol. 00822 * sockaddr means struct sockaddr which can be used for connect(2), etc. 00823 * family, socktype and protocol are integers which is used for arguments of socket(2). 00824 * 00825 * sockaddr is specified as an array or a string. 00826 * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr. 00827 * The string should be struct sockaddr as generated by 00828 * Socket.sockaddr_in or Socket.unpack_sockaddr_un. 00829 * 00830 * sockaddr examples: 00831 * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] 00832 * - ["AF_INET6", 42304, "ip6-localhost", "::1"] 00833 * - ["AF_UNIX", "/tmp/sock"] 00834 * - Socket.sockaddr_in("smtp", "2001:DB8::1") 00835 * - Socket.sockaddr_in(80, "172.18.22.42") 00836 * - Socket.sockaddr_in(80, "www.ruby-lang.org") 00837 * - Socket.sockaddr_un("/tmp/sock") 00838 * 00839 * In an AF_INET/AF_INET6 sockaddr array, the 4th element, 00840 * numeric IP address, is used to construct socket address in the Addrinfo instance. 00841 * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect. 00842 * 00843 * family is specified as an integer to specify the protocol family such as Socket::PF_INET. 00844 * It can be a symbol or a string which is the constant name 00845 * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc. 00846 * If omitted, PF_UNSPEC is assumed. 00847 * 00848 * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM. 00849 * It can be a symbol or a string which is the constant name 00850 * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc. 00851 * If omitted, 0 is assumed. 00852 * 00853 * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP. 00854 * It must be an integer, unlike family and socktype. 00855 * If omitted, 0 is assumed. 00856 * Note that 0 is reasonable value for most protocols, except raw socket. 00857 * 00858 */ 00859 static VALUE 00860 addrinfo_initialize(int argc, VALUE *argv, VALUE self) 00861 { 00862 rb_addrinfo_t *rai; 00863 VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol; 00864 int i_pfamily, i_socktype, i_protocol; 00865 struct sockaddr *sockaddr_ptr; 00866 socklen_t sockaddr_len; 00867 VALUE canonname = Qnil, inspectname = Qnil; 00868 00869 if (check_addrinfo(self)) 00870 rb_raise(rb_eTypeError, "already initialized socket address"); 00871 DATA_PTR(self) = rai = alloc_addrinfo(); 00872 00873 rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol); 00874 00875 i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily); 00876 i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype); 00877 i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol); 00878 00879 sockaddr_ary = rb_check_array_type(sockaddr_arg); 00880 if (!NIL_P(sockaddr_ary)) { 00881 VALUE afamily = rb_ary_entry(sockaddr_ary, 0); 00882 int af; 00883 StringValue(afamily); 00884 if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1) 00885 rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); 00886 switch (af) { 00887 case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */ 00888 #ifdef INET6 00889 case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */ 00890 #endif 00891 { 00892 VALUE service = rb_ary_entry(sockaddr_ary, 1); 00893 VALUE nodename = rb_ary_entry(sockaddr_ary, 2); 00894 VALUE numericnode = rb_ary_entry(sockaddr_ary, 3); 00895 int flags; 00896 00897 service = INT2NUM(NUM2INT(service)); 00898 if (!NIL_P(nodename)) 00899 StringValue(nodename); 00900 StringValue(numericnode); 00901 flags = AI_NUMERICHOST; 00902 #ifdef AI_NUMERICSERV 00903 flags |= AI_NUMERICSERV; 00904 #endif 00905 00906 init_addrinfo_getaddrinfo(rai, numericnode, service, 00907 INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol), 00908 INT2NUM(flags), 00909 nodename, service); 00910 break; 00911 } 00912 00913 #ifdef HAVE_SYS_UN_H 00914 case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */ 00915 { 00916 VALUE path = rb_ary_entry(sockaddr_ary, 1); 00917 StringValue(path); 00918 init_unix_addrinfo(rai, path, SOCK_STREAM); 00919 break; 00920 } 00921 #endif 00922 00923 default: 00924 rb_raise(rb_eSocket, "unexpected address family"); 00925 } 00926 } 00927 else { 00928 StringValue(sockaddr_arg); 00929 sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg); 00930 sockaddr_len = RSTRING_LENINT(sockaddr_arg); 00931 init_addrinfo(rai, sockaddr_ptr, sockaddr_len, 00932 i_pfamily, i_socktype, i_protocol, 00933 canonname, inspectname); 00934 } 00935 00936 return self; 00937 } 00938 00939 static int 00940 get_afamily(struct sockaddr *addr, socklen_t len) 00941 { 00942 if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len) 00943 return addr->sa_family; 00944 else 00945 return AF_UNSPEC; 00946 } 00947 00948 static int 00949 ai_get_afamily(rb_addrinfo_t *rai) 00950 { 00951 return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len); 00952 } 00953 00954 static VALUE 00955 inspect_sockaddr(VALUE addrinfo, VALUE ret) 00956 { 00957 rb_addrinfo_t *rai = get_addrinfo(addrinfo); 00958 00959 if (rai->sockaddr_len == 0) { 00960 rb_str_cat2(ret, "empty-sockaddr"); 00961 } 00962 else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr) 00963 rb_str_cat2(ret, "too-short-sockaddr"); 00964 else { 00965 switch (rai->addr.ss_family) { 00966 case AF_INET: 00967 { 00968 struct sockaddr_in *addr; 00969 int port; 00970 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) { 00971 rb_str_cat2(ret, "too-short-AF_INET-sockaddr"); 00972 } 00973 else { 00974 addr = (struct sockaddr_in *)&rai->addr; 00975 rb_str_catf(ret, "%d.%d.%d.%d", 00976 ((unsigned char*)&addr->sin_addr)[0], 00977 ((unsigned char*)&addr->sin_addr)[1], 00978 ((unsigned char*)&addr->sin_addr)[2], 00979 ((unsigned char*)&addr->sin_addr)[3]); 00980 port = ntohs(addr->sin_port); 00981 if (port) 00982 rb_str_catf(ret, ":%d", port); 00983 if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len) 00984 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in))); 00985 } 00986 break; 00987 } 00988 00989 #ifdef AF_INET6 00990 case AF_INET6: 00991 { 00992 struct sockaddr_in6 *addr; 00993 char hbuf[1024]; 00994 int port; 00995 int error; 00996 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) { 00997 rb_str_cat2(ret, "too-short-AF_INET6-sockaddr"); 00998 } 00999 else { 01000 addr = (struct sockaddr_in6 *)&rai->addr; 01001 /* use getnameinfo for scope_id. 01002 * RFC 4007: IPv6 Scoped Address Architecture 01003 * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API 01004 */ 01005 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01006 hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 01007 NI_NUMERICHOST|NI_NUMERICSERV); 01008 if (error) { 01009 rsock_raise_socket_error("getnameinfo", error); 01010 } 01011 if (addr->sin6_port == 0) { 01012 rb_str_cat2(ret, hbuf); 01013 } 01014 else { 01015 port = ntohs(addr->sin6_port); 01016 rb_str_catf(ret, "[%s]:%d", hbuf, port); 01017 } 01018 if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len) 01019 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6))); 01020 } 01021 break; 01022 } 01023 #endif 01024 01025 #ifdef HAVE_SYS_UN_H 01026 case AF_UNIX: 01027 { 01028 struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr; 01029 char *p, *s, *e; 01030 s = addr->sun_path; 01031 e = (char*)addr + rai->sockaddr_len; 01032 while (s < e && *(e-1) == '\0') 01033 e--; 01034 if (e < s) 01035 rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr"); 01036 else if (s == e) 01037 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr"); 01038 else { 01039 int printable_only = 1; 01040 p = s; 01041 while (p < e) { 01042 printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p); 01043 p++; 01044 } 01045 if (printable_only) { /* only printable, no space */ 01046 if (s[0] != '/') /* relative path */ 01047 rb_str_cat2(ret, "AF_UNIX "); 01048 rb_str_cat(ret, s, p - s); 01049 } 01050 else { 01051 rb_str_cat2(ret, "AF_UNIX"); 01052 while (s < e) 01053 rb_str_catf(ret, ":%02x", (unsigned char)*s++); 01054 } 01055 if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len) 01056 rb_str_catf(ret, "(sockaddr %d bytes too long)", 01057 (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr))); 01058 } 01059 break; 01060 } 01061 #endif 01062 01063 default: 01064 { 01065 ID id = rsock_intern_family(rai->addr.ss_family); 01066 if (id == 0) 01067 rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family); 01068 else 01069 rb_str_catf(ret, "%s address format unknown", rb_id2name(id)); 01070 break; 01071 } 01072 } 01073 } 01074 01075 return ret; 01076 } 01077 01078 /* 01079 * call-seq: 01080 * addrinfo.inspect => string 01081 * 01082 * returns a string which shows addrinfo in human-readable form. 01083 * 01084 * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost)>" 01085 * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>" 01086 * 01087 */ 01088 static VALUE 01089 addrinfo_inspect(VALUE self) 01090 { 01091 rb_addrinfo_t *rai = get_addrinfo(self); 01092 int internet_p; 01093 VALUE ret; 01094 01095 ret = rb_sprintf("#<%s: ", rb_obj_classname(self)); 01096 01097 inspect_sockaddr(self, ret); 01098 01099 if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) { 01100 ID id = rsock_intern_protocol_family(rai->pfamily); 01101 if (id) 01102 rb_str_catf(ret, " %s", rb_id2name(id)); 01103 else 01104 rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily); 01105 } 01106 01107 internet_p = rai->pfamily == PF_INET; 01108 #ifdef INET6 01109 internet_p = internet_p || rai->pfamily == PF_INET6; 01110 #endif 01111 if (internet_p && rai->socktype == SOCK_STREAM && 01112 (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) { 01113 rb_str_cat2(ret, " TCP"); 01114 } 01115 else if (internet_p && rai->socktype == SOCK_DGRAM && 01116 (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) { 01117 rb_str_cat2(ret, " UDP"); 01118 } 01119 else { 01120 if (rai->socktype) { 01121 ID id = rsock_intern_socktype(rai->socktype); 01122 if (id) 01123 rb_str_catf(ret, " %s", rb_id2name(id)); 01124 else 01125 rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype); 01126 } 01127 01128 if (rai->protocol) { 01129 if (internet_p) { 01130 ID id = rsock_intern_ipproto(rai->protocol); 01131 if (id) 01132 rb_str_catf(ret, " %s", rb_id2name(id)); 01133 else 01134 goto unknown_protocol; 01135 } 01136 else { 01137 unknown_protocol: 01138 rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol); 01139 } 01140 } 01141 } 01142 01143 if (!NIL_P(rai->canonname)) { 01144 VALUE name = rai->canonname; 01145 rb_str_catf(ret, " %s", StringValueCStr(name)); 01146 } 01147 01148 if (!NIL_P(rai->inspectname)) { 01149 VALUE name = rai->inspectname; 01150 rb_str_catf(ret, " (%s)", StringValueCStr(name)); 01151 } 01152 01153 rb_str_buf_cat2(ret, ">"); 01154 return ret; 01155 } 01156 01157 /* 01158 * call-seq: 01159 * addrinfo.inspect_sockaddr => string 01160 * 01161 * returns a string which shows the sockaddr in _addrinfo_ with human-readable form. 01162 * 01163 * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80" 01164 * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80" 01165 * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock" 01166 * 01167 */ 01168 static VALUE 01169 addrinfo_inspect_sockaddr(VALUE self) 01170 { 01171 return inspect_sockaddr(self, rb_str_new("", 0)); 01172 } 01173 01174 /* :nodoc: */ 01175 static VALUE 01176 addrinfo_mdump(VALUE self) 01177 { 01178 rb_addrinfo_t *rai = get_addrinfo(self); 01179 VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname; 01180 int afamily_int = ai_get_afamily(rai); 01181 ID id; 01182 01183 id = rsock_intern_protocol_family(rai->pfamily); 01184 if (id == 0) 01185 rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily); 01186 pfamily = rb_id2str(id); 01187 01188 if (rai->socktype == 0) 01189 socktype = INT2FIX(0); 01190 else { 01191 id = rsock_intern_socktype(rai->socktype); 01192 if (id == 0) 01193 rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype); 01194 socktype = rb_id2str(id); 01195 } 01196 01197 if (rai->protocol == 0) 01198 protocol = INT2FIX(0); 01199 else if (IS_IP_FAMILY(afamily_int)) { 01200 id = rsock_intern_ipproto(rai->protocol); 01201 if (id == 0) 01202 rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol); 01203 protocol = rb_id2str(id); 01204 } 01205 else { 01206 rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol); 01207 } 01208 01209 canonname = rai->canonname; 01210 01211 inspectname = rai->inspectname; 01212 01213 id = rsock_intern_family(afamily_int); 01214 if (id == 0) 01215 rb_raise(rb_eSocket, "unknown address family: %d", afamily_int); 01216 afamily = rb_id2str(id); 01217 01218 switch(afamily_int) { 01219 #ifdef HAVE_SYS_UN_H 01220 case AF_UNIX: 01221 { 01222 struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr; 01223 char *s, *e; 01224 s = su->sun_path; 01225 e = (char*)su + rai->sockaddr_len; 01226 while (s < e && *(e-1) == '\0') 01227 e--; 01228 sockaddr = rb_str_new(s, e-s); 01229 break; 01230 } 01231 #endif 01232 01233 default: 01234 { 01235 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 01236 int error; 01237 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01238 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01239 NI_NUMERICHOST|NI_NUMERICSERV); 01240 if (error) { 01241 rsock_raise_socket_error("getnameinfo", error); 01242 } 01243 sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); 01244 break; 01245 } 01246 } 01247 01248 return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname); 01249 } 01250 01251 /* :nodoc: */ 01252 static VALUE 01253 addrinfo_mload(VALUE self, VALUE ary) 01254 { 01255 VALUE v; 01256 VALUE canonname, inspectname; 01257 int afamily, pfamily, socktype, protocol; 01258 struct sockaddr_storage ss; 01259 socklen_t len; 01260 rb_addrinfo_t *rai; 01261 01262 if (check_addrinfo(self)) 01263 rb_raise(rb_eTypeError, "already initialized socket address"); 01264 01265 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 01266 01267 v = rb_ary_entry(ary, 0); 01268 StringValue(v); 01269 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1) 01270 rb_raise(rb_eTypeError, "unexpected address family"); 01271 01272 v = rb_ary_entry(ary, 2); 01273 StringValue(v); 01274 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1) 01275 rb_raise(rb_eTypeError, "unexpected protocol family"); 01276 01277 v = rb_ary_entry(ary, 3); 01278 if (v == INT2FIX(0)) 01279 socktype = 0; 01280 else { 01281 StringValue(v); 01282 if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1) 01283 rb_raise(rb_eTypeError, "unexpected socktype"); 01284 } 01285 01286 v = rb_ary_entry(ary, 4); 01287 if (v == INT2FIX(0)) 01288 protocol = 0; 01289 else { 01290 StringValue(v); 01291 if (IS_IP_FAMILY(afamily)) { 01292 if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1) 01293 rb_raise(rb_eTypeError, "unexpected protocol"); 01294 } 01295 else { 01296 rb_raise(rb_eTypeError, "unexpected protocol"); 01297 } 01298 } 01299 01300 v = rb_ary_entry(ary, 5); 01301 if (NIL_P(v)) 01302 canonname = Qnil; 01303 else { 01304 StringValue(v); 01305 canonname = v; 01306 } 01307 01308 v = rb_ary_entry(ary, 6); 01309 if (NIL_P(v)) 01310 inspectname = Qnil; 01311 else { 01312 StringValue(v); 01313 inspectname = v; 01314 } 01315 01316 v = rb_ary_entry(ary, 1); 01317 switch(afamily) { 01318 #ifdef HAVE_SYS_UN_H 01319 case AF_UNIX: 01320 { 01321 struct sockaddr_un uaddr; 01322 MEMZERO(&uaddr, struct sockaddr_un, 1); 01323 uaddr.sun_family = AF_UNIX; 01324 01325 StringValue(v); 01326 if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v)) 01327 rb_raise(rb_eSocket, 01328 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01329 (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path)); 01330 memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v)); 01331 len = (socklen_t)sizeof(uaddr); 01332 memcpy(&ss, &uaddr, len); 01333 break; 01334 } 01335 #endif 01336 01337 default: 01338 { 01339 VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary"); 01340 struct addrinfo *res; 01341 int flags = AI_NUMERICHOST; 01342 #ifdef AI_NUMERICSERV 01343 flags |= AI_NUMERICSERV; 01344 #endif 01345 res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), 01346 INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol), 01347 INT2NUM(flags), 1); 01348 01349 len = res->ai_addrlen; 01350 memcpy(&ss, res->ai_addr, res->ai_addrlen); 01351 break; 01352 } 01353 } 01354 01355 DATA_PTR(self) = rai = alloc_addrinfo(); 01356 init_addrinfo(rai, (struct sockaddr *)&ss, len, 01357 pfamily, socktype, protocol, 01358 canonname, inspectname); 01359 return self; 01360 } 01361 01362 /* 01363 * call-seq: 01364 * addrinfo.afamily => integer 01365 * 01366 * returns the address family as an integer. 01367 * 01368 * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true 01369 * 01370 */ 01371 static VALUE 01372 addrinfo_afamily(VALUE self) 01373 { 01374 rb_addrinfo_t *rai = get_addrinfo(self); 01375 return INT2NUM(ai_get_afamily(rai)); 01376 } 01377 01378 /* 01379 * call-seq: 01380 * addrinfo.pfamily => integer 01381 * 01382 * returns the protocol family as an integer. 01383 * 01384 * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true 01385 * 01386 */ 01387 static VALUE 01388 addrinfo_pfamily(VALUE self) 01389 { 01390 rb_addrinfo_t *rai = get_addrinfo(self); 01391 return INT2NUM(rai->pfamily); 01392 } 01393 01394 /* 01395 * call-seq: 01396 * addrinfo.socktype => integer 01397 * 01398 * returns the socket type as an integer. 01399 * 01400 * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true 01401 * 01402 */ 01403 static VALUE 01404 addrinfo_socktype(VALUE self) 01405 { 01406 rb_addrinfo_t *rai = get_addrinfo(self); 01407 return INT2NUM(rai->socktype); 01408 } 01409 01410 /* 01411 * call-seq: 01412 * addrinfo.protocol => integer 01413 * 01414 * returns the socket type as an integer. 01415 * 01416 * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true 01417 * 01418 */ 01419 static VALUE 01420 addrinfo_protocol(VALUE self) 01421 { 01422 rb_addrinfo_t *rai = get_addrinfo(self); 01423 return INT2NUM(rai->protocol); 01424 } 01425 01426 /* 01427 * call-seq: 01428 * addrinfo.to_sockaddr => string 01429 * addrinfo.to_s => string 01430 * 01431 * returns the socket address as packed struct sockaddr string. 01432 * 01433 * Addrinfo.tcp("localhost", 80).to_sockaddr 01434 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 01435 * 01436 */ 01437 static VALUE 01438 addrinfo_to_sockaddr(VALUE self) 01439 { 01440 rb_addrinfo_t *rai = get_addrinfo(self); 01441 VALUE ret; 01442 ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len); 01443 OBJ_INFECT(ret, self); 01444 return ret; 01445 } 01446 01447 /* 01448 * call-seq: 01449 * addrinfo.canonname => string or nil 01450 * 01451 * returns the canonical name as an string. 01452 * 01453 * nil is returned if no canonical name. 01454 * 01455 * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified. 01456 * 01457 * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME) 01458 * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org)> 01459 * p list[0].canonname #=> "carbon.ruby-lang.org" 01460 * 01461 */ 01462 static VALUE 01463 addrinfo_canonname(VALUE self) 01464 { 01465 rb_addrinfo_t *rai = get_addrinfo(self); 01466 return rai->canonname; 01467 } 01468 01469 /* 01470 * call-seq: 01471 * addrinfo.ip? => true or false 01472 * 01473 * returns true if addrinfo is internet (IPv4/IPv6) address. 01474 * returns false otherwise. 01475 * 01476 * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true 01477 * Addrinfo.tcp("::1", 80).ip? #=> true 01478 * Addrinfo.unix("/tmp/sock").ip? #=> false 01479 * 01480 */ 01481 static VALUE 01482 addrinfo_ip_p(VALUE self) 01483 { 01484 rb_addrinfo_t *rai = get_addrinfo(self); 01485 int family = ai_get_afamily(rai); 01486 return IS_IP_FAMILY(family) ? Qtrue : Qfalse; 01487 } 01488 01489 /* 01490 * call-seq: 01491 * addrinfo.ipv4? => true or false 01492 * 01493 * returns true if addrinfo is IPv4 address. 01494 * returns false otherwise. 01495 * 01496 * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true 01497 * Addrinfo.tcp("::1", 80).ipv4? #=> false 01498 * Addrinfo.unix("/tmp/sock").ipv4? #=> false 01499 * 01500 */ 01501 static VALUE 01502 addrinfo_ipv4_p(VALUE self) 01503 { 01504 rb_addrinfo_t *rai = get_addrinfo(self); 01505 return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse; 01506 } 01507 01508 /* 01509 * call-seq: 01510 * addrinfo.ipv6? => true or false 01511 * 01512 * returns true if addrinfo is IPv6 address. 01513 * returns false otherwise. 01514 * 01515 * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false 01516 * Addrinfo.tcp("::1", 80).ipv6? #=> true 01517 * Addrinfo.unix("/tmp/sock").ipv6? #=> false 01518 * 01519 */ 01520 static VALUE 01521 addrinfo_ipv6_p(VALUE self) 01522 { 01523 #ifdef AF_INET6 01524 rb_addrinfo_t *rai = get_addrinfo(self); 01525 return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse; 01526 #else 01527 return Qfalse; 01528 #endif 01529 } 01530 01531 /* 01532 * call-seq: 01533 * addrinfo.unix? => true or false 01534 * 01535 * returns true if addrinfo is UNIX address. 01536 * returns false otherwise. 01537 * 01538 * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false 01539 * Addrinfo.tcp("::1", 80).unix? #=> false 01540 * Addrinfo.unix("/tmp/sock").unix? #=> true 01541 * 01542 */ 01543 static VALUE 01544 addrinfo_unix_p(VALUE self) 01545 { 01546 rb_addrinfo_t *rai = get_addrinfo(self); 01547 #ifdef AF_UNIX 01548 return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse; 01549 #else 01550 return Qfalse; 01551 #endif 01552 } 01553 01554 /* 01555 * call-seq: 01556 * addrinfo.getnameinfo => [nodename, service] 01557 * addrinfo.getnameinfo(flags) => [nodename, service] 01558 * 01559 * returns nodename and service as a pair of strings. 01560 * This converts struct sockaddr in addrinfo to textual representation. 01561 * 01562 * flags should be bitwise OR of Socket::NI_??? constants. 01563 * 01564 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"] 01565 * 01566 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV) 01567 * #=> ["localhost", "80"] 01568 */ 01569 static VALUE 01570 addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) 01571 { 01572 rb_addrinfo_t *rai = get_addrinfo(self); 01573 VALUE vflags; 01574 char hbuf[1024], pbuf[1024]; 01575 int flags, error; 01576 01577 rb_scan_args(argc, argv, "01", &vflags); 01578 01579 flags = NIL_P(vflags) ? 0 : NUM2INT(vflags); 01580 01581 if (rai->socktype == SOCK_DGRAM) 01582 flags |= NI_DGRAM; 01583 01584 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01585 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01586 flags); 01587 if (error) { 01588 rsock_raise_socket_error("getnameinfo", error); 01589 } 01590 01591 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); 01592 } 01593 01594 /* 01595 * call-seq: 01596 * addrinfo.ip_unpack => [addr, port] 01597 * 01598 * Returns the IP address and port number as 2-element array. 01599 * 01600 * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80] 01601 * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80] 01602 */ 01603 static VALUE 01604 addrinfo_ip_unpack(VALUE self) 01605 { 01606 rb_addrinfo_t *rai = get_addrinfo(self); 01607 int family = ai_get_afamily(rai); 01608 VALUE vflags; 01609 VALUE ret, portstr; 01610 01611 if (!IS_IP_FAMILY(family)) 01612 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01613 01614 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01615 ret = addrinfo_getnameinfo(1, &vflags, self); 01616 portstr = rb_ary_entry(ret, 1); 01617 rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr)))); 01618 return ret; 01619 } 01620 01621 /* 01622 * call-seq: 01623 * addrinfo.ip_address => string 01624 * 01625 * Returns the IP address as a string. 01626 * 01627 * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1" 01628 * Addrinfo.tcp("::1", 80).ip_address #=> "::1" 01629 */ 01630 static VALUE 01631 addrinfo_ip_address(VALUE self) 01632 { 01633 rb_addrinfo_t *rai = get_addrinfo(self); 01634 int family = ai_get_afamily(rai); 01635 VALUE vflags; 01636 VALUE ret; 01637 01638 if (!IS_IP_FAMILY(family)) 01639 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01640 01641 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01642 ret = addrinfo_getnameinfo(1, &vflags, self); 01643 return rb_ary_entry(ret, 0); 01644 } 01645 01646 /* 01647 * call-seq: 01648 * addrinfo.ip_port => port 01649 * 01650 * Returns the port number as an integer. 01651 * 01652 * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80 01653 * Addrinfo.tcp("::1", 80).ip_port #=> 80 01654 */ 01655 static VALUE 01656 addrinfo_ip_port(VALUE self) 01657 { 01658 rb_addrinfo_t *rai = get_addrinfo(self); 01659 int family = ai_get_afamily(rai); 01660 int port; 01661 01662 if (!IS_IP_FAMILY(family)) { 01663 bad_family: 01664 #ifdef AF_INET6 01665 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01666 #else 01667 rb_raise(rb_eSocket, "need IPv4 address"); 01668 #endif 01669 } 01670 01671 switch (family) { 01672 case AF_INET: 01673 if (rai->sockaddr_len != sizeof(struct sockaddr_in)) 01674 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4"); 01675 port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port); 01676 break; 01677 01678 #ifdef AF_INET6 01679 case AF_INET6: 01680 if (rai->sockaddr_len != sizeof(struct sockaddr_in6)) 01681 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6"); 01682 port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port); 01683 break; 01684 #endif 01685 01686 default: 01687 goto bad_family; 01688 } 01689 01690 return INT2NUM(port); 01691 } 01692 01693 static int 01694 extract_in_addr(VALUE self, uint32_t *addrp) 01695 { 01696 rb_addrinfo_t *rai = get_addrinfo(self); 01697 int family = ai_get_afamily(rai); 01698 if (family != AF_INET) return 0; 01699 *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr); 01700 return 1; 01701 } 01702 01703 /* 01704 * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). 01705 * It returns false otherwise. 01706 */ 01707 static VALUE 01708 addrinfo_ipv4_private_p(VALUE self) 01709 { 01710 uint32_t a; 01711 if (!extract_in_addr(self, &a)) return Qfalse; 01712 if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */ 01713 (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */ 01714 (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */ 01715 return Qtrue; 01716 return Qfalse; 01717 } 01718 01719 /* 01720 * Returns true for IPv4 loopback address (127.0.0.0/8). 01721 * It returns false otherwise. 01722 */ 01723 static VALUE 01724 addrinfo_ipv4_loopback_p(VALUE self) 01725 { 01726 uint32_t a; 01727 if (!extract_in_addr(self, &a)) return Qfalse; 01728 if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */ 01729 return Qtrue; 01730 return Qfalse; 01731 } 01732 01733 /* 01734 * Returns true for IPv4 multicast address (224.0.0.0/4). 01735 * It returns false otherwise. 01736 */ 01737 static VALUE 01738 addrinfo_ipv4_multicast_p(VALUE self) 01739 { 01740 uint32_t a; 01741 if (!extract_in_addr(self, &a)) return Qfalse; 01742 if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */ 01743 return Qtrue; 01744 return Qfalse; 01745 } 01746 01747 #ifdef INET6 01748 01749 static struct in6_addr * 01750 extract_in6_addr(VALUE self) 01751 { 01752 rb_addrinfo_t *rai = get_addrinfo(self); 01753 int family = ai_get_afamily(rai); 01754 if (family != AF_INET6) return NULL; 01755 return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01756 } 01757 01758 /* 01759 * Returns true for IPv6 unspecified address (::). 01760 * It returns false otherwise. 01761 */ 01762 static VALUE 01763 addrinfo_ipv6_unspecified_p(VALUE self) 01764 { 01765 struct in6_addr *addr = extract_in6_addr(self); 01766 if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue; 01767 return Qfalse; 01768 } 01769 01770 /* 01771 * Returns true for IPv6 loopback address (::1). 01772 * It returns false otherwise. 01773 */ 01774 static VALUE 01775 addrinfo_ipv6_loopback_p(VALUE self) 01776 { 01777 struct in6_addr *addr = extract_in6_addr(self); 01778 if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue; 01779 return Qfalse; 01780 } 01781 01782 /* 01783 * Returns true for IPv6 multicast address (ff00::/8). 01784 * It returns false otherwise. 01785 */ 01786 static VALUE 01787 addrinfo_ipv6_multicast_p(VALUE self) 01788 { 01789 struct in6_addr *addr = extract_in6_addr(self); 01790 if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue; 01791 return Qfalse; 01792 } 01793 01794 /* 01795 * Returns true for IPv6 link local address (ff80::/10). 01796 * It returns false otherwise. 01797 */ 01798 static VALUE 01799 addrinfo_ipv6_linklocal_p(VALUE self) 01800 { 01801 struct in6_addr *addr = extract_in6_addr(self); 01802 if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue; 01803 return Qfalse; 01804 } 01805 01806 /* 01807 * Returns true for IPv6 site local address (ffc0::/10). 01808 * It returns false otherwise. 01809 */ 01810 static VALUE 01811 addrinfo_ipv6_sitelocal_p(VALUE self) 01812 { 01813 struct in6_addr *addr = extract_in6_addr(self); 01814 if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue; 01815 return Qfalse; 01816 } 01817 01818 /* 01819 * Returns true for IPv6 unique local address (fc00::/7, RFC4193). 01820 * It returns false otherwise. 01821 */ 01822 static VALUE 01823 addrinfo_ipv6_unique_local_p(VALUE self) 01824 { 01825 struct in6_addr *addr = extract_in6_addr(self); 01826 if (addr && IN6_IS_ADDR_UNIQUE_LOCAL(addr)) return Qtrue; 01827 return Qfalse; 01828 } 01829 01830 /* 01831 * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80). 01832 * It returns false otherwise. 01833 */ 01834 static VALUE 01835 addrinfo_ipv6_v4mapped_p(VALUE self) 01836 { 01837 struct in6_addr *addr = extract_in6_addr(self); 01838 if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue; 01839 return Qfalse; 01840 } 01841 01842 /* 01843 * Returns true for IPv4-compatible IPv6 address (::/80). 01844 * It returns false otherwise. 01845 */ 01846 static VALUE 01847 addrinfo_ipv6_v4compat_p(VALUE self) 01848 { 01849 struct in6_addr *addr = extract_in6_addr(self); 01850 if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue; 01851 return Qfalse; 01852 } 01853 01854 /* 01855 * Returns true for IPv6 multicast node-local scope address. 01856 * It returns false otherwise. 01857 */ 01858 static VALUE 01859 addrinfo_ipv6_mc_nodelocal_p(VALUE self) 01860 { 01861 struct in6_addr *addr = extract_in6_addr(self); 01862 if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue; 01863 return Qfalse; 01864 } 01865 01866 /* 01867 * Returns true for IPv6 multicast link-local scope address. 01868 * It returns false otherwise. 01869 */ 01870 static VALUE 01871 addrinfo_ipv6_mc_linklocal_p(VALUE self) 01872 { 01873 struct in6_addr *addr = extract_in6_addr(self); 01874 if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue; 01875 return Qfalse; 01876 } 01877 01878 /* 01879 * Returns true for IPv6 multicast site-local scope address. 01880 * It returns false otherwise. 01881 */ 01882 static VALUE 01883 addrinfo_ipv6_mc_sitelocal_p(VALUE self) 01884 { 01885 struct in6_addr *addr = extract_in6_addr(self); 01886 if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue; 01887 return Qfalse; 01888 } 01889 01890 /* 01891 * Returns true for IPv6 multicast organization-local scope address. 01892 * It returns false otherwise. 01893 */ 01894 static VALUE 01895 addrinfo_ipv6_mc_orglocal_p(VALUE self) 01896 { 01897 struct in6_addr *addr = extract_in6_addr(self); 01898 if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue; 01899 return Qfalse; 01900 } 01901 01902 /* 01903 * Returns true for IPv6 multicast global scope address. 01904 * It returns false otherwise. 01905 */ 01906 static VALUE 01907 addrinfo_ipv6_mc_global_p(VALUE self) 01908 { 01909 struct in6_addr *addr = extract_in6_addr(self); 01910 if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue; 01911 return Qfalse; 01912 } 01913 01914 /* 01915 * Returns IPv4 address of IPv4 mapped/compatible IPv6 address. 01916 * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address. 01917 * 01918 * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01919 * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01920 * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil 01921 * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil 01922 * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil 01923 */ 01924 static VALUE 01925 addrinfo_ipv6_to_ipv4(VALUE self) 01926 { 01927 rb_addrinfo_t *rai = get_addrinfo(self); 01928 struct in6_addr *addr; 01929 int family = ai_get_afamily(rai); 01930 if (family != AF_INET6) return Qnil; 01931 addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01932 if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) { 01933 struct sockaddr_in sin4; 01934 MEMZERO(&sin4, struct sockaddr_in, 1); 01935 sin4.sin_family = AF_INET; 01936 SET_SIN_LEN(&sin4, sizeof(sin4)); 01937 memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr)); 01938 return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4), 01939 PF_INET, rai->socktype, rai->protocol, 01940 rai->canonname, rai->inspectname); 01941 } 01942 else { 01943 return Qnil; 01944 } 01945 } 01946 01947 #endif 01948 01949 #ifdef HAVE_SYS_UN_H 01950 /* 01951 * call-seq: 01952 * addrinfo.unix_path => path 01953 * 01954 * Returns the socket path as a string. 01955 * 01956 * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock" 01957 */ 01958 static VALUE 01959 addrinfo_unix_path(VALUE self) 01960 { 01961 rb_addrinfo_t *rai = get_addrinfo(self); 01962 int family = ai_get_afamily(rai); 01963 struct sockaddr_un *addr; 01964 char *s, *e; 01965 01966 if (family != AF_UNIX) 01967 rb_raise(rb_eSocket, "need AF_UNIX address"); 01968 01969 addr = (struct sockaddr_un *)&rai->addr; 01970 01971 s = addr->sun_path; 01972 e = (char*)addr + rai->sockaddr_len; 01973 if (e < s) 01974 rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.", 01975 (size_t)rai->sockaddr_len, (size_t)(s - (char *)addr)); 01976 if (addr->sun_path + sizeof(addr->sun_path) < e) 01977 rb_raise(rb_eSocket, 01978 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01979 (size_t)(e - addr->sun_path), sizeof(addr->sun_path)); 01980 while (s < e && *(e-1) == '\0') 01981 e--; 01982 return rb_str_new(s, e-s); 01983 } 01984 #endif 01985 01986 /* 01987 * call-seq: 01988 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...] 01989 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...] 01990 * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...] 01991 * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...] 01992 * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...] 01993 * 01994 * returns a list of addrinfo objects as an array. 01995 * 01996 * This method converts nodename (hostname) and service (port) to addrinfo. 01997 * Since the conversion is not unique, the result is a list of addrinfo objects. 01998 * 01999 * nodename or service can be nil if no conversion intended. 02000 * 02001 * family, socktype and protocol are hint for preferred protocol. 02002 * If the result will be used for a socket with SOCK_STREAM, 02003 * SOCK_STREAM should be specified as socktype. 02004 * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM. 02005 * If they are omitted or nil is given, the result is not restricted. 02006 * 02007 * Similarly, PF_INET6 as family restricts for IPv6. 02008 * 02009 * flags should be bitwise OR of Socket::AI_??? constants such as follows. 02010 * Note that the exact list of the constants depends on OS. 02011 * 02012 * AI_PASSIVE Get address to use with bind() 02013 * AI_CANONNAME Fill in the canonical name 02014 * AI_NUMERICHOST Prevent host name resolution 02015 * AI_NUMERICSERV Prevent service name resolution 02016 * AI_V4MAPPED Accept IPv4-mapped IPv6 addresses 02017 * AI_ALL Allow all addresses 02018 * AI_ADDRCONFIG Accept only if any address is assigned 02019 * 02020 * Note that socktype should be specified whenever application knows the usage of the address. 02021 * Some platform causes an error when socktype is omitted and servname is specified as an integer 02022 * because some port numbers, 512 for example, are ambiguous without socktype. 02023 * 02024 * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM) 02025 * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net)>, 02026 * # #<Addrinfo: [2001:200:dff:fff1:216:3eff:feb1:44d7]:80 TCP (www.kame.net)>] 02027 * 02028 */ 02029 static VALUE 02030 addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self) 02031 { 02032 VALUE node, service, family, socktype, protocol, flags; 02033 02034 rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags); 02035 return addrinfo_list_new(node, service, family, socktype, protocol, flags); 02036 } 02037 02038 /* 02039 * call-seq: 02040 * Addrinfo.ip(host) => addrinfo 02041 * 02042 * returns an addrinfo object for IP address. 02043 * 02044 * The port, socktype, protocol of the result is filled by zero. 02045 * So, it is not appropriate to create a socket. 02046 * 02047 * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)> 02048 */ 02049 static VALUE 02050 addrinfo_s_ip(VALUE self, VALUE host) 02051 { 02052 VALUE ret; 02053 rb_addrinfo_t *rai; 02054 ret = addrinfo_firstonly_new(host, Qnil, 02055 INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0)); 02056 rai = get_addrinfo(ret); 02057 rai->socktype = 0; 02058 rai->protocol = 0; 02059 return ret; 02060 } 02061 02062 /* 02063 * call-seq: 02064 * Addrinfo.tcp(host, port) => addrinfo 02065 * 02066 * returns an addrinfo object for TCP address. 02067 * 02068 * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)> 02069 */ 02070 static VALUE 02071 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port) 02072 { 02073 return addrinfo_firstonly_new(host, port, 02074 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0)); 02075 } 02076 02077 /* 02078 * call-seq: 02079 * Addrinfo.udp(host, port) => addrinfo 02080 * 02081 * returns an addrinfo object for UDP address. 02082 * 02083 * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)> 02084 */ 02085 static VALUE 02086 addrinfo_s_udp(VALUE self, VALUE host, VALUE port) 02087 { 02088 return addrinfo_firstonly_new(host, port, 02089 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0)); 02090 } 02091 02092 #ifdef HAVE_SYS_UN_H 02093 02094 /* 02095 * call-seq: 02096 * Addrinfo.unix(path [, socktype]) => addrinfo 02097 * 02098 * returns an addrinfo object for UNIX socket address. 02099 * 02100 * _socktype_ specifies the socket type. 02101 * If it is omitted, :STREAM is used. 02102 * 02103 * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM> 02104 * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM> 02105 */ 02106 static VALUE 02107 addrinfo_s_unix(int argc, VALUE *argv, VALUE self) 02108 { 02109 VALUE path, vsocktype, addr; 02110 int socktype; 02111 rb_addrinfo_t *rai; 02112 02113 rb_scan_args(argc, argv, "11", &path, &vsocktype); 02114 02115 if (NIL_P(vsocktype)) 02116 socktype = SOCK_STREAM; 02117 else 02118 socktype = rsock_socktype_arg(vsocktype); 02119 02120 addr = addrinfo_s_allocate(rb_cAddrinfo); 02121 DATA_PTR(addr) = rai = alloc_addrinfo(); 02122 init_unix_addrinfo(rai, path, socktype); 02123 OBJ_INFECT(addr, path); 02124 return addr; 02125 } 02126 02127 #endif 02128 02129 VALUE 02130 rsock_sockaddr_string_value(volatile VALUE *v) 02131 { 02132 VALUE val = *v; 02133 if (IS_ADDRINFO(val)) { 02134 *v = addrinfo_to_sockaddr(val); 02135 } 02136 StringValue(*v); 02137 return *v; 02138 } 02139 02140 char * 02141 rsock_sockaddr_string_value_ptr(volatile VALUE *v) 02142 { 02143 rsock_sockaddr_string_value(v); 02144 return RSTRING_PTR(*v); 02145 } 02146 02147 VALUE 02148 rb_check_sockaddr_string_type(VALUE val) 02149 { 02150 if (IS_ADDRINFO(val)) 02151 return addrinfo_to_sockaddr(val); 02152 return rb_check_string_type(val); 02153 } 02154 02155 VALUE 02156 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len) 02157 { 02158 int family; 02159 int socktype; 02160 int ret; 02161 socklen_t optlen = (socklen_t)sizeof(socktype); 02162 02163 /* assumes protocol family and address family are identical */ 02164 family = get_afamily(addr, len); 02165 02166 ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); 02167 if (ret == -1) { 02168 rb_sys_fail("getsockopt(SO_TYPE)"); 02169 } 02170 02171 return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil); 02172 } 02173 02174 VALUE 02175 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) 02176 { 02177 rb_io_t *fptr; 02178 02179 switch (TYPE(io)) { 02180 case T_FIXNUM: 02181 return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len); 02182 02183 case T_BIGNUM: 02184 return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len); 02185 02186 case T_FILE: 02187 GetOpenFile(io, fptr); 02188 return rsock_fd_socket_addrinfo(fptr->fd, addr, len); 02189 02190 default: 02191 rb_raise(rb_eTypeError, "neither IO nor file descriptor"); 02192 } 02193 02194 UNREACHABLE; 02195 } 02196 02197 /* 02198 * Addrinfo class 02199 */ 02200 void 02201 rsock_init_addrinfo(void) 02202 { 02203 /* 02204 * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This 02205 * structure identifies an Internet host and a service. 02206 */ 02207 rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); 02208 rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); 02209 rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); 02210 rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); 02211 rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0); 02212 rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1); 02213 rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1); 02214 rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2); 02215 rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2); 02216 #ifdef HAVE_SYS_UN_H 02217 rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1); 02218 #endif 02219 02220 rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0); 02221 rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0); 02222 rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0); 02223 rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0); 02224 rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0); 02225 02226 rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0); 02227 rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0); 02228 rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0); 02229 02230 rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0); 02231 rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0); 02232 rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0); 02233 rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0); 02234 02235 rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0); 02236 rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0); 02237 rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0); 02238 02239 #ifdef INET6 02240 rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0); 02241 rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0); 02242 rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0); 02243 rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0); 02244 rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0); 02245 rb_define_method(rb_cAddrinfo, "ipv6_unique_local?", addrinfo_ipv6_unique_local_p, 0); 02246 rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0); 02247 rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0); 02248 rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0); 02249 rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0); 02250 rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0); 02251 rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0); 02252 rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0); 02253 02254 rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0); 02255 #endif 02256 02257 #ifdef HAVE_SYS_UN_H 02258 rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0); 02259 #endif 02260 02261 rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0); 02262 rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */ 02263 02264 rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1); 02265 02266 rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0); 02267 rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1); 02268 } 02269