summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-05-22 14:26:36 +0200
committerLennart Poettering <lennart@poettering.net>2016-05-22 14:26:36 +0200
commite095f51dd16c530e56d8eb96960c0517be12d9bb (patch)
tree6143d02763c9f025babc7848b0b46f6d1db9e4ae /src/libsystemd-network
parente78f9587abfe03ae49acb388becb64c8353a6cb2 (diff)
ipv4acd/ipv4ll: stop using read() on SOCK_DGRAM sockets
This is a follow-up to cf447cb62d01137f4cbd1cd14b83b88823542bbf. Let's generally follow the rule to not use read() on SOCK_DGRAM sockets, let's always use recv() on that. Also, don't abort IPV4ACD logic in case we read a short packet. Simply log and ignore.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c32
-rw-r--r--src/libsystemd-network/test-ipv4ll.c9
2 files changed, 29 insertions, 12 deletions
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index 68563ad423..c1f43c824b 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -156,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) {
@@ -347,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;
@@ -381,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.");
}
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);