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