|
Ruby
1.9.3p448(2013-06-27revision41675)
|
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 VALUE 00158 nogvl_getaddrinfo(void *arg) 00159 { 00160 struct getaddrinfo_arg *ptr = arg; 00161 return 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)BLOCKING_REGION(nogvl_getaddrinfo, &arg); 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 VALUE 00199 nogvl_getnameinfo(void *arg) 00200 { 00201 struct getnameinfo_arg *ptr = arg; 00202 return 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)BLOCKING_REGION(nogvl_getnameinfo, &arg); 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 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 00691 int ret; 00692 ret = rb_getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 00693 sizeof(hbuf), pbuf, sizeof(pbuf), 00694 NI_NUMERICHOST|NI_NUMERICSERV); 00695 if (ret == 0) { 00696 if (TYPE(node) == T_STRING && strcmp(hbuf, RSTRING_PTR(node)) == 0) 00697 node = Qnil; 00698 if (TYPE(service) == T_STRING && strcmp(pbuf, RSTRING_PTR(service)) == 0) 00699 service = Qnil; 00700 else if (TYPE(service) == T_FIXNUM && atoi(pbuf) == FIX2INT(service)) 00701 service = Qnil; 00702 } 00703 } 00704 00705 if (TYPE(node) == T_STRING) { 00706 inspectname = rb_str_dup(node); 00707 } 00708 if (TYPE(service) == T_STRING) { 00709 if (NIL_P(inspectname)) 00710 inspectname = rb_sprintf(":%s", StringValueCStr(service)); 00711 else 00712 rb_str_catf(inspectname, ":%s", StringValueCStr(service)); 00713 } 00714 else if (TYPE(service) == T_FIXNUM && FIX2INT(service) != 0) 00715 { 00716 if (NIL_P(inspectname)) 00717 inspectname = rb_sprintf(":%d", FIX2INT(service)); 00718 else 00719 rb_str_catf(inspectname, ":%d", FIX2INT(service)); 00720 } 00721 if (!NIL_P(inspectname)) { 00722 OBJ_INFECT(inspectname, node); 00723 OBJ_INFECT(inspectname, service); 00724 OBJ_FREEZE(inspectname); 00725 } 00726 return inspectname; 00727 } 00728 00729 static VALUE 00730 addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00731 { 00732 VALUE ret; 00733 VALUE canonname; 00734 VALUE inspectname; 00735 00736 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00737 00738 inspectname = make_inspectname(node, service, res); 00739 00740 canonname = Qnil; 00741 if (res->ai_canonname) { 00742 canonname = rb_tainted_str_new_cstr(res->ai_canonname); 00743 OBJ_FREEZE(canonname); 00744 } 00745 00746 ret = rsock_addrinfo_new(res->ai_addr, res->ai_addrlen, 00747 res->ai_family, res->ai_socktype, res->ai_protocol, 00748 canonname, inspectname); 00749 00750 freeaddrinfo(res); 00751 return ret; 00752 } 00753 00754 static VALUE 00755 addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) 00756 { 00757 VALUE ret; 00758 struct addrinfo *r; 00759 VALUE inspectname; 00760 00761 struct addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); 00762 00763 inspectname = make_inspectname(node, service, res); 00764 00765 ret = rb_ary_new(); 00766 for (r = res; r; r = r->ai_next) { 00767 VALUE addr; 00768 VALUE canonname = Qnil; 00769 00770 if (r->ai_canonname) { 00771 canonname = rb_tainted_str_new_cstr(r->ai_canonname); 00772 OBJ_FREEZE(canonname); 00773 } 00774 00775 addr = rsock_addrinfo_new(r->ai_addr, r->ai_addrlen, 00776 r->ai_family, r->ai_socktype, r->ai_protocol, 00777 canonname, inspectname); 00778 00779 rb_ary_push(ret, addr); 00780 } 00781 00782 freeaddrinfo(res); 00783 return ret; 00784 } 00785 00786 00787 #ifdef HAVE_SYS_UN_H 00788 static void 00789 init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) 00790 { 00791 struct sockaddr_un un; 00792 socklen_t len; 00793 00794 StringValue(path); 00795 00796 if (sizeof(un.sun_path) < (size_t)RSTRING_LEN(path)) 00797 rb_raise(rb_eArgError, 00798 "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 00799 (size_t)RSTRING_LEN(path), sizeof(un.sun_path)); 00800 00801 MEMZERO(&un, struct sockaddr_un, 1); 00802 00803 un.sun_family = AF_UNIX; 00804 memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); 00805 00806 len = rsock_unix_sockaddr_len(path); 00807 init_addrinfo(rai, (struct sockaddr *)&un, len, 00808 PF_UNIX, socktype, 0, Qnil, Qnil); 00809 } 00810 #endif 00811 00812 /* 00813 * call-seq: 00814 * Addrinfo.new(sockaddr) => addrinfo 00815 * Addrinfo.new(sockaddr, family) => addrinfo 00816 * Addrinfo.new(sockaddr, family, socktype) => addrinfo 00817 * Addrinfo.new(sockaddr, family, socktype, protocol) => addrinfo 00818 * 00819 * returns a new instance of Addrinfo. 00820 * The instance contains sockaddr, family, socktype, protocol. 00821 * sockaddr means struct sockaddr which can be used for connect(2), etc. 00822 * family, socktype and protocol are integers which is used for arguments of socket(2). 00823 * 00824 * sockaddr is specified as an array or a string. 00825 * The array should be compatible to the value of IPSocket#addr or UNIXSocket#addr. 00826 * The string should be struct sockaddr as generated by 00827 * Socket.sockaddr_in or Socket.unpack_sockaddr_un. 00828 * 00829 * sockaddr examples: 00830 * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] 00831 * - ["AF_INET6", 42304, "ip6-localhost", "::1"] 00832 * - ["AF_UNIX", "/tmp/sock"] 00833 * - Socket.sockaddr_in("smtp", "2001:DB8::1") 00834 * - Socket.sockaddr_in(80, "172.18.22.42") 00835 * - Socket.sockaddr_in(80, "www.ruby-lang.org") 00836 * - Socket.sockaddr_un("/tmp/sock") 00837 * 00838 * In an AF_INET/AF_INET6 sockaddr array, the 4th element, 00839 * numeric IP address, is used to construct socket address in the Addrinfo instance. 00840 * If the 3rd element, textual host name, is non-nil, it is also recorded but used only for Addrinfo#inspect. 00841 * 00842 * family is specified as an integer to specify the protocol family such as Socket::PF_INET. 00843 * It can be a symbol or a string which is the constant name 00844 * with or without PF_ prefix such as :INET, :INET6, :UNIX, "PF_INET", etc. 00845 * If omitted, PF_UNSPEC is assumed. 00846 * 00847 * socktype is specified as an integer to specify the socket type such as Socket::SOCK_STREAM. 00848 * It can be a symbol or a string which is the constant name 00849 * with or without SOCK_ prefix such as :STREAM, :DGRAM, :RAW, "SOCK_STREAM", etc. 00850 * If omitted, 0 is assumed. 00851 * 00852 * protocol is specified as an integer to specify the protocol such as Socket::IPPROTO_TCP. 00853 * It must be an integer, unlike family and socktype. 00854 * If omitted, 0 is assumed. 00855 * Note that 0 is reasonable value for most protocols, except raw socket. 00856 * 00857 */ 00858 static VALUE 00859 addrinfo_initialize(int argc, VALUE *argv, VALUE self) 00860 { 00861 rb_addrinfo_t *rai; 00862 VALUE sockaddr_arg, sockaddr_ary, pfamily, socktype, protocol; 00863 int i_pfamily, i_socktype, i_protocol; 00864 struct sockaddr *sockaddr_ptr; 00865 socklen_t sockaddr_len; 00866 VALUE canonname = Qnil, inspectname = Qnil; 00867 00868 if (check_addrinfo(self)) 00869 rb_raise(rb_eTypeError, "already initialized socket address"); 00870 DATA_PTR(self) = rai = alloc_addrinfo(); 00871 00872 rb_scan_args(argc, argv, "13", &sockaddr_arg, &pfamily, &socktype, &protocol); 00873 00874 i_pfamily = NIL_P(pfamily) ? PF_UNSPEC : rsock_family_arg(pfamily); 00875 i_socktype = NIL_P(socktype) ? 0 : rsock_socktype_arg(socktype); 00876 i_protocol = NIL_P(protocol) ? 0 : NUM2INT(protocol); 00877 00878 sockaddr_ary = rb_check_array_type(sockaddr_arg); 00879 if (!NIL_P(sockaddr_ary)) { 00880 VALUE afamily = rb_ary_entry(sockaddr_ary, 0); 00881 int af; 00882 StringValue(afamily); 00883 if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1) 00884 rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); 00885 switch (af) { 00886 case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */ 00887 #ifdef INET6 00888 case AF_INET6: /* ["AF_INET6", 42304, "ip6-localhost", "::1"] */ 00889 #endif 00890 { 00891 VALUE service = rb_ary_entry(sockaddr_ary, 1); 00892 VALUE nodename = rb_ary_entry(sockaddr_ary, 2); 00893 VALUE numericnode = rb_ary_entry(sockaddr_ary, 3); 00894 int flags; 00895 00896 service = INT2NUM(NUM2INT(service)); 00897 if (!NIL_P(nodename)) 00898 StringValue(nodename); 00899 StringValue(numericnode); 00900 flags = AI_NUMERICHOST; 00901 #ifdef AI_NUMERICSERV 00902 flags |= AI_NUMERICSERV; 00903 #endif 00904 00905 init_addrinfo_getaddrinfo(rai, numericnode, service, 00906 INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol), 00907 INT2NUM(flags), 00908 nodename, service); 00909 break; 00910 } 00911 00912 #ifdef HAVE_SYS_UN_H 00913 case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */ 00914 { 00915 VALUE path = rb_ary_entry(sockaddr_ary, 1); 00916 StringValue(path); 00917 init_unix_addrinfo(rai, path, SOCK_STREAM); 00918 break; 00919 } 00920 #endif 00921 00922 default: 00923 rb_raise(rb_eSocket, "unexpected address family"); 00924 } 00925 } 00926 else { 00927 StringValue(sockaddr_arg); 00928 sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg); 00929 sockaddr_len = RSTRING_LENINT(sockaddr_arg); 00930 init_addrinfo(rai, sockaddr_ptr, sockaddr_len, 00931 i_pfamily, i_socktype, i_protocol, 00932 canonname, inspectname); 00933 } 00934 00935 return self; 00936 } 00937 00938 static int 00939 get_afamily(struct sockaddr *addr, socklen_t len) 00940 { 00941 if ((socklen_t)((char*)&addr->sa_family + sizeof(addr->sa_family) - (char*)addr) <= len) 00942 return addr->sa_family; 00943 else 00944 return AF_UNSPEC; 00945 } 00946 00947 static int 00948 ai_get_afamily(rb_addrinfo_t *rai) 00949 { 00950 return get_afamily((struct sockaddr *)&rai->addr, rai->sockaddr_len); 00951 } 00952 00953 static VALUE 00954 inspect_sockaddr(VALUE addrinfo, VALUE ret) 00955 { 00956 rb_addrinfo_t *rai = get_addrinfo(addrinfo); 00957 00958 if (rai->sockaddr_len == 0) { 00959 rb_str_cat2(ret, "empty-sockaddr"); 00960 } 00961 else if ((long)rai->sockaddr_len < ((char*)&rai->addr.ss_family + sizeof(rai->addr.ss_family)) - (char*)&rai->addr) 00962 rb_str_cat2(ret, "too-short-sockaddr"); 00963 else { 00964 switch (rai->addr.ss_family) { 00965 case AF_INET: 00966 { 00967 struct sockaddr_in *addr; 00968 int port; 00969 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in)) { 00970 rb_str_cat2(ret, "too-short-AF_INET-sockaddr"); 00971 } 00972 else { 00973 addr = (struct sockaddr_in *)&rai->addr; 00974 rb_str_catf(ret, "%d.%d.%d.%d", 00975 ((unsigned char*)&addr->sin_addr)[0], 00976 ((unsigned char*)&addr->sin_addr)[1], 00977 ((unsigned char*)&addr->sin_addr)[2], 00978 ((unsigned char*)&addr->sin_addr)[3]); 00979 port = ntohs(addr->sin_port); 00980 if (port) 00981 rb_str_catf(ret, ":%d", port); 00982 if ((socklen_t)sizeof(struct sockaddr_in) < rai->sockaddr_len) 00983 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in))); 00984 } 00985 break; 00986 } 00987 00988 #ifdef AF_INET6 00989 case AF_INET6: 00990 { 00991 struct sockaddr_in6 *addr; 00992 char hbuf[1024]; 00993 int port; 00994 int error; 00995 if (rai->sockaddr_len < (socklen_t)sizeof(struct sockaddr_in6)) { 00996 rb_str_cat2(ret, "too-short-AF_INET6-sockaddr"); 00997 } 00998 else { 00999 addr = (struct sockaddr_in6 *)&rai->addr; 01000 /* use getnameinfo for scope_id. 01001 * RFC 4007: IPv6 Scoped Address Architecture 01002 * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API 01003 */ 01004 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01005 hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 01006 NI_NUMERICHOST|NI_NUMERICSERV); 01007 if (error) { 01008 rsock_raise_socket_error("getnameinfo", error); 01009 } 01010 if (addr->sin6_port == 0) { 01011 rb_str_cat2(ret, hbuf); 01012 } 01013 else { 01014 port = ntohs(addr->sin6_port); 01015 rb_str_catf(ret, "[%s]:%d", hbuf, port); 01016 } 01017 if ((socklen_t)sizeof(struct sockaddr_in6) < rai->sockaddr_len) 01018 rb_str_catf(ret, "(sockaddr %d bytes too long)", (int)(rai->sockaddr_len - sizeof(struct sockaddr_in6))); 01019 } 01020 break; 01021 } 01022 #endif 01023 01024 #ifdef HAVE_SYS_UN_H 01025 case AF_UNIX: 01026 { 01027 struct sockaddr_un *addr = (struct sockaddr_un *)&rai->addr; 01028 char *p, *s, *e; 01029 s = addr->sun_path; 01030 e = (char*)addr + rai->sockaddr_len; 01031 while (s < e && *(e-1) == '\0') 01032 e--; 01033 if (e < s) 01034 rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr"); 01035 else if (s == e) 01036 rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr"); 01037 else { 01038 int printable_only = 1; 01039 p = s; 01040 while (p < e) { 01041 printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p); 01042 p++; 01043 } 01044 if (printable_only) { /* only printable, no space */ 01045 if (s[0] != '/') /* relative path */ 01046 rb_str_cat2(ret, "AF_UNIX "); 01047 rb_str_cat(ret, s, p - s); 01048 } 01049 else { 01050 rb_str_cat2(ret, "AF_UNIX"); 01051 while (s < e) 01052 rb_str_catf(ret, ":%02x", (unsigned char)*s++); 01053 } 01054 if (addr->sun_path + sizeof(addr->sun_path) < (char*)&rai->addr + rai->sockaddr_len) 01055 rb_str_catf(ret, "(sockaddr %d bytes too long)", 01056 (int)(rai->sockaddr_len - (addr->sun_path + sizeof(addr->sun_path) - (char*)&rai->addr))); 01057 } 01058 break; 01059 } 01060 #endif 01061 01062 default: 01063 { 01064 ID id = rsock_intern_family(rai->addr.ss_family); 01065 if (id == 0) 01066 rb_str_catf(ret, "unknown address family %d", rai->addr.ss_family); 01067 else 01068 rb_str_catf(ret, "%s address format unknown", rb_id2name(id)); 01069 break; 01070 } 01071 } 01072 } 01073 01074 return ret; 01075 } 01076 01077 /* 01078 * call-seq: 01079 * addrinfo.inspect => string 01080 * 01081 * returns a string which shows addrinfo in human-readable form. 01082 * 01083 * Addrinfo.tcp("localhost", 80).inspect #=> "#<Addrinfo: 127.0.0.1:80 TCP (localhost:80)>" 01084 * Addrinfo.unix("/tmp/sock").inspect #=> "#<Addrinfo: /tmp/sock SOCK_STREAM>" 01085 * 01086 */ 01087 static VALUE 01088 addrinfo_inspect(VALUE self) 01089 { 01090 rb_addrinfo_t *rai = get_addrinfo(self); 01091 int internet_p; 01092 VALUE ret; 01093 01094 ret = rb_sprintf("#<%s: ", rb_obj_classname(self)); 01095 01096 inspect_sockaddr(self, ret); 01097 01098 if (rai->pfamily && ai_get_afamily(rai) != rai->pfamily) { 01099 ID id = rsock_intern_protocol_family(rai->pfamily); 01100 if (id) 01101 rb_str_catf(ret, " %s", rb_id2name(id)); 01102 else 01103 rb_str_catf(ret, " PF_\?\?\?(%d)", rai->pfamily); 01104 } 01105 01106 internet_p = rai->pfamily == PF_INET; 01107 #ifdef INET6 01108 internet_p = internet_p || rai->pfamily == PF_INET6; 01109 #endif 01110 if (internet_p && rai->socktype == SOCK_STREAM && 01111 (rai->protocol == 0 || rai->protocol == IPPROTO_TCP)) { 01112 rb_str_cat2(ret, " TCP"); 01113 } 01114 else if (internet_p && rai->socktype == SOCK_DGRAM && 01115 (rai->protocol == 0 || rai->protocol == IPPROTO_UDP)) { 01116 rb_str_cat2(ret, " UDP"); 01117 } 01118 else { 01119 if (rai->socktype) { 01120 ID id = rsock_intern_socktype(rai->socktype); 01121 if (id) 01122 rb_str_catf(ret, " %s", rb_id2name(id)); 01123 else 01124 rb_str_catf(ret, " SOCK_\?\?\?(%d)", rai->socktype); 01125 } 01126 01127 if (rai->protocol) { 01128 if (internet_p) { 01129 ID id = rsock_intern_ipproto(rai->protocol); 01130 if (id) 01131 rb_str_catf(ret, " %s", rb_id2name(id)); 01132 else 01133 goto unknown_protocol; 01134 } 01135 else { 01136 unknown_protocol: 01137 rb_str_catf(ret, " UNKNOWN_PROTOCOL(%d)", rai->protocol); 01138 } 01139 } 01140 } 01141 01142 if (!NIL_P(rai->canonname)) { 01143 VALUE name = rai->canonname; 01144 rb_str_catf(ret, " %s", StringValueCStr(name)); 01145 } 01146 01147 if (!NIL_P(rai->inspectname)) { 01148 VALUE name = rai->inspectname; 01149 rb_str_catf(ret, " (%s)", StringValueCStr(name)); 01150 } 01151 01152 rb_str_buf_cat2(ret, ">"); 01153 return ret; 01154 } 01155 01156 /* 01157 * call-seq: 01158 * addrinfo.inspect_sockaddr => string 01159 * 01160 * returns a string which shows the sockaddr in _addrinfo_ with human-readable form. 01161 * 01162 * Addrinfo.tcp("localhost", 80).inspect_sockaddr #=> "127.0.0.1:80" 01163 * Addrinfo.tcp("ip6-localhost", 80).inspect_sockaddr #=> "[::1]:80" 01164 * Addrinfo.unix("/tmp/sock").inspect_sockaddr #=> "/tmp/sock" 01165 * 01166 */ 01167 static VALUE 01168 addrinfo_inspect_sockaddr(VALUE self) 01169 { 01170 return inspect_sockaddr(self, rb_str_new("", 0)); 01171 } 01172 01173 /* :nodoc: */ 01174 static VALUE 01175 addrinfo_mdump(VALUE self) 01176 { 01177 rb_addrinfo_t *rai = get_addrinfo(self); 01178 VALUE sockaddr, afamily, pfamily, socktype, protocol, canonname, inspectname; 01179 int afamily_int = ai_get_afamily(rai); 01180 ID id; 01181 01182 id = rsock_intern_protocol_family(rai->pfamily); 01183 if (id == 0) 01184 rb_raise(rb_eSocket, "unknown protocol family: %d", rai->pfamily); 01185 pfamily = rb_id2str(id); 01186 01187 if (rai->socktype == 0) 01188 socktype = INT2FIX(0); 01189 else { 01190 id = rsock_intern_socktype(rai->socktype); 01191 if (id == 0) 01192 rb_raise(rb_eSocket, "unknown socktype: %d", rai->socktype); 01193 socktype = rb_id2str(id); 01194 } 01195 01196 if (rai->protocol == 0) 01197 protocol = INT2FIX(0); 01198 else if (IS_IP_FAMILY(afamily_int)) { 01199 id = rsock_intern_ipproto(rai->protocol); 01200 if (id == 0) 01201 rb_raise(rb_eSocket, "unknown IP protocol: %d", rai->protocol); 01202 protocol = rb_id2str(id); 01203 } 01204 else { 01205 rb_raise(rb_eSocket, "unknown protocol: %d", rai->protocol); 01206 } 01207 01208 canonname = rai->canonname; 01209 01210 inspectname = rai->inspectname; 01211 01212 id = rsock_intern_family(afamily_int); 01213 if (id == 0) 01214 rb_raise(rb_eSocket, "unknown address family: %d", afamily_int); 01215 afamily = rb_id2str(id); 01216 01217 switch(afamily_int) { 01218 #ifdef HAVE_SYS_UN_H 01219 case AF_UNIX: 01220 { 01221 struct sockaddr_un *su = (struct sockaddr_un *)&rai->addr; 01222 char *s, *e; 01223 s = su->sun_path; 01224 e = (char*)su + rai->sockaddr_len; 01225 while (s < e && *(e-1) == '\0') 01226 e--; 01227 sockaddr = rb_str_new(s, e-s); 01228 break; 01229 } 01230 #endif 01231 01232 default: 01233 { 01234 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 01235 int error; 01236 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01237 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01238 NI_NUMERICHOST|NI_NUMERICSERV); 01239 if (error) { 01240 rsock_raise_socket_error("getnameinfo", error); 01241 } 01242 sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); 01243 break; 01244 } 01245 } 01246 01247 return rb_ary_new3(7, afamily, sockaddr, pfamily, socktype, protocol, canonname, inspectname); 01248 } 01249 01250 /* :nodoc: */ 01251 static VALUE 01252 addrinfo_mload(VALUE self, VALUE ary) 01253 { 01254 VALUE v; 01255 VALUE canonname, inspectname; 01256 int afamily, pfamily, socktype, protocol; 01257 struct sockaddr_storage ss; 01258 socklen_t len; 01259 rb_addrinfo_t *rai; 01260 01261 if (check_addrinfo(self)) 01262 rb_raise(rb_eTypeError, "already initialized socket address"); 01263 01264 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 01265 01266 v = rb_ary_entry(ary, 0); 01267 StringValue(v); 01268 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &afamily) == -1) 01269 rb_raise(rb_eTypeError, "unexpected address family"); 01270 01271 v = rb_ary_entry(ary, 2); 01272 StringValue(v); 01273 if (rsock_family_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &pfamily) == -1) 01274 rb_raise(rb_eTypeError, "unexpected protocol family"); 01275 01276 v = rb_ary_entry(ary, 3); 01277 if (v == INT2FIX(0)) 01278 socktype = 0; 01279 else { 01280 StringValue(v); 01281 if (rsock_socktype_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &socktype) == -1) 01282 rb_raise(rb_eTypeError, "unexpected socktype"); 01283 } 01284 01285 v = rb_ary_entry(ary, 4); 01286 if (v == INT2FIX(0)) 01287 protocol = 0; 01288 else { 01289 StringValue(v); 01290 if (IS_IP_FAMILY(afamily)) { 01291 if (rsock_ipproto_to_int(RSTRING_PTR(v), RSTRING_LEN(v), &protocol) == -1) 01292 rb_raise(rb_eTypeError, "unexpected protocol"); 01293 } 01294 else { 01295 rb_raise(rb_eTypeError, "unexpected protocol"); 01296 } 01297 } 01298 01299 v = rb_ary_entry(ary, 5); 01300 if (NIL_P(v)) 01301 canonname = Qnil; 01302 else { 01303 StringValue(v); 01304 canonname = v; 01305 } 01306 01307 v = rb_ary_entry(ary, 6); 01308 if (NIL_P(v)) 01309 inspectname = Qnil; 01310 else { 01311 StringValue(v); 01312 inspectname = v; 01313 } 01314 01315 v = rb_ary_entry(ary, 1); 01316 switch(afamily) { 01317 #ifdef HAVE_SYS_UN_H 01318 case AF_UNIX: 01319 { 01320 struct sockaddr_un uaddr; 01321 MEMZERO(&uaddr, struct sockaddr_un, 1); 01322 uaddr.sun_family = AF_UNIX; 01323 01324 StringValue(v); 01325 if (sizeof(uaddr.sun_path) < (size_t)RSTRING_LEN(v)) 01326 rb_raise(rb_eSocket, 01327 "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", 01328 (size_t)RSTRING_LEN(v), sizeof(uaddr.sun_path)); 01329 memcpy(uaddr.sun_path, RSTRING_PTR(v), RSTRING_LEN(v)); 01330 len = (socklen_t)sizeof(uaddr); 01331 memcpy(&ss, &uaddr, len); 01332 break; 01333 } 01334 #endif 01335 01336 default: 01337 { 01338 VALUE pair = rb_convert_type(v, T_ARRAY, "Array", "to_ary"); 01339 struct addrinfo *res; 01340 int flags = AI_NUMERICHOST; 01341 #ifdef AI_NUMERICSERV 01342 flags |= AI_NUMERICSERV; 01343 #endif 01344 res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), 01345 INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol), 01346 INT2NUM(flags), 1); 01347 01348 len = res->ai_addrlen; 01349 memcpy(&ss, res->ai_addr, res->ai_addrlen); 01350 break; 01351 } 01352 } 01353 01354 DATA_PTR(self) = rai = alloc_addrinfo(); 01355 init_addrinfo(rai, (struct sockaddr *)&ss, len, 01356 pfamily, socktype, protocol, 01357 canonname, inspectname); 01358 return self; 01359 } 01360 01361 /* 01362 * call-seq: 01363 * addrinfo.afamily => integer 01364 * 01365 * returns the address family as an integer. 01366 * 01367 * Addrinfo.tcp("localhost", 80).afamily == Socket::AF_INET #=> true 01368 * 01369 */ 01370 static VALUE 01371 addrinfo_afamily(VALUE self) 01372 { 01373 rb_addrinfo_t *rai = get_addrinfo(self); 01374 return INT2NUM(ai_get_afamily(rai)); 01375 } 01376 01377 /* 01378 * call-seq: 01379 * addrinfo.pfamily => integer 01380 * 01381 * returns the protocol family as an integer. 01382 * 01383 * Addrinfo.tcp("localhost", 80).pfamily == Socket::PF_INET #=> true 01384 * 01385 */ 01386 static VALUE 01387 addrinfo_pfamily(VALUE self) 01388 { 01389 rb_addrinfo_t *rai = get_addrinfo(self); 01390 return INT2NUM(rai->pfamily); 01391 } 01392 01393 /* 01394 * call-seq: 01395 * addrinfo.socktype => integer 01396 * 01397 * returns the socket type as an integer. 01398 * 01399 * Addrinfo.tcp("localhost", 80).socktype == Socket::SOCK_STREAM #=> true 01400 * 01401 */ 01402 static VALUE 01403 addrinfo_socktype(VALUE self) 01404 { 01405 rb_addrinfo_t *rai = get_addrinfo(self); 01406 return INT2NUM(rai->socktype); 01407 } 01408 01409 /* 01410 * call-seq: 01411 * addrinfo.protocol => integer 01412 * 01413 * returns the socket type as an integer. 01414 * 01415 * Addrinfo.tcp("localhost", 80).protocol == Socket::IPPROTO_TCP #=> true 01416 * 01417 */ 01418 static VALUE 01419 addrinfo_protocol(VALUE self) 01420 { 01421 rb_addrinfo_t *rai = get_addrinfo(self); 01422 return INT2NUM(rai->protocol); 01423 } 01424 01425 /* 01426 * call-seq: 01427 * addrinfo.to_sockaddr => string 01428 * addrinfo.to_s => string 01429 * 01430 * returns the socket address as packed struct sockaddr string. 01431 * 01432 * Addrinfo.tcp("localhost", 80).to_sockaddr 01433 * #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" 01434 * 01435 */ 01436 static VALUE 01437 addrinfo_to_sockaddr(VALUE self) 01438 { 01439 rb_addrinfo_t *rai = get_addrinfo(self); 01440 VALUE ret; 01441 ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len); 01442 OBJ_INFECT(ret, self); 01443 return ret; 01444 } 01445 01446 /* 01447 * call-seq: 01448 * addrinfo.canonname => string or nil 01449 * 01450 * returns the canonical name as an string. 01451 * 01452 * nil is returned if no canonical name. 01453 * 01454 * The canonical name is set by Addrinfo.getaddrinfo when AI_CANONNAME is specified. 01455 * 01456 * list = Addrinfo.getaddrinfo("www.ruby-lang.org", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME) 01457 * p list[0] #=> #<Addrinfo: 221.186.184.68:80 TCP carbon.ruby-lang.org (www.ruby-lang.org:80)> 01458 * p list[0].canonname #=> "carbon.ruby-lang.org" 01459 * 01460 */ 01461 static VALUE 01462 addrinfo_canonname(VALUE self) 01463 { 01464 rb_addrinfo_t *rai = get_addrinfo(self); 01465 return rai->canonname; 01466 } 01467 01468 /* 01469 * call-seq: 01470 * addrinfo.ip? => true or false 01471 * 01472 * returns true if addrinfo is internet (IPv4/IPv6) address. 01473 * returns false otherwise. 01474 * 01475 * Addrinfo.tcp("127.0.0.1", 80).ip? #=> true 01476 * Addrinfo.tcp("::1", 80).ip? #=> true 01477 * Addrinfo.unix("/tmp/sock").ip? #=> false 01478 * 01479 */ 01480 static VALUE 01481 addrinfo_ip_p(VALUE self) 01482 { 01483 rb_addrinfo_t *rai = get_addrinfo(self); 01484 int family = ai_get_afamily(rai); 01485 return IS_IP_FAMILY(family) ? Qtrue : Qfalse; 01486 } 01487 01488 /* 01489 * call-seq: 01490 * addrinfo.ipv4? => true or false 01491 * 01492 * returns true if addrinfo is IPv4 address. 01493 * returns false otherwise. 01494 * 01495 * Addrinfo.tcp("127.0.0.1", 80).ipv4? #=> true 01496 * Addrinfo.tcp("::1", 80).ipv4? #=> false 01497 * Addrinfo.unix("/tmp/sock").ipv4? #=> false 01498 * 01499 */ 01500 static VALUE 01501 addrinfo_ipv4_p(VALUE self) 01502 { 01503 rb_addrinfo_t *rai = get_addrinfo(self); 01504 return ai_get_afamily(rai) == AF_INET ? Qtrue : Qfalse; 01505 } 01506 01507 /* 01508 * call-seq: 01509 * addrinfo.ipv6? => true or false 01510 * 01511 * returns true if addrinfo is IPv6 address. 01512 * returns false otherwise. 01513 * 01514 * Addrinfo.tcp("127.0.0.1", 80).ipv6? #=> false 01515 * Addrinfo.tcp("::1", 80).ipv6? #=> true 01516 * Addrinfo.unix("/tmp/sock").ipv6? #=> false 01517 * 01518 */ 01519 static VALUE 01520 addrinfo_ipv6_p(VALUE self) 01521 { 01522 #ifdef AF_INET6 01523 rb_addrinfo_t *rai = get_addrinfo(self); 01524 return ai_get_afamily(rai) == AF_INET6 ? Qtrue : Qfalse; 01525 #else 01526 return Qfalse; 01527 #endif 01528 } 01529 01530 /* 01531 * call-seq: 01532 * addrinfo.unix? => true or false 01533 * 01534 * returns true if addrinfo is UNIX address. 01535 * returns false otherwise. 01536 * 01537 * Addrinfo.tcp("127.0.0.1", 80).unix? #=> false 01538 * Addrinfo.tcp("::1", 80).unix? #=> false 01539 * Addrinfo.unix("/tmp/sock").unix? #=> true 01540 * 01541 */ 01542 static VALUE 01543 addrinfo_unix_p(VALUE self) 01544 { 01545 rb_addrinfo_t *rai = get_addrinfo(self); 01546 #ifdef AF_UNIX 01547 return ai_get_afamily(rai) == AF_UNIX ? Qtrue : Qfalse; 01548 #else 01549 return Qfalse; 01550 #endif 01551 } 01552 01553 /* 01554 * call-seq: 01555 * addrinfo.getnameinfo => [nodename, service] 01556 * addrinfo.getnameinfo(flags) => [nodename, service] 01557 * 01558 * returns nodename and service as a pair of strings. 01559 * This converts struct sockaddr in addrinfo to textual representation. 01560 * 01561 * flags should be bitwise OR of Socket::NI_??? constants. 01562 * 01563 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo #=> ["localhost", "www"] 01564 * 01565 * Addrinfo.tcp("127.0.0.1", 80).getnameinfo(Socket::NI_NUMERICSERV) 01566 * #=> ["localhost", "80"] 01567 */ 01568 static VALUE 01569 addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) 01570 { 01571 rb_addrinfo_t *rai = get_addrinfo(self); 01572 VALUE vflags; 01573 char hbuf[1024], pbuf[1024]; 01574 int flags, error; 01575 01576 rb_scan_args(argc, argv, "01", &vflags); 01577 01578 flags = NIL_P(vflags) ? 0 : NUM2INT(vflags); 01579 01580 if (rai->socktype == SOCK_DGRAM) 01581 flags |= NI_DGRAM; 01582 01583 error = getnameinfo((struct sockaddr *)&rai->addr, rai->sockaddr_len, 01584 hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), 01585 flags); 01586 if (error) { 01587 rsock_raise_socket_error("getnameinfo", error); 01588 } 01589 01590 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); 01591 } 01592 01593 /* 01594 * call-seq: 01595 * addrinfo.ip_unpack => [addr, port] 01596 * 01597 * Returns the IP address and port number as 2-element array. 01598 * 01599 * Addrinfo.tcp("127.0.0.1", 80).ip_unpack #=> ["127.0.0.1", 80] 01600 * Addrinfo.tcp("::1", 80).ip_unpack #=> ["::1", 80] 01601 */ 01602 static VALUE 01603 addrinfo_ip_unpack(VALUE self) 01604 { 01605 rb_addrinfo_t *rai = get_addrinfo(self); 01606 int family = ai_get_afamily(rai); 01607 VALUE vflags; 01608 VALUE ret, portstr; 01609 01610 if (!IS_IP_FAMILY(family)) 01611 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01612 01613 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01614 ret = addrinfo_getnameinfo(1, &vflags, self); 01615 portstr = rb_ary_entry(ret, 1); 01616 rb_ary_store(ret, 1, INT2NUM(atoi(StringValueCStr(portstr)))); 01617 return ret; 01618 } 01619 01620 /* 01621 * call-seq: 01622 * addrinfo.ip_address => string 01623 * 01624 * Returns the IP address as a string. 01625 * 01626 * Addrinfo.tcp("127.0.0.1", 80).ip_address #=> "127.0.0.1" 01627 * Addrinfo.tcp("::1", 80).ip_address #=> "::1" 01628 */ 01629 static VALUE 01630 addrinfo_ip_address(VALUE self) 01631 { 01632 rb_addrinfo_t *rai = get_addrinfo(self); 01633 int family = ai_get_afamily(rai); 01634 VALUE vflags; 01635 VALUE ret; 01636 01637 if (!IS_IP_FAMILY(family)) 01638 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01639 01640 vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); 01641 ret = addrinfo_getnameinfo(1, &vflags, self); 01642 return rb_ary_entry(ret, 0); 01643 } 01644 01645 /* 01646 * call-seq: 01647 * addrinfo.ip_port => port 01648 * 01649 * Returns the port number as an integer. 01650 * 01651 * Addrinfo.tcp("127.0.0.1", 80).ip_port #=> 80 01652 * Addrinfo.tcp("::1", 80).ip_port #=> 80 01653 */ 01654 static VALUE 01655 addrinfo_ip_port(VALUE self) 01656 { 01657 rb_addrinfo_t *rai = get_addrinfo(self); 01658 int family = ai_get_afamily(rai); 01659 int port; 01660 01661 if (!IS_IP_FAMILY(family)) { 01662 bad_family: 01663 #ifdef AF_INET6 01664 rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); 01665 #else 01666 rb_raise(rb_eSocket, "need IPv4 address"); 01667 #endif 01668 } 01669 01670 switch (family) { 01671 case AF_INET: 01672 if (rai->sockaddr_len != sizeof(struct sockaddr_in)) 01673 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv4"); 01674 port = ntohs(((struct sockaddr_in *)&rai->addr)->sin_port); 01675 break; 01676 01677 #ifdef AF_INET6 01678 case AF_INET6: 01679 if (rai->sockaddr_len != sizeof(struct sockaddr_in6)) 01680 rb_raise(rb_eSocket, "unexpected sockaddr size for IPv6"); 01681 port = ntohs(((struct sockaddr_in6 *)&rai->addr)->sin6_port); 01682 break; 01683 #endif 01684 01685 default: 01686 goto bad_family; 01687 } 01688 01689 return INT2NUM(port); 01690 } 01691 01692 static int 01693 extract_in_addr(VALUE self, uint32_t *addrp) 01694 { 01695 rb_addrinfo_t *rai = get_addrinfo(self); 01696 int family = ai_get_afamily(rai); 01697 if (family != AF_INET) return 0; 01698 *addrp = ntohl(((struct sockaddr_in *)&rai->addr)->sin_addr.s_addr); 01699 return 1; 01700 } 01701 01702 /* 01703 * Returns true for IPv4 private address (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). 01704 * It returns false otherwise. 01705 */ 01706 static VALUE 01707 addrinfo_ipv4_private_p(VALUE self) 01708 { 01709 uint32_t a; 01710 if (!extract_in_addr(self, &a)) return Qfalse; 01711 if ((a & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */ 01712 (a & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */ 01713 (a & 0xffff0000) == 0xc0a80000) /* 192.168.0.0/16 */ 01714 return Qtrue; 01715 return Qfalse; 01716 } 01717 01718 /* 01719 * Returns true for IPv4 loopback address (127.0.0.0/8). 01720 * It returns false otherwise. 01721 */ 01722 static VALUE 01723 addrinfo_ipv4_loopback_p(VALUE self) 01724 { 01725 uint32_t a; 01726 if (!extract_in_addr(self, &a)) return Qfalse; 01727 if ((a & 0xff000000) == 0x7f000000) /* 127.0.0.0/8 */ 01728 return Qtrue; 01729 return Qfalse; 01730 } 01731 01732 /* 01733 * Returns true for IPv4 multicast address (224.0.0.0/4). 01734 * It returns false otherwise. 01735 */ 01736 static VALUE 01737 addrinfo_ipv4_multicast_p(VALUE self) 01738 { 01739 uint32_t a; 01740 if (!extract_in_addr(self, &a)) return Qfalse; 01741 if ((a & 0xf0000000) == 0xe0000000) /* 224.0.0.0/4 */ 01742 return Qtrue; 01743 return Qfalse; 01744 } 01745 01746 #ifdef INET6 01747 01748 static struct in6_addr * 01749 extract_in6_addr(VALUE self) 01750 { 01751 rb_addrinfo_t *rai = get_addrinfo(self); 01752 int family = ai_get_afamily(rai); 01753 if (family != AF_INET6) return NULL; 01754 return &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01755 } 01756 01757 /* 01758 * Returns true for IPv6 unspecified address (::). 01759 * It returns false otherwise. 01760 */ 01761 static VALUE 01762 addrinfo_ipv6_unspecified_p(VALUE self) 01763 { 01764 struct in6_addr *addr = extract_in6_addr(self); 01765 if (addr && IN6_IS_ADDR_UNSPECIFIED(addr)) return Qtrue; 01766 return Qfalse; 01767 } 01768 01769 /* 01770 * Returns true for IPv6 loopback address (::1). 01771 * It returns false otherwise. 01772 */ 01773 static VALUE 01774 addrinfo_ipv6_loopback_p(VALUE self) 01775 { 01776 struct in6_addr *addr = extract_in6_addr(self); 01777 if (addr && IN6_IS_ADDR_LOOPBACK(addr)) return Qtrue; 01778 return Qfalse; 01779 } 01780 01781 /* 01782 * Returns true for IPv6 multicast address (ff00::/8). 01783 * It returns false otherwise. 01784 */ 01785 static VALUE 01786 addrinfo_ipv6_multicast_p(VALUE self) 01787 { 01788 struct in6_addr *addr = extract_in6_addr(self); 01789 if (addr && IN6_IS_ADDR_MULTICAST(addr)) return Qtrue; 01790 return Qfalse; 01791 } 01792 01793 /* 01794 * Returns true for IPv6 link local address (ff80::/10). 01795 * It returns false otherwise. 01796 */ 01797 static VALUE 01798 addrinfo_ipv6_linklocal_p(VALUE self) 01799 { 01800 struct in6_addr *addr = extract_in6_addr(self); 01801 if (addr && IN6_IS_ADDR_LINKLOCAL(addr)) return Qtrue; 01802 return Qfalse; 01803 } 01804 01805 /* 01806 * Returns true for IPv6 site local address (ffc0::/10). 01807 * It returns false otherwise. 01808 */ 01809 static VALUE 01810 addrinfo_ipv6_sitelocal_p(VALUE self) 01811 { 01812 struct in6_addr *addr = extract_in6_addr(self); 01813 if (addr && IN6_IS_ADDR_SITELOCAL(addr)) return Qtrue; 01814 return Qfalse; 01815 } 01816 01817 /* 01818 * Returns true for IPv4-mapped IPv6 address (::ffff:0:0/80). 01819 * It returns false otherwise. 01820 */ 01821 static VALUE 01822 addrinfo_ipv6_v4mapped_p(VALUE self) 01823 { 01824 struct in6_addr *addr = extract_in6_addr(self); 01825 if (addr && IN6_IS_ADDR_V4MAPPED(addr)) return Qtrue; 01826 return Qfalse; 01827 } 01828 01829 /* 01830 * Returns true for IPv4-compatible IPv6 address (::/80). 01831 * It returns false otherwise. 01832 */ 01833 static VALUE 01834 addrinfo_ipv6_v4compat_p(VALUE self) 01835 { 01836 struct in6_addr *addr = extract_in6_addr(self); 01837 if (addr && IN6_IS_ADDR_V4COMPAT(addr)) return Qtrue; 01838 return Qfalse; 01839 } 01840 01841 /* 01842 * Returns true for IPv6 multicast node-local scope address. 01843 * It returns false otherwise. 01844 */ 01845 static VALUE 01846 addrinfo_ipv6_mc_nodelocal_p(VALUE self) 01847 { 01848 struct in6_addr *addr = extract_in6_addr(self); 01849 if (addr && IN6_IS_ADDR_MC_NODELOCAL(addr)) return Qtrue; 01850 return Qfalse; 01851 } 01852 01853 /* 01854 * Returns true for IPv6 multicast link-local scope address. 01855 * It returns false otherwise. 01856 */ 01857 static VALUE 01858 addrinfo_ipv6_mc_linklocal_p(VALUE self) 01859 { 01860 struct in6_addr *addr = extract_in6_addr(self); 01861 if (addr && IN6_IS_ADDR_MC_LINKLOCAL(addr)) return Qtrue; 01862 return Qfalse; 01863 } 01864 01865 /* 01866 * Returns true for IPv6 multicast site-local scope address. 01867 * It returns false otherwise. 01868 */ 01869 static VALUE 01870 addrinfo_ipv6_mc_sitelocal_p(VALUE self) 01871 { 01872 struct in6_addr *addr = extract_in6_addr(self); 01873 if (addr && IN6_IS_ADDR_MC_SITELOCAL(addr)) return Qtrue; 01874 return Qfalse; 01875 } 01876 01877 /* 01878 * Returns true for IPv6 multicast organization-local scope address. 01879 * It returns false otherwise. 01880 */ 01881 static VALUE 01882 addrinfo_ipv6_mc_orglocal_p(VALUE self) 01883 { 01884 struct in6_addr *addr = extract_in6_addr(self); 01885 if (addr && IN6_IS_ADDR_MC_ORGLOCAL(addr)) return Qtrue; 01886 return Qfalse; 01887 } 01888 01889 /* 01890 * Returns true for IPv6 multicast global scope address. 01891 * It returns false otherwise. 01892 */ 01893 static VALUE 01894 addrinfo_ipv6_mc_global_p(VALUE self) 01895 { 01896 struct in6_addr *addr = extract_in6_addr(self); 01897 if (addr && IN6_IS_ADDR_MC_GLOBAL(addr)) return Qtrue; 01898 return Qfalse; 01899 } 01900 01901 /* 01902 * Returns IPv4 address of IPv4 mapped/compatible IPv6 address. 01903 * It returns nil if +self+ is not IPv4 mapped/compatible IPv6 address. 01904 * 01905 * Addrinfo.ip("::192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01906 * Addrinfo.ip("::ffff:192.0.2.3").ipv6_to_ipv4 #=> #<Addrinfo: 192.0.2.3> 01907 * Addrinfo.ip("::1").ipv6_to_ipv4 #=> nil 01908 * Addrinfo.ip("192.0.2.3").ipv6_to_ipv4 #=> nil 01909 * Addrinfo.unix("/tmp/sock").ipv6_to_ipv4 #=> nil 01910 */ 01911 static VALUE 01912 addrinfo_ipv6_to_ipv4(VALUE self) 01913 { 01914 rb_addrinfo_t *rai = get_addrinfo(self); 01915 struct in6_addr *addr; 01916 int family = ai_get_afamily(rai); 01917 if (family != AF_INET6) return Qnil; 01918 addr = &((struct sockaddr_in6 *)&rai->addr)->sin6_addr; 01919 if (IN6_IS_ADDR_V4MAPPED(addr) || IN6_IS_ADDR_V4COMPAT(addr)) { 01920 struct sockaddr_in sin4; 01921 MEMZERO(&sin4, struct sockaddr_in, 1); 01922 sin4.sin_family = AF_INET; 01923 SET_SIN_LEN(&sin4, sizeof(sin4)); 01924 memcpy(&sin4.sin_addr, (char*)addr + sizeof(*addr) - sizeof(sin4.sin_addr), sizeof(sin4.sin_addr)); 01925 return rsock_addrinfo_new((struct sockaddr *)&sin4, (socklen_t)sizeof(sin4), 01926 PF_INET, rai->socktype, rai->protocol, 01927 rai->canonname, rai->inspectname); 01928 } 01929 else { 01930 return Qnil; 01931 } 01932 } 01933 01934 #endif 01935 01936 #ifdef HAVE_SYS_UN_H 01937 /* 01938 * call-seq: 01939 * addrinfo.unix_path => path 01940 * 01941 * Returns the socket path as a string. 01942 * 01943 * Addrinfo.unix("/tmp/sock").unix_path #=> "/tmp/sock" 01944 */ 01945 static VALUE 01946 addrinfo_unix_path(VALUE self) 01947 { 01948 rb_addrinfo_t *rai = get_addrinfo(self); 01949 int family = ai_get_afamily(rai); 01950 struct sockaddr_un *addr; 01951 char *s, *e; 01952 01953 if (family != AF_UNIX) 01954 rb_raise(rb_eSocket, "need AF_UNIX address"); 01955 01956 addr = (struct sockaddr_un *)&rai->addr; 01957 01958 s = addr->sun_path; 01959 e = (char*)addr + rai->sockaddr_len; 01960 if (e < s) 01961 rb_raise(rb_eSocket, "too short AF_UNIX address"); 01962 if (addr->sun_path + sizeof(addr->sun_path) < e) 01963 rb_raise(rb_eSocket, "too long AF_UNIX address"); 01964 while (s < e && *(e-1) == '\0') 01965 e--; 01966 return rb_str_new(s, e-s); 01967 } 01968 #endif 01969 01970 /* 01971 * call-seq: 01972 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...] 01973 * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol) => [addrinfo, ...] 01974 * Addrinfo.getaddrinfo(nodename, service, family, socktype) => [addrinfo, ...] 01975 * Addrinfo.getaddrinfo(nodename, service, family) => [addrinfo, ...] 01976 * Addrinfo.getaddrinfo(nodename, service) => [addrinfo, ...] 01977 * 01978 * returns a list of addrinfo objects as an array. 01979 * 01980 * This method converts nodename (hostname) and service (port) to addrinfo. 01981 * Since the conversion is not unique, the result is a list of addrinfo objects. 01982 * 01983 * nodename or service can be nil if no conversion intended. 01984 * 01985 * family, socktype and protocol are hint for preferred protocol. 01986 * If the result will be used for a socket with SOCK_STREAM, 01987 * SOCK_STREAM should be specified as socktype. 01988 * If so, Addrinfo.getaddrinfo returns addrinfo list appropriate for SOCK_STREAM. 01989 * If they are omitted or nil is given, the result is not restricted. 01990 * 01991 * Similarly, PF_INET6 as family restricts for IPv6. 01992 * 01993 * flags should be bitwise OR of Socket::AI_??? constants. 01994 * 01995 * Note that socktype should be specified whenever application knows the usage of the address. 01996 * Some platform causes an error when socktype is omitted and servname is specified as an integer 01997 * because some port numbers, 512 for example, are ambiguous without socktype. 01998 * 01999 * Addrinfo.getaddrinfo("www.kame.net", 80, nil, :STREAM) 02000 * #=> [#<Addrinfo: 203.178.141.194:80 TCP (www.kame.net:80)>, 02001 * # #<Addrinfo: [2001:200:0:8002:203:47ff:fea5:3085]:80 TCP (www.kame.net:80)>] 02002 * 02003 */ 02004 static VALUE 02005 addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self) 02006 { 02007 VALUE node, service, family, socktype, protocol, flags; 02008 02009 rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags); 02010 return addrinfo_list_new(node, service, family, socktype, protocol, flags); 02011 } 02012 02013 /* 02014 * call-seq: 02015 * Addrinfo.ip(host) => addrinfo 02016 * 02017 * returns an addrinfo object for IP address. 02018 * 02019 * The port, socktype, protocol of the result is filled by zero. 02020 * So, it is not appropriate to create a socket. 02021 * 02022 * Addrinfo.ip("localhost") #=> #<Addrinfo: 127.0.0.1 (localhost)> 02023 */ 02024 static VALUE 02025 addrinfo_s_ip(VALUE self, VALUE host) 02026 { 02027 VALUE ret; 02028 rb_addrinfo_t *rai; 02029 ret = addrinfo_firstonly_new(host, Qnil, 02030 INT2NUM(PF_UNSPEC), INT2FIX(0), INT2FIX(0), INT2FIX(0)); 02031 rai = get_addrinfo(ret); 02032 rai->socktype = 0; 02033 rai->protocol = 0; 02034 return ret; 02035 } 02036 02037 /* 02038 * call-seq: 02039 * Addrinfo.tcp(host, port) => addrinfo 02040 * 02041 * returns an addrinfo object for TCP address. 02042 * 02043 * Addrinfo.tcp("localhost", "smtp") #=> #<Addrinfo: 127.0.0.1:25 TCP (localhost:smtp)> 02044 */ 02045 static VALUE 02046 addrinfo_s_tcp(VALUE self, VALUE host, VALUE port) 02047 { 02048 return addrinfo_firstonly_new(host, port, 02049 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_STREAM), INT2NUM(IPPROTO_TCP), INT2FIX(0)); 02050 } 02051 02052 /* 02053 * call-seq: 02054 * Addrinfo.udp(host, port) => addrinfo 02055 * 02056 * returns an addrinfo object for UDP address. 02057 * 02058 * Addrinfo.udp("localhost", "daytime") #=> #<Addrinfo: 127.0.0.1:13 UDP (localhost:daytime)> 02059 */ 02060 static VALUE 02061 addrinfo_s_udp(VALUE self, VALUE host, VALUE port) 02062 { 02063 return addrinfo_firstonly_new(host, port, 02064 INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0)); 02065 } 02066 02067 #ifdef HAVE_SYS_UN_H 02068 02069 /* 02070 * call-seq: 02071 * Addrinfo.unix(path [, socktype]) => addrinfo 02072 * 02073 * returns an addrinfo object for UNIX socket address. 02074 * 02075 * _socktype_ specifies the socket type. 02076 * If it is omitted, :STREAM is used. 02077 * 02078 * Addrinfo.unix("/tmp/sock") #=> #<Addrinfo: /tmp/sock SOCK_STREAM> 02079 * Addrinfo.unix("/tmp/sock", :DGRAM) #=> #<Addrinfo: /tmp/sock SOCK_DGRAM> 02080 */ 02081 static VALUE 02082 addrinfo_s_unix(int argc, VALUE *argv, VALUE self) 02083 { 02084 VALUE path, vsocktype, addr; 02085 int socktype; 02086 rb_addrinfo_t *rai; 02087 02088 rb_scan_args(argc, argv, "11", &path, &vsocktype); 02089 02090 if (NIL_P(vsocktype)) 02091 socktype = SOCK_STREAM; 02092 else 02093 socktype = rsock_socktype_arg(vsocktype); 02094 02095 addr = addrinfo_s_allocate(rb_cAddrinfo); 02096 DATA_PTR(addr) = rai = alloc_addrinfo(); 02097 init_unix_addrinfo(rai, path, socktype); 02098 OBJ_INFECT(addr, path); 02099 return addr; 02100 } 02101 02102 #endif 02103 02104 VALUE 02105 rsock_sockaddr_string_value(volatile VALUE *v) 02106 { 02107 VALUE val = *v; 02108 if (IS_ADDRINFO(val)) { 02109 *v = addrinfo_to_sockaddr(val); 02110 } 02111 StringValue(*v); 02112 return *v; 02113 } 02114 02115 char * 02116 rsock_sockaddr_string_value_ptr(volatile VALUE *v) 02117 { 02118 rsock_sockaddr_string_value(v); 02119 return RSTRING_PTR(*v); 02120 } 02121 02122 VALUE 02123 rb_check_sockaddr_string_type(VALUE val) 02124 { 02125 if (IS_ADDRINFO(val)) 02126 return addrinfo_to_sockaddr(val); 02127 return rb_check_string_type(val); 02128 } 02129 02130 VALUE 02131 rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len) 02132 { 02133 int family; 02134 int socktype; 02135 int ret; 02136 socklen_t optlen = (socklen_t)sizeof(socktype); 02137 02138 /* assumes protocol family and address family are identical */ 02139 family = get_afamily(addr, len); 02140 02141 ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); 02142 if (ret == -1) { 02143 rb_sys_fail("getsockopt(SO_TYPE)"); 02144 } 02145 02146 return rsock_addrinfo_new(addr, len, family, socktype, 0, Qnil, Qnil); 02147 } 02148 02149 VALUE 02150 rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) 02151 { 02152 rb_io_t *fptr; 02153 02154 switch (TYPE(io)) { 02155 case T_FIXNUM: 02156 return rsock_fd_socket_addrinfo(FIX2INT(io), addr, len); 02157 02158 case T_BIGNUM: 02159 return rsock_fd_socket_addrinfo(NUM2INT(io), addr, len); 02160 02161 case T_FILE: 02162 GetOpenFile(io, fptr); 02163 return rsock_fd_socket_addrinfo(fptr->fd, addr, len); 02164 02165 default: 02166 rb_raise(rb_eTypeError, "neither IO nor file descriptor"); 02167 } 02168 } 02169 02170 /* 02171 * Addrinfo class 02172 */ 02173 void 02174 rsock_init_addrinfo(void) 02175 { 02176 /* 02177 * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This 02178 * structure identifies an Internet host and a service. 02179 */ 02180 rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); 02181 rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); 02182 rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); 02183 rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); 02184 rb_define_method(rb_cAddrinfo, "inspect_sockaddr", addrinfo_inspect_sockaddr, 0); 02185 rb_define_singleton_method(rb_cAddrinfo, "getaddrinfo", addrinfo_s_getaddrinfo, -1); 02186 rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1); 02187 rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2); 02188 rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2); 02189 #ifdef HAVE_SYS_UN_H 02190 rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1); 02191 #endif 02192 02193 rb_define_method(rb_cAddrinfo, "afamily", addrinfo_afamily, 0); 02194 rb_define_method(rb_cAddrinfo, "pfamily", addrinfo_pfamily, 0); 02195 rb_define_method(rb_cAddrinfo, "socktype", addrinfo_socktype, 0); 02196 rb_define_method(rb_cAddrinfo, "protocol", addrinfo_protocol, 0); 02197 rb_define_method(rb_cAddrinfo, "canonname", addrinfo_canonname, 0); 02198 02199 rb_define_method(rb_cAddrinfo, "ipv4?", addrinfo_ipv4_p, 0); 02200 rb_define_method(rb_cAddrinfo, "ipv6?", addrinfo_ipv6_p, 0); 02201 rb_define_method(rb_cAddrinfo, "unix?", addrinfo_unix_p, 0); 02202 02203 rb_define_method(rb_cAddrinfo, "ip?", addrinfo_ip_p, 0); 02204 rb_define_method(rb_cAddrinfo, "ip_unpack", addrinfo_ip_unpack, 0); 02205 rb_define_method(rb_cAddrinfo, "ip_address", addrinfo_ip_address, 0); 02206 rb_define_method(rb_cAddrinfo, "ip_port", addrinfo_ip_port, 0); 02207 02208 rb_define_method(rb_cAddrinfo, "ipv4_private?", addrinfo_ipv4_private_p, 0); 02209 rb_define_method(rb_cAddrinfo, "ipv4_loopback?", addrinfo_ipv4_loopback_p, 0); 02210 rb_define_method(rb_cAddrinfo, "ipv4_multicast?", addrinfo_ipv4_multicast_p, 0); 02211 02212 #ifdef INET6 02213 rb_define_method(rb_cAddrinfo, "ipv6_unspecified?", addrinfo_ipv6_unspecified_p, 0); 02214 rb_define_method(rb_cAddrinfo, "ipv6_loopback?", addrinfo_ipv6_loopback_p, 0); 02215 rb_define_method(rb_cAddrinfo, "ipv6_multicast?", addrinfo_ipv6_multicast_p, 0); 02216 rb_define_method(rb_cAddrinfo, "ipv6_linklocal?", addrinfo_ipv6_linklocal_p, 0); 02217 rb_define_method(rb_cAddrinfo, "ipv6_sitelocal?", addrinfo_ipv6_sitelocal_p, 0); 02218 rb_define_method(rb_cAddrinfo, "ipv6_v4mapped?", addrinfo_ipv6_v4mapped_p, 0); 02219 rb_define_method(rb_cAddrinfo, "ipv6_v4compat?", addrinfo_ipv6_v4compat_p, 0); 02220 rb_define_method(rb_cAddrinfo, "ipv6_mc_nodelocal?", addrinfo_ipv6_mc_nodelocal_p, 0); 02221 rb_define_method(rb_cAddrinfo, "ipv6_mc_linklocal?", addrinfo_ipv6_mc_linklocal_p, 0); 02222 rb_define_method(rb_cAddrinfo, "ipv6_mc_sitelocal?", addrinfo_ipv6_mc_sitelocal_p, 0); 02223 rb_define_method(rb_cAddrinfo, "ipv6_mc_orglocal?", addrinfo_ipv6_mc_orglocal_p, 0); 02224 rb_define_method(rb_cAddrinfo, "ipv6_mc_global?", addrinfo_ipv6_mc_global_p, 0); 02225 02226 rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0); 02227 #endif 02228 02229 #ifdef HAVE_SYS_UN_H 02230 rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0); 02231 #endif 02232 02233 rb_define_method(rb_cAddrinfo, "to_sockaddr", addrinfo_to_sockaddr, 0); 02234 rb_define_method(rb_cAddrinfo, "to_s", addrinfo_to_sockaddr, 0); /* compatibility for ruby before 1.9.2 */ 02235 02236 rb_define_method(rb_cAddrinfo, "getnameinfo", addrinfo_getnameinfo, -1); 02237 02238 rb_define_method(rb_cAddrinfo, "marshal_dump", addrinfo_mdump, 0); 02239 rb_define_method(rb_cAddrinfo, "marshal_load", addrinfo_mload, 1); 02240 } 02241
1.7.6.1