SlideShare a Scribd company logo
More Info Https://ThesisScientist.com
Appendix A
Implementation Coding of AODV
#include "aodv_hello.h"
#include "aodv_timeout.h"
#include "aodv_rrep.h"
#include "aodv_rreq.h"
#include "routing_table.h"
#include "timer_queue.h"
#include "params.h"
#include "aodv_socket.h"
#include "defs.h"
#include "debug.h"
extern int unidir_hack, receive_n_hellos, hello_jittering, optimized_hellos;
static struct timer hello_timer;
#endif
long NS_CLASS hello_jitter()
{
if (hello_jittering) {
#ifdef NS_PORT
return (long) (((float) Random::integer(RAND_MAX + 1) / RAND_MAX - 0.5)
* JITTER_INTERVAL);
#else
return (long) (((float) random() / RAND_MAX - 0.5) * JITTER_INTERVAL);
#endif
} else
return 0;
}
void NS_CLASS hello_start()
{
if (hello_timer.used)
return;
gettimeofday(&this_host.fwd_time, NULL);
DEBUG(LOG_DEBUG, 0, "Starting to send HELLOs!");
timer_init(&hello_timer, &NS_CLASS hello_send, NULL);
hello_send(NULL);
}
void NS_CLASS hello_stop()
{
DEBUG(LOG_DEBUG, 0,
"No active forwarding routes - stopped sending HELLOs!");
timer_remove(&hello_timer);
}
void NS_CLASS hello_send(void *arg)
{
RREP *rrep;
More Info Https://ThesisScientist.com
AODV_ext *ext = NULL;
u_int8_t flags = 0;
struct in_addr dest;
long time_diff, jitter;
struct timeval now;
int msg_size = RREP_SIZE;
int i;
gettimeofday(&now, NULL);
if (optimized_hellos &&
timeval_diff(&now, &this_host.fwd_time) > ACTIVE_ROUTE_TIMEOUT) {
hello_stop();
return;
}
time_diff = timeval_diff(&now, &this_host.bcast_time);
jitter = hello_jitter();
if (time_diff >= HELLO_INTERVAL) {
for (i = 0; i < MAX_NR_INTERFACES; i++) {
if (!DEV_NR(i).enabled)
continue;
#ifdef DEBUG_HELLO
DEBUG(LOG_DEBUG, 0, "sending Hello to 255.255.255.255");
#endif
rrep = rrep_create(flags, 0, 0, DEV_NR(i).ipaddr,
this_host.seqno,
DEV_NR(i).ipaddr,
ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
/* Assemble a RREP extension which contain our neighbor set... */
if (unidir_hack) {
int i;
if (ext)
ext = AODV_EXT_NEXT(ext);
else
ext = (AODV_ext *) ((char *) rrep + RREP_SIZE);
ext->type = RREP_HELLO_NEIGHBOR_SET_EXT;
ext->length = 0;
for (i = 0; i < RT_TABLESIZE; i++) {
list_t *pos;
list_foreach(pos, &rt_tbl.tbl[i]) {
rt_table_t *rt = (rt_table_t *) pos;
if (rt->hello_timer.used) {
#ifdef DEBUG_HELLO
DEBUG(LOG_INFO, 0,
"Adding %s to hello neighbor set ext",
ip_to_str(rt->dest_addr));
#endif
More Info Https://ThesisScientist.com
memcpy(AODV_EXT_DATA(ext), &rt->dest_addr,
sizeof(struct in_addr));
ext->length += sizeof(struct in_addr);
}
}
}
if (ext->length)
msg_size = RREP_SIZE + AODV_EXT_SIZE(ext);
}
dest.s_addr = AODV_BROADCAST;
aodv_socket_send((AODV_msg *) rrep, dest, msg_size, 1, &DEV_NR(i));
}
timer_set_timeout(&hello_timer, HELLO_INTERVAL + jitter);
} else {
if (HELLO_INTERVAL - time_diff + jitter < 0)
timer_set_timeout(&hello_timer,
HELLO_INTERVAL - time_diff - jitter);
else
timer_set_timeout(&hello_timer,
HELLO_INTERVAL - time_diff + jitter);
}
}
/* Process a hello message */
void NS_CLASS hello_process(RREP * hello, int rreplen, unsigned int ifindex)
{
u_int32_t hello_seqno, timeout, hello_interval = HELLO_INTERVAL;
u_int8_t state, flags = 0;
struct in_addr ext_neighbor, hello_dest;
rt_table_t *rt;
AODV_ext *ext = NULL;
int i;
struct timeval now;
gettimeofday(&now, NULL);
hello_dest.s_addr = hello->dest_addr;
hello_seqno = ntohl(hello->dest_seqno);
rt = rt_table_find(hello_dest);
if (rt)
flags = rt->flags;
if (unidir_hack)
flags |= RT_UNIDIR;
/* Check for hello interval extension: */
ext = (AODV_ext *) ((char *) hello + RREP_SIZE);
while (rreplen > (int) RREP_SIZE) {
switch (ext->type) {
case RREP_HELLO_INTERVAL_EXT:
if (ext->length == 4) {
More Info Https://ThesisScientist.com
memcpy(&hello_interval, AODV_EXT_DATA(ext), 4);
hello_interval = ntohl(hello_interval);
#ifdef DEBUG_HELLO
DEBUG(LOG_INFO, 0, "Hello extension interval=%lu!",
hello_interval);
#endif
} else
alog(LOG_WARNING, 0,
__FUNCTION__, "Bad hello interval extension!");
break;
case RREP_HELLO_NEIGHBOR_SET_EXT:
#ifdef DEBUG_HELLO
DEBUG(LOG_INFO, 0, "RREP_HELLO_NEIGHBOR_SET_EXT");
#endif
for (i = 0; i < ext->length; i = i + 4) {
ext_neighbor.s_addr =
*(in_addr_t *) ((char *) AODV_EXT_DATA(ext) + i);
if (ext_neighbor.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
flags &= ~RT_UNIDIR;
}
break;
default:
alog(LOG_WARNING, 0, __FUNCTION__,
"Bad extension!! type=%d, length=%d", ext->type, ext->length);
ext = NULL;
break;
}
if (ext == NULL)
break;
rreplen -= AODV_EXT_SIZE(ext);
ext = AODV_EXT_NEXT(ext);
}
#ifdef DEBUG_HELLO
DEBUG(LOG_DEBUG, 0, "rcvd HELLO from %s, seqno %lu",
ip_to_str(hello_dest), hello_seqno);
#endif
/* This neighbor should only be valid after receiving 3
consecutive hello messages... */
if (receive_n_hellos)
state = INVALID;
else
state = VALID;
timeout = ALLOWED_HELLO_LOSS * hello_interval + ROUTE_TIMEOUT_SLACK;
if (!rt) {
rt = rt_table_insert(hello_dest, hello_dest, 1,
hello_seqno, timeout, state, flags, ifindex);
More Info Https://ThesisScientist.com
if (flags & RT_UNIDIR) {
DEBUG(LOG_INFO, 0, "%s new NEIGHBOR, link UNI-DIR",
ip_to_str(rt->dest_addr));
} else {
DEBUG(LOG_INFO, 0, "%s new NEIGHBOR!", ip_to_str(rt->dest_addr));
}
rt->hello_cnt = 1;
} else {
if ((flags & RT_UNIDIR) && rt->state == VALID && rt->hcnt > 1) {
goto hello_update;
}
if (receive_n_hellos && rt->hello_cnt < (receive_n_hellos - 1)) {
if (timeval_diff(&now, &rt->last_hello_time) <
(long) (hello_interval + hello_interval / 2))
rt->hello_cnt++;
else
rt->hello_cnt = 1;
memcpy(&rt->last_hello_time, &now, sizeof(struct timeval));
return;
}
rt_table_update(rt, hello_dest, 1, hello_seqno, timeout, VALID, flags);
}
hello_update:
hello_update_timeout(rt, &now, ALLOWED_HELLO_LOSS * hello_interval);
return;
}
#define HELLO_DELAY 50 /* The extra time we should allow an hello
message to take (due to processing) before
assuming lost . */
NS_INLINE void NS_CLASS hello_update_timeout(rt_table_t * rt,
struct timeval *now, long time)
{
timer_set_timeout(&rt->hello_timer, time + HELLO_DELAY);
memcpy(&rt->last_hello_time, now, sizeof(struct timeval));
}
extern int unidir_hack, optimized_hellos, llfeedback;
#endif
RREP *NS_CLASS rrep_create(u_int8_t flags,
u_int8_t prefix,
u_int8_t hcnt,
struct in_addr dest_addr,
u_int32_t dest_seqno,
struct in_addr orig_addr, u_int32_t life)
More Info Https://ThesisScientist.com
{
RREP *rrep;
rrep = (RREP *) aodv_socket_new_msg();
rrep->type = AODV_RREP;
rrep->res1 = 0;
rrep->res2 = 0;
rrep->prefix = prefix;
rrep->hcnt = hcnt;
rrep->dest_addr = dest_addr.s_addr;
rrep->dest_seqno = htonl(dest_seqno);
rrep->orig_addr = orig_addr.s_addr;
rrep->lifetime = htonl(life);
if (flags & RREP_REPAIR)
rrep->r = 1;
if (flags & RREP_ACK)
rrep->a = 1;
/* Don't print information about hello messages... */
#ifdef DEBUG_OUTPUT
if (rrep->dest_addr != rrep->orig_addr) {
DEBUG(LOG_DEBUG, 0, "Assembled RREP:");
log_pkt_fields((AODV_msg *) rrep);
}
#endif
return rrep;
}
RREP_ack *NS_CLASS rrep_ack_create()
{
RREP_ack *rrep_ack;
rrep_ack = (RREP_ack *) aodv_socket_new_msg();
rrep_ack->type = AODV_RREP_ACK;
DEBUG(LOG_DEBUG, 0, "Assembled RREP_ack");
return rrep_ack;
}
void NS_CLASS rrep_ack_process(RREP_ack * rrep_ack, int rrep_acklen,
struct in_addr ip_src, struct in_addr ip_dst)
{
rt_table_t *rt;
rt = rt_table_find(ip_src);
if (rt == NULL) {
DEBUG(LOG_WARNING, 0, "No RREP_ACK expected for %s", ip_to_str(ip_src));
return;
}
DEBUG(LOG_DEBUG, 0, "Received RREP_ACK from %s", ip_to_str(ip_src));
More Info Https://ThesisScientist.com
/* Remove unexpired timer for this RREP_ACK */
timer_remove(&rt->ack_timer);
}
AODV_ext *NS_CLASS rrep_add_ext(RREP * rrep, int type, unsigned int offset,
int len, char *data)
{
AODV_ext *ext = NULL;
if (offset < RREP_SIZE)
return NULL;
ext = (AODV_ext *) ((char *) rrep + offset);
ext->type = type;
ext->length = len;
memcpy(AODV_EXT_DATA(ext), data, len);
return ext;
}
void NS_CLASS rrep_send(RREP * rrep, rt_table_t * rev_rt,
rt_table_t * fwd_rt, int size)
{
u_int8_t rrep_flags = 0;
struct in_addr dest;
if (!rev_rt) {
DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!");
return;
}
dest.s_addr = rrep->dest_addr;
/* Check if we should request a RREP-ACK */
if ((rev_rt->state == VALID && rev_rt->flags & RT_UNIDIR) ||
(rev_rt->hcnt == 1 && unidir_hack)) {
rt_table_t *neighbor = rt_table_find(rev_rt->next_hop);
if (neighbor && neighbor->state == VALID && !neighbor->ack_timer.used) {
rrep_flags |= RREP_ACK;
neighbor->flags |= RT_UNIDIR;
timer_remove(&neighbor->hello_timer);
neighbor_link_break(neighbor);
DEBUG(LOG_DEBUG, 0, "Link to %s is unidirectional!",
ip_to_str(neighbor->dest_addr));
timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
}
}
More Info Https://ThesisScientist.com
DEBUG(LOG_DEBUG, 0, "Sending RREP to next hop %s about %s->%s",
ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr),
ip_to_str(dest));
aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, MAXTTL,
&DEV_IFINDEX(rev_rt->ifindex));
/* Update precursor lists */
if (fwd_rt) {
precursor_add(fwd_rt, rev_rt->next_hop);
precursor_add(rev_rt, fwd_rt->next_hop);
}
if (!llfeedback && optimized_hellos)
hello_start();
}
void NS_CLASS rrep_forward(RREP * rrep, int size, rt_table_t * rev_rt,
rt_table_t * fwd_rt, int ttl)
{
/* Sanity checks... */
if (!fwd_rt || !rev_rt) {
DEBUG(LOG_WARNING, 0, "Could not forward RREP because of NULL route!");
return;
}
if (!rrep) {
DEBUG(LOG_WARNING, 0, "No RREP to forward!");
return;
}
DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s", ip_to_str(rev_rt->next_hop));
rt_table_t *neighbor;
if (rev_rt->dest_addr.s_addr != rev_rt->next_hop.s_addr)
neighbor = rt_table_find(rev_rt->next_hop);
else
neighbor = rev_rt;
if (neighbor && !neighbor->ack_timer.used) {
rrep->a = 1;
neighbor->flags |= RT_UNIDIR;
timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
}
}
rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size);
rrep->hcnt = fwd_rt->hcnt; /* Update the hopcount */
aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl,
&DEV_IFINDEX(rev_rt->ifindex));
More Info Https://ThesisScientist.com
precursor_add(fwd_rt, rev_rt->next_hop);
precursor_add(rev_rt, fwd_rt->next_hop);
rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
}
void NS_CLASS rrep_process(RREP * rrep, int rreplen, struct in_addr ip_src,
struct in_addr ip_dst, int ip_ttl,
unsigned int ifindex)
{
u_int32_t rrep_lifetime, rrep_seqno, rrep_new_hcnt;
u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0;
rt_table_t *fwd_rt, *rev_rt;
AODV_ext *ext;
unsigned int extlen = 0;
int rt_flags = 0;
struct in_addr rrep_dest, rrep_orig;
#ifdef CONFIG_GATEWAY
struct in_addr inet_dest_addr;
int inet_rrep = 0;
#endif
/* Convert to correct byte order on affeected fields: */
rrep_dest.s_addr = rrep->dest_addr;
rrep_orig.s_addr = rrep->orig_addr;
rrep_seqno = ntohl(rrep->dest_seqno);
rrep_lifetime = ntohl(rrep->lifetime);
/* Increment RREP hop count to account for intermediate node... */
rrep_new_hcnt = rrep->hcnt + 1;
if (rreplen < (int) RREP_SIZE) {
alog(LOG_WARNING, 0, __FUNCTION__,
"IP data field too short (%u bytes)"
" from %s to %s", rreplen, ip_to_str(ip_src), ip_to_str(ip_dst));
return;
}
/* Ignore messages which aim to a create a route to one self */
if (rrep_dest.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
return;
DEBUG(LOG_DEBUG, 0, "from %s about %s->%s",
ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
#ifdef DEBUG_OUTPUT
log_pkt_fields((AODV_msg *) rrep);
#endif
/* Determine whether there are any extensions */
ext = (AODV_ext *) ((char *) rrep + RREP_SIZE);
while ((rreplen - extlen) > RREP_SIZE) {
switch (ext->type) {
case RREP_EXT:
DEBUG(LOG_INFO, 0, "RREP include EXTENSION");
More Info Https://ThesisScientist.com
/* Do something here */
break;
#ifdef CONFIG_GATEWAY
case RREP_INET_DEST_EXT:
if (ext->length == sizeof(u_int32_t)) {
memcpy(&inet_dest_addr, AODV_EXT_DATA(ext), ext->length);
DEBUG(LOG_DEBUG, 0, "RREP_INET_DEST_EXT: <%s>",
ip_to_str(inet_dest_addr));
/* This was a RREP from a gateway */
rt_flags |= RT_GATEWAY;
inet_rrep = 1;
break;
}
#endif
default:
alog(LOG_WARNING, 0, __FUNCTION__, "Unknown or bad extension %d",
ext->type);
break;
}
extlen += AODV_EXT_SIZE(ext);
ext = AODV_EXT_NEXT(ext);
}
fwd_rt = rt_table_find(rrep_dest);
rev_rt = rt_table_find(rrep_orig);
if (!fwd_rt) {
/* We didn't have an existing entry, so we insert a new one. */
fwd_rt = rt_table_insert(rrep_dest, ip_src, rrep_new_hcnt, rrep_seqno,
rrep_lifetime, VALID, rt_flags, ifindex);
} else if (fwd_rt->dest_seqno == 0 ||
(int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno ||
(rrep_seqno == fwd_rt->dest_seqno &&
(fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR ||
rrep_new_hcnt < fwd_rt->hcnt))) {
pre_repair_hcnt = fwd_rt->hcnt;
pre_repair_flags = fwd_rt->flags;
fwd_rt = rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno,
rrep_lifetime, VALID,
rt_flags | fwd_rt->flags);
} else {
if (fwd_rt->hcnt > 1) {
DEBUG(LOG_DEBUG, 0,
"Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld",
fwd_rt->hcnt, fwd_rt->dest_seqno);
}
return;
}
RREP_ack *rrep_ack;
rrep_ack = rrep_ack_create();
More Info Https://ThesisScientist.com
aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
NEXT_HOP_WAIT, MAXTTL, &DEV_IFINDEX(fwd_rt->ifindex));
/* Remove RREP_ACK flag... */
rrep->a = 0;
}
if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) {
#ifdef CONFIG_GATEWAY
if (inet_rrep) {
rt_table_t *inet_rt;
inet_rt = rt_table_find(inet_dest_addr);
if (!inet_rt)
rt_table_insert(inet_dest_addr, rrep_dest, rrep_new_hcnt, 0,
rrep_lifetime, VALID, RT_INET_DEST, ifindex);
else if (inet_rt->state == INVALID || rrep_new_hcnt < inet_rt->hcnt) {
rt_table_update(inet_rt, rrep_dest, rrep_new_hcnt, 0,
rrep_lifetime, VALID, RT_INET_DEST |
inet_rt->flags);
} else {
DEBUG(LOG_DEBUG, 0, "INET Response, but no update %s",
ip_to_str(inet_dest_addr));
}
}
#endif
if (pre_repair_flags & RT_REPAIR) {
if (fwd_rt->hcnt > pre_repair_hcnt) {
RERR *rerr;
u_int8_t rerr_flags = 0;
struct in_addr dest;
dest.s_addr = AODV_BROADCAST;
rerr_flags |= RERR_NODELETE;
rerr = rerr_create(rerr_flags, fwd_rt->dest_addr,
fwd_rt->dest_seqno);
if (fwd_rt->nprec)
aodv_socket_send((AODV_msg *) rerr, dest,
RERR_CALC_SIZE(rerr), 1,
&DEV_IFINDEX(fwd_rt->ifindex));
}
}
} else {
if (rev_rt && rev_rt->state == VALID) {
rrep_forward(rrep, rreplen, rev_rt, fwd_rt, --ip_ttl);
} else {
DEBUG(LOG_DEBUG, 0, "Could not forward RREP - NO ROUTE!!!");
}
}
if (!llfeedback && optimized_hellos)
hello_start();
}
More Info Https://ThesisScientist.com
int rrep_add_hello_ext(RREP * rrep, int offset, u_int32_t interval)
{
AODV_ext *ext;
ext = (AODV_ext *) ((char *) rrep + RREP_SIZE + offset);
ext->type = RREP_HELLO_INTERVAL_EXT;
ext->length = sizeof(interval);
memcpy(AODV_EXT_DATA(ext), &interval, sizeof(interval));
return (offset + AODV_EXT_SIZE(ext));
}
endif /* NS_PORT */
#ifndef NS_PORT
#define SO_RECVBUF_SIZE 256*1024
static char recv_buf[RECV_BUF_SIZE];
static char send_buf[SEND_BUF_SIZE];
extern int wait_on_reboot, hello_qual_threshold, ratelimit;
static void aodv_socket_read(int fd);
static struct cmsghdr *__cmsg_nxthdr_fix(void *__ctl, size_t __size,
struct cmsghdr *__cmsg)
{
struct cmsghdr *__ptr;
__ptr = (struct cmsghdr *) (((unsigned char *) __cmsg) +
CMSG_ALIGN(__cmsg->cmsg_len));
if ((unsigned long) ((char *) (__ptr + 1) - (char *) __ctl) > __size)
return NULL;
return __ptr;
}
struct cmsghdr *cmsg_nxthdr_fix(struct msghdr *__msg, struct cmsghdr *__cmsg)
{
return __cmsg_nxthdr_fix(__msg->msg_control, __msg->msg_controllen, __cmsg);
}
#endif /* NS_PORT */
void NS_CLASS aodv_socket_init()
{
#ifndef NS_PORT
struct sockaddr_in aodv_addr;
struct ifreq ifr;
int i, retval = 0;
int on = 1;
int tos = IPTOS_LOWDELAY;
int bufsize = SO_RECVBUF_SIZE;
socklen_t optlen = sizeof(bufsize);
More Info Https://ThesisScientist.com
/* Create a UDP socket */
if (this_host.nif == 0) {
fprintf(stderr, "No interfaces configuredn");
exit(-1);
}
/* Open a socket for every AODV enabled interface */
for (i = 0; i < MAX_NR_INTERFACES; i++) {
if (!DEV_NR(i).enabled)
continue;
/* AODV socket */
DEV_NR(i).sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (DEV_NR(i).sock < 0) {
perror("");
exit(-1);
}
#ifdef CONFIG_GATEWAY
/* Data packet send socket */
DEV_NR(i).psock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (DEV_NR(i).psock < 0) {
perror("");
exit(-1);
}
#endif
/* Bind the socket to the AODV port number */
memset(&aodv_addr, 0, sizeof(aodv_addr));
aodv_addr.sin_family = AF_INET;
aodv_addr.sin_port = htons(AODV_PORT);
aodv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
retval = bind(DEV_NR(i).sock, (struct sockaddr *) &aodv_addr,
sizeof(struct sockaddr));
if (retval < 0) {
perror("Bind failed ");
exit(-1);
}
if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BROADCAST,
&on, sizeof(int)) < 0) {
perror("SO_BROADCAST failed ");
exit(-1);
}
memset(&ifr, 0, sizeof(struct ifreq));
strcpy(ifr.ifr_name, DEV_NR(i).ifname);
if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BINDTODEVICE,
&ifr, sizeof(ifr)) < 0) {
fprintf(stderr, "SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname);
perror(" ");
exit(-1);
}
More Info Https://ThesisScientist.com
if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_PRIORITY,
&tos, sizeof(int)) < 0) {
perror("Setsockopt SO_PRIORITY failed ");
exit(-1);
}
if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_RECVTTL,
&on, sizeof(int)) < 0) {
perror("Setsockopt IP_RECVTTL failed ");
exit(-1);
}
if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_PKTINFO,
&on, sizeof(int)) < 0) {
perror("Setsockopt IP_PKTINFO failed ");
exit(-1);
}
#ifdef CONFIG_GATEWAY
if (setsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_BINDTODEVICE,
&ifr, sizeof(ifr)) < 0) {
fprintf(stderr, "SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname);
perror(" ");
exit(-1);
}
bufsize = 4 * 65535;
if (setsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_SNDBUF,
(char *) &bufsize, optlen) < 0) {
DEBUG(LOG_NOTICE, 0, "Could not set send socket buffer size");
}
if (getsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_SNDBUF,
(char *) &bufsize, &optlen) == 0) {
alog(LOG_NOTICE, 0, __FUNCTION__,
"RAW send socket buffer size set to %d", bufsize);
}
#endif
/* Set max allowable receive buffer size... */
for (;; bufsize -= 1024) {
if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_RCVBUF,
(char *) &bufsize, optlen) == 0) {
alog(LOG_NOTICE, 0, __FUNCTION__,
"Receive buffer size set to %d", bufsize);
break;
}
if (bufsize < RECV_BUF_SIZE) {
alog(LOG_ERR, 0, __FUNCTION__,
"Could not set receive buffer size");
exit(-1);
}
}
retval = attach_callback_func(DEV_NR(i).sock, aodv_socket_read);
if (retval < 0) {
More Info Https://ThesisScientist.com
perror("register input handler failed ");
exit(-1);
}
}
#endif /* NS_PORT */
num_rreq = 0;
num_rerr = 0;
}
void NS_CLASS aodv_socket_process_packet(AODV_msg * aodv_msg, int len,
struct in_addr src,
struct in_addr dst,
int ttl, unsigned int ifindex)
{
/* If this was a HELLO message... Process as HELLO. */
if ((aodv_msg->type == AODV_RREP && ttl == 1 &&
dst.s_addr == AODV_BROADCAST)) {
hello_process((RREP *) aodv_msg, len, ifindex);
return;
}
/* Make sure we add/update neighbors */
neighbor_add(aodv_msg, src, ifindex);
switch (aodv_msg->type) {
case AODV_RREQ:
rreq_process((RREQ *) aodv_msg, len, src, dst, ttl, ifindex);
break;
case AODV_RREP:
DEBUG(LOG_DEBUG, 0, "Received RREP");
rrep_process((RREP *) aodv_msg, len, src, dst, ttl, ifindex);
break;
case AODV_RERR:
DEBUG(LOG_DEBUG, 0, "Received RERR");
rerr_process((RERR *) aodv_msg, len, src, dst);
break;
case AODV_RREP_ACK:
DEBUG(LOG_DEBUG, 0, "Received RREP_ACK");
rrep_ack_process((RREP_ack *) aodv_msg, len, src, dst);
break;
default:
alog(LOG_WARNING, 0, __FUNCTION__,
"Unknown msg type %u rcvd from %s to %s", aodv_msg->type,
ip_to_str(src), ip_to_str(dst));
}
}
#ifdef NS_PORT
void NS_CLASS recvAODVUUPacket(Packet * p)
{
int len, i, ttl = 0;
struct in_addr src, dst;
struct hdr_cmn *ch = HDR_CMN(p);
More Info Https://ThesisScientist.com
struct hdr_ip *ih = HDR_IP(p);
hdr_aodvuu *ah = HDR_AODVUU(p);
src.s_addr = ih->saddr();
dst.s_addr = ih->daddr();
len = ch->size() - IP_HDR_LEN;
ttl = ih->ttl();
AODV_msg *aodv_msg = (AODV_msg *) recv_buf;
/* Only handle AODVUU packets */
assert(ch->ptype() == PT_AODVUU);
/* Only process incoming packets */
assert(ch->direction() == hdr_cmn::UP);
/* Copy message to receive buffer */
memcpy(recv_buf, ah, RECV_BUF_SIZE);
/* Deallocate packet, we have the information we need... */
Packet::free(p);
/* Ignore messages generated locally */
for (i = 0; i < MAX_NR_INTERFACES; i++)
if (this_host.devs[i].enabled &&
memcmp(&src, &this_host.devs[i].ipaddr,
sizeof(struct in_addr)) == 0)
return;
aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, NS_IFINDEX);
}
#else
static void aodv_socket_read(int fd)
{
struct in_addr src, dst;
int i, len, ttl = -1;
AODV_msg *aodv_msg;
struct dev_info *dev;
struct msghdr msgh;
struct cmsghdr *cmsg;
struct iovec iov;
char ctrlbuf[CMSG_SPACE(sizeof(int)) +
CMSG_SPACE(sizeof(struct in_pktinfo))];
struct sockaddr_in src_addr;
dst.s_addr = -1;
iov.iov_base = recv_buf;
iov.iov_len = RECV_BUF_SIZE;
msgh.msg_name = &src_addr;
msgh.msg_namelen = sizeof(src_addr);
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
msgh.msg_control = ctrlbuf;
msgh.msg_controllen = sizeof(ctrlbuf);
More Info Https://ThesisScientist.com
len = recvmsg(fd, &msgh, 0);
if (len < 0) {
alog(LOG_WARNING, 0, __FUNCTION__, "receive ERROR len=%d!", len);
return;
}
src.s_addr = src_addr.sin_addr.s_addr;
/* Get the ttl and destination address from the control message */
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
cmsg = CMSG_NXTHDR_FIX(&msgh, cmsg)) {
if (cmsg->cmsg_level == SOL_IP) {
switch (cmsg->cmsg_type) {
case IP_TTL:
ttl = *(CMSG_DATA(cmsg));
break;
case IP_PKTINFO:
{
struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsg);
dst.s_addr = pi->ipi_addr.s_addr;
}
}
}
}
if (ttl < 0) {
DEBUG(LOG_DEBUG, 0, "No TTL, packet ignored!");
return;
}
/* Ignore messages generated locally */
for (i = 0; i < MAX_NR_INTERFACES; i++)
if (this_host.devs[i].enabled &&
memcmp(&src, &this_host.devs[i].ipaddr,
sizeof(struct in_addr)) == 0)
return;
aodv_msg = (AODV_msg *) recv_buf;
dev = devfromsock(fd);
if (!dev) {
DEBUG(LOG_ERR, 0, "Could not get device info!n");
return;
}
aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, dev->ifindex);
}
#endif /* NS_PORT */
void NS_CLASS aodv_socket_send(AODV_msg * aodv_msg, struct in_addr dst,
int len, u_int8_t ttl, struct dev_info *dev)
{
int retval = 0;
struct timeval now;
More Info Https://ThesisScientist.com
/* Rate limit stuff: */
#ifndef NS_PORT
struct sockaddr_in dst_addr;
if (wait_on_reboot && aodv_msg->type == AODV_RREP)
return;
memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr = dst;
dst_addr.sin_port = htons(AODV_PORT);
/* Set ttl */
if (setsockopt(dev->sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
alog(LOG_WARNING, 0, __FUNCTION__, "ERROR setting ttl!");
return;
}
#else
Packet *p = allocpkt();
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
hdr_aodvuu *ah = HDR_AODVUU(p);
// Clear AODVUU part of packet
memset(ah, '0', ah->size());
// Copy message contents into packet
memcpy(ah, aodv_msg, len);
// Set common header fields
ch->ptype() = PT_AODVUU;
ch->direction() = hdr_cmn::DOWN;
ch->size() += len + IP_HDR_LEN;
ch->iface() = -2;
ch->error() = 0;
ch->prev_hop_ = (nsaddr_t) dev->ipaddr.s_addr;
// Set IP header fields
ih->saddr() = (nsaddr_t) dev->ipaddr.s_addr;
ih->daddr() = (nsaddr_t) dst.s_addr;
ih->ttl() = ttl;
// Note: Port number for routing agents, not AODV port number!
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
// Fake success
retval = len;
#endif
gettimeofday(&now, NULL);
switch (aodv_msg->type) {
case AODV_RREQ:
More Info Https://ThesisScientist.com
if (num_rreq == (RREQ_RATELIMIT - 1)) {
if (timeval_diff(&now, &rreq_ratel[0]) < 1000) {
DEBUG(LOG_DEBUG, 0, "RATELIMIT: Dropping RREQ %ld ms",
timeval_diff(&now, &rreq_ratel[0]));
#ifdef NS_PORT
Packet::free(p);
#endif
return;
} else {
memmove(rreq_ratel, &rreq_ratel[1],
sizeof(struct timeval) * (num_rreq - 1));
memcpy(&rreq_ratel[num_rreq - 1], &now,
sizeof(struct timeval));
}
} else {
memcpy(&rreq_ratel[num_rreq], &now, sizeof(struct timeval));
num_rreq++;
}
break;
case AODV_RERR:
if (num_rerr == (RERR_RATELIMIT - 1)) {
if (timeval_diff(&now, &rerr_ratel[0]) < 1000) {
DEBUG(LOG_DEBUG, 0, "RATELIMIT: Dropping RERR %ld ms",
timeval_diff(&now, &rerr_ratel[0]));
#ifdef NS_PORT
Packet::free(p);
#endif
return;
} else {
memmove(rerr_ratel, &rerr_ratel[1],
sizeof(struct timeval) * (num_rerr - 1));
memcpy(&rerr_ratel[num_rerr - 1], &now,
sizeof(struct timeval));
}
} else {
memcpy(&rerr_ratel[num_rerr], &now, sizeof(struct timeval));
num_rerr++;
}
break;
}
}
if (dst.s_addr == AODV_BROADCAST) {
gettimeofday(&this_host.bcast_time, NULL);
#ifdef NS_PORT
ch->addr_type() = NS_AF_NONE;
sendPacket(p, dst, 0.0);
#else
retval = sendto(dev->sock, send_buf, len, 0,
(struct sockaddr *) &dst_addr, sizeof(dst_addr));
if (retval < 0) {
More Info Https://ThesisScientist.com
alog(LOG_WARNING, errno, __FUNCTION__, "Failed send to bc %s",
ip_to_str(dst));
return;
}
#endif
} else {
#ifdef NS_PORT
ch->addr_type() = NS_AF_INET;
/* We trust the decision of next hop for all AODV messages... */
if (dst.s_addr == AODV_BROADCAST)
sendPacket(p, dst, 0.001 * Random::uniform());
else
sendPacket(p, dst, 0.0);
#else
retval = sendto(dev->sock, send_buf, len, 0,
(struct sockaddr *) &dst_addr, sizeof(dst_addr));
if (retval < 0) {
alog(LOG_WARNING, errno, __FUNCTION__, "Failed send to %s",
ip_to_str(dst));
return;
}
#endif
}
/* Do not print hello msgs... */
if (!(aodv_msg->type == AODV_RREP && (dst.s_addr == AODV_BROADCAST)))
DEBUG(LOG_INFO, 0, "AODV msg to %s ttl=%d size=%u",
ip_to_str(dst), ttl, retval, len);
return;
}
AODV_msg *NS_CLASS aodv_socket_new_msg(void)
{
memset(send_buf, '0', SEND_BUF_SIZE);
return (AODV_msg *) (send_buf);
}
AODV_msg *NS_CLASS aodv_socket_queue_msg(AODV_msg * aodv_msg, int size)
{
memcpy((char *) send_buf, aodv_msg, size);
return (AODV_msg *) send_buf;
}
void aodv_socket_cleanup(void)
{
#ifndef NS_PORT
int i;
for (i = 0; i < MAX_NR_INTERFACES; i++) {
if (!DEV_NR(i).enabled)
More Info Https://ThesisScientist.com
continue;
close(DEV_NR(i).sock);
}
#endif /* NS_PORT */
}
oid NS_CLASS rt_table_init()
{
int i;
rt_tbl.num_entries = 0;
rt_tbl.num_active = 0;
/* We do a for loop here... NS does not like us to use memset() */
for (i = 0; i < RT_TABLESIZE; i++) {
INIT_LIST_HEAD(&rt_tbl.tbl[i]);
}
}
void NS_CLASS rt_table_destroy()
{
int i;
list_t *tmp = NULL, *pos = NULL;
for (i = 0; i < RT_TABLESIZE; i++) {
list_foreach_safe(pos, tmp, &rt_tbl.tbl[i]) {
rt_table_t *rt = (rt_table_t *) pos;
rt_table_delete(rt);
}
}
}
/* Calculate a hash value and table index given a key... */
unsigned int hashing(struct in_addr *addr, hash_value * hash)
{
/* *hash = (*addr & 0x7fffffff); */
*hash = (hash_value) addr->s_addr;
return (*hash & RT_TABLEMASK);
}
rt_table_t *NS_CLASS rt_table_insert(struct in_addr dest_addr,
struct in_addr next,
u_int8_t hops, u_int32_t seqno,
u_int32_t life, u_int8_t state,
u_int16_t flags, unsigned int ifindex)
{
hash_value hash;
unsigned int index;
list_t *pos;
rt_table_t *rt;
struct in_addr nm;
nm.s_addr = 0;
/* Calculate hash key */
More Info Https://ThesisScientist.com
index = hashing(&dest_addr, &hash);
/* Check if we already have an entry for dest_addr */
list_foreach(pos, &rt_tbl.tbl[index]) {
rt = (rt_table_t *) pos;
if (memcmp(&rt->dest_addr, &dest_addr, sizeof(struct in_addr))
== 0) {
DEBUG(LOG_INFO, 0, "%s already exist in routing table!",
ip_to_str(dest_addr));
return NULL;
}
}
if ((rt = (rt_table_t *) malloc(sizeof(rt_table_t))) == NULL) {
fprintf(stderr, "Malloc failed!n");
exit(-1);
}
memset(rt, 0, sizeof(rt_table_t));
rt->dest_addr = dest_addr;
rt->next_hop = next;
rt->dest_seqno = seqno;
rt->flags = flags;
rt->hcnt = hops;
rt->ifindex = ifindex;
rt->hash = hash;
rt->state = state;
timer_init(&rt->rt_timer, &NS_CLASS route_expire_timeout, rt);
timer_init(&rt->ack_timer, &NS_CLASS rrep_ack_timeout, rt);
timer_init(&rt->hello_timer, &NS_CLASS hello_timeout, rt);
rt->last_hello_time.tv_sec = 0;
rt->last_hello_time.tv_usec = 0;
rt->hello_cnt = 0;
rt->nprec = 0;
INIT_LIST_HEAD(&rt->precursors);
/* Insert first in bucket... */
rt_tbl.num_entries++;
DEBUG(LOG_INFO, 0, "Inserting %s (bucket %d) next hop %s",
ip_to_str(dest_addr), index, ip_to_str(next));
list_add(&rt_tbl.tbl[index], &rt->l);
if (state == INVALID) {
if (flags & RT_REPAIR) {
rt->rt_timer.handler = &NS_CLASS local_repair_timeout;
More Info Https://ThesisScientist.com
life = ACTIVE_ROUTE_TIMEOUT;
} else {
rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
life = DELETE_PERIOD;
}
} else {
rt_tbl.num_active++;
#ifndef NS_PORT
nl_send_add_route_msg(dest_addr, next, hops, life, flags,
ifindex);
#endif
}
#ifdef CONFIG_GATEWAY_DISABLE
if (rt->flags & RT_GATEWAY)
rt_table_update_inet_rt(rt, life);
#endif
//#ifdef NS_PORT
DEBUG(LOG_INFO, 0, "New timer for %s, life=%d",
ip_to_str(rt->dest_addr), life);
if (life != 0)
timer_set_timeout(&rt->rt_timer, life);
//#endif
/* In case there are buffered packets for this destination, we
* send them on the new route. */
if (rt->state == VALID && seek_list_remove(seek_list_find(dest_addr))) {
#ifdef NS_PORT
if (rt->flags & RT_INET_DEST)
packet_queue_set_verdict(dest_addr, PQ_ENC_SEND);
else
packet_queue_set_verdict(dest_addr, PQ_SEND);
#endif
}
return rt;
}
rt_table_t *NS_CLASS rt_table_update(rt_table_t * rt, struct in_addr next,
u_int8_t hops, u_int32_t seqno,
u_int32_t lifetime, u_int8_t state,
u_int16_t flags)
{
struct in_addr nm;
nm.s_addr = 0;
if (rt->state == INVALID && state == VALID) {
rt_tbl.num_active++;
if (rt->flags & RT_REPAIR)
flags &= ~RT_REPAIR;
#ifndef NS_PORT
More Info Https://ThesisScientist.com
nl_send_add_route_msg(rt->dest_addr, next, hops, lifetime,
flags, rt->ifindex);
#endif
} else if (rt->next_hop.s_addr != 0 &&
rt->next_hop.s_addr != next.s_addr) {
DEBUG(LOG_INFO, 0, "rt->next_hop=%s, new_next_hop=%s",
ip_to_str(rt->next_hop), ip_to_str(next));
#ifndef NS_PORT
nl_send_add_route_msg(rt->dest_addr, next, hops, lifetime,
flags, rt->ifindex);
#endif
}
if (hops > 1 && rt->hcnt == 1) {
rt->last_hello_time.tv_sec = 0;
rt->last_hello_time.tv_usec = 0;
rt->hello_cnt = 0;
timer_remove(&rt->hello_timer);
neighbor_link_break(rt);
}
rt->flags = flags;
rt->dest_seqno = seqno;
rt->next_hop = next;
rt->hcnt = hops;
#ifdef CONFIG_GATEWAY
if (rt->flags & RT_GATEWAY)
rt_table_update_inet_rt(rt, lifetime);
#endif
//#ifdef NS_PORT
rt->rt_timer.handler = &NS_CLASS route_expire_timeout;
if (!(rt->flags & RT_INET_DEST))
rt_table_update_timeout(rt, lifetime);
//#endif
/* Finally, mark as VALID */
rt->state = state;
if (rt->state == VALID
&& seek_list_remove(seek_list_find(rt->dest_addr))) {
#ifdef NS_PORT
if (rt->flags & RT_INET_DEST)
packet_queue_set_verdict(rt->dest_addr, PQ_ENC_SEND);
else
packet_queue_set_verdict(rt->dest_addr, PQ_SEND);
#endif
}
return rt;
More Info Https://ThesisScientist.com
}
NS_INLINE rt_table_t *NS_CLASS rt_table_update_timeout(rt_table_t * rt,
u_int32_t lifetime)
{
struct timeval new_timeout;
if (!rt)
return NULL;
if (rt->state == VALID) {
gettimeofday(&new_timeout, NULL);
timeval_add_msec(&new_timeout, lifetime);
if (timeval_diff(&rt->rt_timer.timeout, &new_timeout) < 0)
timer_set_timeout(&rt->rt_timer, lifetime);
} else
timer_set_timeout(&rt->rt_timer, lifetime);
return rt;
}
/* Update route timeouts in response to an incoming or outgoing data packet. */
void NS_CLASS rt_table_update_route_timeouts(rt_table_t * fwd_rt,
rt_table_t * rev_rt)
{
rt_table_t *next_hop_rt = NULL;
if (fwd_rt && fwd_rt->state == VALID) {
if (llfeedback || fwd_rt->flags & RT_INET_DEST ||
fwd_rt->hcnt != 1 || fwd_rt->hello_timer.used)
rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);
next_hop_rt = rt_table_find(fwd_rt->next_hop);
if (next_hop_rt && next_hop_rt->state == VALID &&
next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr &&
(llfeedback || fwd_rt->hello_timer.used))
rt_table_update_timeout(next_hop_rt,
ACTIVE_ROUTE_TIMEOUT);
}
if (rev_rt && rev_rt->state == VALID) {
if (llfeedback || rev_rt->hcnt != 1 || rev_rt->hello_timer.used)
rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
next_hop_rt = rt_table_find(rev_rt->next_hop);
if (next_hop_rt && next_hop_rt->state == VALID && rev_rt &&
next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr &&
More Info Https://ThesisScientist.com
(llfeedback || rev_rt->hello_timer.used))
rt_table_update_timeout(next_hop_rt,
ACTIVE_ROUTE_TIMEOUT);
rt_table_t *NS_CLASS rt_table_find(struct in_addr dest_addr)
{
hash_value hash;
unsigned int index;
list_t *pos;
if (rt_tbl.num_entries == 0)
return NULL;
/* Calculate index */
index = hashing(&dest_addr, &hash);
/* Handle collisions: */
list_foreach(pos, &rt_tbl.tbl[index]) {
rt_table_t *rt = (rt_table_t *) pos;
if (rt->hash != hash)
continue;
if (memcmp(&dest_addr, &rt->dest_addr, sizeof(struct in_addr))
== 0)
return rt;
}
return NULL;
}
rt_table_t *NS_CLASS rt_table_find_gateway()
{
rt_table_t *gw = NULL;
int i;
for (i = 0; i < RT_TABLESIZE; i++) {
list_t *pos;
list_foreach(pos, &rt_tbl.tbl[i]) {
rt_table_t *rt = (rt_table_t *) pos;
if (rt->flags & RT_GATEWAY && rt->state == VALID) {
if (!gw || rt->hcnt < gw->hcnt)
gw = rt;
}
}
}
return gw;
}
#ifdef CONFIG_GATEWAY
int NS_CLASS rt_table_update_inet_rt(rt_table_t * gw, u_int32_t life)
{
int n = 0;
More Info Https://ThesisScientist.com
int i;
if (!gw)
return -1;
for (i = 0; i < RT_TABLESIZE; i++) {
list_t *pos;
list_foreach(pos, &rt_tbl.tbl[i]) {
rt_table_t *rt = (rt_table_t *) pos;
if (rt->flags & RT_INET_DEST && rt->state == VALID) {
rt_table_update(rt, gw->dest_addr, gw->hcnt, 0,
life, VALID, rt->flags);
n++;
}
}
}
return n;
}
#endif /* CONFIG_GATEWAY_DISABLED */
/* Route expiry and Deletion. */
int NS_CLASS rt_table_invalidate(rt_table_t * rt)
{
struct timeval now;
gettimeofday(&now, NULL);
if (rt == NULL)
return -1;
/* If the route is already invalidated, do nothing... */
if (rt->state == INVALID) {
DEBUG(LOG_DEBUG, 0, "Route %s already invalidated!!!",
ip_to_str(rt->dest_addr));
return -1;
}
if (rt->hello_timer.used) {
DEBUG(LOG_DEBUG, 0, "last HELLO: %ld",
timeval_diff(&now, &rt->last_hello_time));
}
/* Remove any pending, but now obsolete timers. */
timer_remove(&rt->rt_timer);
timer_remove(&rt->hello_timer);
timer_remove(&rt->ack_timer);
/* Mark the route as invalid */
rt->state = INVALID;
rt_tbl.num_active--;
rt->hello_cnt = 0;
/* When the lifetime of a route entry expires, increase the sequence
number for that entry. */
More Info Https://ThesisScientist.com
seqno_incr(rt->dest_seqno);
rt->last_hello_time.tv_sec = 0;
rt->last_hello_time.tv_usec = 0;
#ifndef NS_PORT
nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt);
#endif
#ifdef CONFIG_GATEWAY
if (rt->flags & RT_GATEWAY) {
int i;
rt_table_t *gw = rt_table_find_gateway();
for (i = 0; i < RT_TABLESIZE; i++) {
list_t *pos;
list_foreach(pos, &rt_tbl.tbl[i]) {
rt_table_t *rt2 = (rt_table_t *) pos;
if (rt2->state == VALID
&& (rt2->flags & RT_INET_DEST)
&& (rt2->next_hop.s_addr ==
rt->dest_addr.s_addr)) {
if (0) {
DEBUG(LOG_DEBUG, 0,
"Invalidated GW %s but found new GW %s for
%s",
ip_to_str(rt->dest_addr),
ip_to_str(gw->dest_addr),
ip_to_str(rt2->
dest_addr));
rt_table_update(rt2,
gw->dest_addr,
gw->hcnt, 0,
timeval_diff
(&rt->rt_timer.
timeout, &now),
VALID,
rt2->flags);
} else {
rt_table_invalidate(rt2);
precursor_list_destroy(rt2);
}
}
}
}
}
#endif
if (rt->flags & RT_REPAIR) {
/* Set a timeout for the repair */
rt->rt_timer.handler = &NS_CLASS local_repair_timeout;
More Info Https://ThesisScientist.com
timer_set_timeout(&rt->rt_timer, ACTIVE_ROUTE_TIMEOUT);
DEBUG(LOG_DEBUG, 0, "%s kept for repairs during %u msecs",
ip_to_str(rt->dest_addr), ACTIVE_ROUTE_TIMEOUT);
} else {
/* Schedule a deletion timer */
rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);
DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",
ip_to_str(rt->dest_addr), DELETE_PERIOD);
}
return 0;
}
void NS_CLASS rt_table_delete(rt_table_t * rt)
{
if (!rt) {
DEBUG(LOG_ERR, 0, "No route entry to delete");
return;
}
list_detach(&rt->l);
precursor_list_destroy(rt);
if (rt->state == VALID) {
#ifndef NS_PORT
nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt);
#endif
rt_tbl.num_active--;
}
/* Make sure timers are removed... */
timer_remove(&rt->rt_timer);
timer_remove(&rt->hello_timer);
timer_remove(&rt->ack_timer);
rt_tbl.num_entries--;
free(rt);
return;
}
void NS_CLASS precursor_add(rt_table_t * rt, struct in_addr addr)
{
precursor_t *pr;
list_t *pos;
/* Sanity check */
if (!rt)
return;
list_foreach(pos, &rt->precursors) {
More Info Https://ThesisScientist.com
pr = (precursor_t *) pos;
if (pr->neighbor.s_addr == addr.s_addr)
return;
}
if ((pr = (precursor_t *) malloc(sizeof(precursor_t))) == NULL) {
perror("Could not allocate memory for precursor node!!n");
exit(-1);
}
DEBUG(LOG_INFO, 0, "Adding precursor %s to rte %s",
ip_to_str(addr), ip_to_str(rt->dest_addr));
pr->neighbor.s_addr = addr.s_addr;
/* Insert in precursors list */
list_add(&rt->precursors, &pr->l);
rt->nprec++;
return;
}
void NS_CLASS precursor_remove(rt_table_t * rt, struct in_addr addr)
{
list_t *pos;
/* Sanity check */
if (!rt)
return;
list_foreach(pos, &rt->precursors) {
precursor_t *pr = (precursor_t *) pos;
if (pr->neighbor.s_addr == addr.s_addr) {
DEBUG(LOG_INFO, 0, "Removing precursor %s from rte %s",
ip_to_str(addr), ip_to_str(rt->dest_addr));
list_detach(pos);
rt->nprec--;
free(pr);
return;
}
}
}
void precursor_list_destroy(rt_table_t * rt)
{
list_t *pos, *tmp;
/* Sanity check */
if (!rt)
return;
list_foreach_safe(pos, tmp, &rt->precursors) {
precursor_t *pr = (precursor_t *) pos;
More Info Https://ThesisScientist.com
list_detach(pos);
rt->nprec--;
free(pr);
}
}

