diff options
-rw-r--r-- | ffd/ffd.c | 83 |
1 files changed, 58 insertions, 25 deletions
@@ -100,11 +100,7 @@ static bool init_self(void) { announce->key = 1337; announce->interval = 6000; - ffd_nexthop_t *nexthop = announce->nexthop_list = malloc(sizeof(ffd_nexthop_t)); - - nexthop->addr = ETH_ADDR_UNSPEC; - nexthop->metric_seqno.metric = 0; - nexthop->metric_seqno.seqno = 0; + announce->nexthop_list = calloc(1, sizeof(ffd_nexthop_t)); return true; } @@ -185,7 +181,18 @@ static void update_netifs(void) { } } -static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const eth_addr_t *addr, ffd_iface_t *iface) { +typedef struct _handle_tlv_arg_t { + ffd_iface_t *iface; + const eth_addr_t *addr; + + ffd_node_id_t node_id; +} handle_tlv_arg_t; + +static inline ffd_neigh_t* get_tlv_neigh(handle_tlv_arg_t *arg) { + return ffd_neigh_get(arg->iface, arg->addr); +} + +static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(ffd_tlv_hello_t)) { fprintf(stderr, "warn: received short hello TLV.\n"); return; @@ -193,7 +200,7 @@ static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const fprintf(stderr, "debug: received hello with seqno %u.\n", ntohs(tlv_hello->seqno)); - ffd_neigh_t *neigh = ffd_neigh_get(iface, addr); + ffd_neigh_t *neigh = get_tlv_neigh(arg); uint16_t seqno = ntohs(tlv_hello->seqno); @@ -226,12 +233,12 @@ static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const neigh->last_hello = now; if (neigh->hello_log == 1) /* new or reset neighbour */ - ffd_neigh_reset(iface, neigh); + ffd_neigh_reset(arg->iface, neigh); fprintf(stderr, "debug: accepted hello, log %04x, rxcost is %u, cost is %u now.\n", neigh->hello_log, ffd_neigh_get_rxcost(neigh), ffd_neigh_get_cost(neigh)); } -static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, const eth_addr_t *addr, ffd_iface_t *iface) { +static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(ffd_tlv_ihu_t)) { fprintf(stderr, "warn: received short IHU TLV.\n"); return; @@ -243,21 +250,39 @@ static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, const eth_a return; } - if (memcmp(tlv_ihu->address, &iface->addr, sizeof(eth_addr_t)) != 0) + if (memcmp(tlv_ihu->address, &arg->iface->addr, sizeof(eth_addr_t)) != 0) return; } else if (tlv_ihu->ae != ADDR_ENC_UNSPEC) { return; } - ffd_neigh_t *neigh = ffd_neigh_get(iface, addr); + ffd_neigh_t *neigh = get_tlv_neigh(arg); neigh->last_ihu = now; neigh->txcost = ntohs(tlv_ihu->rxcost); fprintf(stderr, "debug: accepted IHU, txcost is %u, cost is %u now.\n", neigh->txcost, ffd_neigh_get_cost(neigh)); } -static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_t len, const eth_addr_t *addr, ffd_iface_t *iface) { +static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) { + if (len < sizeof(ffd_tlv_node_id_t)) { + fprintf(stderr, "warn: received short node id TLV.\n"); + return; + } + + arg->node_id = tlv_node_id->id; +} + +static void handle_tlv_update(const ffd_tlv_node_id_t *tlv_node_id, size_t len, handle_tlv_arg_t *arg) { + if (len < sizeof(ffd_tlv_update_t)) { + fprintf(stderr, "warn: received short update TLV.\n"); + return; + } + + fprintf(stderr, "debug: update received from %04x%04x.\n", ntohl(*(uint32_t*)arg->node_id.id), ntohl(*(uint32_t*)(arg->node_id.id+4))); +} + +static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_t len, handle_tlv_arg_t *arg) { if (len < sizeof(ffd_tlv_announce_req_t)) { fprintf(stderr, "warn: received short announce request TLV.\n"); return; @@ -269,32 +294,33 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_ announce = NULL; } - ffd_send_update(iface, ffd_neigh_get(iface, addr), announce); + ffd_send_update(arg->iface, get_tlv_neigh(arg), announce); } static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) { - const struct sockaddr_ll *from = arg; - const eth_addr_t *addr = (const eth_addr_t*)from->sll_addr; - ffd_iface_t *iface = get_iface(from->sll_ifindex); - - if (!iface) - return; - switch (type) { case TLV_HELLO: - handle_tlv_hello(data, len, addr, iface); + handle_tlv_hello(data, len, arg); return; case TLV_IHU: - handle_tlv_ihu(data, len, addr, iface); + handle_tlv_ihu(data, len, arg); + return; + + case TLV_NODE_ID: + handle_tlv_node_id(data, len, arg); + return; + + case TLV_UPDATE: + handle_tlv_update(data, len, arg); return; case TLV_ANNOUNCE_REQ: - handle_tlv_announce_req(data, len, addr, iface); + handle_tlv_announce_req(data, len, arg); return; default: - fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, iface->name); + fprintf(stderr, "debug: received unknown TLV %u on %s.\n", type, ((handle_tlv_arg_t*)arg)->iface->name); return; } } @@ -321,7 +347,14 @@ static void receive_packet(void) { return; } - if (!ffd_tlv_parse(packet, handle_tlv, &from)) { + handle_tlv_arg_t arg = { .iface = get_iface(from.sll_ifindex), .addr = (const eth_addr_t*)&from.sll_addr }; + + if (!arg.iface) { + fprintf(stderr, "debug: received packet on unknown interface.\n"); + return; + } + + if (!ffd_tlv_parse(packet, handle_tlv, &arg)) { fprintf(stderr, "debug: received invalid packet.\n"); } } |