summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-ipv4ll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network/sd-ipv4ll.c')
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c80
1 files changed, 45 insertions, 35 deletions
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 14b9444dab..f292a9dba9 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -28,7 +28,7 @@
#include "list.h"
#include "random-util.h"
-#include "ipv4ll-internal.h"
+#include "arp-util.h"
#include "sd-ipv4ll.h"
/* Constants from the RFC */
@@ -46,6 +46,8 @@
#define IPV4LL_NETWORK 0xA9FE0000L
#define IPV4LL_NETMASK 0xFFFF0000L
+#define log_ipv4ll(ll, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "IPv4LL: " fmt, ##__VA_ARGS__)
+
typedef enum IPv4LLTrigger{
IPV4LL_TRIGGER_NULL,
IPV4LL_TRIGGER_PACKET,
@@ -72,7 +74,6 @@ struct sd_ipv4ll {
IPv4LLState state;
int index;
int fd;
- union sockaddr_union link;
int iteration;
int conflict;
sd_event_source *receive_message;
@@ -196,8 +197,7 @@ static bool ipv4ll_arp_conflict (sd_ipv4ll *ll, struct ether_arp *arp) {
assert(ll);
assert(arp);
- if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0 &&
- memcmp(arp->arp_sha, &ll->mac_addr, ETH_ALEN) != 0)
+ if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0)
return true;
return false;
@@ -210,16 +210,13 @@ static bool ipv4ll_arp_probe_conflict (sd_ipv4ll *ll, struct ether_arp *arp) {
if (ipv4ll_arp_conflict(ll, arp))
return true;
- if (memcmp(arp->arp_tpa, &ll->address, sizeof(ll->address)) == 0 &&
- memcmp(arp->arp_sha, &ll->mac_addr, ETH_ALEN))
+ if (memcmp(arp->arp_tpa, &ll->address, sizeof(ll->address)) == 0)
return true;
return false;
}
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void *trigger_data) {
- struct ether_arp out_packet;
- int out_packet_ready = 0;
int r = 0;
assert(ll);
@@ -235,8 +232,12 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
(ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < PROBE_NUM-2)) {
/* Send a probe */
- arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
- out_packet_ready = 1;
+ r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
+ if (r < 0) {
+ log_ipv4ll(ll, "Failed to send ARP probe.");
+ goto out;
+ }
+
ipv4ll_set_state(ll, IPV4LL_STATE_PROBING, 0);
ipv4ll_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
@@ -244,8 +245,12 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
} else if (ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration >= PROBE_NUM-2) {
/* Send the last probe */
- arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
- out_packet_ready = 1;
+ r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
+ if (r < 0) {
+ log_ipv4ll(ll, "Failed to send ARP probe.");
+ goto out;
+ }
+
ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_ANNOUNCE, 1);
ipv4ll_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
@@ -254,8 +259,12 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
(ll->state == IPV4LL_STATE_ANNOUNCING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < ANNOUNCE_NUM-1)) {
/* Send announcement packet */
- arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
- out_packet_ready = 1;
+ r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
+ if (r < 0) {
+ log_ipv4ll(ll, "Failed to send ARP announcement.");
+ goto out;
+ }
+
ipv4ll_set_state(ll, IPV4LL_STATE_ANNOUNCING, 0);
ipv4ll_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
@@ -295,8 +304,12 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
/* Defend address */
if (time_now > ll->defend_window) {
ll->defend_window = time_now + DEFEND_INTERVAL * USEC_PER_SEC;
- arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
- out_packet_ready = 1;
+ r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
+ if (r < 0) {
+ log_ipv4ll(ll, "Failed to send ARP announcement.");
+ goto out;
+ }
+
} else
conflicted = 1;
}
@@ -320,6 +333,15 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
r = ipv4ll_pick_address(ll, &ll->address);
if (r < 0)
goto out;
+
+ ll->fd = safe_close(ll->fd);
+
+ r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
+ if (r < 0)
+ goto out;
+
+ ll->fd = r;
+
ll->conflict++;
ll->defend_window = 0;
ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_PROBE, 1);
@@ -329,15 +351,6 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void
ipv4ll_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
} else
ipv4ll_set_next_wakeup(ll, 0, PROBE_WAIT);
-
- }
- }
-
- if (out_packet_ready) {
- r = arp_network_send_raw_socket(ll->fd, &ll->link, &out_packet);
- if (r < 0) {
- log_ipv4ll(ll, "failed to send arp packet out");
- goto out;
}
}
@@ -374,10 +387,6 @@ static int ipv4ll_receive_message(sd_event_source *s, int fd,
if (r < (int) sizeof(struct ether_arp))
return 0;
- r = arp_packet_verify_headers(&arp);
- if (r < 0)
- return 0;
-
ipv4ll_run_state_machine(ll, IPV4LL_TRIGGER_PACKET, &arp);
return 0;
@@ -523,12 +532,6 @@ int sd_ipv4ll_start (sd_ipv4ll *ll) {
ll->state = IPV4LL_STATE_INIT;
- r = arp_network_bind_raw_socket(ll->index, &ll->link);
-
- if (r < 0)
- goto out;
-
- ll->fd = r;
ll->conflict = 0;
ll->defend_window = 0;
ll->claimed_address = 0;
@@ -551,6 +554,13 @@ int sd_ipv4ll_start (sd_ipv4ll *ll) {
goto out;
}
+ r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
+ if (r < 0)
+ goto out;
+
+ safe_close(ll->fd);
+ ll->fd = r;
+
ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,