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