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