dhcp: bind udp sockets to interfaces (#4822)

This commit is contained in:
27o
2016-12-07 02:00:05 +01:00
committed by Lennart Poettering
parent 73e383cc62
commit 3e7b9f76f5
5 changed files with 18 additions and 6 deletions

View File

@@ -30,11 +30,11 @@
#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,

View 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)

View 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;

View 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;

View 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);