ipv4acd/ipv4ll: stop using read() on SOCK_DGRAM sockets
This is a follow-up to cf447cb62d
.
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.
This commit is contained in:
parent
e78f9587ab
commit
e095f51dd1
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue