You are on page 1of 31

Appendix A

Implementation Coding of Jamming Attack in MANET


#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;

Https://WWW.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

Https://WWW.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) {

Https://WWW.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);

Https://WWW.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)

Https://WWW.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));

Https://WWW.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);
}
}

Https://WWW.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));

Https://WWW.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");

Https://WWW.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();

Https://WWW.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();
}

Https://WWW.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);

Https://WWW.ThesisScientist.com
/* Create a UDP socket */

if (this_host.nif == 0) {
fprintf(stderr, "No interfaces configured\n");
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);
}

Https://WWW.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) {

Https://WWW.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);

Https://WWW.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);

Https://WWW.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;

Https://WWW.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:

Https://WWW.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) {

Https://WWW.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)

Https://WWW.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 */

Https://WWW.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;

Https://WWW.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

Https://WWW.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;

Https://WWW.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 &&

Https://WWW.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;

Https://WWW.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. */

Https://WWW.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;

Https://WWW.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) {

Https://WWW.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;

Https://WWW.ThesisScientist.com
list_detach(pos);
rt->nprec--;
free(pr);
}
}

Https://WWW.ThesisScientist.com

You might also like