I brought this issue up a while ago. I noticed that it isn't just not setting these addresses, but also removing any that were already present when it started. (This also affects "real" SLAAC addresses.)
On Tue, Jul 19, 2016 at 10:01 AM, Marc Seeger <[email protected]> wrote: > Hey! > > We noticed that the DHCPv6 client included with busybox does not set the IPv6 > link-local address of the interface as the source IP in > d6_mcast_from_client_config_ifindex(). > RFC3315 mentions that: > > a) In "4.1. IPv6 Terminology": > "Every interface has a link-local address." > > and > > b) In "16. Client Source Address and Interface Selection": > "The client MUST use a link-local address assigned to the interface for which > it is requesting configuration information as the source address in the > header of the IP datagram. > > In the current codebase, udhcp sets the source address to NULL when it's > calling d6_send_raw_packet (--> > https://git.busybox.net/busybox/tree/networking/udhcp/d6_dhcpc.c#n314). > While this isn't quite RFC conform as far as I can tell, it seems to work > fine with most switches. We did however see some cases where the switch > doesn't correctly forward DHCP responses back to the client if the link local > address is missing. > > I created a patch that parses the address from /proc/net/if_inet6 and we've > been running it in production successfully for a few weeks. > A lot of the code is taken from ife_print6() in interface.c and could > probably be abstracted and reused. > > I don't think it's quite ready to be merged yet, but I just wanted to gather > some initial feedback/concerns. > Things like: Do we want to fall back to the old "just use NULL" approach if > we fail to discover a link local address for whatever reason? > > Cheers, > Marc > > > > diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c > index 345ca5e..eda474a 100644 > --- a/networking/udhcp/d6_dhcpc.c > +++ b/networking/udhcp/d6_dhcpc.c > @@ -434,9 +434,65 @@ static int d6_mcast_from_client_config_ifindex(struct > d6_packet *packet, uint8_t > 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, > }; > > + #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" > + #define IPV6_ADDR_LINKLOCAL 0x0020U > + #define IPV6_ADDR_SCOPE_MASK 0x00f0U > + > + FILE *f; > + char addr6[40], devname[21]; > + struct sockaddr_in6 sap; > + int plen, scope, dad_status, if_idx; > + char addr6p[8][5]; > + int link_local_parsing_success = 0; > + > + f = fopen_for_read(_PATH_PROCNET_IFINET6); > + if (f == NULL){ > + log1("Could not find /proc/net/if_inet6, can't set link local > addr, not sending package."); > + return; > + } > + // cat /proc/net/if_inet6 > + // 00000000000000000000000000000001 01 80 10 80 lo > + // 2401db000020a01eface000000230000 02 40 00 80 eth0 > + // fe8000000000000062eb69fffe9bb5c2 02 40 20 80 eth0 > + // Iterate over every one of those lines and extract the parts into > variables > + while (fscanf > + (f,"%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x > %20s\n", > + addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], > + addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, > &scope, > + &dad_status, devname) != EOF > + ) { > + // check that it's the interface we're currently listening on > + if (!strcmp(devname, client_config.interface)) { > + // See if it's link-local. if not we don't care > + // about it at this point > + if ((scope & IPV6_ADDR_SCOPE_MASK) == > IPV6_ADDR_LINKLOCAL) { > + // Re-assemble the readable v6 address into > addr6 > + sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", > + addr6p[0], addr6p[1], > addr6p[2], addr6p[3], > + addr6p[4], addr6p[5], > addr6p[6], addr6p[7]); > + log1("Found Link Local address for %s: %s", > devname, addr6); > + // Set the socket address to all zeros > + memset(&sap, 0, sizeof(sap)); > + // Convert the printable v6 address to the > binary equivalent > + // and write it to the sockaddr_in6 struct > into &sap.sin6_addr > + inet_pton(AF_INET6, addr6, (struct sockaddr > *) &sap.sin6_addr); > + // Set the family to v6 just to have a proper > data structure > + sap.sin6_family = AF_INET6; > + // Cool, we found what we're looking for. Our > work here is done! > + link_local_parsing_success = 1; > + break; > + } > + } > + } > + fclose(f); > + > + if (link_local_parsing_success == 0) { > + log1("Could not find link local addr among interfaces, not > sending package."); > + return; > + } > return d6_send_raw_packet( > packet, (end - (uint8_t*) packet), > - /*src*/ NULL, CLIENT_PORT6, > + /*src*/ (struct in6_addr*)&sap.sin6_addr, CLIENT_PORT6, > /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, > MAC_BCAST_ADDR, > client_config.ifindex > ); > _______________________________________________ > busybox mailing list > [email protected] > http://lists.busybox.net/mailman/listinfo/busybox _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
