Lots of bugfixes, correctly handle announcements
This commit is contained in:
parent
87d8cbe72d
commit
044be347c8
1 changed files with 106 additions and 22 deletions
110
ffvisd/ffvisd.c
110
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]))
|
||||
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]);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
static int sockfd;
|
||||
static char *mesh = "bat0";
|
||||
|
||||
|
||||
ffvisd_announce_t *announcements = NULL;
|
||||
|
||||
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,15 +423,34 @@ 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) {
|
||||
char *if_mesh = iface_get_mesh(ifname);
|
||||
|
||||
if (if_mesh && !strcmp(if_mesh, mesh)) {
|
||||
ffvisd_packet_announce_t *packet = arg;
|
||||
|
||||
struct sockaddr_ll sa;
|
||||
|
@ -415,6 +463,8 @@ static void send_announcement(const char *ifname, unsigned ifindex, void *arg) {
|
|||
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));
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
Reference in a new issue