udhcp6: fix releasing
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 27 Mar 2017 20:32:44 +0000 (22:32 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 27 Mar 2017 20:44:22 +0000 (22:44 +0200)
Patch is based on work by tiggerswelt.net. They say:
"
We wanted udhcpc6 to release its 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 is 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

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.
"

Three last patches together:

function                                             old     new   delta
d6_read_interface                                      -     454    +454
d6_recv_raw_packet                                     -     283    +283
option_to_env                                        249     504    +255
.rodata                                           165226  165371    +145
send_d6_discover                                     195     237     +42
send_d6_select                                       118     159     +41
send_d6_renew                                        173     186     +13
send_d6_release                                      162     173     +11
opt_req                                                -      10     +10
d6_send_kernel_packet                                304     312      +8
opt_fqdn_req                                           -       6      +6
d6_mcast_from_client_config_ifindex                   48      51      +3
d6_find_option                                        63      61      -2
udhcpc6_main                                        2416    2411      -5
static.d6_recv_raw_packet                            266       -    -266
------------------------------------------------------------------------------
(add/remove: 5/1 grow/shrink: 8/2 up/down: 1271/-273)         Total: 998 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/udhcp/d6_common.h
networking/udhcp/d6_dhcpc.c
networking/udhcp/d6_packet.c

index 335a0927a00249d582fd63266fa7a69630373ce2..fcec8c15af322e207699238cdcff41b70aa32afb 100644 (file)
@@ -121,7 +121,8 @@ int FAST_FUNC d6_send_raw_packet(
 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
index a0cdded11937e477d9156807bae431b6488910a2..95de74f9b67c97605e562679d710e316d50ebfdb 100644 (file)
@@ -623,7 +623,8 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
                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);
 }
@@ -645,15 +646,14 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
        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;
@@ -702,6 +702,9 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
 //             return -2;
 //     }
 
+       if (peer_ipv6)
+               *peer_ipv6 = packet.ip6.ip6_src; /* struct copy */
+
        log1("received %s", "a packet");
        d6_dump_packet(&packet.data);
 
index e166f520de994b50c2c9f77094297ee4dc4e103e..79a0ac8a867463bf43eaab3cc21f03a57d98c427 100644 (file)
@@ -127,7 +127,8 @@ int FAST_FUNC d6_send_raw_packet(
 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;
@@ -154,6 +155,7 @@ int FAST_FUNC d6_send_kernel_packet(
        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;