diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-05-22 14:26:36 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-05-22 14:26:36 +0200 |
commit | e095f51dd16c530e56d8eb96960c0517be12d9bb (patch) | |
tree | 6143d02763c9f025babc7848b0b46f6d1db9e4ae /src/libsystemd-network/sd-ipv4acd.c | |
parent | e78f9587abfe03ae49acb388becb64c8353a6cb2 (diff) | |
download | systemd-e095f51dd16c530e56d8eb96960c0517be12d9bb.tar.gz |
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/sd-ipv4acd.c')
-rw-r--r-- | src/libsystemd-network/sd-ipv4acd.c | 32 |
1 files changed, 24 insertions, 8 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."); } |