summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-08-30 01:04:47 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-08-30 01:04:47 +0200
commit044be347c872df833a454b76adfec817ada1be8c (patch)
tree833a4d8df6d301b4a90ae8c3890e0168941eb5ae
parent87d8cbe72d6d983b0a4659eaee6240a39d9731af (diff)
downloadffd-044be347c872df833a454b76adfec817ada1be8c.tar
ffd-044be347c872df833a454b76adfec817ada1be8c.zip
Lots of bugfixes, correctly handle announcements
-rw-r--r--ffvisd/ffvisd.c128
1 files changed, 106 insertions, 22 deletions
diff --git a/ffvisd/ffvisd.c b/ffvisd/ffvisd.c
index 9ad00c8..d1b36f0 100644
--- a/ffvisd/ffvisd.c
+++ b/ffvisd/ffvisd.c
@@ -126,6 +126,13 @@ static const eth_addr_t eth_addr_unspec = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
static const eth_addr_t ffd_addr = {{0x03, 0x00, 0x00, 0x00, 0x0f, 0xfd}};
+static int sockfd;
+static char *mesh = "bat0";
+
+static struct timespec now;
+static ffvisd_announce_t *announcements = NULL;
+
+
static inline bool is_eth_addr_unspec(const eth_addr_t *address) {
const uint8_t *a = address->address;
@@ -135,16 +142,19 @@ static inline bool is_eth_addr_unspec(const eth_addr_t *address) {
return true;
}
+static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_addr_t *address2) {
+ const uint8_t *a = address1->address;
+ const uint8_t *b = address2->address;
-#define ETH_ADDR_IS_UNSPEC(a) (!((a).address[0]||(a).address[0]||(a).address[0]||(a).address[0]||(a).address[0]||(a).address[0]))
-
-
-static int sockfd;
-static char *mesh = "bat0";
-
+ return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]);
+}
-ffvisd_announce_t *announcements = NULL;
+static inline bool are_ipv6_host_addrs_equal(const ffvisd_ipv6_host_addr_t *address1, const ffvisd_ipv6_host_addr_t *address2) {
+ const uint8_t *a = address1->address;
+ const uint8_t *b = address2->address;
+ return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5] && a[6]==b[6] && a[7]==b[7]);
+}
/* returns (tp1 - tp2) in milliseconds */
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
@@ -152,6 +162,23 @@ static inline int timespec_diff(const struct timespec *tp1, const struct timespe
}
+static inline bool are_announcements_equal(const ffvisd_packet_server_announce_t *a1, const ffvisd_packet_server_announce_t *a2) {
+ return (are_eth_addrs_equal(&a1->eth_address, &a2->eth_address) && are_ipv6_host_addrs_equal(&a1->address, &a2->address));
+}
+
+static inline bool is_announcement_local(const ffvisd_announce_t *a) {
+ return (a->received.tv_sec == 0);
+}
+
+static inline bool is_announcement_valid(const ffvisd_announce_t *a) {
+ if (is_announcement_local(a))
+ return true;
+
+ int diff = timespec_diff(&now, &a->received);
+ return (diff < ANNOUNCE_TIMEOUT*1000);
+}
+
+
static bool file_readv(const char *file, const char *format, va_list ap) {
FILE *f = fopen(file, "r");
if (!f)
@@ -322,13 +349,13 @@ static void pr_announcement_packet(const ffvisd_packet_server_announce_t *announ
const uint8_t *e = announce->eth_address.address, *a = announce->address.address;
printf("seqno: %u, ether: %02x:%02x:%02x:%02x:%02x:%02x, address: fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
- announce->seqno,
+ ntohs(announce->seqno),
e[0], e[1], e[2], e[3], e[4], e[5],
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}
static void pr_announcement(const ffvisd_announce_t *announce) {
- if (!announce->received.tv_sec) {
+ if (is_announcement_local(announce)) {
printf("local, ");
}
else {
@@ -337,6 +364,8 @@ static void pr_announcement(const ffvisd_announce_t *announce) {
printf("age: %.1fs, ", timespec_diff(&tv, &announce->received)/1000.0);
}
+ printf("valid: %s, ", is_announcement_valid(announce) ? "yes" : "no");
+
pr_announcement_packet(&announce->announce);
}
@@ -394,27 +423,48 @@ static bool init_announcements() {
}
static void maintenance() {
- ffvisd_announce_t **announce;
+ clock_gettime(CLOCK_MONOTONIC, &now);
- for(announce = &announcements; *announce; announce = &(*announce)->next) {
- if (!(*announce)->received.tv_sec) /* announcement is local */
+ ffvisd_announce_t **announce, **next;
+
+ for(announce = &announcements; *announce; announce = next) {
+ next = &(*announce)->next;
+
+ if (is_announcement_local(*announce)) {
(*announce)->announce.seqno = htons(ntohs((*announce)->announce.seqno)+1);
+ continue;
+ }
+
+ int diff = timespec_diff(&now, &(*announce)->received);
+ if (diff >= ANNOUNCE_PRUNE*1000) {
+ ffvisd_announce_t *del = *announce;
+
+ *announce = *next;
+ next = announce;
+
+ free(del);
+ }
}
}
static void send_announcement(const char *ifname, unsigned ifindex, void *arg) {
- ffvisd_packet_announce_t *packet = arg;
+ char *if_mesh = iface_get_mesh(ifname);
+
+ if (if_mesh && !strcmp(if_mesh, mesh)) {
+ ffvisd_packet_announce_t *packet = arg;
- struct sockaddr_ll sa;
- memset(&sa, 0, sizeof(sa));
+ struct sockaddr_ll sa;
+ memset(&sa, 0, sizeof(sa));
- sa.sll_family = AF_PACKET;
- sa.sll_protocol = htons(FFD_PROTO);
- sa.sll_ifindex = ifindex;
- sa.sll_halen = ETH_ALEN;
- memcpy(sa.sll_addr, ffd_addr.address, ETH_ALEN);
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = htons(FFD_PROTO);
+ sa.sll_ifindex = ifindex;
+ sa.sll_halen = ETH_ALEN;
+ memcpy(sa.sll_addr, ffd_addr.address, ETH_ALEN);
- sendto(sockfd, packet, sizeof(ffvisd_packet_announce_t) + ntohs(packet->n_servers)*sizeof(ffvisd_packet_server_announce_t), 0, (struct sockaddr*)&sa, sizeof(sa));
+ sendto(sockfd, packet, sizeof(ffvisd_packet_announce_t) + ntohs(packet->n_servers)*sizeof(ffvisd_packet_server_announce_t), 0, (struct sockaddr*)&sa, sizeof(sa));
+ }
+ free(if_mesh);
}
static void send_announcements() {
@@ -427,6 +477,9 @@ static void send_announcements() {
uint16_t n_servers = 0;
ffvisd_announce_t *announce;
for(announce = announcements; announce; announce = announce->next) {
+ if (!is_announcement_valid(announce))
+ continue;
+
packet->servers[n_servers++] = announce->announce;
}
@@ -462,6 +515,38 @@ static void receive_announcement() {
for(i = 0; i < n_servers; i++)
pr_announcement_packet(&packet->servers[i]);
puts("");
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ for(i = 0; i < n_servers; i++) {
+ ffvisd_announce_t *announce;
+ for(announce = announcements; announce; announce = announce->next) {
+ if (!are_announcements_equal(&packet->servers[i], &announce->announce))
+ continue;
+
+ if (is_announcement_local(announce))
+ break;
+
+ uint16_t seqno_diff = ntohs(packet->servers[i].seqno) - ntohs(announce->announce.seqno);
+
+ if (seqno_diff > 0 && seqno_diff < 0x8000) {
+ announce->received = now;
+ announce->announce = packet->servers[i];
+ }
+
+ break;
+ }
+
+ if (!announce) { /* no matching annouce was found */
+ announce = calloc(1, sizeof(ffvisd_announce_t));
+ announce->received = now;
+ announce->announce = packet->servers[i];
+
+ announce->next = announcements;
+ announcements = announce;
+ }
+
+ }
}
int main() {
@@ -493,7 +578,6 @@ int main() {
next_announce.tv_sec += ANNOUNCE_INTERVAL;
while (true) {
- struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
int timeout = timespec_diff(&next_announce, &now);