Hey there,

this is my first post on the list and my first set of patches I wrote
for busybox, so please forgive me if I'm missing something.

We are currently trying to build an IPv6-only-environment with statefull
autoconfiguration using busybox-udhcpc6 on client-side. During
development I was wondering if anyone out there might be using udhcpc6
as well es we encountered some severe bugs.

This weekend I shared an initial patch on bugzilla [0], but had to find
out some time later that someone already has done it years ago here on
the mailinglist [1] - although the patch didn't make it into any release.

At the moment the vanilla udhcpc6 uses a null-source-address when asking
for dhcp6-autoconfiguration. As already said on the ticket and on the
referenced mailinglist-post, this behaviour is wrong as the
link-local-address of the interface should be used and any interface is
supposed to have one.
You'll find our patch attached to this e-mail (udhcpc-read-ipv6.patch)
that has evolved since the post on bugzilla and is similar to the patch
by Mathias Krüger - it also utilizes getifaddrs() but instead of using a
new additional function, we had rewritten udhcp_read_interface().

Using this patch it was no problem to acquire an IPv6-Address via DHCPv6
using ISC DHCPD6 on server-side.

But when we tried to use dnsmasq on server-side, udhcpc6 was unable to
forward the acquired address to its setup-script although the
IPv6-Address had been assigned by the server as we could see via
tcpdump. We traced this issue down to a problem on how udhcpc6 parses
DHCPv6-Options: When moving to next option, a pointer-address is
increased and a length buffer is decreased by the length of the option.
The problem is that it is done in this order:

  option += 4 + option[3];
  len_m4 -= 4 + option[3];

But this has to be switched as the length is decreased by the length of
the *next* option, not the current one. This affected both - internal
checks if a required option is present and the function to expose
options to the environment of the setup-script.
There was also a bug parsing D6_OPT_STATUS_CODE Options, that made
dnsmasq not work as udhcpc6 thought it is receiving a non-positive
status-code (because it did not parse the status-code as required in RFC
3315).
In addition we introduced basic support for RFC 3646 (OPTION_DNS_SERVERS
and OPTION_DOMAIN_LIST) and RFC 4704 (OPTION_CLIENT_FQDN). All this
option-related patches are located in the attached udhcpc-v6-options.patch.

Last but not least: We wanted udhcpc6 to release it's IPv6-Addresses on
quit (-R-commandline-option) which turned out to generate once again
kind of garbage on the network-link.
We tracked this down to two issues:

 - udhcpc6 uses a variable called "srv6_buf" to send packets to
   the dhcp6-server, but this variable gets never initialized correctly
   and contained kind of a garbage-address

 - The address of the dhcp6-server is usually a link-local-address,
   that requires an interface-index when using connect() on an AF_INET6-
   socket

In the attached patch "udhcpc-fix-kernel-send.patch" we added an
additional parameter for ifindex to d6_send_kernel_packet() and made
d6_recv_raw_packet() to capture the address of the dhcp6-server and
forward it to its callee.

With these three patches applied busybox just worked like a charme in
our IPv6-only-environment. The patches may required some review, but I
would be very happy if you find them useful, too.



Kind regards,

Bernd


[0] https://bugs.busybox.net/show_bug.cgi?id=6194
[1] http://lists.busybox.net/pipermail/busybox/2013-August/079703.html

-- 
    \\\||///
  \\  - -  //
   (  @ @  )
-oOo--( )--oOo-------------------------------------------------------
 tiggersWelt.net                                 www.tiggersWelt.net
 Inhaber Bernd Holzmüller                       [email protected]
                                            Büro: 07 11 / 550 425-90
 Marktstraße 57                             Fax: 07 11 / 550 425-99
 70372 Stuttgart
diff -Nru busybox-1.26.2.org/networking/udhcp/common.h busybox-1.26.2.mod/networking/udhcp/common.h
--- busybox-1.26.2.org/networking/udhcp/common.h	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/common.h	2017-03-06 19:38:31.076316233 +0100
@@ -303,7 +303,7 @@
 int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC;
 int udhcp_sp_read(const fd_set *rfds) FAST_FUNC;
 
