diff options
Diffstat (limited to 'ext/socket/ifaddr.c')
| -rw-r--r-- | ext/socket/ifaddr.c | 97 |
1 files changed, 59 insertions, 38 deletions
diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c index 15395d7088..3596c40a11 100644 --- a/ext/socket/ifaddr.c +++ b/ext/socket/ifaddr.c @@ -24,7 +24,6 @@ typedef struct rb_ifaddr_root_tag rb_ifaddr_root_t; struct rb_ifaddr_tag { int ord; struct ifaddrs *ifaddr; - rb_ifaddr_root_t *root; }; struct rb_ifaddr_root_tag { @@ -41,11 +40,6 @@ get_root(const rb_ifaddr_t *ifaddr) } static void -ifaddr_mark(void *ptr) -{ -} - -static void ifaddr_free(void *ptr) { rb_ifaddr_t *ifaddr = ptr; @@ -60,18 +54,17 @@ ifaddr_free(void *ptr) static size_t ifaddr_memsize(const void *ptr) { + size_t size = offsetof(rb_ifaddr_root_t, ary); const rb_ifaddr_t *ifaddr; - const rb_ifaddr_root_t *root; - if (ptr == NULL) - return 0; ifaddr = ptr; - root = get_root(ifaddr); - return sizeof(rb_ifaddr_root_t) + (root->numifaddrs - 1) * sizeof(rb_ifaddr_t); + if (ifaddr->ord == 0) size = sizeof(rb_ifaddr_root_t); + size += sizeof(struct ifaddrs); + return size; } static const rb_data_type_t ifaddr_type = { "socket/ifaddr", - {ifaddr_mark, ifaddr_free, ifaddr_memsize,}, + {0, ifaddr_free, ifaddr_memsize,}, }; static inline rb_ifaddr_t * @@ -91,6 +84,12 @@ get_ifaddr(VALUE self) return rifaddr; } +static struct ifaddrs * +get_ifaddrs(VALUE self) +{ + return get_ifaddr(self)->ifaddr; +} + static VALUE rsock_getifaddrs(void) { @@ -98,34 +97,40 @@ rsock_getifaddrs(void) int numifaddrs, i; struct ifaddrs *ifaddrs, *ifa; rb_ifaddr_root_t *root; - VALUE result; + VALUE result, addr; ret = getifaddrs(&ifaddrs); if (ret == -1) rb_sys_fail("getifaddrs"); if (!ifaddrs) { - return rb_ary_new(); + return rb_ary_new(); } numifaddrs = 0; for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) numifaddrs++; - root = xmalloc(sizeof(rb_ifaddr_root_t) + (numifaddrs-1) * sizeof(rb_ifaddr_t)); - root->refcount = root->numifaddrs = numifaddrs; + addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, 0); + root = xmalloc(offsetof(rb_ifaddr_root_t, ary) + numifaddrs * sizeof(rb_ifaddr_t)); + root->refcount = 0; + root->numifaddrs = numifaddrs; ifa = ifaddrs; for (i = 0; i < numifaddrs; i++) { root->ary[i].ord = i; root->ary[i].ifaddr = ifa; - root->ary[i].root = root; ifa = ifa->ifa_next; } + RTYPEDDATA_DATA(addr) = &root->ary[0]; + root->refcount++; result = rb_ary_new2(numifaddrs); - for (i = 0; i < numifaddrs; i++) { - rb_ary_push(result, TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i])); + rb_ary_push(result, addr); + for (i = 1; i < numifaddrs; i++) { + addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]); + root->refcount++; + rb_ary_push(result, addr); } return result; @@ -141,8 +146,7 @@ rsock_getifaddrs(void) static VALUE ifaddr_name(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); return rb_str_new_cstr(ifa->ifa_name); } @@ -157,8 +161,7 @@ ifaddr_name(VALUE self) static VALUE ifaddr_ifindex(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); unsigned int ifindex = if_nametoindex(ifa->ifa_name); if (ifindex == 0) { rb_raise(rb_eArgError, "invalid interface name: %s", ifa->ifa_name); @@ -174,13 +177,14 @@ ifaddr_ifindex(VALUE self) * ifaddr.flags => integer * * Returns the flags of _ifaddr_. + * + * The value is bitwise-or of Socket::IFF_* constants such as Socket::IFF_LOOPBACK. */ static VALUE ifaddr_flags(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); return IFAFLAGS2NUM(ifa->ifa_flags); } @@ -195,8 +199,7 @@ ifaddr_flags(VALUE self) static VALUE ifaddr_addr(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); if (ifa->ifa_addr) return rsock_sockaddr_obj(ifa->ifa_addr, rsock_sockaddr_len(ifa->ifa_addr)); return Qnil; @@ -213,8 +216,7 @@ ifaddr_addr(VALUE self) static VALUE ifaddr_netmask(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); if (ifa->ifa_netmask) return rsock_sockaddr_obj(ifa->ifa_netmask, rsock_sockaddr_len(ifa->ifa_netmask)); return Qnil; @@ -231,8 +233,7 @@ ifaddr_netmask(VALUE self) static VALUE ifaddr_broadaddr(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr) return rsock_sockaddr_obj(ifa->ifa_broadaddr, rsock_sockaddr_len(ifa->ifa_broadaddr)); return Qnil; @@ -249,13 +250,32 @@ ifaddr_broadaddr(VALUE self) static VALUE ifaddr_dstaddr(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa = rifaddr->ifaddr; + struct ifaddrs *ifa = get_ifaddrs(self); if ((ifa->ifa_flags & IFF_POINTOPOINT) && ifa->ifa_dstaddr) return rsock_sockaddr_obj(ifa->ifa_dstaddr, rsock_sockaddr_len(ifa->ifa_dstaddr)); return Qnil; } +#ifdef HAVE_STRUCT_IF_DATA_IFI_VHID +/* + * call-seq: + * ifaddr.vhid => Integer + * + * Returns the vhid address of _ifaddr_. + * nil is returned if there is no vhid. + */ + +static VALUE +ifaddr_vhid(VALUE self) +{ + struct ifaddrs *ifa = get_ifaddrs(self); + if (ifa->ifa_data) + return (INT2FIX(((struct if_data*)ifa->ifa_data)->ifi_vhid)); + else + return Qnil; +} +#endif + static void ifaddr_inspect_flags(ifa_flags_t flags, VALUE result) { @@ -338,12 +358,9 @@ ifaddr_inspect_flags(ifa_flags_t flags, VALUE result) static VALUE ifaddr_inspect(VALUE self) { - rb_ifaddr_t *rifaddr = get_ifaddr(self); - struct ifaddrs *ifa; + struct ifaddrs *ifa = get_ifaddrs(self); VALUE result; - ifa = rifaddr->ifaddr; - result = rb_str_new_cstr("#<"); rb_str_append(result, rb_class_name(CLASS_OF(self))); @@ -444,7 +461,8 @@ rsock_init_sockifaddr(void) * * Socket::Ifaddr represents a result of getifaddrs() function. */ - rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cData); + rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cObject); + rb_undef_alloc_func(rb_cSockIfaddr); rb_define_method(rb_cSockIfaddr, "inspect", ifaddr_inspect, 0); rb_define_method(rb_cSockIfaddr, "name", ifaddr_name, 0); rb_define_method(rb_cSockIfaddr, "ifindex", ifaddr_ifindex, 0); @@ -453,6 +471,9 @@ rsock_init_sockifaddr(void) rb_define_method(rb_cSockIfaddr, "netmask", ifaddr_netmask, 0); rb_define_method(rb_cSockIfaddr, "broadaddr", ifaddr_broadaddr, 0); rb_define_method(rb_cSockIfaddr, "dstaddr", ifaddr_dstaddr, 0); +#ifdef HAVE_STRUCT_IF_DATA_IFI_VHID + rb_define_method(rb_cSockIfaddr, "vhid", ifaddr_vhid, 0); +#endif #endif rb_define_singleton_method(rb_cSocket, "getifaddrs", socket_s_getifaddrs, 0); |
