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 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) {
|
static inline bool is_eth_addr_unspec(const eth_addr_t *address) {
|
||||||
const uint8_t *a = address->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;
|
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;
|
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]);
|
||||||
static char *mesh = "bat0";
|
}
|
||||||
|
|
||||||
|
|
||||||
ffvisd_announce_t *announcements = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/* returns (tp1 - tp2) in milliseconds */
|
/* returns (tp1 - tp2) in milliseconds */
|
||||||
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
|
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) {
|
static bool file_readv(const char *file, const char *format, va_list ap) {
|
||||||
FILE *f = fopen(file, "r");
|
FILE *f = fopen(file, "r");
|
||||||
if (!f)
|
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;
|
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",
|
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],
|
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]);
|
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) {
|
static void pr_announcement(const ffvisd_announce_t *announce) {
|
||||||
if (!announce->received.tv_sec) {
|
if (is_announcement_local(announce)) {
|
||||||
printf("local, ");
|
printf("local, ");
|
||||||
}
|
}
|
||||||
else {
|
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("age: %.1fs, ", timespec_diff(&tv, &announce->received)/1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("valid: %s, ", is_announcement_valid(announce) ? "yes" : "no");
|
||||||
|
|
||||||
pr_announcement_packet(&announce->announce);
|
pr_announcement_packet(&announce->announce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,15 +423,34 @@ static bool init_announcements() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maintenance() {
|
static void maintenance() {
|
||||||
ffvisd_announce_t **announce;
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
for(announce = &announcements; *announce; announce = &(*announce)->next) {
|
ffvisd_announce_t **announce, **next;
|
||||||
if (!(*announce)->received.tv_sec) /* announcement is local */
|
|
||||||
|
for(announce = &announcements; *announce; announce = next) {
|
||||||
|
next = &(*announce)->next;
|
||||||
|
|
||||||
|
if (is_announcement_local(*announce)) {
|
||||||
(*announce)->announce.seqno = htons(ntohs((*announce)->announce.seqno)+1);
|
(*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) {
|
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;
|
ffvisd_packet_announce_t *packet = arg;
|
||||||
|
|
||||||
struct sockaddr_ll sa;
|
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);
|
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() {
|
static void send_announcements() {
|
||||||
|
@ -427,6 +477,9 @@ static void send_announcements() {
|
||||||
uint16_t n_servers = 0;
|
uint16_t n_servers = 0;
|
||||||
ffvisd_announce_t *announce;
|
ffvisd_announce_t *announce;
|
||||||
for(announce = announcements; announce; announce = announce->next) {
|
for(announce = announcements; announce; announce = announce->next) {
|
||||||
|
if (!is_announcement_valid(announce))
|
||||||
|
continue;
|
||||||
|
|
||||||
packet->servers[n_servers++] = announce->announce;
|
packet->servers[n_servers++] = announce->announce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +515,38 @@ static void receive_announcement() {
|
||||||
for(i = 0; i < n_servers; i++)
|
for(i = 0; i < n_servers; i++)
|
||||||
pr_announcement_packet(&packet->servers[i]);
|
pr_announcement_packet(&packet->servers[i]);
|
||||||
puts("");
|
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() {
|
int main() {
|
||||||
|
@ -493,7 +578,6 @@ int main() {
|
||||||
next_announce.tv_sec += ANNOUNCE_INTERVAL;
|
next_announce.tv_sec += ANNOUNCE_INTERVAL;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
struct timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
int timeout = timespec_diff(&next_announce, &now);
|
int timeout = timespec_diff(&next_announce, &now);
|
||||||
|
|
||||||
|
|
Reference in a new issue