udhcp: bind to device even for ucast packets
No binary (build failed)
—
(log yok)
| @@ -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; | |
| @@ -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); | |
| } | |
| @@ -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) | |
| @@ -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); | |