summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp-server-internal.h2
-rw-r--r--src/libsystemd-network/dhcp6-internal.h3
-rw-r--r--src/libsystemd-network/icmp6-util.c9
-rw-r--r--src/libsystemd-network/network-internal.c15
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c31
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c28
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c45
-rw-r--r--src/libsystemd-network/test-ipv4ll.c9
9 files changed, 90 insertions, 54 deletions
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index adb557167a..0c76956fad 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -63,6 +63,8 @@ struct sd_dhcp_server {
struct in_addr *ntp, *dns;
unsigned n_ntp, n_dns;
+ bool emit_router;
+
Hashmap *leases_by_client_id;
DHCPLease **bound_leases;
DHCPLease invalid_lease;
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h
index 749086d33a..945c3b9721 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -55,7 +55,8 @@ struct DHCP6IA {
typedef struct DHCP6IA DHCP6IA;
-#define log_dhcp6_client(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
+#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
+#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__)
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index acad9d7d6a..d81e9ebd88 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -26,6 +26,7 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
+#include <net/if.h>
#include <linux/if_packet.h>
#include "fd-util.h"
@@ -47,6 +48,7 @@ int icmp6_bind_router_solicitation(int index) {
.ipv6mr_interface = index,
};
_cleanup_close_ int s = -1;
+ char ifname[IF_NAMESIZE] = "";
int r, zero = 0, one = 1, hops = 255;
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
@@ -83,6 +85,13 @@ int icmp6_bind_router_solicitation(int index) {
if (r < 0)
return -errno;
+ if (if_indextoname(index, ifname) == 0)
+ return -errno;
+
+ r = setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
+ if (r < 0)
+ return -errno;
+
r = s;
s = -1;
return r;
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 2badcdff58..046b0f9393 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -27,6 +27,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "dhcp-lease-internal.h"
+#include "ether-addr-util.c"
#include "hexdecoct.h"
#include "log.h"
#include "network-internal.h"
@@ -272,6 +273,8 @@ int config_parse_hwaddr(const char *unit,
void *userdata) {
struct ether_addr **hwaddr = data;
struct ether_addr *n;
+ const char *start;
+ size_t offset;
int r;
assert(filename);
@@ -283,14 +286,10 @@ int config_parse_hwaddr(const char *unit,
if (!n)
return log_oom();
- r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
- &n->ether_addr_octet[0],
- &n->ether_addr_octet[1],
- &n->ether_addr_octet[2],
- &n->ether_addr_octet[3],
- &n->ether_addr_octet[4],
- &n->ether_addr_octet[5]);
- if (r != 6) {
+ start = rvalue + strspn(rvalue, WHITESPACE);
+ r = ether_addr_from_string(start, n, &offset);
+
+ if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
free(n);
return 0;
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 3846cf7476..ad79c6cc2c 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1640,7 +1640,7 @@ static int client_receive_message_udp(
if (!message)
return -ENOMEM;
- len = read(fd, message, buflen);
+ len = recv(fd, message, buflen, 0);
if (len < 0) {
if (errno == EAGAIN || errno == EINTR)
return 0;
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 9adf8ec19d..fb335337c4 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -468,10 +468,12 @@ static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req,
if (r < 0)
return r;
- r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- SD_DHCP_OPTION_ROUTER, 4, &server->address);
- if (r < 0)
- return r;
+ if (server->emit_router) {
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ SD_DHCP_OPTION_ROUTER, 4, &server->address);
+ if (r < 0)
+ return r;
+ }
r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
if (r < 0)
@@ -505,10 +507,12 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
if (r < 0)
return r;
- r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
- SD_DHCP_OPTION_ROUTER, 4, &server->address);
- if (r < 0)
- return r;
+ if (server->emit_router) {
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ SD_DHCP_OPTION_ROUTER, 4, &server->address);
+ if (r < 0)
+ return r;
+ }
if (server->n_dns > 0) {
r = dhcp_option_append(
@@ -1158,3 +1162,14 @@ int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], u
return 1;
}
+
+int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
+ assert_return(server, -EINVAL);
+
+ if (enabled == server->emit_router)
+ return 0;
+
+ server->emit_router = enabled;
+
+ return 1;
+}
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 4adb053a57..05972e01c9 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -917,14 +917,13 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
if (!message)
return -ENOMEM;
- len = read(fd, message, buflen);
+ len = recv(fd, message, buflen, 0);
if (len < 0) {
if (errno == EAGAIN || errno == EINTR)
return 0;
- log_dhcp6_client(client, "Could not receive message from UDP socket: %m");
+ return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m");
- return -errno;
} else if ((size_t)len < sizeof(DHCP6Message))
return 0;
@@ -947,8 +946,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
break;
default:
- log_dhcp6_client(client, "unknown message type %d",
- message->type);
+ log_dhcp6_client(client, "Unknown message type %d", message->type);
return 0;
}
@@ -1007,10 +1005,9 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
return 0;
}
- if (r >= 0) {
+ if (r >= 0)
log_dhcp6_client(client, "Recv %s",
dhcp6_message_type_to_string(message->type));
- }
return 0;
}
@@ -1063,7 +1060,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
if (client->lease->ia.lifetime_t1 == 0xffffffff ||
client->lease->ia.lifetime_t2 == 0xffffffff) {
- log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x",
+ log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x",
be32toh(client->lease->ia.lifetime_t1),
be32toh(client->lease->ia.lifetime_t2));
@@ -1179,8 +1176,13 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
return r;
r = dhcp6_network_bind_udp_socket(client->index, &client->local_address);
- if (r < 0)
- return r;
+ if (r < 0) {
+ _cleanup_free_ char *p = NULL;
+
+ (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p);
+ return log_dhcp6_client_errno(client, r,
+ "Failed to bind to UDP socket at address %s: %m", strna(p));
+ }
client->fd = r;
@@ -1196,7 +1198,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
goto error;
r = sd_event_source_set_description(client->receive_message,
- "dhcp6-receive-message");
+ "dhcp6-receive-message");
if (r < 0)
goto error;
@@ -1204,8 +1206,8 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
state = DHCP6_STATE_INFORMATION_REQUEST;
log_dhcp6_client(client, "Started in %s mode",
- client->information_request? "Information request":
- "Managed");
+ client->information_request? "Information request":
+ "Managed");
return client_start(client, state);
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index cc7436db6b..c1f43c824b 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -28,6 +28,7 @@
#include "alloc-util.h"
#include "arp-util.h"
+#include "ether-addr-util.h"
#include "fd-util.h"
#include "in-addr-util.h"
#include "list.h"
@@ -155,8 +156,10 @@ static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counte
static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) {
assert(ll);
- if (ll->cb)
- ll->cb(ll, event, ll->userdata);
+ if (!ll->cb)
+ return;
+
+ ll->cb(ll, event, ll->userdata);
}
static void ipv4acd_stop(sd_ipv4acd *ll) {
@@ -346,22 +349,36 @@ static void ipv4acd_on_conflict(sd_ipv4acd *ll) {
ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT);
}
-static int ipv4acd_on_packet(sd_event_source *s, int fd,
- uint32_t revents, void *userdata) {
+static int ipv4acd_on_packet(
+ sd_event_source *s,
+ int fd,
+ uint32_t revents,
+ void *userdata) {
+
sd_ipv4acd *ll = userdata;
struct ether_arp packet;
+ ssize_t n;
int r;
+ assert(s);
assert(ll);
assert(fd >= 0);
- r = read(fd, &packet, sizeof(struct ether_arp));
- if (r < (int) sizeof(struct ether_arp))
+ n = recv(fd, &packet, sizeof(struct ether_arp), 0);
+ if (n < 0) {
+ r = log_ipv4acd_debug_errno(ll, errno, "Failed to read ARP packet: %m");
goto out;
+ }
+ if ((size_t) n != sizeof(struct ether_arp)) {
+ log_ipv4acd_debug(ll, "Ignoring too short ARP packet.");
+ return 0;
+ }
switch (ll->state) {
+
case IPV4ACD_STATE_ANNOUNCING:
case IPV4ACD_STATE_RUNNING:
+
if (ipv4acd_arp_conflict(ll, &packet)) {
usec_t ts;
@@ -380,15 +397,15 @@ static int ipv4acd_on_packet(sd_event_source *s, int fd,
} else
ipv4acd_on_conflict(ll);
}
-
break;
+
case IPV4ACD_STATE_WAITING_PROBE:
case IPV4ACD_STATE_PROBING:
case IPV4ACD_STATE_WAITING_ANNOUNCE:
/* BPF ensures this packet indicates a conflict */
ipv4acd_on_conflict(ll);
-
break;
+
default:
assert_not_reached("Invalid state.");
}
@@ -472,16 +489,6 @@ int sd_ipv4acd_is_running(sd_ipv4acd *ll) {
return ll->state != IPV4ACD_STATE_INIT;
}
-static bool ether_addr_is_nul(const struct ether_addr *addr) {
- const struct ether_addr nul_addr = {};
-
- assert(addr);
-
- return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0;
-}
-
-#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
-
int sd_ipv4acd_start(sd_ipv4acd *ll) {
int r;
@@ -489,7 +496,7 @@ int sd_ipv4acd_start(sd_ipv4acd *ll) {
assert_return(ll->event, -EINVAL);
assert_return(ll->index > 0, -EINVAL);
assert_return(ll->address != 0, -EINVAL);
- assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL);
+ assert_return(!ether_addr_is_null(&ll->mac_addr), -EINVAL);
assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
ll->defend_window = 0;
diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c
index a233e0378c..8cdbfb8ed8 100644
--- a/src/libsystemd-network/test-ipv4ll.c
+++ b/src/libsystemd-network/test-ipv4ll.c
@@ -38,7 +38,8 @@ static int test_fd[2];
static int basic_request_handler_bind = 0;
static int basic_request_handler_stop = 0;
-static void* basic_request_handler_userdata = (void*)0xCABCAB;
+static void* basic_request_handler_userdata = (void*) 0xCABCAB;
+
static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) {
assert_se(userdata == basic_request_handler_userdata);
@@ -181,16 +182,16 @@ static void test_basic_request(sd_event *e) {
/* PROBE */
sd_event_run(e, (uint64_t) -1);
- assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
+ assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
if (extended) {
/* PROBE */
sd_event_run(e, (uint64_t) -1);
- assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
+ assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
/* PROBE */
sd_event_run(e, (uint64_t) -1);
- assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp));
+ assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp));
sd_event_run(e, (uint64_t) -1);
assert_se(basic_request_handler_bind == 1);