-int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC;
+int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, struct in6_addr **nip6, uint8_t *mac) FAST_FUNC;
 
 int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC;
 
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_common.h busybox-1.26.2.mod/networking/udhcp/d6_common.h
--- busybox-1.26.2.org/networking/udhcp/d6_common.h	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_common.h	2017-03-06 20:14:11.636939559 +0100
@@ -91,6 +96,7 @@
 	struct d6_option *ia_na;
 	char **env_ptr;
 	unsigned env_idx;
+	struct in6_addr *ll_addr;
 };
 
 #define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)]))
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c
--- busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c	2017-03-06 20:16:58.441939869 +0100
@@ -308,10 +369,10 @@
 		0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
 	};
-
+	
 	return d6_send_raw_packet(
 		packet, (end - (uint8_t*) packet),
-		/*src*/ NULL, CLIENT_PORT6,
+		/*src*/ client6_data.ll_addr, CLIENT_PORT6,
 		/*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR,
 		client_config.ifindex
 	);
@@ -1008,6 +1079,7 @@
 	if (udhcp_read_interface(client_config.interface,
 			&client_config.ifindex,
 			NULL,
+			&client6_data.ll_addr,
 			client_config.client_mac)
 	) {
 		return 1;
@@ -1111,10 +1183,12 @@
 			if (udhcp_read_interface(client_config.interface,
 					&client_config.ifindex,
 					NULL,
+					&client6_data.ll_addr,
 					client_config.client_mac)
 			) {
 				goto ret0; /* iface is gone? */
 			}
+			
 			memcpy(clientid_mac_ptr, client_config.client_mac, 6);
 
 			/* We will restart the wait in any case */
diff -Nru busybox-1.26.2.org/networking/udhcp/dhcpc.c busybox-1.26.2.mod/networking/udhcp/dhcpc.c
--- busybox-1.26.2.org/networking/udhcp/dhcpc.c	2016-12-10 18:46:36.000000000 +0100
+++ busybox-1.26.2.mod/networking/udhcp/dhcpc.c	2017-03-06 19:38:31.076316233 +0100
@@ -1372,6 +1372,7 @@
 	if (udhcp_read_interface(client_config.interface,
 			&client_config.ifindex,
 			NULL,
+			NULL,
 			client_config.client_mac)
 	) {
 		return 1;
@@ -1479,6 +1480,7 @@
 			if (udhcp_read_interface(client_config.interface,
 					&client_config.ifindex,
 					NULL,
+					NULL,
 					client_config.client_mac)
 			) {
 				goto ret0; /* iface is gone? */
diff -Nru busybox-1.26.2.org/networking/udhcp/dhcpd.c busybox-1.26.2.mod/networking/udhcp/dhcpd.c
--- busybox-1.26.2.org/networking/udhcp/dhcpd.c	2016-12-10 18:46:36.000000000 +0100
+++ busybox-1.26.2.mod/networking/udhcp/dhcpd.c	2017-03-06 19:38:31.076316233 +0100
@@ -879,6 +879,7 @@
 	if (udhcp_read_interface(server_config.interface,
 			&server_config.ifindex,
 			(server_config.server_nip == 0 ? &server_config.server_nip : NULL),
+			NULL,
 			server_config.server_mac)
 	) {
 		retval = 1;
diff -Nru busybox-1.26.2.org/networking/udhcp/dhcprelay.c busybox-1.26.2.mod/networking/udhcp/dhcprelay.c
--- busybox-1.26.2.org/networking/udhcp/dhcprelay.c	2016-12-10 18:46:36.000000000 +0100
+++ busybox-1.26.2.mod/networking/udhcp/dhcprelay.c	2017-03-06 19:38:31.076316233 +0100
@@ -283,7 +283,7 @@
 	max_socket = init_sockets(iface_list, num_sockets, fds);
 
 	/* Get our IP on server_iface */
-	if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL))
+	if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL, NULL))
 		return 1;
 
 	/* Main loop */
@@ -363,7 +363,7 @@
 //   of the 'giaddr' field does not match one of the relay agent's
 //   directly-connected logical interfaces, the BOOTREPLY messsage MUST be
 //   silently discarded.
