Exemple #1
0
void clienttable_delete_client(struct netaddr *addr)
{
    if (!clienttable_is_client(addr)) {
        return;
    }

    mutex_lock(&clientt_mutex);
    for (unsigned i = 0; i < AODVV2_MAX_CLIENTS; i++) {
        if (!netaddr_cmp(&client_table[i], addr)) {
            memset(&client_table[i], 0, sizeof(client_table[i]));
            mutex_unlock(&clientt_mutex);
            return;
        }
    }
}
Exemple #2
0
void clienttable_add_client(struct netaddr *addr)
{
    if (clienttable_is_client(addr)){
        return;
    }

    /*find free spot in client table and place client address there */
    mutex_lock(&clientt_mutex);
    for (unsigned i = 0; i < AODVV2_MAX_CLIENTS; i++) {
        if ((client_table[i]._type == AF_UNSPEC) &&
            (client_table[i]._prefix_len == 0)) {
            client_table[i] = *addr;
            AODV_DEBUG("clienttable: added client %s\n",
                  netaddr_to_string(&nbuf, addr));
            mutex_unlock(&clientt_mutex);
            return;
        }
    }
    AODV_DEBUG("Error: Client could not be added: Client table is full.\n");
    mutex_unlock(&clientt_mutex);
}
Exemple #3
0
/**
 * This callback is called every time the _rreq_consumer finishes reading a
 * packet.
 * @param cont
 * @param dropped indicates wehther the packet has been dropped previously by
 *                another callback
 */
static enum rfc5444_result _cb_rrep_end_callback(
    struct rfc5444_reader_tlvblock_context *cont, bool dropped)
{
    (void) cont;

    VDEBUG("%s()\n", __func__);

    struct aodvv2_routing_entry_t *rt_entry;
#if ENABLE_DEBUG
    struct netaddr_str nbuf;
#endif
    timex_t now;

    /* Check if packet contains the required information */
    if (dropped) {
        DEBUG("\t Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.origNode.addr._type == AF_UNSPEC)
        || !packet_data.origNode.seqnum) {
        DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.targNode.addr._type == AF_UNSPEC)
        || !packet_data.targNode.seqnum) {
        DEBUG("\tERROR: missing TargNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType))
        <= packet_data.targNode.metric) {
        DEBUG("\tMetric Limit reached. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }

    /* Update the cost of the route, since the packet has successfully traversed
     * one more hop. */
    packet_data.targNode.metric = _get_route_cost(packet_data.metricType,
                                                  packet_data.targNode.metric);
    vtimer_now(&now);
    packet_data.timestamp = now;

    /* for every relevant address (RteMsg.Addr) in the RteMsg, HandlingRtr
    searches its route table to see if there is a route table entry with the
    same MetricType of the RteMsg, matching RteMsg.Addr. */

    rt_entry = routingtable_get_entry(&packet_data.targNode.addr, packet_data.metricType);

    if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) {
        /* CAUTION SUPER HACKY FIX FIXME ASAP
        problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then
        AODVv2 gets super confused when they're not in the routing table and starts a
        Route discovery to find them and all hell breaks loose. let's see if we can fix
        this (horribly).

        (another fix would be to stop bouncing the RREP back to the sender and asking
        the routing table for the next hop (or just send towards TargNode and let the network stack figure out the rest?))
        TODO evaluate that
        */

        ipv6_addr_t sender_tmp;
        netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp);
        ndp_neighbor_cache_t *ndp_nc_entry = ndp_neighbor_cache_search(&sender_tmp);

        if (ndp_nc_entry == NULL) {
            DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* HACKY FIX ENDS HERE */
        VDEBUG("\tCreating new Routing Table entry...\n");

        struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *)
                                                       malloc(sizeof(struct aodvv2_routing_entry_t));
        memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry));

        routingtable_fill_routing_entry_t_rrep(&packet_data, tmp_rt_entry);
        routingtable_add_entry(tmp_rt_entry);

        /* add entry to FIB */
        fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0,
                      tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t);

        free(tmp_rt_entry);
    }
    else {
        if (!routingtable_offers_improvement(rt_entry, &packet_data.targNode)) {
            DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* The incoming routing information is better than existing routing
         * table information and SHOULD be used to improve the route table. */
        VDEBUG("\tUpdating Routing Table entry...\n");
        routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry);

        /* update the FIB */
        fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr,
                         sizeof(ipv6_addr_t), 0, aodvv2_validity_t);
    }

    /* If HandlingRtr is RREQ_Gen then the RREP satisfies RREQ_Gen's
    earlier RREQ, and RREP processing is completed.  Any packets
    buffered for OrigNode should be transmitted. */
    if (clienttable_is_client(&packet_data.origNode.addr)) {
#if ENABLE_DEBUG
        static struct netaddr_str nbuf2;
#endif

        DEBUG("\t{%" PRIu32 ":%" PRIu32 "} %s:  This is my RREP (SeqNum: %d). We are done here, thanks %s!\n",
              now.seconds, now.microseconds, netaddr_to_string(&nbuf, &packet_data.origNode.addr),
              packet_data.origNode.seqnum, netaddr_to_string(&nbuf2, &packet_data.targNode.addr));
    }

    else {
        /* If HandlingRtr is not RREQ_Gen then the outgoing RREP is sent to the
         * Route.NextHopAddress for the RREP.AddrBlk[OrigNodeNdx]. */
        AODV_DEBUG("Not my RREP, passing it on to the next hop\n");
        aodv_send_rrep(&packet_data,
                       routingtable_get_next_hop(&packet_data.origNode.addr,packet_data.metricType));
    }
    return RFC5444_OKAY;
}
Exemple #4
0
/**
 * This callback is called every time the _rreq_consumer finishes reading a
 * packet.
 * @param cont
 * @param dropped indicates whether the packet has been dropped previously by
 *                another callback
 */
