]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dhcp: bind udp sockets to interfaces (#4822)
author27o <27o@users.noreply.github.com>
Wed, 7 Dec 2016 01:00:05 +0000 (02:00 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 7 Dec 2016 01:00:05 +0000 (02:00 +0100)
src/libsystemd-network/dhcp-internal.h
src/libsystemd-network/dhcp-network.c
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/test-dhcp-client.c

index 5aa8aca42610bb522689a385c921dc4f6f6bcda1..3fdf02da3e919ff93b3150545388d42627230c5f 100644 (file)
 #include "dhcp-protocol.h"
 #include "socket-util.h"
 
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
+int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
                                  uint32_t xid, const uint8_t *mac_addr,
                                  size_t mac_addr_len, uint16_t arp_type,
                                  uint16_t port);
-int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
+int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port);
 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
                                  const void *packet, size_t len);
 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
index 3c85bb0b54b56e5e2250031974a65b61348a3a95..65405dcce07cddd8c95f5935f01f5f1f4b09e1df 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <net/ethernet.h>
+#include <net/if.h>
 #include <net/if_arp.h>
 #include <stdio.h>
 #include <string.h>
@@ -156,13 +157,14 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
                                 bcast_addr, &eth_mac, arp_type, dhcp_hlen, port);
 }
 
-int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
+int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
         union sockaddr_union src = {
                 .in.sin_family = AF_INET,
                 .in.sin_port = htobe16(port),
                 .in.sin_addr.s_addr = address,
         };
         _cleanup_close_ int s = -1;
+        char ifname[IF_NAMESIZE] = "";
         int r, on = 1, tos = IPTOS_CLASS_CS6;
 
         s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
@@ -177,6 +179,15 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
         if (r < 0)
                 return -errno;
 
+        if (ifindex > 0) {
+                if (if_indextoname(ifindex, ifname) == 0)
+                        return -errno;
+
+                r = setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
+                if (r < 0)
+                        return -errno;
+        }
+
         if (address == INADDR_ANY) {
                 r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
                 if (r < 0)
@@ -185,6 +196,7 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
                 r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
                 if (r < 0)
                         return -errno;
+
         } else {
                 r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
                 if (r < 0)
index 14232648068a4a64613a8669092ff7e05d67379c..b4bf75a3dc2cda58fe8050e59567d0710398a669 100644 (file)
@@ -1546,7 +1546,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                                 goto error;
                         }
 
-                        r = dhcp_network_bind_udp_socket(client->lease->address, client->port);
+                        r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port);
                         if (r < 0) {
                                 log_dhcp_client(client, "could not bind UDP socket");
                                 goto error;
index f16314a37fbef630d81543952a16e533091750b3..0e57ab6b6929087da95b1300e1b31d1b21b4a815 100644 (file)
@@ -1022,7 +1022,7 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
         }
         server->fd_raw = r;
 
-        r = dhcp_network_bind_udp_socket(INADDR_ANY, DHCP_PORT_SERVER);
+        r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER);
         if (r < 0) {
                 sd_dhcp_server_stop(server);
                 return r;
index c10ca74b863bc316d82b519d6a9ac2e46e471016..f5f1284e6dd3524b0490a7e59e46efc47c92f0aa 100644 (file)
@@ -203,7 +203,7 @@ int dhcp_network_bind_raw_socket(
         return test_fd[0];
 }
 
-int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
+int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
         int fd;
 
         fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);