
16 changed files with 2014 additions and 0 deletions
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup net_fib Forwarding Information Base (FIB) |
||||
* @ingroup net |
||||
* @brief FIB implementation |
||||
* |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Types and functions for FIB |
||||
* @author Martin Landsmann |
||||
*/ |
||||
|
||||
#ifndef FIB_H_ |
||||
#define FIB_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Reactive Routing Protocol (RRP) message content to request/reply route discovery |
||||
*/ |
||||
typedef struct rrp_address_msg_t { |
||||
uint8_t *address; /**< The pointer to the address */ |
||||
uint8_t address_size; /**< The address size */ |
||||
uint32_t address_flags; /**< The flags for the given address */ |
||||
} rrp_address_msg_t; |
||||
|
||||
#define FIB_MSG_RRP_SIGNAL (0x99) /**< message type for RRP notifications */ |
||||
|
||||
/**
|
||||
* @brief indicator of a lifetime that does not expire (2^32 - 1) |
||||
*/ |
||||
#define FIB_LIFETIME_NO_EXPIRE (0xFFFFFFFF) |
||||
|
||||
/**
|
||||
* @brief initializes all FIB entries with 0 |
||||
*/ |
||||
void fib_init(void); |
||||
|
||||
/**
|
||||
* @brief de-initializes the FIB entries |
||||
*/ |
||||
void fib_deinit(void); |
||||
|
||||
/**
|
||||
* @brief Registration of reactive routing protocol handler function |
||||
*/ |
||||
void fib_register_rrp(void); |
||||
|
||||
/**
|
||||
* @brief Adds a new entry in the corresponding FIB table for global destination and next hop |
||||
* |
||||
* @param[in] iface_id the interface ID |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* @param[in] dst_flags the destination address flags |
||||
* @param[in] next_hop the next hop address to be updated |
||||
* @param[in] next_hop_size the next hop address size |
||||
* @param[in] next_hop_flags the next-hop address flags |
||||
* @param[in] lifetime the lifetime in ms to be updates |
||||
* |
||||
* @return 0 on success |
||||
* -ENOMEM if the entry cannot be created due to unsufficient RAM |
||||
*/ |
||||
int fib_add_entry(kernel_pid_t iface_id, uint8_t *dst, size_t dst_size, uint32_t dst_flags, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime); |
||||
|
||||
/**
|
||||
* @brief Updates an entry in the FIB table with next hop and lifetime |
||||
* |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* @param[in] next_hop the next hop address to be updated |
||||
* @param[in] next_hop_size the next hop address size |
||||
* @param[in] next_hop_flags the next-hop address flags |
||||
* @param[in] lifetime the lifetime in ms to be updates |
||||
* |
||||
* @return 0 on success |
||||
* -ENOMEM if the entry cannot be updated due to unsufficient RAM |
||||
*/ |
||||
int fib_update_entry(uint8_t *dst, size_t dst_size, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime); |
||||
|
||||
/**
|
||||
* @brief removes an entry from the corresponding FIB table |
||||
* |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
*/ |
||||
void fib_remove_entry(uint8_t *dst, size_t dst_size); |
||||
|
||||
/**
|
||||
* @brief provides a next hop for a given destination |
||||
* |
||||
* @param[in, out] iface_id pointer to store the interface ID for the next hop |
||||
* @param[out] next_hop pointer where the next hop address should be stored |
||||
* @param[in, out] next_hop_size the next hop address size. The value is |
||||
* overwritten with the actual next hop size |
||||
* @param[out] next_hop_flags the next-hop address flags, e.g. compression type |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* @param[in] dst_flags the destination address flags |
||||
* |
||||
* @return 0 on success |
||||
* -EHOSTUNREACH if no next hop is available in any FIB table |
||||
* all RRPs are notified before the return |
||||
* -ENOBUFS if the size for the next hop address is insufficient low |
||||
*/ |
||||
int fib_get_next_hop(kernel_pid_t *iface_id, |
||||
uint8_t *next_hop, size_t *next_hop_size, uint32_t* next_hop_flags, |
||||
uint8_t *dst, size_t dst_size, uint32_t dst_flags); |
||||
|
||||
/**
|
||||
* @brief returns the actual number of used FIB entries |
||||
*/ |
||||
int fib_get_num_used_entries(void); |
||||
|
||||
/**
|
||||
* @brief Prints the kernel_pid_t for all registered RRPs |
||||
*/ |
||||
void fib_print_notify_rrp(void); |
||||
|
||||
/**
|
||||
* @brief Prints the FIB content (does not print the entries) |
||||
*/ |
||||
void fib_print_fib_table(void); |
||||
|
||||
/**
|
||||
* @brief Prints the FIB content |
||||
*/ |
||||
void fib_print_routes(void); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* FIB_H_ */ |
||||
/** @} */ |
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief forwarding table structs |
||||
* @ingroup net_fib |
||||
* |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Types and functions for operating fib tables |
||||
* @author Martin Landsmann |
||||
*/ |
||||
|
||||
#ifndef FIB_TABLE_H_ |
||||
#define FIB_TABLE_H_ |
||||
|
||||
#include <stdint.h> |
||||
#include "vtimer.h" |
||||
#include "ng_universal_address.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Container descriptor for a FIB entry |
||||
*/ |
||||
typedef struct fib_entry_t { |
||||
/** interface ID */ |
||||
kernel_pid_t iface_id; |
||||
/** Lifetime of this entry */ |
||||
timex_t lifetime; |
||||
/** Unique identifier for the type of the global address */ |
||||
uint32_t global_flags; |
||||
/** Pointer to the shared generic address */ |
||||
struct universal_address_container_t *global; |
||||
/** Unique identifier for the type of the next hop address */ |
||||
uint32_t next_hop_flags; |
||||
/** Pointer to the shared generic address */ |
||||
struct universal_address_container_t *next_hop; |
||||
} fib_entry_t; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* FIB_TABLE_H_ */ |
||||
/** @} */ |
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup net_universal_address Universal Address Container |
||||
* @ingroup net |
||||
* @brief universal address container |
||||
* |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Types and functions for operating universal addresses |
||||
* @author Martin Landsmann |
||||
*/ |
||||
|
||||
#ifndef UNIVERSAL_ADDRESS_H_ |
||||
#define UNIVERSAL_ADDRESS_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define UNIVERSAL_ADDRESS_SIZE (16) /**< size of the used addresses in bytes */ |
||||
|
||||
/**
|
||||
* @brief The container descriptor used to identify a universal address entry |
||||
*/ |
||||
typedef struct universal_address_container_t { |
||||
uint8_t use_count; /**< The number of entries link here */ |
||||
uint8_t address_size; /**< Size in bytes of the used genereic address */ |
||||
uint8_t address[UNIVERSAL_ADDRESS_SIZE]; /**< the genereic address data */ |
||||
} universal_address_container_t; |
||||
|
||||
/**
|
||||
* @brief initializes the datastructure for the entries |
||||
*/ |
||||
void universal_address_init(void); |
||||
|
||||
/**
|
||||
* @brief resets the usecoumt for all entries |
||||
*/ |
||||
void universal_address_reset(void); |
||||
|
||||
/**
|
||||
* @brief Adds a given address to the universal address entries |
||||
* if the entry already exists, the use_count will be increased. |
||||
* |
||||
* @param[in] addr pointer to the address |
||||
* @param[in] addr_size the number of bytes required for the address entry |
||||
* |
||||
* @return pointer to the universal_address_container_t containing the address on success |
||||
* NULL if the address could not be inserted |
||||
*/ |
||||
universal_address_container_t *universal_address_add(uint8_t *addr, size_t addr_size); |
||||
|
||||
/**
|
||||
* @brief Adds a given container from the universal address entries |
||||
* if the entry exists, the use_count will be decreased. |
||||
* |
||||
* @param[in] entry pointer to the universal_address_container_t to be removed |
||||
*/ |
||||
void universal_address_rem(universal_address_container_t *entry); |
||||
|
||||
/**
|
||||
* @brief copies the address from the given container to the provided pointer |
||||
* |
||||
* @param[in] entry pointer to the universal_address_container_t |
||||
* @param[out] addr pointer to store the address entry |
||||
* @param[in, out] addr_size pointer providing the size of available memory on addr |
||||
* this value is overwritten with the actual size required |
||||
* |
||||
* @return addr if the address is copied to the addr destination |
||||
* NULL if the size is unsufficient for copy |
||||
*/ |
||||
uint8_t* universal_address_get_address(universal_address_container_t *entry, |
||||
uint8_t *addr, size_t *addr_size); |
||||
|
||||
/**
|
||||
* @brief determines if the entry equals the provided address |
||||
* |
||||
* @param[in] entry pointer to the universal_address_container_t for compare |
||||
* @param[in] addr pointer to the address for compare |
||||
* @param[in, out] addr_size the number of bytes used for the address entry |
||||
* on sucessfull return this value is overwritten |
||||
* with the number of matching bytes till the |
||||
* first of trailing `0`s indicating a prefix |
||||
* |
||||
* @return 0 if the entries are equal or comperable |
||||
* -ENOENT if the given adresses do not match |
||||
*/ |
||||
int universal_address_compare(universal_address_container_t *entry, |
||||
uint8_t *addr, size_t *addr_size); |
||||
|
||||
/**
|
||||
* @brief Prints the content of the given entry |
||||
* |
||||
* @param[in] entry pointer to the universal_address_container_t to be printed |
||||
*/ |
||||
void universal_address_print_entry(universal_address_container_t *entry); |
||||
|
||||
/**
|
||||
* @brief returns the number of used entries |
||||
*/ |
||||
int universal_address_get_num_used_entries(void); |
||||
|
||||
/**
|
||||
* @brief Prints the content of the genereic address table up to the used element |
||||
*/ |
||||
void universal_address_print_table(void); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* UNIVERSAL_ADDRESS_H_ */ |
||||
/** @} */ |
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,584 @@
|
||||
/**
|
||||
* FIB implementation |
||||
* |
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup fib |
||||
* @{ |
||||
* @file fib.c |
||||
* @brief Functions to manage FIB entries |
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <errno.h> |
||||
#include "thread.h" |
||||
#include "mutex.h" |
||||
#include "msg.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
#include "ng_fib.h" |
||||
#include "ng_fib/ng_fib_table.h" |
||||
|
||||
/**
|
||||
* @brief access mutex to control exclusive operations on calls |
||||
*/ |
||||
static mutex_t mtx_access = MUTEX_INIT; |
||||
|
||||
/**
|
||||
* @brief maximum number of handled reactice routing protocols (RRP) |
||||
* used to notify the saved kernel_pid_t |
||||
*/ |
||||
#define FIB_MAX_RRP (5) |
||||
|
||||
/**
|
||||
* @brief registered RRPs for notification un unreachable destinations |
||||
*/ |
||||
static size_t notify_rrp_pos = 0; |
||||
|
||||
/**
|
||||
* @brief the kernel_pid_t for notifying the RRPs |
||||
*/ |
||||
static kernel_pid_t notify_rrp[FIB_MAX_RRP]; |
||||
|
||||
/**
|
||||
* @brief maximum number of FIB tables entries handled |
||||
*/ |
||||
#define FIB_MAX_FIB_TABLE_ENTRIES (20) |
||||
|
||||
/**
|
||||
* @brief array of the FIB tables |
||||
*/ |
||||
static fib_entry_t fib_table[FIB_MAX_FIB_TABLE_ENTRIES]; |
||||
|
||||
/**
|
||||
* @brief convert given ms to a timepoint from now on in the future |
||||
* @param[in] ms the miliseconds to be converted |
||||
* @param[out] timex the converted timepoint |
||||
*/ |
||||
static void fib_ms_to_timex(uint32_t ms, timex_t *timex) |
||||
{ |
||||
vtimer_now(timex); |
||||
timex->seconds += ms / 1000; |
||||
timex->microseconds += (ms - timex->seconds * 1000) * 1000; |
||||
} |
||||
|
||||
/**
|
||||
* @brief returns pointer to the entry for the given destination address |
||||
* |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* @param[out] entry_arr the array to scribe the found match |
||||
* @param[in, out] entry_arr_size the number of entries provided by entry_arr (should be always 1) |
||||
* this value is overwritten with the actual found number |
||||
* |
||||
* @return 0 if we found a next-hop prefix |
||||
* 1 if we found the exact address next-hop |
||||
* -EHOSTUNREACH if no fitting next-hop is available |
||||
*/ |
||||
static int fib_find_entry(uint8_t *dst, size_t dst_size, |
||||
fib_entry_t **entry_arr, size_t *entry_arr_size) |
||||
{ |
||||
timex_t now; |
||||
vtimer_now(&now); |
||||
|
||||
size_t count = 0; |
||||
size_t prefix_size = 0; |
||||
size_t match_size = dst_size; |
||||
int ret = -EHOSTUNREACH; |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
|
||||
/* autoinvalidate if the entry lifetime is not set to not expire */ |
||||
if ((fib_table[i].lifetime.seconds != FIB_LIFETIME_NO_EXPIRE) |
||||
|| (fib_table[i].lifetime.microseconds != FIB_LIFETIME_NO_EXPIRE)) { |
||||
|
||||
/* check if the lifetime expired */ |
||||
if (timex_cmp(now, fib_table[i].lifetime) > -1) { |
||||
/* remove this entry if its lifetime expired */ |
||||
fib_table[i].lifetime.seconds = 0; |
||||
fib_table[i].lifetime.microseconds = 0; |
||||
|
||||
if (fib_table[i].global != NULL) { |
||||
universal_address_rem(fib_table[i].global); |
||||
fib_table[i].global = NULL; |
||||
} |
||||
|
||||
if (fib_table[i].next_hop != NULL) { |
||||
universal_address_rem(fib_table[i].next_hop); |
||||
fib_table[i].next_hop = NULL; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if ((prefix_size < dst_size) && |
||||
(fib_table[i].global != NULL) && |
||||
(universal_address_compare(fib_table[i].global, dst, &match_size) == 0)) { |
||||
|
||||
/* If we found an exact match */ |
||||
if (match_size == dst_size) { |
||||
entry_arr[0] = &(fib_table[i]); |
||||
*entry_arr_size = 1; |
||||
/* we will not find a better one so we return */ |
||||
return 1; |
||||
} |
||||
else { |
||||
/* we try to find the most fitting prefix */ |
||||
if (match_size > prefix_size) { |
||||
entry_arr[0] = &(fib_table[i]); |
||||
/* we could find a better one so we move on */ |
||||
ret = 0; |
||||
} |
||||
} |
||||
|
||||
prefix_size = match_size; |
||||
match_size = dst_size; |
||||
count = 1; |
||||
} |
||||
} |
||||
|
||||
*entry_arr_size = count; |
||||
return ret; |
||||
} |
||||
|
||||
/**
|
||||
* @brief updates the next hop the lifetime and the interface id for a given entry |
||||
* |
||||
* @param[in] entry the entry to be updated |
||||
* @param[in] next_hop the next hop address to be updated |
||||
* @param[in] next_hop_size the next hop address size |
||||
* @param[in] next_hop_flags the next-hop address flags |
||||
* @param[in] lifetime the lifetime in ms |
||||
* |
||||
* @return 0 if the entry has been updated |
||||
* -ENOMEM if the entry cannot be updated due to unsufficient RAM |
||||
*/ |
||||
static int fib_upd_entry(fib_entry_t *entry, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime) |
||||
{ |
||||
universal_address_container_t *container = universal_address_add(next_hop, next_hop_size); |
||||
|
||||
if (container == NULL) { |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
universal_address_rem(entry->next_hop); |
||||
entry->next_hop = container; |
||||
entry->next_hop_flags = next_hop_flags; |
||||
|
||||
if (lifetime < FIB_LIFETIME_NO_EXPIRE) { |
||||
fib_ms_to_timex(lifetime, &entry->lifetime); |
||||
} |
||||
else { |
||||
entry->lifetime.seconds = FIB_LIFETIME_NO_EXPIRE; |
||||
entry->lifetime.microseconds = FIB_LIFETIME_NO_EXPIRE; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* @brief creates a new FIB entry with the provided parameters |
||||
* |
||||
* @param[in] iface_id the interface ID |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* @param[in] dst_flags the destination address flags |
||||
* @param[in] next_hop the next hop address |
||||
* @param[in] next_hop_size the next hop address size |
||||
* @param[in] next_hop_flags the next-hop address flags |
||||
* @param[in] lifetime the lifetime in ms |
||||
* |
||||
* @return 0 on success |
||||
* -ENOMEM if no new entry can be created |
||||
*/ |
||||
static int fib_create_entry(kernel_pid_t iface_id, |
||||
uint8_t *dst, size_t dst_size, uint32_t dst_flags, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime) |
||||
{ |
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
if (fib_table[i].lifetime.seconds == 0 && fib_table[i].lifetime.microseconds == 0) { |
||||
|
||||
fib_table[i].global = universal_address_add(dst, dst_size); |
||||
|
||||
if (fib_table[i].global != NULL) { |
||||
fib_table[i].global_flags = dst_flags; |
||||
fib_table[i].next_hop = universal_address_add(next_hop, next_hop_size); |
||||
fib_table[i].next_hop_flags = next_hop_flags; |
||||
} |
||||
|
||||
if (fib_table[i].next_hop != NULL) { |
||||
/* everything worked fine */ |
||||
fib_table[i].iface_id = iface_id; |
||||
|
||||
if (lifetime < FIB_LIFETIME_NO_EXPIRE) { |
||||
fib_ms_to_timex(lifetime, &fib_table[i].lifetime); |
||||
} |
||||
else { |
||||
fib_table[i].lifetime.seconds = FIB_LIFETIME_NO_EXPIRE; |
||||
fib_table[i].lifetime.microseconds = FIB_LIFETIME_NO_EXPIRE; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return -ENOMEM; |
||||
} |
||||
|
||||
/**
|
||||
* @brief removes the given entry |
||||
* |
||||
* @param[in] entry the entry to be removed |
||||
* |
||||
* @return 0 on success |
||||
*/ |
||||
static int fib_remove(fib_entry_t *entry) |
||||
{ |
||||
if (entry->global != NULL) { |
||||
universal_address_rem(entry->global); |
||||
} |
||||
|
||||
if (entry->next_hop) { |
||||
universal_address_rem(entry->next_hop); |
||||
} |
||||
|
||||
entry->global = NULL; |
||||
entry->global_flags = 0; |
||||
entry->next_hop = NULL; |
||||
entry->next_hop_flags = 0; |
||||
|
||||
entry->iface_id = KERNEL_PID_UNDEF; |
||||
entry->lifetime.seconds = 0; |
||||
entry->lifetime.microseconds = 0; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* @brief signalls (sends a message to) all registered RRPs |
||||
* to start a route discovery for the provided destination. |
||||
* The receiver MUST copy the content, i.e. the address before reply. |
||||
* |
||||
* @param[in] dst the destination address |
||||
* @param[in] dst_size the destination address size |
||||
* |
||||
* @return 0 on a new available entry, |
||||
* -ENOENT if no suiting entry is provided. |
||||
*/ |
||||
static int fib_signal_rrp(uint8_t *dst, size_t dst_size, uint32_t dst_flags) |
||||
{ |
||||
msg_t msg, reply; |
||||
rrp_address_msg_t content; |
||||
content.address = dst; |
||||
content.address_size = dst_size; |
||||
content.address_flags = dst_flags; |
||||
int ret = -ENOENT; |
||||
|
||||
msg.type = FIB_MSG_RRP_SIGNAL; |
||||
msg.content.ptr = (void *)&content; |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_RRP; ++i) { |
||||
if (notify_rrp[i] != KERNEL_PID_UNDEF) { |
||||
DEBUG("[fib_signal_rrp] send msg@: %p to pid[%d]: %d\n", \
|
||||
msg.content.ptr, (int)i, (int)notify_rrp[i]); |
||||
|
||||
/* the receiver, i.e. the RRP, MUST copy the content value.
|
||||
* using the provided pointer after replying this message |
||||
* will lead to errors |
||||
*/ |
||||
msg_send_receive(&msg, &reply, notify_rrp[i]); |
||||
DEBUG("[fib_signal_rrp] got reply."); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int fib_add_entry(kernel_pid_t iface_id, uint8_t *dst, size_t dst_size, uint32_t dst_flags, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
DEBUG("[fib_add_entry]"); |
||||
size_t count = 1; |
||||
fib_entry_t *entry[count]; |
||||
|
||||
int ret = fib_find_entry(dst, dst_size, &(entry[0]), &count); |
||||
|
||||
if (ret == 1) { |
||||
/* we must take the according entry and update the values */ |
||||
ret = fib_upd_entry(entry[0], next_hop, next_hop_size, next_hop_flags, lifetime); |
||||
} |
||||
else { |
||||
ret = fib_create_entry(iface_id, dst, dst_size, dst_flags, |
||||
next_hop, next_hop_size, next_hop_flags, lifetime); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
return ret; |
||||
} |
||||
|
||||
int fib_update_entry(uint8_t *dst, size_t dst_size, |
||||
uint8_t *next_hop, size_t next_hop_size, uint32_t next_hop_flags, |
||||
uint32_t lifetime) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
DEBUG("[fib_update_entry]"); |
||||
size_t count = 1; |
||||
fib_entry_t *entry[count]; |
||||
int ret = -ENOMEM; |
||||
|
||||
if (fib_find_entry(dst, dst_size, &(entry[0]), &count) == 1) { |
||||
DEBUG("[fib_update_entry] found entry: %p\n", (void *)(entry[0])); |
||||
/* we must take the according entry and update the values */ |
||||
ret = fib_upd_entry(entry[0], next_hop, next_hop_size, next_hop_flags, lifetime); |
||||
} |
||||
else { |
||||
/* we have ambigious entries, i.e. count > 1
|
||||
* this should never happen |
||||
*/ |
||||
DEBUG("[fib_update_entry] ambigious entries detected!!!"); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
return ret; |
||||
} |
||||
|
||||
void fib_remove_entry(uint8_t *dst, size_t dst_size) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
DEBUG("[fib_remove_entry]"); |
||||
size_t count = 1; |
||||
fib_entry_t *entry[count]; |
||||
|
||||
int ret = fib_find_entry(dst, dst_size, &(entry[0]), &count); |
||||
|
||||
if (ret == 1) { |
||||
/* we must take the according entry and update the values */ |
||||
fib_remove(entry[0]); |
||||
} |
||||
else { |
||||
/* we have ambigious entries, i.e. count > 1
|
||||
* this should never happen |
||||
*/ |
||||
DEBUG("[fib_update_entry] ambigious entries detected!!!"); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
int fib_get_next_hop(kernel_pid_t *iface_id, |
||||
uint8_t *next_hop, size_t *next_hop_size, uint32_t *next_hop_flags, |
||||
uint8_t *dst, size_t dst_size, uint32_t dst_flags) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
DEBUG("[fib_get_next_hop]"); |
||||
size_t count = 1; |
||||
fib_entry_t *entry[count]; |
||||
|
||||
int ret = fib_find_entry(dst, dst_size, &(entry[0]), &count); |
||||
|
||||
if (!(ret == 0 || ret == 1)) { |
||||
/* notify all RRPs for route discovery if available */ |
||||
if (fib_signal_rrp(dst, dst_size, dst_flags) == 0) { |
||||
count = 1; |
||||
/* now lets see if the RRPs have found a valid next-hop */ |
||||
ret = fib_find_entry(dst, dst_size, &(entry[0]), &count); |
||||
} |
||||
} |
||||
|
||||
if (ret == 0 || ret == 1) { |
||||
|
||||
uint8_t *address_ret = universal_address_get_address(entry[0]->next_hop, |
||||
next_hop, next_hop_size); |
||||
|
||||
if (address_ret == NULL) { |
||||
mutex_unlock(&mtx_access); |
||||
return -ENOBUFS; |
||||
} |
||||
} |
||||
else { |
||||
mutex_unlock(&mtx_access); |
||||
return -EHOSTUNREACH; |
||||
} |
||||
|
||||
*iface_id = entry[0]->iface_id; |
||||
*next_hop_flags = entry[0]->next_hop_flags; |
||||
mutex_unlock(&mtx_access); |
||||
return 0; |
||||
} |
||||
|
||||
void fib_init(void) |
||||
{ |
||||
DEBUG("[fib_init] hello. Initializing some stuff."); |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_RRP; ++i) { |
||||
notify_rrp[i] = KERNEL_PID_UNDEF; |
||||
} |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
fib_table[i].iface_id = 0; |
||||
fib_table[i].lifetime.seconds = 0; |
||||
fib_table[i].lifetime.microseconds = 0; |
||||
fib_table[i].global_flags = 0; |
||||
fib_table[i].global = NULL; |
||||
fib_table[i].next_hop_flags = 0; |
||||
fib_table[i].next_hop = NULL; |
||||
} |
||||
|
||||
universal_address_init(); |
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
void fib_deinit(void) |
||||
{ |
||||
DEBUG("[fib_deinit] hello. De-Initializing stuff."); |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_RRP; ++i) { |
||||
notify_rrp[i] = KERNEL_PID_UNDEF; |
||||
} |
||||
|
||||
notify_rrp_pos = 0; |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
fib_table[i].iface_id = 0; |
||||
fib_table[i].lifetime.seconds = 0; |
||||
fib_table[i].lifetime.microseconds = 0; |
||||
fib_table[i].global_flags = 0; |
||||
fib_table[i].global = NULL; |
||||
fib_table[i].next_hop_flags = 0; |
||||
fib_table[i].next_hop = NULL; |
||||
} |
||||
|
||||
universal_address_reset(); |
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
void fib_register_rrp(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
if (notify_rrp_pos < FIB_MAX_RRP) { |
||||
notify_rrp[notify_rrp_pos] = sched_active_pid; |
||||
notify_rrp_pos++; |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
int fib_get_num_used_entries(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
size_t used_entries = 0; |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
used_entries += (size_t)(fib_table[i].global != NULL); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
return used_entries; |
||||
} |
||||
|
||||
/* print functions */ |
||||
|
||||
void fib_print_notify_rrp(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_RRP; ++i) { |
||||
printf("[fib_print_notify_rrp] pid[%d]: %d\n", (int)i, (int)notify_rrp[i]); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
void fib_print_fib_table(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
printf("[fib_print_fib_table] %d) iface_id: %d, global: %p, next hop: %p, lifetime: %d.%d\n", \
|
||||
(int)i, \
|
||||
(int)fib_table[i].iface_id, \
|
||||
(void *)fib_table[i].global, \
|
||||
(void *)fib_table[i].next_hop, \
|
||||
(int)fib_table[i].lifetime.seconds, \
|
||||
(int)fib_table[i].lifetime.microseconds); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
static void fib_print_adress(universal_address_container_t *entry) |
||||
{ |
||||
uint8_t address[UNIVERSAL_ADDRESS_SIZE]; |
||||
size_t addr_size = UNIVERSAL_ADDRESS_SIZE; |
||||
uint8_t *ret = universal_address_get_address(entry, address, &addr_size); |
||||
|
||||
if (ret == address) { |
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_SIZE; ++i) { |
||||
if (i <= addr_size) { |
||||
printf("%02x", address[i]); |
||||
} |
||||
else { |
||||
printf(" "); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void fib_print_routes(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
printf("%-32s %-6s %-32s %-6s %-16s Interface\n" |
||||
, "Destination", "Flags", "Next Hop", "Flags", "Expires"); |
||||
|
||||
timex_t now; |
||||
vtimer_now(&now); |
||||
|
||||
for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { |
||||
if (fib_table[i].lifetime.seconds != 0 || fib_table[i].lifetime.microseconds != 0) { |
||||
fib_print_adress(fib_table[i].global); |
||||
printf(" 0x%04x ", fib_table[i].global_flags); |
||||
fib_print_adress(fib_table[i].next_hop); |
||||
printf(" 0x%04x ", fib_table[i].next_hop_flags); |
||||
|
||||
if ((fib_table[i].lifetime.seconds != FIB_LIFETIME_NO_EXPIRE) |
||||
|| (fib_table[i].lifetime.microseconds != FIB_LIFETIME_NO_EXPIRE)) { |
||||
|
||||
timex_t tm = timex_sub(fib_table[i].lifetime, now); |
||||
|
||||
/* we must interpret the values as signed */ |
||||
if ((int32_t)tm.seconds < 0 |
||||
|| (tm.seconds == 0 && (int32_t)tm.microseconds < 0)) { |
||||
printf("%-16s ", "EXPIRED"); |
||||
} |
||||
else { |
||||
printf("%"PRIu32".%05"PRIu32, tm.seconds, tm.microseconds); |
||||
} |
||||
} |
||||
else { |
||||
printf("%-16s ", "NEVER"); |
||||
} |
||||
|
||||
printf("%d\n", (int)fib_table[i].iface_id); |
||||
} |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
@ -0,0 +1,261 @@
|
||||
/**
|
||||
* universal address container implementation |
||||
* |
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup fib |
||||
* @{ |
||||
* @file universal_address.c |
||||
* @brief Functions to manage universal address container |
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <errno.h> |
||||
#include "mutex.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
#include "ng_fib/ng_universal_address.h" |
||||
|
||||
/**
|
||||
* @brief Maximum number of entries handled |
||||
*/ |
||||
#define UNIVERSAL_ADDRESS_MAX_ENTRIES (40) |
||||
|
||||
/**
|
||||
* @brief counter indicating the number of entries allocated |
||||
*/ |
||||
static size_t universal_address_table_filled = 0; |
||||
|
||||
/**
|
||||
* @brief The array of universal_address containers |
||||
*/ |
||||
static universal_address_container_t universal_address_table[UNIVERSAL_ADDRESS_MAX_ENTRIES]; |
||||
|
||||
/**
|
||||
* @brief access mutex to control exclusive operations on calls |
||||
*/ |
||||
static mutex_t mtx_access = MUTEX_INIT; |
||||
|
||||
/**
|
||||
* @brief finds the universal address container for the given address |
||||
* |
||||
* @param[in] addr pointer to the address |
||||
* @param[in] addr_size the number of bytes required for the address entry |
||||
* |
||||
* @return pointer to the universal_address_container_t containing the address on success |
||||
* NULL if the address could not be inserted |
||||
*/ |
||||
static universal_address_container_t *universal_address_find_entry(uint8_t *addr, size_t addr_size) |
||||
{ |
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_MAX_ENTRIES; ++i) { |
||||
if ((universal_address_table[i].address_size == addr_size) && (universal_address_table[i].address != NULL)) { |
||||
if (memcmp((universal_address_table[i].address), addr, addr_size) == 0) { |
||||
return &(universal_address_table[i]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
/**
|
||||
* @brief finds the next empty or unused universal address containers |
||||
* |
||||
* @return pointer to the next free/unused universal_address_container_t |
||||
* or NULL if no memory is left in universal_address_table |
||||
*/ |
||||
static universal_address_container_t *universal_address_get_next_unused_entry(void) |
||||
{ |
||||
if (universal_address_table_filled < UNIVERSAL_ADDRESS_MAX_ENTRIES) { |
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_MAX_ENTRIES; ++i) { |
||||
if ((universal_address_table[i].use_count == 0)) { |
||||
return &(universal_address_table[i]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
universal_address_container_t *universal_address_add(uint8_t *addr, size_t addr_size) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
universal_address_container_t *pEntry = universal_address_find_entry(addr, addr_size); |
||||
|
||||
if (pEntry == NULL) { |
||||
/* look for a free entry */ |
||||
pEntry = universal_address_get_next_unused_entry(); |
||||
|
||||
if (pEntry == NULL) { |
||||
mutex_unlock(&mtx_access); |
||||
/* no free room */ |
||||
return NULL; |
||||
} |
||||
|
||||
/* look if the former memory has distinct size */ |
||||
if (pEntry->address_size != addr_size) { |
||||
/* clean the address */ |
||||
memset(pEntry->address, 0, UNIVERSAL_ADDRESS_SIZE); |
||||
|
||||
/* set the used bytes */ |
||||
pEntry->address_size = addr_size; |
||||
pEntry->use_count = 0; |
||||
} |
||||
|
||||
/* copy the address */ |
||||
memcpy((pEntry->address), addr, addr_size); |
||||
} |
||||
|
||||
pEntry->use_count++; |
||||
|
||||
if (pEntry->use_count == 1) { |
||||
DEBUG("[universal_address_add] universal_address_table_filled: %d\n", \
|
||||
(int)universal_address_table_filled); |
||||
universal_address_table_filled++; |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
return pEntry; |
||||
} |
||||
|
||||
void universal_address_rem(universal_address_container_t *entry) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
DEBUG("[universal_address_rem] entry: %p\n", (void *)entry); |
||||
|
||||
/* we do not delete anything on remove */ |
||||
if (entry != NULL) { |
||||
if (entry->use_count != 0) { |
||||
entry->use_count--; |
||||
|
||||
if (entry->use_count == 0) { |
||||
universal_address_table_filled--; |
||||
} |
||||
} |
||||
else { |
||||
DEBUG("[universal_address_rem] universal_address_table_filled: %d\n", \
|
||||
(int)universal_address_table_filled); |
||||
} |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
uint8_t* universal_address_get_address(universal_address_container_t *entry, |
||||
uint8_t *addr, size_t *addr_size) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
if (*addr_size >= entry->address_size) { |
||||
memcpy(addr, entry->address, entry->address_size); |
||||
*addr_size = entry->address_size; |
||||
mutex_unlock(&mtx_access); |
||||
return addr; |
||||
} |
||||
|
||||
*addr_size = entry->address_size; |
||||
mutex_unlock(&mtx_access); |
||||
return NULL; |
||||
} |
||||
|
||||
int universal_address_compare(universal_address_container_t *entry, |
||||
uint8_t *addr, size_t *addr_size) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
int ret = -ENOENT; |
||||
|
||||
/* If we have distinct sizes, the addresses are probably not comperable */ |
||||
if (entry->address_size != *addr_size) { |
||||
mutex_unlock(&mtx_access); |
||||
return ret; |
||||
} |
||||
|
||||
/* Get the index of the first trailing `0` (indicates a network prefix) */ |
||||
int i = 0; |
||||
for( i = entry->address_size-1; i >= 0; --i) { |
||||
if( entry->address[i] != 0 ) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if( memcmp(entry->address, addr, i+1) == 0 ) { |
||||
ret = 0; |
||||
*addr_size = i+1; |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
return ret; |
||||
} |
||||
|
||||
void universal_address_init(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_MAX_ENTRIES; ++i) { |
||||
universal_address_table[i].use_count = 0; |
||||
universal_address_table[i].address_size = 0; |
||||
memset(universal_address_table[i].address, 0, UNIVERSAL_ADDRESS_SIZE); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
void universal_address_reset(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_MAX_ENTRIES; ++i) { |
||||
universal_address_table[i].use_count = 0; |
||||
} |
||||
|
||||
universal_address_table_filled = 0; |
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
void universal_address_print_entry(universal_address_container_t *entry) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
|
||||
if (entry != NULL) { |
||||
printf("[universal_address_print_entry] entry@: %p, use_count: %d, \
|
||||
address_size: %d, content: ", \
|
||||
(void *)entry, (int)entry->use_count, (int)entry->address_size); |
||||
|
||||
for (size_t i = 0; i < entry->address_size; ++i) { |
||||
/* printf("%02x ", (char)entry->address[i]); */ |
||||
printf("%c", (char)entry->address[i]); |
||||
} |
||||
|
||||
puts(""); |
||||
} |
||||
|
||||
mutex_unlock(&mtx_access); |
||||
} |
||||
|
||||
int universal_address_get_num_used_entries(void) |
||||
{ |
||||
mutex_lock(&mtx_access); |
||||
size_t ret = universal_address_table_filled; |
||||
mutex_unlock(&mtx_access); |
||||
return ret; |
||||
} |
||||
|
||||
void universal_address_print_table(void) |
||||
{ |
||||
printf("[universal_address_print_table] universal_address_table_filled: %d\n", \
|
||||
(int)universal_address_table_filled); |
||||
|
||||
for (size_t i = 0; i < UNIVERSAL_ADDRESS_MAX_ENTRIES; ++i) { |
||||
universal_address_print_entry((&universal_address_table[i])); |
||||
} |
||||
} |
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup sys_shell_commands |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Provides shell commands to manage and show FIB Entries |
||||
* |
||||
* @author 2015 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include "thread.h" |
||||
#include "inet_pton.h" |
||||
#include "ng_fib.h" |
||||
|
||||
#define INFO1_TXT "fibroute add <destination> via <next hop> dev <device>" |
||||
#define INFO2_TXT " [lifetime <lifetime>]" |
||||
#define INFO3_TXT " <destination> - the destination address\n" \ |
||||
" <next hop> - the address of the next-hop towards the <destination>\n" \
|
||||
" <device> - the device id of the Interface to use\n" |
||||
#define INFO4_TXT " <lifetime> - optional lifetime in ms when the entry automatically invalidates\n" |
||||
#define INFO5_TXT "fibroute del <destination>\n" \ |
||||
" <destination> - the destination address of the entry to be deleted\n" |
||||
|
||||
static unsigned char tmp_ipv4_dst[INADDRSZ]; /**< buffer for ipv4 address conversion */ |
||||
static unsigned char tmp_ipv4_nxt[INADDRSZ]; /**< buffer for ipv4 address conversion */ |
||||
static unsigned char tmp_ipv6_dst[IN6ADDRSZ]; /**< buffer for ipv6 address conversion */ |
||||
static unsigned char tmp_ipv6_nxt[IN6ADDRSZ]; /**< buffer for ipv6 address conversion */ |
||||
|
||||
static void _fib_usage(int info) |
||||
{ |
||||
switch (info) { |
||||
case 1: { |
||||
puts("\nbrief: adds a new entry to the FIB.\nusage: " |
||||
INFO1_TXT "\n" INFO3_TXT); |
||||
break; |
||||
} |
||||
|
||||
case 2: { |
||||
puts("\nbrief: adds a new entry to the FIB.\nusage: " |
||||
INFO1_TXT INFO2_TXT "\n" INFO3_TXT INFO4_TXT); |
||||
break; |
||||
} |
||||
|
||||
case 3: { |
||||
puts("\nbrief: deletes an entry from the FIB.\nusage: " |
||||
INFO5_TXT); |
||||
break; |
||||
} |
||||
|
||||
default: |
||||
break; |
||||
}; |
||||
} |
||||
|
||||
void _fib_route_handler(int argc, char **argv) |
||||
{ |
||||
/* e.g. fibroute right now dont care about the adress/protocol family */ |
||||
if (argc == 1) { |
||||
fib_print_routes(); |
||||
return; |
||||
} |
||||
|
||||
/* e.g. firoute [add|del] */ |
||||
if (argc == 2) { |
||||
if ((strcmp("add", argv[1]) == 0)) { |
||||
_fib_usage(2); |
||||
} |
||||
else if ((strcmp("del", argv[1]) == 0)) { |
||||
_fib_usage(3); |
||||
} |
||||
else { |
||||
puts("\nunrecognized parameter1.\nPlease enter fibroute [add|del] for more information."); |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
if (argc > 2 && !((strcmp("add", argv[1]) == 0) || (strcmp("del", argv[1]) == 0))) { |
||||
puts("\nunrecognized parameter2.\nPlease enter fibroute [add|del] for more information."); |
||||
return; |
||||
} |
||||
|
||||
/* e.g. fibroute del <destination> */ |
||||
if (argc == 3) { |
||||
if (inet_pton(AF_INET6, argv[2], tmp_ipv6_dst)) { |
||||
fib_remove_entry(tmp_ipv6_dst, IN6ADDRSZ); |
||||
} |
||||
else if (inet_pton(AF_INET, argv[2], tmp_ipv4_dst)) { |
||||
fib_remove_entry(tmp_ipv4_dst, INADDRSZ); |
||||
} |
||||
else { |
||||
fib_remove_entry((uint8_t *)argv[2], (strlen(argv[2]))); |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
/* e.g. fibroute add <destination> via <next hop> dev <device> */ |
||||
if (argc == 7) { |
||||
if ((strcmp("add", argv[1]) == 0) && (strcmp("via", argv[3]) == 0) |
||||
&& (strcmp("dev", argv[5]) == 0)) { |
||||
|
||||
unsigned char *dst = (unsigned char *)argv[2]; |
||||
size_t dst_size = (strlen(argv[2])); |
||||
uint32_t dst_flags = 0xffff; |
||||
unsigned char *nxt = (unsigned char *)argv[4]; |
||||
size_t nxt_size = (strlen(argv[4])); |
||||
uint32_t nxt_flags = 0xffff; |
||||
|
||||
/* determine destination address */ |
||||
if (inet_pton(AF_INET6, argv[2], tmp_ipv6_dst)) { |
||||
dst = tmp_ipv6_dst; |
||||
dst_size = IN6ADDRSZ; |
||||
dst_flags = AF_INET6; |
||||
} |
||||
else if (inet_pton(AF_INET, argv[2], tmp_ipv4_dst)) { |
||||
dst = tmp_ipv4_dst; |
||||
dst_size = INADDRSZ; |
||||
dst_flags = AF_INET; |
||||
} |
||||
|
||||
/* determine next-hop address */ |
||||
if (inet_pton(AF_INET6, argv[4], tmp_ipv6_nxt)) { |
||||
nxt = tmp_ipv6_nxt; |
||||
nxt_size = IN6ADDRSZ; |
||||
nxt_flags = AF_INET6; |
||||
} |
||||
else if (inet_pton(AF_INET, argv[4], tmp_ipv4_nxt)) { |
||||
nxt = tmp_ipv4_nxt; |
||||
nxt_size = INADDRSZ; |
||||
nxt_flags = AF_INET; |
||||
} |
||||
|
||||
fib_add_entry((kernel_pid_t) atoi(argv[6]), |
||||
dst, dst_size, dst_flags, |
||||
nxt, nxt_size, nxt_flags, |
||||
FIB_LIFETIME_NO_EXPIRE); |
||||
} |
||||
else { |
||||
_fib_usage(1); |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
/* e.g. fibroute add <destination> via <next hop> dev <device> lifetime <lifetime> */ |
||||
if (argc == 9) { |
||||
if ((strcmp("add", argv[1]) == 0) && (strcmp("via", argv[3]) == 0) |
||||
&& (strcmp("dev", argv[5]) == 0) |
||||
&& (strcmp("lifetime", argv[7]) == 0)) { |
||||
|
||||
unsigned char *dst = (unsigned char *)argv[2]; |
||||
size_t dst_size = (strlen(argv[2])); |
||||
uint32_t dst_flags = 0xffff; |
||||
unsigned char *nxt = (unsigned char *)argv[4]; |
||||
size_t nxt_size = (strlen(argv[4])); |
||||
uint32_t nxt_flags = 0xffff; |
||||
|
||||
/* determine destination address */ |
||||
if (inet_pton(AF_INET6, argv[2], tmp_ipv6_dst)) { |
||||