diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 3cbd2d3c8..cc0abd269 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -343,7 +343,8 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) FAST_FUNC; + uint32_t dest_nip, int dest_port, + const char *ifname) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 66aa38c20..98720b45b 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -702,7 +702,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t if (server) return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, - server, SERVER_PORT); + server, SERVER_PORT, + client_data.interface); return raw_bcast_from_client_data_ifindex(packet, ciaddr); } diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index de16cf955..9e950ca1f 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -612,7 +612,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) udhcp_send_kernel_packet(dhcp_pkt, server_data.server_nip, SERVER_PORT, - dhcp_pkt->gateway_nip, SERVER_PORT); + dhcp_pkt->gateway_nip, SERVER_PORT, + server_data.interface); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 51374646d..4d8e005d4 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -189,7 +189,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, /* Let the kernel do all the work for packet generation */ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) + uint32_t dest_nip, int dest_port, + const char *ifname) { struct sockaddr_in sa; unsigned padding; @@ -204,6 +205,21 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, } setsockopt_reuseaddr(fd); + /* If interface carrier goes down, unless we + * bind socket to a particular netdev, the packet + * can go out through another interface, eg. via + * default route despite being bound to a specific + * source IP. As such, bind to device hard and fail + * otherwise. Sending renewal packets on foreign + * interfaces makes no sense. + */ + if (ifname) { + if (setsockopt_bindtodevice(fd, ifname) < 0) { + msg = "bindtodevice"; + goto ret_close; + } + } + memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(source_port);