]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ipv4acd/ipv4ll: stop using read() on SOCK_DGRAM sockets 3322/head
authorLennart Poettering <lennart@poettering.net>
Sun, 22 May 2016 12:26:36 +0000 (14:26 +0200)
committerLennart Poettering <lennart@poettering.net>
Sun, 22 May 2016 12:26:36 +0000 (14:26 +0200)
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.

src/libsystemd-network/sd-ipv4acd.c
src/libsystemd-network/test-ipv4ll.c

index 68563ad4233aa5efc867bf65b1556085edcaf5de..c1f43c824bb30a6b085a21f830b4b899ed0789a9 100644 (file)
@@ -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.");
         }
index a233e0378c4415efd923861ab23f92d6709cb93c..8cdbfb8ed8a1c67f5b3456abdd86567afb600304 100644 (file)
@@ -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);