summaryrefslogtreecommitdiffstats
path: root/ffd/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/send.c')
-rw-r--r--ffd/send.c89
1 files changed, 69 insertions, 20 deletions
diff --git a/ffd/send.c b/ffd/send.c
index 97ff3f1..283b36e 100644
--- a/ffd/send.c
+++ b/ffd/send.c
@@ -40,7 +40,7 @@
#include <sys/uio.h>
-static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t len) {
+static bool send_eth(const eth_addr_t *addr, unsigned ifindex, const void *buf, size_t len) {
static const uint8_t zeros[46] = {0};
struct sockaddr_ll sa;
@@ -52,7 +52,7 @@ static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t
memcpy(sa.sll_addr, addr->d, ETH_ALEN);
struct iovec vec[2] = {
- { .iov_base = buf, .iov_len = len },
+ { .iov_base = (void*)buf, .iov_len = len },
{ .iov_base = (void*)zeros, .iov_len = sizeof(zeros) - len },
};
@@ -72,7 +72,43 @@ static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t
return true;
}
-void ffd_send_ack(ffd_iface_t *iface, ffd_neigh_t *neigh, uint16_t nonce) {
+static inline bool send_neigh(const ffd_neigh_t *neigh, const ffd_packet_t *packet) {
+ if (!neigh->iface)
+ return false;
+
+ if (!send_eth(&neigh->addr, neigh->iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) {
+ fprintf(stderr, "send_eth: %m\n");
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool send_iface(const ffd_iface_t *iface, const ffd_packet_t *packet) {
+ if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) {
+ fprintf(stderr, "send_eth: %m\n");
+ return false;
+ }
+
+ return true;
+}
+
+static inline void send_broadcast(const ffd_packet_t *packet) {
+ ffd_iface_t *iface;
+ for (iface = iface_list; iface; iface = iface->next)
+ send_iface(iface, packet);
+}
+
+static inline void send_any(const ffd_iface_t *iface, const ffd_neigh_t *neigh, const ffd_packet_t *packet) {
+ if (neigh)
+ send_neigh(neigh, packet);
+ else if(iface)
+ send_iface(iface, packet);
+ else
+ send_broadcast(packet);
+}
+
+void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce) {
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
packet->version_magic = htons(FFD_VERSION_MAGIC);
@@ -84,8 +120,7 @@ void ffd_send_ack(ffd_iface_t *iface, ffd_neigh_t *neigh, uint16_t nonce) {
ack->nonce = htons(nonce);
- if (!send_eth(&neigh->addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
- fprintf(stderr, "send_eth: %m\n");
+ send_neigh(neigh, packet);
}
static void add_ihus(ffd_packet_t *packet, size_t max_len, const ffd_iface_t *iface) {
@@ -127,8 +162,7 @@ void ffd_send_hellos(void) {
add_ihus(packet, FFD_PACKET_MAX, iface);
- if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
- fprintf(stderr, "send_eth: %m\n");
+ send_iface(iface, packet);
}
}
@@ -192,11 +226,6 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann
packet->version_magic = htons(FFD_VERSION_MAGIC);
packet->len = 0;
- const eth_addr_t *addr = &ffd_addr;
-
- if (neigh)
- addr = &neigh->addr;
-
if (announce) {
add_update(packet, FFD_PACKET_MAX, NULL, announce, with_data);
}
@@ -206,8 +235,7 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann
ffd_announce_t *a;
for (a = announce_list; a; a = a->next) {
if (!add_update(packet, FFD_PACKET_MAX, &node_id, a, with_data)) {
- if (!send_eth(addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
- fprintf(stderr, "send_eth: %m\n");
+ send_any(iface, neigh, packet);
node_id = FFD_NODE_ID_UNSPEC;
packet->len = 0;
@@ -220,10 +248,32 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann
}
}
- if (packet->len) {
- if (!send_eth(addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
- fprintf(stderr, "send_eth: %m\n");
- }
+ if (packet->len)
+ send_any(iface, neigh, packet);
+}
+
+void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key) {
+ ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
+
+ packet->version_magic = htons(FFD_VERSION_MAGIC);
+ packet->len = 0;
+
+ if (!add_node_id(packet, FFD_PACKET_MAX, node))
+ return;
+
+ ffd_tlv_update_t *req = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_UPDATE, sizeof(ffd_tlv_update_t));
+ if (!req)
+ return;
+
+ req->flags = 0;
+ req->reserved = 0;
+ req->interval = htons(FFD_UPDATE_INTERVAL);
+ req->seqno = 0;
+ req->metric = 0xffff; /* no need to htons */
+ req->type = htons(type);
+ req->key = htons(key);
+
+ send_neigh(neigh, packet);
}
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data) {
@@ -245,6 +295,5 @@ void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_
if (with_data)
req->flags |= FFD_UPDATE_WITH_DATA;
- if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
- fprintf(stderr, "send_eth: %m\n");
+ send_any(iface, neigh, packet);
}