-				if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL)) {
+				if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL, NULL)) {
 					/* Fall back to our IP on server iface */
 // this makes more sense!
 					dhcp_msg.gateway_nip = our_nip;
diff -Nru busybox-1.26.2.org/networking/udhcp/socket.c busybox-1.26.2.mod/networking/udhcp/socket.c
--- busybox-1.26.2.org/networking/udhcp/socket.c	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/socket.c	2017-03-06 20:05:28.853795123 +0100
@@ -24,54 +24,52 @@
  */
 #include "common.h"
 #include <net/if.h>
+#include <ifaddrs.h>
+#include <netpacket/packet.h>
 
-int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac)
-{
-	/* char buffer instead of bona-fide struct avoids aliasing warning */
-	char ifr_buf[sizeof(struct ifreq)];
-	struct ifreq *const ifr = (void *)ifr_buf;
-
-	int fd;
-	struct sockaddr_in *our_ip;
-
-	memset(ifr, 0, sizeof(*ifr));
-	fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-
-	ifr->ifr_addr.sa_family = AF_INET;
-	strncpy_IFNAMSIZ(ifr->ifr_name, interface);
-	if (nip) {
-		if (ioctl_or_perror(fd, SIOCGIFADDR, ifr,
-			"is interface %s up and configured?", interface)
-		) {
-			close(fd);
-			return -1;
-		}
-		our_ip = (struct sockaddr_in *) &ifr->ifr_addr;
-		*nip = our_ip->sin_addr.s_addr;
-		log1("IP %s", inet_ntoa(our_ip->sin_addr));
-	}
-
-	if (ifindex) {
-		if (ioctl_or_warn(fd, SIOCGIFINDEX, ifr) != 0) {
-			close(fd);
-			return -1;
-		}
-		log1("adapter index %d", ifr->ifr_ifindex);
-		*ifindex = ifr->ifr_ifindex;
-	}
-
-	if (mac) {
-		if (ioctl_or_warn(fd, SIOCGIFHWADDR, ifr) != 0) {
-			close(fd);
-			return -1;
-		}
-		memcpy(mac, ifr->ifr_hwaddr.sa_data, 6);
-		log1("MAC %02x:%02x:%02x:%02x:%02x:%02x",
-			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-	}
-
-	close(fd);
-	return 0;
+int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, struct in6_addr **nip6, uint8_t *mac) {
+  struct ifaddrs *ifap, *ifa;
+  
+  getifaddrs (&ifap);
+  
+  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+    if (!ifa->ifa_addr || (strcmp (ifa->ifa_name, interface) != 0))
+      continue;
+    
+    if (ifa->ifa_addr->sa_family == AF_PACKET) {
+      if (mac) {
+        memcpy (mac, ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr, 6);
+        log1 ("MAC %02x:%02x:%02x:%02x:%02x:%02x", mac [0], mac [1], mac [2], mac [3], mac [4], mac [5]);
+      }
+      
+      if (ifindex) {
+        log1 ("adapter index %d", ((struct sockaddr_ll *)ifa->ifa_addr)->sll_ifindex);
+        *ifindex = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_ifindex;
+      }
+    } else if (nip && (ifa->ifa_addr->sa_family == AF_INET)) {
+      *nip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
+      log1 ("IP %s", inet_ntoa (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr));
+    
+    } else if (nip6 && (ifa->ifa_addr->sa_family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
+      *nip6 = malloc (sizeof (struct in6_addr));
+      memcpy (*nip6, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, sizeof (struct in6_addr));
+      log1 (
+        "IPv6 %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+        (*nip6)->s6_addr [0], (*nip6)->s6_addr [1],
+        (*nip6)->s6_addr [2], (*nip6)->s6_addr [3],
+        (*nip6)->s6_addr [4], (*nip6)->s6_addr [5],
+        (*nip6)->s6_addr [6], (*nip6)->s6_addr [7],
+        (*nip6)->s6_addr [8], (*nip6)->s6_addr [9],
+        (*nip6)->s6_addr [10], (*nip6)->s6_addr [11],
+        (*nip6)->s6_addr [12], (*nip6)->s6_addr [13],
+        (*nip6)->s6_addr [14], (*nip6)->s6_addr [15]
+      );
+    }
+  }
+  
+  freeifaddrs (ifap);
+  
+  return 0;
 }
 
 /* 1. None of the callers expects it to ever fail */
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_common.h busybox-1.26.2.mod/networking/udhcp/d6_common.h
--- busybox-1.26.2.org/networking/udhcp/d6_common.h	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_common.h	2017-03-06 20:14:11.636939559 +0100
@@ -81,9 +81,14 @@
 #define D6_OPT_RECONF_MSG    19
 #define D6_OPT_RECONF_ACCEPT 20
 
+#define D6_OPT_DNS_SERVERS   23
+#define D6_OPT_DOMAIN_LIST   24
+
 #define D6_OPT_IA_PD         25
 #define D6_OPT_IAPREFIX      26
 
+#define D6_OPT_CLIENT_FQDN   39
+
 /*** Other shared functions ***/
 
 struct client6_data_t {
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c
--- busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c	2017-03-06 20:16:58.441939869 +0100
@@ -86,6 +86,19 @@
 	IF_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
 };
 
+const char opt_req[] = {
+  (D6_OPT_ORO >> 8), (D6_OPT_ORO & 0xFF),
+  0, 6,
+  (D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xFF),
+  (D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xFF),
+  (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xFF)
+};
+
+const char opt_fqdn_req[] = {
+  (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xFF),
+  0, 2,
+  0, 0
+};
 
 /*** Utility functions ***/
 
@@ -107,8 +120,8 @@
 		/* Does its code match? */
 		if (option[1] == code)
 			return option; /* yes! */
-		option += option[3] + 4;
 		len_m4 -= option[3] + 4;
+		option += option[3] + 4;
 	}
 	return NULL;
 }