More Related Content

PDF
Jamming attack in wireless network
TXT
Procesos
PDF
Introduction to ATS plugins
PPT
W8_2: Inside the UoS Educational Processor
DOCX
codings related to avr micro controller
PPTX
Groovy
KEY
Cypher inside out: Como a linguagem de pesquisas em grafo do Neo4j foi constr...
DOCX
Jamming attack in wireless network
Procesos
Introduction to ATS plugins
W8_2: Inside the UoS Educational Processor
codings related to avr micro controller
Groovy
Cypher inside out: Como a linguagem de pesquisas em grafo do Neo4j foi constr...

What's hot (20)

PDF
Алексей Кутумов, Coroutines everywhere
PPTX
System Calls
PDF
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
DOC
Network security Lab manual
PDF
Preparation for mit ose lab4
DOCX
Operating system and embedded systems
PDF
The Magnificent Seven
PDF
Rich and Snappy Apps (No Scaling Required)
KEY
Breaking the wall
PDF
Extreme JavaScript Performance
PDF
Ugly code
PPTX
Cisco IOS shellcode: All-in-one
PDF
iCloud keychain
PDF
Qt Rest Server
PDF
The Evolution of Async-Programming (SD 2.0, JavaScript)
PDF
The Ring programming language version 1.5.3 book - Part 87 of 184
PDF
Ieee 1149.1-2013-tutorial-ijtag
PPTX
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
PDF
Zn task - defcon russia 20
PDF
Taipei.py 2018 - Control device via ioctl from Python
Алексей Кутумов, Coroutines everywhere
System Calls
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
Network security Lab manual
Preparation for mit ose lab4
Operating system and embedded systems
The Magnificent Seven
Rich and Snappy Apps (No Scaling Required)
Breaking the wall
Extreme JavaScript Performance
Ugly code
Cisco IOS shellcode: All-in-one
iCloud keychain
Qt Rest Server
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Ring programming language version 1.5.3 book - Part 87 of 184
Ieee 1149.1-2013-tutorial-ijtag
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Zn task - defcon russia 20
Taipei.py 2018 - Control device via ioctl from Python
Ad

