diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-08-30 01:04:47 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-08-30 01:04:47 +0200 |
commit | 044be347c872df833a454b76adfec817ada1be8c (patch) | |
tree | 833a4d8df6d301b4a90ae8c3890e0168941eb5ae | |
parent | 87d8cbe72d6d983b0a4659eaee6240a39d9731af (diff) | |
download | ffd-044be347c872df833a454b76adfec817ada1be8c.tar ffd-044be347c872df833a454b76adfec817ada1be8c.zip |
Lots of bugfixes, correctly handle announcements
-rw-r--r-- | ffvisd/ffvisd.c | 128 |
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); |