Hi,
Is it normal that getifaddrs() leaks the kernel's scope ID representation of IPv6 link-local addresses? In other words, is every user of getifaddrs() expected to fill the sin6_scope_id member from the 3rd byte of the address, and then clear that byte? Looking at ifconfig.c, it's full of calls to this function: > void > in6_fillscopeid(struct sockaddr_in6 *sin6) > { > #ifdef __KAME__ > if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { > sin6->sin6_scope_id = > ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); > sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; > } > #endif /* __KAME__ */ > } Shouldn't this be done once in getifaddrs() itself instead of replicated everywhere it's used? Simon |
Penned by Simon Perreault on 20120830 13:47.22, we have:
| Hi, | | Is it normal that getifaddrs() leaks the kernel's scope ID | representation of IPv6 link-local addresses? | | In other words, is every user of getifaddrs() expected to fill the | sin6_scope_id member from the 3rd byte of the address, and then | clear that byte? | | Looking at ifconfig.c, it's full of calls to this function: | | >void | >in6_fillscopeid(struct sockaddr_in6 *sin6) | >{ | >#ifdef __KAME__ | > if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { | > sin6->sin6_scope_id = | > ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); | > sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; | > } | >#endif /* __KAME__ */ | >} | | Shouldn't this be done once in getifaddrs() itself instead of | replicated everywhere it's used? | | Simon I'm sure people will correct me if I am misremembering but .. to the best of my understanding... It would be ideal for the kernel to use the sin6_scope_id when communicating with userland everywhere, and never should the userland have to do the horrendous hacks required to clear this from the s6_addr[2] and s6_addr[3] fields. No one has taken this on, and so this desire for cleaning the ugly mess KAME left us has been left undone. Thanks, -- Todd Fries .. [hidden email] _____________________________________________ | \ 1.636.410.0632 (voice) | Free Daemon Consulting, LLC \ 1.405.227.9094 (voice) | http://FreeDaemonConsulting.com \ 1.866.792.3418 (FAX) | 2525 NW Expy #525, Oklahoma City, OK 73112 \ sip:[hidden email] | "..in support of free software solutions." \ sip:[hidden email] \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 37E7 D3EB 74D0 8D66 A68D B866 0326 204E 3F42 004A http://todd.fries.net/pgp.txt |
On 30.08.2012 20:50, Todd T. Fries wrote:
> Penned by Simon Perreault on 20120830 13:47.22, we have: > | Hi, > | > | Is it normal that getifaddrs() leaks the kernel's scope ID > | representation of IPv6 link-local addresses? > | > | In other words, is every user of getifaddrs() expected to fill the > | sin6_scope_id member from the 3rd byte of the address, and then > | clear that byte? > | > | Looking at ifconfig.c, it's full of calls to this function: > | > | >void > | >in6_fillscopeid(struct sockaddr_in6 *sin6) > | >{ > | >#ifdef __KAME__ > | > if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { > | > sin6->sin6_scope_id = > | > ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); > | > sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; > | > } > | >#endif /* __KAME__ */ > | >} > | > | Shouldn't this be done once in getifaddrs() itself instead of > | replicated everywhere it's used? > | > | Simon > > I'm sure people will correct me if I am misremembering but .. to the best of > my understanding... > > It would be ideal for the kernel to use the sin6_scope_id when communicating with > userland everywhere, and never should the userland have to do the horrendous > hacks required to clear this from the s6_addr[2] and s6_addr[3] fields. > No one has taken this on, and so this desire for cleaning the ugly mess KAME left > us has been left undone. Hi, Leaking scope ID to userspace is only one part of the story. The other direction seems to be broken as well. My link-local address is fe80::a:b:c:d and the iterface index is 2. I was able to bind a udp socket to fe80:2::a:b:c:d address, transmit *and* receive data. (the data received sent to fe80::a:b:c:d, yet I was able to receive it). Call to bind() should fail in the first place. If you are interested in the reproduction code, you may want to use latest dibbler git repo (see http://klub.com.pl/dhcpv6/ for details). The code for socket operations is in Port-bsd/lowlevel-bsd.c. It is shared between all BSDs and Mac OS. If you decide that for some reason you do not want to fix this, it should be at least documented somewhere. A simple sentence in getifaddrs man page would be helpful. Obviously, fixing the code is more preferable. Cheers, Tomek p.s. What's the recommended API a userland application (dhcpv6 client) should use for adding/updating lifetimes/removing IPv6 addresses on an interface? How about the same for configuring prefixes? |
Le 2012-08-31 03:34, Tomek Mrugalski a écrit :
> If you decide that for some reason you do not want to fix this, I think it's pretty clear that something has to be fixed. I'm wondering why FreeBSD doesn't have the same issues. Looking at the code I can't figure it out. > What's the recommended API a userland application (dhcpv6 client) should > use for adding/updating lifetimes/removing IPv6 addresses on an > interface? It's all ioctls. add: SIOCAIFADDR_IN6 remove: SIOCDIFADDR_IN6 update lifetime: SIOCSIFALIFETIME_IN6 Check out ifconfig.c for examples. http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/ifconfig/ifconfig.c > How about the same for configuring prefixes? Not sure what you mean. The SIOCAIFADDR_IN6 ioctl takes a struct in6_aliasreq argument, which has a prefix mask member. Simon |
Free forum by Nabble | Edit this page |