@@ -140,14 +153,16 @@
 static void option_to_env(uint8_t *option, uint8_t *option_end)
 {
 	/* "length minus 4" */
+	char *dlist, *ptr;
 	int len_m4 = option_end - option - 4;
+	int olen, ooff;
 	while (len_m4 >= 0) {
 		uint32_t v32;
 		char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
 
 		if (option[0] != 0 || option[2] != 0)
 			break;
-
+		
 		switch (option[1]) {
 		//case D6_OPT_CLIENTID:
 		//case D6_OPT_SERVERID:
@@ -217,9 +232,55 @@
 
 			sprint_nip6(ipv6str, option + 4 + 4 + 1);
 			*new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
+			break;
+		case D6_OPT_DNS_SERVERS:
+			olen = ((option [2] << 8) | option [3]) / 16;
+			dlist = ptr = malloc (4 + olen * 40 - 1);
+			
+			memcpy (ptr, "dns=", 4);
+			ptr += 4;
+			ooff = 0;
+			
+			while (olen--) {
+			  sprint_nip6 (ptr, option + 4 + ooff);
+			  
+			  ptr += 39;
+			  ooff += 16;
+			  
+			  if (olen) *ptr++ = ' ';
+			}
+			
+			*new_env() = dlist;
+			
+			break;
+		case D6_OPT_DOMAIN_LIST:
+			if (!(dlist = dname_dec (option + 4, (option [2] << 8) | option [3], "search=")))
+			  break;
+			
+			*new_env() = dlist;
+			
+			break;
+		case D6_OPT_CLIENT_FQDN:
+			// Work around broken ISC DHCPD6
+			if (option [4] & 0xF8) {
+			  olen = ((option [2] << 8) | option [3]);
+			  dlist = malloc (olen);
+			  memcpy (dlist, option + 4, olen);
+			  *new_env() = xasprintf("fqdn=%s", dlist);
+			  free (dlist);
+			  
+			  break;
+			}
+			
+			if (!(dlist = dname_dec (option + 5, ((option [2] << 8) | option [3]) - 1, "fqdn=")))
+			  break;
+			
+			*new_env() = dlist;
+			
+			break;
 		}
-		option += 4 + option[3];
 		len_m4 -= 4 + option[3];
+		option += 4 + option[3];
 	}
 }
 
@@ -422,7 +483,11 @@
 		memcpy(iaaddr->data, requested_ipv6, 16);
 	}
 	opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len);
-
+	
+	/* Request additional options */
+	opt_ptr = d6_store_blob (opt_ptr, &opt_req, sizeof (opt_req));
+	opt_ptr = d6_store_blob (opt_ptr, &opt_fqdn_req, sizeof (opt_fqdn_req));
+	
 	/* Add options:
 	 * "param req" option according to -O, options specified with -x
 	 */
@@ -475,7 +540,11 @@
 	opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
 	/* IA NA (contains requested IP) */
 	opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