static enum rfc5444_result _cb_rreq_end_callback(
    struct rfc5444_reader_tlvblock_context *cont, bool dropped)
{
    (void) cont;

    struct aodvv2_routing_entry_t *rt_entry;
    timex_t now;

    /* Check if packet contains the required information */
    if (dropped) {
        DEBUG("\t Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.origNode.addr._type == AF_UNSPEC) || !packet_data.origNode.seqnum) {
        DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if (packet_data.targNode.addr._type == AF_UNSPEC) {
        DEBUG("\tERROR: missing TargNode Address. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if (packet_data.hoplimit == 0) {
        DEBUG("\tERROR: Hoplimit is 0. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType))
        <= packet_data.origNode.metric) {
        DEBUG("\tMetric Limit reached. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }

    /*
      The incoming RREQ MUST be checked against previously received
      information from the RREQ Table Section 7.6.  If the information
      in the incoming RteMsg is redundant, then then no further action
      is taken.
    */
    if (rreqtable_is_redundant(&packet_data)) {
        DEBUG("\tPacket is redundant. Dropping Packet. %i\n", RFC5444_DROP_PACKET);
        return RFC5444_DROP_PACKET;
    }

    /* Update the cost of the route, since the packet has successfully traversed
     * one more hop. */
    packet_data.origNode.metric = _get_route_cost(packet_data.metricType,
                                                  packet_data.origNode.metric);
    vtimer_now(&now);
    packet_data.timestamp = now;

    /* for every relevant
     * address (RteMsg.Addr) in the RteMsg, HandlingRtr searches its route
     * table to see if there is a route table entry with the same MetricType
     * of the RteMsg, matching RteMsg.Addr.
     */

    rt_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType);

    if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) {
        /* CAUTION SUPER HACKY FIX FIXME ASAP
        problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then
        AODVv2 gets super confused when they're not in the routing table and starts a
        Route discovery to find them and all hell breaks loose. let's see if we can fix
        this (horribly).

        (another fix would be to stop bouncing the RREP back to the sender and asking
        the routing table for the next hop (or just send towards TargNode and let the
        network stack figure out the rest?))
        TODO evaluate that
        */

        ipv6_addr_t sender_tmp;
        netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp);
        ndp_neighbor_cache_t *ndp_nc_entry = ndp_neighbor_cache_search(&sender_tmp);

        if (ndp_nc_entry == NULL) {
            DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* HACKY FIX ENDS HERE */

        VDEBUG("\tCreating new Routing Table entry...\n");

        struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *)
                                                       malloc(sizeof(struct aodvv2_routing_entry_t));
        memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry));

        routingtable_fill_routing_entry_t_rreq(&packet_data, tmp_rt_entry);
        routingtable_add_entry(tmp_rt_entry);

        /* add entry to FIB */
        fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0,
                      tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t);

        free(tmp_rt_entry);
    }
    else {
        if (!routingtable_offers_improvement(rt_entry, &packet_data.origNode)) {
            DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* The incoming routing information is better than existing routing
         * table information and SHOULD be used to improve the route table. */
        VDEBUG("\tUpdating Routing Table entry...\n");
        routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry);

        /* update the FIB */
        fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr,
                         sizeof(ipv6_addr_t), 0, aodvv2_validity_t);
    }

    /*
     * If TargNode is a client of the router receiving the RREQ, then the
     * router generates a RREP message as specified in Section 7.4, and
     * subsequently processing for the RREQ is complete.  Otherwise,
     * processing continues as follows.
     */
    if (clienttable_is_client(&packet_data.targNode.addr)) {
        AODV_DEBUG("TargNode is in client list, sending RREP\n");

        /* make sure to start with a clean metric value */
        packet_data.targNode.metric = 0;
        aodv_send_rrep(&packet_data, &packet_data.sender);
    }
    else {
        AODV_DEBUG("I am not TargNode, forwarding RREQ\n");
        aodv_send_rreq(&packet_data);
    }
    return RFC5444_OKAY;
}