Similar to Aodv routing protocol code in ns2 (20)

DOCX
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docx
PPTX
Module 10: CDB Subscribers
PPTX
L5-Sockets.pptx
PPT
Basic socket programming
PDF
Multithreaded sockets c++11
PDF
Ip Subnet Design
PPT
Np unit2
KEY
Fosscon 2012 firewall workshop
PDF
PDF
PPT
INTRODUCTION TO SOCKETS IN COMPUTER NETWORKS DEPT OF CSE.ppt
PDF
Socket programming using C
PDF
Socket programming
PPT
Socket System Calls
PDF
BOOK - IBM zOS V1R10 communications server TCP / IP implementation volume 1 b...
PDF
Build Dynamic DNS server from scratch in C (Part1)
PDF
Protocol T50: Five months later... So what?
PPT
Sockets
ODP
Sysprog17
PPT
sockets_intro.ppt
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docx
Module 10: CDB Subscribers
L5-Sockets.pptx
Basic socket programming
Multithreaded sockets c++11
Ip Subnet Design
Np unit2
Fosscon 2012 firewall workshop
INTRODUCTION TO SOCKETS IN COMPUTER NETWORKS DEPT OF CSE.ppt
Socket programming using C
Socket programming
Socket System Calls
BOOK - IBM zOS V1R10 communications server TCP / IP implementation volume 1 b...
Build Dynamic DNS server from scratch in C (Part1)
Protocol T50: Five months later... So what?
Sockets
Sysprog17
sockets_intro.ppt
Ad

