From 5aed333e2df4513022acb90cbf2a536817e1bdbd Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Thu, 4 Apr 2019 09:39:10 -0600 Subject: [PATCH] net/ip/dhcpv4: Set source IP address in DHCP Request The source address in unicast DHCPv4 Request packets was found out to be all zeros address 0.0.0.0. This address is only acceptable if the destination is a multicast one, where the host in question is acquiring a DHCP address lease. This is true for the DHCP Discover and the initial DHCP Request message from the client towards the server. As subsequent DHCP Request renewal messages are sent as unicast to the server, the server will drop such packets. Fix this issue by explicitely specifying what source IP address is to be used, if none is specified, the all zeros address 0.0.0.0 is used in multicast addresses. The source address in the other unicast cases is identical to the 'ciaddr' in the DHCP message. Signed-off-by: Patrik Flykt --- subsys/net/ip/dhcpv4.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/subsys/net/ip/dhcpv4.c b/subsys/net/ip/dhcpv4.c index c1bb0cc947cd..d1f60b607613 100644 --- a/subsys/net/ip/dhcpv4.c +++ b/subsys/net/ip/dhcpv4.c @@ -150,15 +150,22 @@ static inline bool dhcpv4_add_sname(struct net_pkt *pkt) /* Create DHCPv4 message and add options as per message type */ static struct net_pkt *dhcpv4_create_message(struct net_if *iface, u8_t type, const struct in_addr *ciaddr, + const struct in_addr *src_addr, const struct in_addr *server_addr, bool server_id, bool requested_ip) { NET_PKT_DATA_ACCESS_DEFINE(dhcp_access, struct dhcp_msg); - const struct in_addr src = INADDR_ANY_INIT; + const struct in_addr *addr; size_t size = DHCPV4_MESSAGE_SIZE; struct net_pkt *pkt; struct dhcp_msg *msg; + if (src_addr == NULL) { + addr = net_ipv4_unspecified_address(); + } else { + addr = src_addr; + } + if (server_id) { size += DHCPV4_OLV_MSG_SERVER_ID; } @@ -176,7 +183,7 @@ static struct net_pkt *dhcpv4_create_message(struct net_if *iface, u8_t type, net_pkt_set_ipv4_ttl(pkt, 0xFF); - if (net_ipv4_create(pkt, &src, server_addr) || + if (net_ipv4_create(pkt, addr, server_addr) || net_udp_create(pkt, htons(DHCPV4_CLIENT_PORT), htons(DHCPV4_SERVER_PORT))) { goto fail; @@ -247,6 +254,7 @@ static u32_t dhcpv4_send_request(struct net_if *iface) { const struct in_addr *server_addr = net_ipv4_broadcast_address(); const struct in_addr *ciaddr = NULL; + const struct in_addr *src_addr = NULL; bool with_server_id = false; bool with_requested_ip = false; struct net_pkt *pkt; @@ -273,6 +281,7 @@ static u32_t dhcpv4_send_request(struct net_if *iface) ciaddr = &iface->config.dhcpv4.requested_ip; /* UNICAST the DHCPREQUEST */ + src_addr = ciaddr; server_addr = &iface->config.dhcpv4.server_id; /* RFC2131 4.4.5 Client MUST NOT include server @@ -283,13 +292,14 @@ static u32_t dhcpv4_send_request(struct net_if *iface) /* Since we have an address populate the ciaddr field. */ ciaddr = &iface->config.dhcpv4.requested_ip; + src_addr = ciaddr; break; } pkt = dhcpv4_create_message(iface, DHCPV4_MSG_TYPE_REQUEST, - ciaddr, server_addr, with_server_id, - with_requested_ip); + ciaddr, src_addr, server_addr, + with_server_id, with_requested_ip); if (!pkt) { goto fail; } @@ -333,7 +343,7 @@ static u32_t dhcpv4_send_discover(struct net_if *iface) iface->config.dhcpv4.xid++; pkt = dhcpv4_create_message(iface, DHCPV4_MSG_TYPE_DISCOVER, - NULL, net_ipv4_broadcast_address(), + NULL, NULL, net_ipv4_broadcast_address(), false, false); if (!pkt) { goto fail;