From 2d1160426dc7c94dddda6ccc6380171c32fd4d75 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Wed, 8 Apr 2020 12:30:58 +0200 Subject: [PATCH] sys/net/dhcpv6: discard stale replies The DHCPv6 server might send reponses multiple times. The DHCPv6 client will only handle the first response, if additional responses are comming in they are left in the RX queue. That results in the client always reading the response of a previous transaction on any subsequent transactions. In this case the client will try again, creating a new transaction - that will again only read the previous response. To fix this, discard previous responses by flushing the RX queue before sending a new message to the DHCPv6 server. fixes #13834 --- sys/net/application_layer/dhcpv6/client.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/net/application_layer/dhcpv6/client.c b/sys/net/application_layer/dhcpv6/client.c index 6a3eb3cd3221..04c3d9440e6c 100644 --- a/sys/net/application_layer/dhcpv6/client.c +++ b/sys/net/application_layer/dhcpv6/client.c @@ -369,6 +369,15 @@ static bool _check_sid_opt(dhcpv6_opt_duid_t *sid) (memcmp(sid->duid, server.duid.u8, server.duid_len) == 0)); } +/* discard stale messages in the receive buffer */ +static void _flush_stale_replies(sock_udp_t *sock) +{ + int res; + while ((res = sock_udp_recv(sock, recv_buf, sizeof(recv_buf), 0, NULL)) >= 0) { + DEBUG("DHCPv6 client: discarding %d stale bytes\n", res); + } +} + static int _preparse_advertise(uint8_t *adv, size_t len, uint8_t **buf) { dhcpv6_opt_duid_t *cid = NULL, *sid = NULL; @@ -696,6 +705,7 @@ static void _solicit_servers(event_t *event) ARRAY_SIZE(oro_opts)); msg_len += _add_ia_pd_from_config(&send_buf[msg_len]); DEBUG("DHCPv6 client: send SOLICIT\n"); + _flush_stale_replies(&sock); res = sock_udp_send(&sock, send_buf, msg_len, &remote); assert(res > 0); /* something went terribly wrong */ while (((res = sock_udp_recv(&sock, recv_buf, sizeof(recv_buf), @@ -802,6 +812,7 @@ static void _request_renew_rebind(uint8_t type) msg_len += _compose_oro_opt((dhcpv6_opt_oro_t *)&send_buf[msg_len], oro_opts, ARRAY_SIZE(oro_opts)); msg_len += _add_ia_pd_from_config(&send_buf[msg_len]); + _flush_stale_replies(&sock); while (sock_udp_send(&sock, send_buf, msg_len, &remote) <= 0) {} while (((res = sock_udp_recv(&sock, recv_buf, sizeof(recv_buf), retrans_timeout, NULL)) <= 0) ||