summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/dhcp-network.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network/dhcp-network.c')
-rw-r--r--src/libsystemd-network/dhcp-network.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 3c85bb0b54..65405dcce0 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -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)