More from Prof Ansari (20)

PDF
Sci Hub New Domain
PDF
Sci Hub cc Not Working
PDF
basics of computer network
PDF
JAVA INTRODUCTION
PDF
Project Evaluation and Estimation in Software Development
PDF
Stepwise Project planning in software development
PDF
Database and Math Relations
PDF
Normalisation in Database management System (DBMS)
PDF
Entity-Relationship Data Model in DBMS
PDF
A Detail Database Architecture
PDF
INTRODUCTION TO Database Management System (DBMS)
PDF
Master thesis on Vehicular Ad hoc Networks (VANET)
PDF
Master Thesis on Vehicular Ad-hoc Network (VANET)
PDF
INTERFACING WITH INTEL 8251A (USART)
PDF
HOST AND NETWORK SECURITY by ThesisScientist.com
PDF
SYSTEM NETWORK ADMINISTRATIONS GOALS and TIPS
PDF
INTRODUCTION TO VISUAL BASICS
PDF
introduction to Blogging ppt
PDF
INTRODUCTION TO SOFTWARE ENGINEERING
PDF
Introduction to E-commerce
Sci Hub New Domain
Sci Hub cc Not Working
basics of computer network
JAVA INTRODUCTION
Project Evaluation and Estimation in Software Development
Stepwise Project planning in software development
Database and Math Relations
Normalisation in Database management System (DBMS)
Entity-Relationship Data Model in DBMS
A Detail Database Architecture
INTRODUCTION TO Database Management System (DBMS)
Master thesis on Vehicular Ad hoc Networks (VANET)
Master Thesis on Vehicular Ad-hoc Network (VANET)
INTERFACING WITH INTEL 8251A (USART)
HOST AND NETWORK SECURITY by ThesisScientist.com
SYSTEM NETWORK ADMINISTRATIONS GOALS and TIPS
INTRODUCTION TO VISUAL BASICS
introduction to Blogging ppt
INTRODUCTION TO SOFTWARE ENGINEERING
Introduction to E-commerce

