Skip to content

Commit

Permalink
Merge pull request freifunk-gluon#30 from freifunk-gluon/christf_retr…
Browse files Browse the repository at this point in the history
…y-claim

Allow retry of claims, fix memleaks
  • Loading branch information
christf authored Dec 18, 2017
2 parents 63bf9bb + 016bd21 commit 28d552d
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 53 deletions.
44 changes: 29 additions & 15 deletions src/clientmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,13 @@ const char *state_str(enum ip_state state) {
void client_ip_set_state(clientmgr_ctx *ctx, struct client *client, struct client_ip *ip, enum ip_state state) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
bool nop = false;

switch (ip->state) {
case IP_INACTIVE:
switch (state) {
case IP_INACTIVE:
nop = true;
// ignore
break;
case IP_ACTIVE:
Expand All @@ -348,12 +350,11 @@ void client_ip_set_state(clientmgr_ctx *ctx, struct client *client, struct clien
client_remove_route(ctx, client, ip);
break;
case IP_ACTIVE:
nop = true;
ip->timestamp = now;
break;
case IP_TENTATIVE:
ip->timestamp = now;
// TODO: are we shure we want to do this just yet?
client_remove_route(ctx, client, ip);
break;
}
break;
Expand All @@ -368,17 +369,17 @@ void client_ip_set_state(clientmgr_ctx *ctx, struct client *client, struct clien
client_add_route(ctx, client, ip);
break;
case IP_TENTATIVE:
nop = true;
ip->timestamp = now;
break;
}
break;
}

char ip_str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ip->addr, ip_str, INET6_ADDRSTRLEN);

printf("%s changes from %s to %s\n", ip_str, state_str(ip->state),
state_str(state));
if (!nop || l3ctx.debug) {
print_ip(&ip->addr);
printf("changes from %s to %s\n", state_str(ip->state), state_str(state));
}

ip->state = state;
}
Expand All @@ -404,17 +405,25 @@ bool clientmgr_is_ipv4(clientmgr_ctx *ctx, struct in6_addr *address) {
/** Remove an address from a client identified by its MAC.
**/
void clientmgr_remove_address(clientmgr_ctx *ctx, struct in6_addr *address, uint8_t *mac, unsigned int ifindex) {
printf("TODO: clientmgr_remove_address - currently not implemented\n");
fprintf(stderr, "TODO: clientmgr_remove_address - currently not implemented\n");
}

/** Add a new address to a client identified by its MAC.
*/
void clientmgr_add_address(clientmgr_ctx *ctx, struct in6_addr *address, uint8_t *mac, unsigned int ifindex) {
char str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, address, str, INET6_ADDRSTRLEN);
printf("clientmgr_add_address: %s\n",str);
if (!clientmgr_valid_address(ctx, address))

if (l3ctx.debug)
printf("clientmgr_add_address: %s is running",str);

if (!clientmgr_valid_address(ctx, address)) {
if (l3ctx.debug)
printf(" but address is not within a client-prefix\n");
return;
}
printf("\n");


struct client *client = get_or_create_client(ctx, mac);
struct client_ip *ip = get_client_ip(client, address);
Expand All @@ -423,7 +432,7 @@ void clientmgr_add_address(clientmgr_ctx *ctx, struct in6_addr *address, uint8_t
bool ip_is_new = ip == NULL;

if (ip_is_new) {
printf("Address: %s to client %02x:%02x:%02x:%02x:%02x:%02x\n", str, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("ADDING Address: %s to client %02x:%02x:%02x:%02x:%02x:%02x\n", str, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
struct client_ip _ip = {};
memcpy(&_ip.addr, address, sizeof(struct in6_addr));
VECTOR_ADD(client->addresses, _ip);
Expand Down Expand Up @@ -474,7 +483,7 @@ void clientmgr_notify_mac(clientmgr_ctx *ctx, uint8_t *mac, unsigned int ifindex
icmp6_send_solicitation(CTX(icmp6), &address);
}

/** Handle info request.
/** Handle claim (info request).
*/
void clientmgr_handle_claim(clientmgr_ctx *ctx, const struct in6_addr *sender, uint8_t mac[6]) {
struct client *client = get_client(ctx, mac);
Expand All @@ -492,13 +501,13 @@ void clientmgr_handle_claim(clientmgr_ctx *ctx, const struct in6_addr *sender, u
if (!client_is_active(client))
return;

printf("Dropping client in response to claim\n");
printf("Dropping client %02x:%02x:%02x:%02x:%02x:%02x in response to claim\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

for (int i = 0; i < VECTOR_LEN(client->addresses); i++) {
struct client_ip *ip = &VECTOR_INDEX(client->addresses, i);

if (ip->state == IP_ACTIVE || ip->state == IP_TENTATIVE)
client_ip_set_state(ctx, client, ip, IP_TENTATIVE);
client_ip_set_state(ctx, client, ip, IP_INACTIVE);
}

}
Expand All @@ -507,6 +516,10 @@ void clientmgr_handle_claim(clientmgr_ctx *ctx, const struct in6_addr *sender, u
*/
void clientmgr_handle_info(clientmgr_ctx *ctx, struct client *foreign_client, bool relinquished) {
struct client *client = get_client(ctx, foreign_client->mac);
if (l3ctx.debug) {
printf("handling info message in clientmgr_handle_info() for foreign_client");
print_client(foreign_client);
}

if (client == NULL || !client_is_active(client))
return;
Expand All @@ -528,7 +541,8 @@ void clientmgr_handle_info(clientmgr_ctx *ctx, struct client *foreign_client, bo
if (relinquished)
add_special_ip(ctx, client);

printf("Merged ");
printf("Client info merged ");
print_client(client);
printf("\n");
}

6 changes: 4 additions & 2 deletions src/clientmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ struct client_ip {
struct timespec timestamp;
};

struct client {
typedef struct client {
unsigned int ifindex;
struct timespec timeout;
uint8_t mac[6];
VECTOR(struct client_ip) addresses;
};
} client_t;



typedef struct {
struct l3ctx *l3ctx;
Expand Down
117 changes: 106 additions & 11 deletions src/intercom.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include "if.h"
#include "icmp6.h"
#include "syscallwrappers.h"
#include "util.h"

//TODO this is used for print_client - remove
#include "clientmgr.h"

#include <time.h>
#include <unistd.h>
Expand All @@ -17,6 +21,13 @@
#define INTERCOM_GROUP "ff02::5523"
#define INTERCOM_MAX_RECENT 100

#define CLAIM_RETRY_MAX 5

// Announce at most 32 addresses per client
#define INFO_MAX 32

void schedule_claim_retry(struct claim_task*);

bool join_mcast(const int sock, const struct in6_addr addr, intercom_if *iface) {
struct ipv6_mreq mreq;

Expand Down Expand Up @@ -132,9 +143,12 @@ bool intercom_send_packet_unicast(intercom_ctx *ctx, const struct in6_addr *reci
.sin6_port = htons(INTERCOM_PORT),
.sin6_addr = *recipient
};

ssize_t rc = sendto(ctx->fd, packet, packet_len, 0, (struct sockaddr*)&addr, sizeof(addr));

if (l3ctx.debug) {
printf("sent intercom packet rc: %zi to ", rc);
print_ip(recipient);
printf("\n");
}
if (rc < 0)
perror("sendto failed");

Expand All @@ -153,7 +167,8 @@ void intercom_send_packet(intercom_ctx *ctx, uint8_t *packet, ssize_t packet_len
groupaddr.sin6_scope_id = iface->ifindex;

ssize_t rc = sendto(ctx->fd, packet, packet_len, 0, (struct sockaddr*)&groupaddr, sizeof(groupaddr));
printf("sent packet to %s on iface %s rc: %zi\n", INTERCOM_GROUP, iface->ifname,rc);
if (l3ctx.debug)
printf("sent intercom packet to %s on iface %s rc: %zi\n", INTERCOM_GROUP, iface->ifname,rc);

if (rc < 0)
iface->ok = false;
Expand Down Expand Up @@ -192,6 +207,29 @@ void intercom_handle_claim(intercom_ctx *ctx, intercom_packet_claim *packet) {
clientmgr_handle_claim(CTX(clientmgr), &sender, packet->mac);
}



/** Finds the entry for a peer with a specified ID in the array \e ctx.peers */
/*
static fastd_peer_t ** peer_p_find_by_id(uint64_t id) {
fastd_peer_t key = {.id = id};
fastd_peer_t *const keyp = &key;
return VECTOR_BSEARCH(&keyp, ctx.peers, peer_id_cmp);
}
*/

bool find_repeatable_claim(uint8_t mac[6], int *index) {
// TODO: replace this with VECTOR_BSEARCH -- see the example above
for (*index=0;*index<VECTOR_LEN(l3ctx.intercom_ctx.repeatable_claims);(*index)++) {
struct client *client = &VECTOR_INDEX(l3ctx.intercom_ctx.repeatable_claims, *index);
if (!memcmp(client->mac, mac, 6))
return true;
}
return false;
}


void intercom_handle_info(intercom_ctx *ctx, intercom_packet_info *packet) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
Expand All @@ -200,6 +238,11 @@ void intercom_handle_info(intercom_ctx *ctx, intercom_packet_info *packet) {

memcpy(client.mac, &packet->mac, sizeof(uint8_t) * 6);

int i;

if (find_repeatable_claim(packet->mac, &i))
VECTOR_DELETE(ctx->repeatable_claims, i);

struct client_ip ip = {
.state = IP_INACTIVE
};
Expand Down Expand Up @@ -262,8 +305,6 @@ void intercom_handle_in(intercom_ctx *ctx, int fd) {
}
}

// Announce at most 32 addresses per client
#define INFO_MAX 32

/* recipient = NULL -> send to neighbours */
void intercom_info(intercom_ctx *ctx, const struct in6_addr *recipient, struct client *client, bool relinquished) {
Expand Down Expand Up @@ -297,15 +338,62 @@ void intercom_info(intercom_ctx *ctx, const struct in6_addr *recipient, struct c
ssize_t packet_len = sizeof(intercom_packet_info) + i * sizeof(intercom_packet_info_entry);

if (recipient != NULL)
// TODO: consider adding resilience here. There *might* be an ACK sensible
intercom_send_packet_unicast(ctx, recipient, (uint8_t*)packet, packet_len);
else {
// forward packet to other l3roamd instances
intercom_recently_seen_add(ctx, &packet->hdr);

intercom_send_packet(ctx, (uint8_t*)packet, packet_len);
}
free(packet);
}

void claim_retry_task(void *d) {
struct claim_task *data = d;

int i;
if (!find_repeatable_claim(data->client->mac, &i))
return;

if (data->recipient != NULL) {
if (l3ctx.debug) {
printf("sending unicast claim for client %02x:%02x:%02x:%02x:%02x:%02x to ", data->client->mac[0], data->client->mac[1], data->client->mac[2], data->client->mac[3], data->client->mac[4], data->client->mac[5]);
print_ip(data->recipient);
printf("\n");
}
intercom_send_packet_unicast(&l3ctx.intercom_ctx, data->recipient, (uint8_t*)&data->packet, sizeof(data->packet));
} else {
if (l3ctx.debug) {
printf("sending multicast claim for client %02x:%02x:%02x:%02x:%02x:%02x\n", data->client->mac[0], data->client->mac[1], data->client->mac[2], data->client->mac[3], data->client->mac[4], data->client->mac[5]);
}
intercom_send_packet(&l3ctx.intercom_ctx, (uint8_t*)&data->packet, sizeof(data->packet));
}

if (data->retries_left > 0)
schedule_claim_retry(data);
}
void free_claim_task(void *d) {
struct claim_task *data = d;
free(data->client);
free(data);
}

void schedule_claim_retry(struct claim_task *data) {
struct claim_task *ndata = calloc(1, sizeof(struct claim_task));
ndata->client = malloc(sizeof(struct client));
memcpy(ndata->client, data->client,sizeof(struct client));
ndata->retries_left = data->retries_left -1;
ndata->packet = data->packet;
ndata->recipient = data->recipient;
ndata->check_task = data->check_task;

if (data->check_task == NULL && data->retries_left > 0)
data->check_task = post_task(&l3ctx.taskqueue_ctx, 3, claim_retry_task, free_claim_task, ndata);
else
free_claim_task(ndata);
}

bool intercom_claim(intercom_ctx *ctx, const struct in6_addr *recipient, struct client *client) {
intercom_packet_claim packet;
uint32_t nonce;
Expand All @@ -324,10 +412,17 @@ bool intercom_claim(intercom_ctx *ctx, const struct in6_addr *recipient, struct

intercom_recently_seen_add(ctx, &packet.hdr);

if (recipient != NULL)
return intercom_send_packet_unicast(ctx, recipient, (uint8_t*)&packet, sizeof(packet));
else {
intercom_send_packet(ctx, (uint8_t*)&packet, sizeof(packet));
return true;
}
VECTOR_ADD(ctx->repeatable_claims, *client);

struct claim_task data ;
data.client = malloc(sizeof(struct client));
memcpy(data.client, client,sizeof(struct client));
data.retries_left = CLAIM_RETRY_MAX;
data.packet = packet;
data.recipient = recipient;
data.check_task=NULL;

claim_retry_task(&data);
free(data.client);
return true;
}
17 changes: 16 additions & 1 deletion src/intercom.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "vector.h"
#include "if.h"
#include "clientmgr.h"
#include "taskqueue.h"

#include <stdint.h>
#include <stdlib.h>
Expand Down Expand Up @@ -46,16 +48,29 @@ typedef struct {
char *ifname;
} intercom_if;

struct claim_task {
struct client *client;
uint8_t retries_left;
const struct in6_addr *recipient;
intercom_packet_claim packet;
taskqueue_t *check_task;
};

typedef struct {
} claim_t;

typedef struct {
struct l3ctx *l3ctx;
int fd;
struct sockaddr_in6 groupaddr;
struct in6_addr ip;
VECTOR(intercom_packet_hdr) recent_packets;
VECTOR(intercom_if) interfaces;
VECTOR(client_t) repeatable_claims;
} intercom_ctx;

struct client;

// struct client;

void intercom_recently_seen_add(intercom_ctx *ctx, intercom_packet_hdr *hdr);
void intercom_send_packet(intercom_ctx *ctx, uint8_t *packet, ssize_t packet_len);
Expand Down
Loading

0 comments on commit 28d552d

Please sign in to comment.