-
+	
+	/* Request additional options */
+        opt_ptr = d6_store_blob (opt_ptr, &opt_req, sizeof (opt_req));
+        opt_ptr = d6_store_blob (opt_ptr, &opt_fqdn_req, sizeof (opt_fqdn_req));
+        
 	/* Add options:
 	 * "param req" option according to -O, options specified with -x
 	 */
@@ -1307,7 +1381,7 @@
 				struct d6_option *option, *iaaddr;
  type_is_ok:
 				option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
-				if (option && option->data[4] != 0) {
+				if (option && (((option->data [0] << 8) | option->data [1]) != 0)) {
 					/* return to init state */
 					bb_error_msg("received DHCP NAK (%u)", option->data[4]);
 					d6_run_script(&packet, "nak");
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_common.h busybox-1.26.2.mod/networking/udhcp/d6_common.h
--- busybox-1.26.2.org/networking/udhcp/d6_common.h	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_common.h	2017-03-06 20:14:11.636939559 +0100
@@ -112,7 +118,8 @@
 int FAST_FUNC d6_send_kernel_packet(
 		struct d6_packet *d6_pkt, unsigned d6_pkt_size,
 		struct in6_addr *src_ipv6, int source_port,
-		struct in6_addr *dst_ipv6, int dest_port
+		struct in6_addr *dst_ipv6, int dest_port,
+		int ifindex
 );
 
 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c
--- busybox-1.26.2.org/networking/udhcp/d6_dhcpc.c	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_dhcpc.c	2017-03-06 20:16:58.441939869 +0100
@@ -555,7 +624,8 @@
 		return d6_send_kernel_packet(
 			&packet, (opt_ptr - (uint8_t*) &packet),
 			our_cur_ipv6, CLIENT_PORT6,
-			server_ipv6, SERVER_PORT6
+			server_ipv6, SERVER_PORT6,
+			client_config.ifindex
 		);
 	return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
 }
@@ -577,16 +647,14 @@
 	return d6_send_kernel_packet(
 		&packet, (opt_ptr - (uint8_t*) &packet),
 		our_cur_ipv6, CLIENT_PORT6,
-		server_ipv6, SERVER_PORT6
+		server_ipv6, SERVER_PORT6,
+		client_config.ifindex
 	);
 }
 
 /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
 /* NOINLINE: limit stack usage in caller */
-static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
-	UNUSED_PARAM
-	, struct d6_packet *d6_pkt, int fd)
-{
+static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_packet *d6_pkt, int fd) {
 	int bytes;
 	struct ip6_udp_d6_packet packet;
 
@@ -634,6 +702,9 @@
 //		return -2;
 //	}
 
+	if (peer_ipv6)
+		memcpy (peer_ipv6, &packet.ip6.ip6_src, sizeof (struct in6_addr));
+
 	log1("received %s", "a packet");
 	d6_dump_packet(&packet.data);
 
diff -Nru busybox-1.26.2.org/networking/udhcp/d6_packet.c busybox-1.26.2.mod/networking/udhcp/d6_packet.c
--- busybox-1.26.2.org/networking/udhcp/d6_packet.c	2016-09-27 18:53:50.000000000 +0200
+++ busybox-1.26.2.mod/networking/udhcp/d6_packet.c	2017-03-06 20:17:19.038063287 +0100
@@ -127,7 +127,8 @@
 int FAST_FUNC d6_send_kernel_packet(
 		struct d6_packet *d6_pkt, unsigned d6_pkt_size,
 		struct in6_addr *src_ipv6, int source_port,
-		struct in6_addr *dst_ipv6, int dest_port)
+		struct in6_addr *dst_ipv6, int dest_port,
+		int ifindex)
 {
 	struct sockaddr_in6 sa;
 	int fd;
@@ -140,7 +141,7 @@
 		goto ret_msg;
 	}
 	setsockopt_reuseaddr(fd);
-
+	
 	memset(&sa, 0, sizeof(sa));
 	sa.sin6_family = AF_INET6;
 	sa.sin6_port = htons(source_port);
@@ -154,6 +155,7 @@
 	sa.sin6_family = AF_INET6;
 	sa.sin6_port = htons(dest_port);
 	sa.sin6_addr = *dst_ipv6; /* struct copy */
+	sa.sin6_scope_id = ifindex;
 	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
 		msg = "connect";
 		goto ret_close;

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to