Recently uploaded (20)

PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PPTX
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
PPTX
Sustainable Sites - Green Building Construction
PPTX
CH1 Production IntroductoryConcepts.pptx
PDF
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx
PPTX
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PPT
Project quality management in manufacturing
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PPTX
Construction Project Organization Group 2.pptx
PPT
Mechanical Engineering MATERIALS Selection
PDF
PPT on Performance Review to get promotions
PPTX
bas. eng. economics group 4 presentation 1.pptx
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PPTX
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
Embodied AI: Ushering in the Next Era of Intelligent Systems
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
Sustainable Sites - Green Building Construction
CH1 Production IntroductoryConcepts.pptx
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
Project quality management in manufacturing
Operating System & Kernel Study Guide-1 - converted.pdf
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Construction Project Organization Group 2.pptx
Mechanical Engineering MATERIALS Selection
PPT on Performance Review to get promotions
bas. eng. economics group 4 presentation 1.pptx
Model Code of Practice - Construction Work - 21102022 .pdf
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...

Aodv routing protocol code in ns2

  • 1. More Info Https://ThesisScientist.com Appendix A Implementation Coding of AODV #include "aodv_hello.h" #include "aodv_timeout.h" #include "aodv_rrep.h" #include "aodv_rreq.h" #include "routing_table.h" #include "timer_queue.h" #include "params.h" #include "aodv_socket.h" #include "defs.h" #include "debug.h" extern int unidir_hack, receive_n_hellos, hello_jittering, optimized_hellos; static struct timer hello_timer; #endif long NS_CLASS hello_jitter() { if (hello_jittering) { #ifdef NS_PORT return (long) (((float) Random::integer(RAND_MAX + 1) / RAND_MAX - 0.5) * JITTER_INTERVAL); #else return (long) (((float) random() / RAND_MAX - 0.5) * JITTER_INTERVAL); #endif } else return 0; } void NS_CLASS hello_start() { if (hello_timer.used) return; gettimeofday(&this_host.fwd_time, NULL); DEBUG(LOG_DEBUG, 0, "Starting to send HELLOs!"); timer_init(&hello_timer, &NS_CLASS hello_send, NULL); hello_send(NULL); } void NS_CLASS hello_stop() { DEBUG(LOG_DEBUG, 0, "No active forwarding routes - stopped sending HELLOs!"); timer_remove(&hello_timer); } void NS_CLASS hello_send(void *arg) { RREP *rrep;
  • 2. More Info Https://ThesisScientist.com AODV_ext *ext = NULL; u_int8_t flags = 0; struct in_addr dest; long time_diff, jitter; struct timeval now; int msg_size = RREP_SIZE; int i; gettimeofday(&now, NULL); if (optimized_hellos && timeval_diff(&now, &this_host.fwd_time) > ACTIVE_ROUTE_TIMEOUT) { hello_stop(); return; } time_diff = timeval_diff(&now, &this_host.bcast_time); jitter = hello_jitter(); if (time_diff >= HELLO_INTERVAL) { for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; #ifdef DEBUG_HELLO DEBUG(LOG_DEBUG, 0, "sending Hello to 255.255.255.255"); #endif rrep = rrep_create(flags, 0, 0, DEV_NR(i).ipaddr, this_host.seqno, DEV_NR(i).ipaddr, ALLOWED_HELLO_LOSS * HELLO_INTERVAL); /* Assemble a RREP extension which contain our neighbor set... */ if (unidir_hack) { int i; if (ext) ext = AODV_EXT_NEXT(ext); else ext = (AODV_ext *) ((char *) rrep + RREP_SIZE); ext->type = RREP_HELLO_NEIGHBOR_SET_EXT; ext->length = 0; for (i = 0; i < RT_TABLESIZE; i++) { list_t *pos; list_foreach(pos, &rt_tbl.tbl[i]) { rt_table_t *rt = (rt_table_t *) pos; if (rt->hello_timer.used) { #ifdef DEBUG_HELLO DEBUG(LOG_INFO, 0, "Adding %s to hello neighbor set ext", ip_to_str(rt->dest_addr)); #endif
  • 3. More Info Https://ThesisScientist.com memcpy(AODV_EXT_DATA(ext), &rt->dest_addr, sizeof(struct in_addr)); ext->length += sizeof(struct in_addr); } } } if (ext->length) msg_size = RREP_SIZE + AODV_EXT_SIZE(ext); } dest.s_addr = AODV_BROADCAST; aodv_socket_send((AODV_msg *) rrep, dest, msg_size, 1, &DEV_NR(i)); } timer_set_timeout(&hello_timer, HELLO_INTERVAL + jitter); } else { if (HELLO_INTERVAL - time_diff + jitter < 0) timer_set_timeout(&hello_timer, HELLO_INTERVAL - time_diff - jitter); else timer_set_timeout(&hello_timer, HELLO_INTERVAL - time_diff + jitter); } } /* Process a hello message */ void NS_CLASS hello_process(RREP * hello, int rreplen, unsigned int ifindex) { u_int32_t hello_seqno, timeout, hello_interval = HELLO_INTERVAL; u_int8_t state, flags = 0; struct in_addr ext_neighbor, hello_dest; rt_table_t *rt; AODV_ext *ext = NULL; int i; struct timeval now; gettimeofday(&now, NULL); hello_dest.s_addr = hello->dest_addr; hello_seqno = ntohl(hello->dest_seqno); rt = rt_table_find(hello_dest); if (rt) flags = rt->flags; if (unidir_hack) flags |= RT_UNIDIR; /* Check for hello interval extension: */ ext = (AODV_ext *) ((char *) hello + RREP_SIZE); while (rreplen > (int) RREP_SIZE) { switch (ext->type) { case RREP_HELLO_INTERVAL_EXT: if (ext->length == 4) {
  • 4. More Info Https://ThesisScientist.com memcpy(&hello_interval, AODV_EXT_DATA(ext), 4); hello_interval = ntohl(hello_interval); #ifdef DEBUG_HELLO DEBUG(LOG_INFO, 0, "Hello extension interval=%lu!", hello_interval); #endif } else alog(LOG_WARNING, 0, __FUNCTION__, "Bad hello interval extension!"); break; case RREP_HELLO_NEIGHBOR_SET_EXT: #ifdef DEBUG_HELLO DEBUG(LOG_INFO, 0, "RREP_HELLO_NEIGHBOR_SET_EXT"); #endif for (i = 0; i < ext->length; i = i + 4) { ext_neighbor.s_addr = *(in_addr_t *) ((char *) AODV_EXT_DATA(ext) + i); if (ext_neighbor.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) flags &= ~RT_UNIDIR; } break; default: alog(LOG_WARNING, 0, __FUNCTION__, "Bad extension!! type=%d, length=%d", ext->type, ext->length); ext = NULL; break; } if (ext == NULL) break; rreplen -= AODV_EXT_SIZE(ext); ext = AODV_EXT_NEXT(ext); } #ifdef DEBUG_HELLO DEBUG(LOG_DEBUG, 0, "rcvd HELLO from %s, seqno %lu", ip_to_str(hello_dest), hello_seqno); #endif /* This neighbor should only be valid after receiving 3 consecutive hello messages... */ if (receive_n_hellos) state = INVALID; else state = VALID; timeout = ALLOWED_HELLO_LOSS * hello_interval + ROUTE_TIMEOUT_SLACK; if (!rt) { rt = rt_table_insert(hello_dest, hello_dest, 1, hello_seqno, timeout, state, flags, ifindex);
  • 5. More Info Https://ThesisScientist.com if (flags & RT_UNIDIR) { DEBUG(LOG_INFO, 0, "%s new NEIGHBOR, link UNI-DIR", ip_to_str(rt->dest_addr)); } else { DEBUG(LOG_INFO, 0, "%s new NEIGHBOR!", ip_to_str(rt->dest_addr)); } rt->hello_cnt = 1; } else { if ((flags & RT_UNIDIR) && rt->state == VALID && rt->hcnt > 1) { goto hello_update; } if (receive_n_hellos && rt->hello_cnt < (receive_n_hellos - 1)) { if (timeval_diff(&now, &rt->last_hello_time) < (long) (hello_interval + hello_interval / 2)) rt->hello_cnt++; else rt->hello_cnt = 1; memcpy(&rt->last_hello_time, &now, sizeof(struct timeval)); return; } rt_table_update(rt, hello_dest, 1, hello_seqno, timeout, VALID, flags); } hello_update: hello_update_timeout(rt, &now, ALLOWED_HELLO_LOSS * hello_interval); return; } #define HELLO_DELAY 50 /* The extra time we should allow an hello message to take (due to processing) before assuming lost . */ NS_INLINE void NS_CLASS hello_update_timeout(rt_table_t * rt, struct timeval *now, long time) { timer_set_timeout(&rt->hello_timer, time + HELLO_DELAY); memcpy(&rt->last_hello_time, now, sizeof(struct timeval)); } extern int unidir_hack, optimized_hellos, llfeedback; #endif RREP *NS_CLASS rrep_create(u_int8_t flags, u_int8_t prefix, u_int8_t hcnt, struct in_addr dest_addr, u_int32_t dest_seqno, struct in_addr orig_addr, u_int32_t life)
  • 6. More Info Https://ThesisScientist.com { RREP *rrep; rrep = (RREP *) aodv_socket_new_msg(); rrep->type = AODV_RREP; rrep->res1 = 0; rrep->res2 = 0; rrep->prefix = prefix; rrep->hcnt = hcnt; rrep->dest_addr = dest_addr.s_addr; rrep->dest_seqno = htonl(dest_seqno); rrep->orig_addr = orig_addr.s_addr; rrep->lifetime = htonl(life); if (flags & RREP_REPAIR) rrep->r = 1; if (flags & RREP_ACK) rrep->a = 1; /* Don't print information about hello messages... */ #ifdef DEBUG_OUTPUT if (rrep->dest_addr != rrep->orig_addr) { DEBUG(LOG_DEBUG, 0, "Assembled RREP:"); log_pkt_fields((AODV_msg *) rrep); } #endif return rrep; } RREP_ack *NS_CLASS rrep_ack_create() { RREP_ack *rrep_ack; rrep_ack = (RREP_ack *) aodv_socket_new_msg(); rrep_ack->type = AODV_RREP_ACK; DEBUG(LOG_DEBUG, 0, "Assembled RREP_ack"); return rrep_ack; } void NS_CLASS rrep_ack_process(RREP_ack * rrep_ack, int rrep_acklen, struct in_addr ip_src, struct in_addr ip_dst) { rt_table_t *rt; rt = rt_table_find(ip_src); if (rt == NULL) { DEBUG(LOG_WARNING, 0, "No RREP_ACK expected for %s", ip_to_str(ip_src)); return; } DEBUG(LOG_DEBUG, 0, "Received RREP_ACK from %s", ip_to_str(ip_src));
  • 7. More Info Https://ThesisScientist.com /* Remove unexpired timer for this RREP_ACK */ timer_remove(&rt->ack_timer); } AODV_ext *NS_CLASS rrep_add_ext(RREP * rrep, int type, unsigned int offset, int len, char *data) { AODV_ext *ext = NULL; if (offset < RREP_SIZE) return NULL; ext = (AODV_ext *) ((char *) rrep + offset); ext->type = type; ext->length = len; memcpy(AODV_EXT_DATA(ext), data, len); return ext; } void NS_CLASS rrep_send(RREP * rrep, rt_table_t * rev_rt, rt_table_t * fwd_rt, int size) { u_int8_t rrep_flags = 0; struct in_addr dest; if (!rev_rt) { DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!"); return; } dest.s_addr = rrep->dest_addr; /* Check if we should request a RREP-ACK */ if ((rev_rt->state == VALID && rev_rt->flags & RT_UNIDIR) || (rev_rt->hcnt == 1 && unidir_hack)) { rt_table_t *neighbor = rt_table_find(rev_rt->next_hop); if (neighbor && neighbor->state == VALID && !neighbor->ack_timer.used) { rrep_flags |= RREP_ACK; neighbor->flags |= RT_UNIDIR; timer_remove(&neighbor->hello_timer); neighbor_link_break(neighbor); DEBUG(LOG_DEBUG, 0, "Link to %s is unidirectional!", ip_to_str(neighbor->dest_addr)); timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT); } }
  • 8. More Info Https://ThesisScientist.com DEBUG(LOG_DEBUG, 0, "Sending RREP to next hop %s about %s->%s", ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr), ip_to_str(dest)); aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, MAXTTL, &DEV_IFINDEX(rev_rt->ifindex)); /* Update precursor lists */ if (fwd_rt) { precursor_add(fwd_rt, rev_rt->next_hop); precursor_add(rev_rt, fwd_rt->next_hop); } if (!llfeedback && optimized_hellos) hello_start(); } void NS_CLASS rrep_forward(RREP * rrep, int size, rt_table_t * rev_rt, rt_table_t * fwd_rt, int ttl) { /* Sanity checks... */ if (!fwd_rt || !rev_rt) { DEBUG(LOG_WARNING, 0, "Could not forward RREP because of NULL route!"); return; } if (!rrep) { DEBUG(LOG_WARNING, 0, "No RREP to forward!"); return; } DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s", ip_to_str(rev_rt->next_hop)); rt_table_t *neighbor; if (rev_rt->dest_addr.s_addr != rev_rt->next_hop.s_addr) neighbor = rt_table_find(rev_rt->next_hop); else neighbor = rev_rt; if (neighbor && !neighbor->ack_timer.used) { rrep->a = 1; neighbor->flags |= RT_UNIDIR; timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT); } } rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size); rrep->hcnt = fwd_rt->hcnt; /* Update the hopcount */ aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl, &DEV_IFINDEX(rev_rt->ifindex));
  • 9. More Info Https://ThesisScientist.com precursor_add(fwd_rt, rev_rt->next_hop); precursor_add(rev_rt, fwd_rt->next_hop); rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); } void NS_CLASS rrep_process(RREP * rrep, int rreplen, struct in_addr ip_src, struct in_addr ip_dst, int ip_ttl, unsigned int ifindex) { u_int32_t rrep_lifetime, rrep_seqno, rrep_new_hcnt; u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0; rt_table_t *fwd_rt, *rev_rt; AODV_ext *ext; unsigned int extlen = 0; int rt_flags = 0; struct in_addr rrep_dest, rrep_orig; #ifdef CONFIG_GATEWAY struct in_addr inet_dest_addr; int inet_rrep = 0; #endif /* Convert to correct byte order on affeected fields: */ rrep_dest.s_addr = rrep->dest_addr; rrep_orig.s_addr = rrep->orig_addr; rrep_seqno = ntohl(rrep->dest_seqno); rrep_lifetime = ntohl(rrep->lifetime); /* Increment RREP hop count to account for intermediate node... */ rrep_new_hcnt = rrep->hcnt + 1; if (rreplen < (int) RREP_SIZE) { alog(LOG_WARNING, 0, __FUNCTION__, "IP data field too short (%u bytes)" " from %s to %s", rreplen, ip_to_str(ip_src), ip_to_str(ip_dst)); return; } /* Ignore messages which aim to a create a route to one self */ if (rrep_dest.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) return; DEBUG(LOG_DEBUG, 0, "from %s about %s->%s", ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest)); #ifdef DEBUG_OUTPUT log_pkt_fields((AODV_msg *) rrep); #endif /* Determine whether there are any extensions */ ext = (AODV_ext *) ((char *) rrep + RREP_SIZE); while ((rreplen - extlen) > RREP_SIZE) { switch (ext->type) { case RREP_EXT: DEBUG(LOG_INFO, 0, "RREP include EXTENSION");
  • 10. More Info Https://ThesisScientist.com /* Do something here */ break; #ifdef CONFIG_GATEWAY case RREP_INET_DEST_EXT: if (ext->length == sizeof(u_int32_t)) { memcpy(&inet_dest_addr, AODV_EXT_DATA(ext), ext->length); DEBUG(LOG_DEBUG, 0, "RREP_INET_DEST_EXT: <%s>", ip_to_str(inet_dest_addr)); /* This was a RREP from a gateway */ rt_flags |= RT_GATEWAY; inet_rrep = 1; break; } #endif default: alog(LOG_WARNING, 0, __FUNCTION__, "Unknown or bad extension %d", ext->type); break; } extlen += AODV_EXT_SIZE(ext); ext = AODV_EXT_NEXT(ext); } fwd_rt = rt_table_find(rrep_dest); rev_rt = rt_table_find(rrep_orig); if (!fwd_rt) { /* We didn't have an existing entry, so we insert a new one. */ fwd_rt = rt_table_insert(rrep_dest, ip_src, rrep_new_hcnt, rrep_seqno, rrep_lifetime, VALID, rt_flags, ifindex); } else if (fwd_rt->dest_seqno == 0 || (int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno || (rrep_seqno == fwd_rt->dest_seqno && (fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR || rrep_new_hcnt < fwd_rt->hcnt))) { pre_repair_hcnt = fwd_rt->hcnt; pre_repair_flags = fwd_rt->flags; fwd_rt = rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno, rrep_lifetime, VALID, rt_flags | fwd_rt->flags); } else { if (fwd_rt->hcnt > 1) { DEBUG(LOG_DEBUG, 0, "Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld", fwd_rt->hcnt, fwd_rt->dest_seqno); } return; } RREP_ack *rrep_ack; rrep_ack = rrep_ack_create();
  • 11. More Info Https://ThesisScientist.com aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop, NEXT_HOP_WAIT, MAXTTL, &DEV_IFINDEX(fwd_rt->ifindex)); /* Remove RREP_ACK flag... */ rrep->a = 0; } if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) { #ifdef CONFIG_GATEWAY if (inet_rrep) { rt_table_t *inet_rt; inet_rt = rt_table_find(inet_dest_addr); if (!inet_rt) rt_table_insert(inet_dest_addr, rrep_dest, rrep_new_hcnt, 0, rrep_lifetime, VALID, RT_INET_DEST, ifindex); else if (inet_rt->state == INVALID || rrep_new_hcnt < inet_rt->hcnt) { rt_table_update(inet_rt, rrep_dest, rrep_new_hcnt, 0, rrep_lifetime, VALID, RT_INET_DEST | inet_rt->flags); } else { DEBUG(LOG_DEBUG, 0, "INET Response, but no update %s", ip_to_str(inet_dest_addr)); } } #endif if (pre_repair_flags & RT_REPAIR) { if (fwd_rt->hcnt > pre_repair_hcnt) { RERR *rerr; u_int8_t rerr_flags = 0; struct in_addr dest; dest.s_addr = AODV_BROADCAST; rerr_flags |= RERR_NODELETE; rerr = rerr_create(rerr_flags, fwd_rt->dest_addr, fwd_rt->dest_seqno); if (fwd_rt->nprec) aodv_socket_send((AODV_msg *) rerr, dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(fwd_rt->ifindex)); } } } else { if (rev_rt && rev_rt->state == VALID) { rrep_forward(rrep, rreplen, rev_rt, fwd_rt, --ip_ttl); } else { DEBUG(LOG_DEBUG, 0, "Could not forward RREP - NO ROUTE!!!"); } } if (!llfeedback && optimized_hellos) hello_start(); }
  • 12. More Info Https://ThesisScientist.com int rrep_add_hello_ext(RREP * rrep, int offset, u_int32_t interval) { AODV_ext *ext; ext = (AODV_ext *) ((char *) rrep + RREP_SIZE + offset); ext->type = RREP_HELLO_INTERVAL_EXT; ext->length = sizeof(interval); memcpy(AODV_EXT_DATA(ext), &interval, sizeof(interval)); return (offset + AODV_EXT_SIZE(ext)); } endif /* NS_PORT */ #ifndef NS_PORT #define SO_RECVBUF_SIZE 256*1024 static char recv_buf[RECV_BUF_SIZE]; static char send_buf[SEND_BUF_SIZE]; extern int wait_on_reboot, hello_qual_threshold, ratelimit; static void aodv_socket_read(int fd); static struct cmsghdr *__cmsg_nxthdr_fix(void *__ctl, size_t __size, struct cmsghdr *__cmsg) { struct cmsghdr *__ptr; __ptr = (struct cmsghdr *) (((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len)); if ((unsigned long) ((char *) (__ptr + 1) - (char *) __ctl) > __size) return NULL; return __ptr; } struct cmsghdr *cmsg_nxthdr_fix(struct msghdr *__msg, struct cmsghdr *__cmsg) { return __cmsg_nxthdr_fix(__msg->msg_control, __msg->msg_controllen, __cmsg); } #endif /* NS_PORT */ void NS_CLASS aodv_socket_init() { #ifndef NS_PORT struct sockaddr_in aodv_addr; struct ifreq ifr; int i, retval = 0; int on = 1; int tos = IPTOS_LOWDELAY; int bufsize = SO_RECVBUF_SIZE; socklen_t optlen = sizeof(bufsize);
  • 13. More Info Https://ThesisScientist.com /* Create a UDP socket */ if (this_host.nif == 0) { fprintf(stderr, "No interfaces configuredn"); exit(-1); } /* Open a socket for every AODV enabled interface */ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; /* AODV socket */ DEV_NR(i).sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (DEV_NR(i).sock < 0) { perror(""); exit(-1); } #ifdef CONFIG_GATEWAY /* Data packet send socket */ DEV_NR(i).psock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); if (DEV_NR(i).psock < 0) { perror(""); exit(-1); } #endif /* Bind the socket to the AODV port number */ memset(&aodv_addr, 0, sizeof(aodv_addr)); aodv_addr.sin_family = AF_INET; aodv_addr.sin_port = htons(AODV_PORT); aodv_addr.sin_addr.s_addr = htonl(INADDR_ANY); retval = bind(DEV_NR(i).sock, (struct sockaddr *) &aodv_addr, sizeof(struct sockaddr)); if (retval < 0) { perror("Bind failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) { perror("SO_BROADCAST failed "); exit(-1); } memset(&ifr, 0, sizeof(struct ifreq)); strcpy(ifr.ifr_name, DEV_NR(i).ifname); if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { fprintf(stderr, "SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); }
  • 14. More Info Https://ThesisScientist.com if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_PRIORITY, &tos, sizeof(int)) < 0) { perror("Setsockopt SO_PRIORITY failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_RECVTTL, &on, sizeof(int)) < 0) { perror("Setsockopt IP_RECVTTL failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_PKTINFO, &on, sizeof(int)) < 0) { perror("Setsockopt IP_PKTINFO failed "); exit(-1); } #ifdef CONFIG_GATEWAY if (setsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { fprintf(stderr, "SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); } bufsize = 4 * 65535; if (setsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, optlen) < 0) { DEBUG(LOG_NOTICE, 0, "Could not set send socket buffer size"); } if (getsockopt(DEV_NR(i).psock, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, &optlen) == 0) { alog(LOG_NOTICE, 0, __FUNCTION__, "RAW send socket buffer size set to %d", bufsize); } #endif /* Set max allowable receive buffer size... */ for (;; bufsize -= 1024) { if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, optlen) == 0) { alog(LOG_NOTICE, 0, __FUNCTION__, "Receive buffer size set to %d", bufsize); break; } if (bufsize < RECV_BUF_SIZE) { alog(LOG_ERR, 0, __FUNCTION__, "Could not set receive buffer size"); exit(-1); } } retval = attach_callback_func(DEV_NR(i).sock, aodv_socket_read); if (retval < 0) {
  • 15. More Info Https://ThesisScientist.com perror("register input handler failed "); exit(-1); } } #endif /* NS_PORT */ num_rreq = 0; num_rerr = 0; } void NS_CLASS aodv_socket_process_packet(AODV_msg * aodv_msg, int len, struct in_addr src, struct in_addr dst, int ttl, unsigned int ifindex) { /* If this was a HELLO message... Process as HELLO. */ if ((aodv_msg->type == AODV_RREP && ttl == 1 && dst.s_addr == AODV_BROADCAST)) { hello_process((RREP *) aodv_msg, len, ifindex); return; } /* Make sure we add/update neighbors */ neighbor_add(aodv_msg, src, ifindex); switch (aodv_msg->type) { case AODV_RREQ: rreq_process((RREQ *) aodv_msg, len, src, dst, ttl, ifindex); break; case AODV_RREP: DEBUG(LOG_DEBUG, 0, "Received RREP"); rrep_process((RREP *) aodv_msg, len, src, dst, ttl, ifindex); break; case AODV_RERR: DEBUG(LOG_DEBUG, 0, "Received RERR"); rerr_process((RERR *) aodv_msg, len, src, dst); break; case AODV_RREP_ACK: DEBUG(LOG_DEBUG, 0, "Received RREP_ACK"); rrep_ack_process((RREP_ack *) aodv_msg, len, src, dst); break; default: alog(LOG_WARNING, 0, __FUNCTION__, "Unknown msg type %u rcvd from %s to %s", aodv_msg->type, ip_to_str(src), ip_to_str(dst)); } } #ifdef NS_PORT void NS_CLASS recvAODVUUPacket(Packet * p) { int len, i, ttl = 0; struct in_addr src, dst; struct hdr_cmn *ch = HDR_CMN(p);
  • 16. More Info Https://ThesisScientist.com struct hdr_ip *ih = HDR_IP(p); hdr_aodvuu *ah = HDR_AODVUU(p); src.s_addr = ih->saddr(); dst.s_addr = ih->daddr(); len = ch->size() - IP_HDR_LEN; ttl = ih->ttl(); AODV_msg *aodv_msg = (AODV_msg *) recv_buf; /* Only handle AODVUU packets */ assert(ch->ptype() == PT_AODVUU); /* Only process incoming packets */ assert(ch->direction() == hdr_cmn::UP); /* Copy message to receive buffer */ memcpy(recv_buf, ah, RECV_BUF_SIZE); /* Deallocate packet, we have the information we need... */ Packet::free(p); /* Ignore messages generated locally */ for (i = 0; i < MAX_NR_INTERFACES; i++) if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(struct in_addr)) == 0) return; aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, NS_IFINDEX); } #else static void aodv_socket_read(int fd) { struct in_addr src, dst; int i, len, ttl = -1; AODV_msg *aodv_msg; struct dev_info *dev; struct msghdr msgh; struct cmsghdr *cmsg; struct iovec iov; char ctrlbuf[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct in_pktinfo))]; struct sockaddr_in src_addr; dst.s_addr = -1; iov.iov_base = recv_buf; iov.iov_len = RECV_BUF_SIZE; msgh.msg_name = &src_addr; msgh.msg_namelen = sizeof(src_addr); msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_control = ctrlbuf; msgh.msg_controllen = sizeof(ctrlbuf);
  • 17. More Info Https://ThesisScientist.com len = recvmsg(fd, &msgh, 0); if (len < 0) { alog(LOG_WARNING, 0, __FUNCTION__, "receive ERROR len=%d!", len); return; } src.s_addr = src_addr.sin_addr.s_addr; /* Get the ttl and destination address from the control message */ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR_FIX(&msgh, cmsg)) { if (cmsg->cmsg_level == SOL_IP) { switch (cmsg->cmsg_type) { case IP_TTL: ttl = *(CMSG_DATA(cmsg)); break; case IP_PKTINFO: { struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsg); dst.s_addr = pi->ipi_addr.s_addr; } } } } if (ttl < 0) { DEBUG(LOG_DEBUG, 0, "No TTL, packet ignored!"); return; } /* Ignore messages generated locally */ for (i = 0; i < MAX_NR_INTERFACES; i++) if (this_host.devs[i].enabled && memcmp(&src, &this_host.devs[i].ipaddr, sizeof(struct in_addr)) == 0) return; aodv_msg = (AODV_msg *) recv_buf; dev = devfromsock(fd); if (!dev) { DEBUG(LOG_ERR, 0, "Could not get device info!n"); return; } aodv_socket_process_packet(aodv_msg, len, src, dst, ttl, dev->ifindex); } #endif /* NS_PORT */ void NS_CLASS aodv_socket_send(AODV_msg * aodv_msg, struct in_addr dst, int len, u_int8_t ttl, struct dev_info *dev) { int retval = 0; struct timeval now;
  • 18. More Info Https://ThesisScientist.com /* Rate limit stuff: */ #ifndef NS_PORT struct sockaddr_in dst_addr; if (wait_on_reboot && aodv_msg->type == AODV_RREP) return; memset(&dst_addr, 0, sizeof(dst_addr)); dst_addr.sin_family = AF_INET; dst_addr.sin_addr = dst; dst_addr.sin_port = htons(AODV_PORT); /* Set ttl */ if (setsockopt(dev->sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { alog(LOG_WARNING, 0, __FUNCTION__, "ERROR setting ttl!"); return; } #else Packet *p = allocpkt(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); hdr_aodvuu *ah = HDR_AODVUU(p); // Clear AODVUU part of packet memset(ah, '0', ah->size()); // Copy message contents into packet memcpy(ah, aodv_msg, len); // Set common header fields ch->ptype() = PT_AODVUU; ch->direction() = hdr_cmn::DOWN; ch->size() += len + IP_HDR_LEN; ch->iface() = -2; ch->error() = 0; ch->prev_hop_ = (nsaddr_t) dev->ipaddr.s_addr; // Set IP header fields ih->saddr() = (nsaddr_t) dev->ipaddr.s_addr; ih->daddr() = (nsaddr_t) dst.s_addr; ih->ttl() = ttl; // Note: Port number for routing agents, not AODV port number! ih->sport() = RT_PORT; ih->dport() = RT_PORT; // Fake success retval = len; #endif gettimeofday(&now, NULL); switch (aodv_msg->type) { case AODV_RREQ:
  • 19. More Info Https://ThesisScientist.com if (num_rreq == (RREQ_RATELIMIT - 1)) { if (timeval_diff(&now, &rreq_ratel[0]) < 1000) { DEBUG(LOG_DEBUG, 0, "RATELIMIT: Dropping RREQ %ld ms", timeval_diff(&now, &rreq_ratel[0])); #ifdef NS_PORT Packet::free(p); #endif return; } else { memmove(rreq_ratel, &rreq_ratel[1], sizeof(struct timeval) * (num_rreq - 1)); memcpy(&rreq_ratel[num_rreq - 1], &now, sizeof(struct timeval)); } } else { memcpy(&rreq_ratel[num_rreq], &now, sizeof(struct timeval)); num_rreq++; } break; case AODV_RERR: if (num_rerr == (RERR_RATELIMIT - 1)) { if (timeval_diff(&now, &rerr_ratel[0]) < 1000) { DEBUG(LOG_DEBUG, 0, "RATELIMIT: Dropping RERR %ld ms", timeval_diff(&now, &rerr_ratel[0])); #ifdef NS_PORT Packet::free(p); #endif return; } else { memmove(rerr_ratel, &rerr_ratel[1], sizeof(struct timeval) * (num_rerr - 1)); memcpy(&rerr_ratel[num_rerr - 1], &now, sizeof(struct timeval)); } } else { memcpy(&rerr_ratel[num_rerr], &now, sizeof(struct timeval)); num_rerr++; } break; } } if (dst.s_addr == AODV_BROADCAST) { gettimeofday(&this_host.bcast_time, NULL); #ifdef NS_PORT ch->addr_type() = NS_AF_NONE; sendPacket(p, dst, 0.0); #else retval = sendto(dev->sock, send_buf, len, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); if (retval < 0) {
  • 20. More Info Https://ThesisScientist.com alog(LOG_WARNING, errno, __FUNCTION__, "Failed send to bc %s", ip_to_str(dst)); return; } #endif } else { #ifdef NS_PORT ch->addr_type() = NS_AF_INET; /* We trust the decision of next hop for all AODV messages... */ if (dst.s_addr == AODV_BROADCAST) sendPacket(p, dst, 0.001 * Random::uniform()); else sendPacket(p, dst, 0.0); #else retval = sendto(dev->sock, send_buf, len, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); if (retval < 0) { alog(LOG_WARNING, errno, __FUNCTION__, "Failed send to %s", ip_to_str(dst)); return; } #endif } /* Do not print hello msgs... */ if (!(aodv_msg->type == AODV_RREP && (dst.s_addr == AODV_BROADCAST))) DEBUG(LOG_INFO, 0, "AODV msg to %s ttl=%d size=%u", ip_to_str(dst), ttl, retval, len); return; } AODV_msg *NS_CLASS aodv_socket_new_msg(void) { memset(send_buf, '0', SEND_BUF_SIZE); return (AODV_msg *) (send_buf); } AODV_msg *NS_CLASS aodv_socket_queue_msg(AODV_msg * aodv_msg, int size) { memcpy((char *) send_buf, aodv_msg, size); return (AODV_msg *) send_buf; } void aodv_socket_cleanup(void) { #ifndef NS_PORT int i; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled)
  • 21. More Info Https://ThesisScientist.com continue; close(DEV_NR(i).sock); } #endif /* NS_PORT */ } oid NS_CLASS rt_table_init() { int i; rt_tbl.num_entries = 0; rt_tbl.num_active = 0; /* We do a for loop here... NS does not like us to use memset() */ for (i = 0; i < RT_TABLESIZE; i++) { INIT_LIST_HEAD(&rt_tbl.tbl[i]); } } void NS_CLASS rt_table_destroy() { int i; list_t *tmp = NULL, *pos = NULL; for (i = 0; i < RT_TABLESIZE; i++) { list_foreach_safe(pos, tmp, &rt_tbl.tbl[i]) { rt_table_t *rt = (rt_table_t *) pos; rt_table_delete(rt); } } } /* Calculate a hash value and table index given a key... */ unsigned int hashing(struct in_addr *addr, hash_value * hash) { /* *hash = (*addr & 0x7fffffff); */ *hash = (hash_value) addr->s_addr; return (*hash & RT_TABLEMASK); } rt_table_t *NS_CLASS rt_table_insert(struct in_addr dest_addr, struct in_addr next, u_int8_t hops, u_int32_t seqno, u_int32_t life, u_int8_t state, u_int16_t flags, unsigned int ifindex) { hash_value hash; unsigned int index; list_t *pos; rt_table_t *rt; struct in_addr nm; nm.s_addr = 0; /* Calculate hash key */
  • 22. More Info Https://ThesisScientist.com index = hashing(&dest_addr, &hash); /* Check if we already have an entry for dest_addr */ list_foreach(pos, &rt_tbl.tbl[index]) { rt = (rt_table_t *) pos; if (memcmp(&rt->dest_addr, &dest_addr, sizeof(struct in_addr)) == 0) { DEBUG(LOG_INFO, 0, "%s already exist in routing table!", ip_to_str(dest_addr)); return NULL; } } if ((rt = (rt_table_t *) malloc(sizeof(rt_table_t))) == NULL) { fprintf(stderr, "Malloc failed!n"); exit(-1); } memset(rt, 0, sizeof(rt_table_t)); rt->dest_addr = dest_addr; rt->next_hop = next; rt->dest_seqno = seqno; rt->flags = flags; rt->hcnt = hops; rt->ifindex = ifindex; rt->hash = hash; rt->state = state; timer_init(&rt->rt_timer, &NS_CLASS route_expire_timeout, rt); timer_init(&rt->ack_timer, &NS_CLASS rrep_ack_timeout, rt); timer_init(&rt->hello_timer, &NS_CLASS hello_timeout, rt); rt->last_hello_time.tv_sec = 0; rt->last_hello_time.tv_usec = 0; rt->hello_cnt = 0; rt->nprec = 0; INIT_LIST_HEAD(&rt->precursors); /* Insert first in bucket... */ rt_tbl.num_entries++; DEBUG(LOG_INFO, 0, "Inserting %s (bucket %d) next hop %s", ip_to_str(dest_addr), index, ip_to_str(next)); list_add(&rt_tbl.tbl[index], &rt->l); if (state == INVALID) { if (flags & RT_REPAIR) { rt->rt_timer.handler = &NS_CLASS local_repair_timeout;
  • 23. More Info Https://ThesisScientist.com life = ACTIVE_ROUTE_TIMEOUT; } else { rt->rt_timer.handler = &NS_CLASS route_delete_timeout; life = DELETE_PERIOD; } } else { rt_tbl.num_active++; #ifndef NS_PORT nl_send_add_route_msg(dest_addr, next, hops, life, flags, ifindex); #endif } #ifdef CONFIG_GATEWAY_DISABLE if (rt->flags & RT_GATEWAY) rt_table_update_inet_rt(rt, life); #endif //#ifdef NS_PORT DEBUG(LOG_INFO, 0, "New timer for %s, life=%d", ip_to_str(rt->dest_addr), life); if (life != 0) timer_set_timeout(&rt->rt_timer, life); //#endif /* In case there are buffered packets for this destination, we * send them on the new route. */ if (rt->state == VALID && seek_list_remove(seek_list_find(dest_addr))) { #ifdef NS_PORT if (rt->flags & RT_INET_DEST) packet_queue_set_verdict(dest_addr, PQ_ENC_SEND); else packet_queue_set_verdict(dest_addr, PQ_SEND); #endif } return rt; } rt_table_t *NS_CLASS rt_table_update(rt_table_t * rt, struct in_addr next, u_int8_t hops, u_int32_t seqno, u_int32_t lifetime, u_int8_t state, u_int16_t flags) { struct in_addr nm; nm.s_addr = 0; if (rt->state == INVALID && state == VALID) { rt_tbl.num_active++; if (rt->flags & RT_REPAIR) flags &= ~RT_REPAIR; #ifndef NS_PORT
  • 24. More Info Https://ThesisScientist.com nl_send_add_route_msg(rt->dest_addr, next, hops, lifetime, flags, rt->ifindex); #endif } else if (rt->next_hop.s_addr != 0 && rt->next_hop.s_addr != next.s_addr) { DEBUG(LOG_INFO, 0, "rt->next_hop=%s, new_next_hop=%s", ip_to_str(rt->next_hop), ip_to_str(next)); #ifndef NS_PORT nl_send_add_route_msg(rt->dest_addr, next, hops, lifetime, flags, rt->ifindex); #endif } if (hops > 1 && rt->hcnt == 1) { rt->last_hello_time.tv_sec = 0; rt->last_hello_time.tv_usec = 0; rt->hello_cnt = 0; timer_remove(&rt->hello_timer); neighbor_link_break(rt); } rt->flags = flags; rt->dest_seqno = seqno; rt->next_hop = next; rt->hcnt = hops; #ifdef CONFIG_GATEWAY if (rt->flags & RT_GATEWAY) rt_table_update_inet_rt(rt, lifetime); #endif //#ifdef NS_PORT rt->rt_timer.handler = &NS_CLASS route_expire_timeout; if (!(rt->flags & RT_INET_DEST)) rt_table_update_timeout(rt, lifetime); //#endif /* Finally, mark as VALID */ rt->state = state; if (rt->state == VALID && seek_list_remove(seek_list_find(rt->dest_addr))) { #ifdef NS_PORT if (rt->flags & RT_INET_DEST) packet_queue_set_verdict(rt->dest_addr, PQ_ENC_SEND); else packet_queue_set_verdict(rt->dest_addr, PQ_SEND); #endif } return rt;
  • 25. More Info Https://ThesisScientist.com } NS_INLINE rt_table_t *NS_CLASS rt_table_update_timeout(rt_table_t * rt, u_int32_t lifetime) { struct timeval new_timeout; if (!rt) return NULL; if (rt->state == VALID) { gettimeofday(&new_timeout, NULL); timeval_add_msec(&new_timeout, lifetime); if (timeval_diff(&rt->rt_timer.timeout, &new_timeout) < 0) timer_set_timeout(&rt->rt_timer, lifetime); } else timer_set_timeout(&rt->rt_timer, lifetime); return rt; } /* Update route timeouts in response to an incoming or outgoing data packet. */ void NS_CLASS rt_table_update_route_timeouts(rt_table_t * fwd_rt, rt_table_t * rev_rt) { rt_table_t *next_hop_rt = NULL; if (fwd_rt && fwd_rt->state == VALID) { if (llfeedback || fwd_rt->flags & RT_INET_DEST || fwd_rt->hcnt != 1 || fwd_rt->hello_timer.used) rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(fwd_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr && (llfeedback || fwd_rt->hello_timer.used)) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } if (rev_rt && rev_rt->state == VALID) { if (llfeedback || rev_rt->hcnt != 1 || rev_rt->hello_timer.used) rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(rev_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && rev_rt && next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr &&
  • 26. More Info Https://ThesisScientist.com (llfeedback || rev_rt->hello_timer.used)) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); rt_table_t *NS_CLASS rt_table_find(struct in_addr dest_addr) { hash_value hash; unsigned int index; list_t *pos; if (rt_tbl.num_entries == 0) return NULL; /* Calculate index */ index = hashing(&dest_addr, &hash); /* Handle collisions: */ list_foreach(pos, &rt_tbl.tbl[index]) { rt_table_t *rt = (rt_table_t *) pos; if (rt->hash != hash) continue; if (memcmp(&dest_addr, &rt->dest_addr, sizeof(struct in_addr)) == 0) return rt; } return NULL; } rt_table_t *NS_CLASS rt_table_find_gateway() { rt_table_t *gw = NULL; int i; for (i = 0; i < RT_TABLESIZE; i++) { list_t *pos; list_foreach(pos, &rt_tbl.tbl[i]) { rt_table_t *rt = (rt_table_t *) pos; if (rt->flags & RT_GATEWAY && rt->state == VALID) { if (!gw || rt->hcnt < gw->hcnt) gw = rt; } } } return gw; } #ifdef CONFIG_GATEWAY int NS_CLASS rt_table_update_inet_rt(rt_table_t * gw, u_int32_t life) { int n = 0;
  • 27. More Info Https://ThesisScientist.com int i; if (!gw) return -1; for (i = 0; i < RT_TABLESIZE; i++) { list_t *pos; list_foreach(pos, &rt_tbl.tbl[i]) { rt_table_t *rt = (rt_table_t *) pos; if (rt->flags & RT_INET_DEST && rt->state == VALID) { rt_table_update(rt, gw->dest_addr, gw->hcnt, 0, life, VALID, rt->flags); n++; } } } return n; } #endif /* CONFIG_GATEWAY_DISABLED */ /* Route expiry and Deletion. */ int NS_CLASS rt_table_invalidate(rt_table_t * rt) { struct timeval now; gettimeofday(&now, NULL); if (rt == NULL) return -1; /* If the route is already invalidated, do nothing... */ if (rt->state == INVALID) { DEBUG(LOG_DEBUG, 0, "Route %s already invalidated!!!", ip_to_str(rt->dest_addr)); return -1; } if (rt->hello_timer.used) { DEBUG(LOG_DEBUG, 0, "last HELLO: %ld", timeval_diff(&now, &rt->last_hello_time)); } /* Remove any pending, but now obsolete timers. */ timer_remove(&rt->rt_timer); timer_remove(&rt->hello_timer); timer_remove(&rt->ack_timer); /* Mark the route as invalid */ rt->state = INVALID; rt_tbl.num_active--; rt->hello_cnt = 0; /* When the lifetime of a route entry expires, increase the sequence number for that entry. */
  • 28. More Info Https://ThesisScientist.com seqno_incr(rt->dest_seqno); rt->last_hello_time.tv_sec = 0; rt->last_hello_time.tv_usec = 0; #ifndef NS_PORT nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt); #endif #ifdef CONFIG_GATEWAY if (rt->flags & RT_GATEWAY) { int i; rt_table_t *gw = rt_table_find_gateway(); for (i = 0; i < RT_TABLESIZE; i++) { list_t *pos; list_foreach(pos, &rt_tbl.tbl[i]) { rt_table_t *rt2 = (rt_table_t *) pos; if (rt2->state == VALID && (rt2->flags & RT_INET_DEST) && (rt2->next_hop.s_addr == rt->dest_addr.s_addr)) { if (0) { DEBUG(LOG_DEBUG, 0, "Invalidated GW %s but found new GW %s for %s", ip_to_str(rt->dest_addr), ip_to_str(gw->dest_addr), ip_to_str(rt2-> dest_addr)); rt_table_update(rt2, gw->dest_addr, gw->hcnt, 0, timeval_diff (&rt->rt_timer. timeout, &now), VALID, rt2->flags); } else { rt_table_invalidate(rt2); precursor_list_destroy(rt2); } } } } } #endif if (rt->flags & RT_REPAIR) { /* Set a timeout for the repair */ rt->rt_timer.handler = &NS_CLASS local_repair_timeout;
  • 29. More Info Https://ThesisScientist.com timer_set_timeout(&rt->rt_timer, ACTIVE_ROUTE_TIMEOUT); DEBUG(LOG_DEBUG, 0, "%s kept for repairs during %u msecs", ip_to_str(rt->dest_addr), ACTIVE_ROUTE_TIMEOUT); } else { /* Schedule a deletion timer */ rt->rt_timer.handler = &NS_CLASS route_delete_timeout; timer_set_timeout(&rt->rt_timer, DELETE_PERIOD); DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs", ip_to_str(rt->dest_addr), DELETE_PERIOD); } return 0; } void NS_CLASS rt_table_delete(rt_table_t * rt) { if (!rt) { DEBUG(LOG_ERR, 0, "No route entry to delete"); return; } list_detach(&rt->l); precursor_list_destroy(rt); if (rt->state == VALID) { #ifndef NS_PORT nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt); #endif rt_tbl.num_active--; } /* Make sure timers are removed... */ timer_remove(&rt->rt_timer); timer_remove(&rt->hello_timer); timer_remove(&rt->ack_timer); rt_tbl.num_entries--; free(rt); return; } void NS_CLASS precursor_add(rt_table_t * rt, struct in_addr addr) { precursor_t *pr; list_t *pos; /* Sanity check */ if (!rt) return; list_foreach(pos, &rt->precursors) {
  • 30. More Info Https://ThesisScientist.com pr = (precursor_t *) pos; if (pr->neighbor.s_addr == addr.s_addr) return; } if ((pr = (precursor_t *) malloc(sizeof(precursor_t))) == NULL) { perror("Could not allocate memory for precursor node!!n"); exit(-1); } DEBUG(LOG_INFO, 0, "Adding precursor %s to rte %s", ip_to_str(addr), ip_to_str(rt->dest_addr)); pr->neighbor.s_addr = addr.s_addr; /* Insert in precursors list */ list_add(&rt->precursors, &pr->l); rt->nprec++; return; } void NS_CLASS precursor_remove(rt_table_t * rt, struct in_addr addr) { list_t *pos; /* Sanity check */ if (!rt) return; list_foreach(pos, &rt->precursors) { precursor_t *pr = (precursor_t *) pos; if (pr->neighbor.s_addr == addr.s_addr) { DEBUG(LOG_INFO, 0, "Removing precursor %s from rte %s", ip_to_str(addr), ip_to_str(rt->dest_addr)); list_detach(pos); rt->nprec--; free(pr); return; } } } void precursor_list_destroy(rt_table_t * rt) { list_t *pos, *tmp; /* Sanity check */ if (!rt) return; list_foreach_safe(pos, tmp, &rt->precursors) { precursor_t *pr = (precursor_t *) pos;