diff --git a/ChangeLog b/ChangeLog index 769dc29ecf..92f0401a6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Mon May 6 20:50:37 2013 Tanaka Akira + + * ext/socket/socket.c (socket_s_ip_address_list): Fill sin6_scope_id + if getifaddrs() returns an IPv6 link local address which + sin6_scope_id is zero, such as on OpenIndiana SunOS 5.11. + Sun May 5 18:56:52 2013 Nobuyoshi Nakada * insns.def (defined): use vm_search_superclass() like as normal super diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 3d59b6cc96..a0c9618ce4 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1658,6 +1658,26 @@ socket_s_ip_address_list(VALUE self) for (p = ifp; p; p = p->ifa_next) { if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) { struct sockaddr *addr = p->ifa_addr; +#if defined(AF_INET6) + /* + * OpenIndiana SunOS 5.11 getifaddrs() returns IPv6 link local + * address with sin6_scope_id == 0. + * So fill it from the interface name (ifa_name). + */ + struct sockaddr_in6 addr6; + if (addr->sa_family == AF_INET6) { + socklen_t len = (socklen_t)sizeof(struct sockaddr_in6); + memcpy(&addr6, addr, len); + addr = (struct sockaddr *)&addr6; + if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) && + addr6.sin6_scope_id == 0) { + unsigned int ifindex = if_nametoindex(p->ifa_name); + if (ifindex != 0) { + addr6.sin6_scope_id = ifindex; + } + } + } +#endif rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr))); } }