codice:
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/sockios.h>
#include <linux/wireless.h>
#include <getopt.h>
#include <ctype.h>
#include <pthread.h>
#include <gcrypt.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;
#include "defs.h"
#include "debug.h"
#include "timer_queue.h"
#include "params.h"
#include "aodv_socket.h"
#include "aodv_timeout.h"
#include "k_route.h"
#include "routing_table.h"
#include "aodv_hello.h"
#include "packet_input.h"
#include "packet_queue.h"
#include "key.h"
#include "crypto.h"
#include "hash.h"
#include "saodv_adapt.h"
#ifdef LLFEEDBACK
#include "llf.h"
#endif
/* Global variables: */
int log_to_file = 0;
int rt_log_interval = 0; /* msecs between routing table logging 0=off */
int unidir_hack = 0;
int rreq_gratuitous = 0;
int expanding_ring_search = 1;
int internet_gw_mode = 0;
int local_repair = 0;
int receive_n_hellos = 0;
int hello_jittering = 1;
int optimized_hellos = 0;
int ratelimit = 1; /* Option for rate limiting RREQs and RERRs. */
char *progname;
int wait_on_reboot = 0;
int hello_qual_threshold = 0;
int llfeedback = 0;
int gw_prefix = 1;
struct timer worb_timer; /* Wait on reboot timer */
u_int8_t my_hash_function = HASH_FUNC_SHA1;
u_int8_t my_hash_function_sign = HASH_FUNC_SIGN_SHA1;
u_int8_t my_sign_meth;
int double_sign = 1;
/* Dynamic configuration values */
int active_route_timeout = ACTIVE_ROUTE_TIMEOUT_HELLO;
int ttl_start = TTL_START_HELLO;
int delete_period = DELETE_PERIOD_HELLO;
static void cleanup();
static void store_seqno();
static void load_seqno();
struct option longopts[] = {
{"interface", required_argument, NULL, 'i'},
{"hello-jitter", no_argument, NULL, 'j'},
{"log", no_argument, NULL, 'l'},
{"n-hellos", required_argument, NULL, 'n'},
{"daemon", no_argument, NULL, 'd'},
{"force-gratuitous", no_argument, NULL, 'g'},
{"opt-hellos", no_argument, NULL, 'o'},
{"quality-threshold", required_argument, NULL, 'q'},
{"log-rt-table", required_argument, NULL, 'r'},
{"unidir_hack", no_argument, NULL, 'u'},
{"gateway-mode", no_argument, NULL, 'w'},
{"help", no_argument, NULL, 'h'},
{"no-expanding-ring", no_argument, NULL, 'x'},
{"worb", no_argument, NULL, 'D'},
{"local-repair", no_argument, NULL, 'L'},
{"rate-limit", no_argument, NULL, 'R'},
{"version", no_argument, NULL, 'V'},
{"llfeedback", no_argument, NULL, 'f'},
{"mdalg", required_argument, NULL, 'm'},
{"mdalg-sign", required_argument, NULL, 's'},
{"double-sign", no_argument, NULL, 'S'},
{0}
};
void usage(int status)
{
if (status != 0) {
fprintf(stderr, "Try `%s --help' for more information.\n", progname);
exit(status);
}
printf
("\nUsage: %s [-dghjlouwxLDRSV] [-i if0,if1,..] [-r N] [-n N] [-q THR] [-m MDALG] [-s MDALG]\n\n"
"-d, --daemon Daemon mode, i.e. detach from the console.\n"
"-g, --force-gratuitous Force the gratuitous flag to be set on all RREQ's.\n"
"-h, --help This information.\n"
"-i, --interface Network interfaces to attach to. Defaults to first\n"
" wireless interface.\n"
"-j, --hello-jitter Toggle hello jittering (default ON).\n"
"-l, --log Log debug output to %s.\n"
"-o, --opt-hellos Send HELLOs only when forwarding data (experimental).\n"
"-r, --log-rt-table Log routing table to %s every N secs.\n"
"-n, --n-hellos Receive N hellos from host before treating as neighbor.\n"
"-u, --unidir-hack Detect and avoid unidirectional links (experimental).\n"
"-w, --gateway-mode Enable experimental Internet gateway support.\n"
"-x, --no-expanding-ring Disable expanding ring search for RREQs.\n"
"-D, --worb Enable 15 seconds wait on reboot delay.\n"
"-L, --local-repair Enable local repair.\n"
"-f, --llfeedback Enable link layer feedback.\n"
"-R, --rate-limit Toggle rate limiting of RREQs and RERRs (default ON).\n"
"-q, --quality-threshold Set a minimum signal quality threshold for control packets.\n"
"-m, --mdalg Message digest algorithm for hash chain (default sha1).\n"
"-s, --mdalg-sign Message digest algorithm for signature (default sha1). \n"
"-S, --double-sign Toggle saodv with/without double signature (default ON), if double signature is disabled set rreq flag destination only also. \n"
"-V, --version Show version.\n\n"
"Adaptive SAODV: to modify saodv adaptive threshold echo $new_threshold > %s, "
"default is to answer always if double signature is enabled.\n"
"See docs for more information \n\n"
"Francesco Dolcini, <francesco.dolcini@students.cefriel.it> \n"
"Erik Nordström, <erik.nordstrom@it.uu.se>\n\n",
progname, AODV_LOG_PATH, AODV_RT_LOG_PATH, SAODV_ADAPT_FIFO);
exit(status);
}
int set_kernel_options()
{
int i, fd = -1;
char on = '1';
char off = '0';
char command[64];
if ((fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY)) < 0)
return -1;
if (write(fd, &on, sizeof(char)) < 0)
return -1;
close(fd);
if ((fd = open("/proc/sys/net/ipv4/route/max_delay", O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
if ((fd = open("/proc/sys/net/ipv4/route/min_delay", O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
/* Disable ICMP redirects on all interfaces: */
for (i = 0; i < MAX_NR_INTERFACES; i++) {
if (!DEV_NR(i).enabled)
continue;
memset(command, '\0', 64);
sprintf(command, "/proc/sys/net/ipv4/conf/%s/send_redirects",
DEV_NR(i).ifname);
if ((fd = open(command, O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
memset(command, '\0', 64);
sprintf(command, "/proc/sys/net/ipv4/conf/%s/accept_redirects",
DEV_NR(i).ifname);
if ((fd = open(command, O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
}
memset(command, '\0', 64);
sprintf(command, "/proc/sys/net/ipv4/conf/all/send_redirects");
if ((fd = open(command, O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
memset(command, '\0', 64);
sprintf(command, "/proc/sys/net/ipv4/conf/all/accept_redirects");
if ((fd = open(command, O_WRONLY)) < 0)
return -1;
if (write(fd, &off, sizeof(char)) < 0)
return -1;
close(fd);
return 0;
}
int find_default_gw(void)
{
FILE *route;
char buf[100], *l;
route = fopen("/proc/net/route", "r");
if (route == NULL) {
perror("open /proc/net/route");
exit(-1);
}
while (fgets(buf, sizeof(buf), route)) {
l = strtok(buf, " \t");
l = strtok(NULL, " \t");
if (l != NULL) {
if (strcmp("00000000", l) == 0) {
l = strtok(NULL, " \t");
l = strtok(NULL, " \t");
if (strcmp("0003", l) == 0) {
fclose(route);
return 1;
}
}
}
}
fclose(route);
return 0;
}
/*
* Returns information on a network interface given its name...
*/
struct sockaddr_in *get_if_info(char *ifname, int type)
{
int skfd;
struct sockaddr_in *ina;
static struct ifreq ifr;
/* Get address of interface... */
skfd = socket(AF_INET, SOCK_DGRAM, 0);
strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, type, &ifr) < 0) {
alog(LOG_ERR, errno, __FUNCTION__,
"Could not get address of %s ", ifname);
close(skfd);
return NULL;
} else {
ina = (struct sockaddr_in *) &ifr.ifr_addr;
close(skfd);
return ina;
}
}
/* This will limit the number of handler functions we can have for
sockets and file descriptors and so on... */
#define CALLBACK_FUNCS 5
static struct callback {
int fd;
callback_func_t func;
} callbacks[CALLBACK_FUNCS];
static int nr_callbacks = 0;
int attach_callback_func(int fd, callback_func_t func)
{
if (nr_callbacks >= CALLBACK_FUNCS) {
fprintf(stderr, "callback attach limit reached!!\n");
exit(-1);
}
callbacks[nr_callbacks].fd = fd;
callbacks[nr_callbacks].func = func;
nr_callbacks++;
return 0;
}
/* Here we find out how to load the kernel modules... If the modules
are located in the current directory. use those. Otherwise fall
back to modprobe. */
void load_modules(char *ifname)
{
struct stat st;
char buf[1024], *l = NULL;
int found = 0;
FILE *m;
memset(buf, '\0', 64);
sprintf(buf, "/sbin/modprobe ip_queue &>/dev/null");
system(buf);
memset(buf, '\0', 64);
if (stat("./kaodv.ko", &st) == 0)
sprintf(buf, "/sbin/insmod kaodv.ko ifname=%s qual_th=%d &>/dev/null",
ifname, hello_qual_threshold);
else if (stat("./kaodv.o", &st) == 0)
sprintf(buf, "/sbin/insmod kaodv.o ifname=%s qual_th=%d &>/dev/null",
ifname, hello_qual_threshold);
else
sprintf(buf, "/sbin/modprobe kaodv ifname=%s qual_th=%d &>/dev/null",
ifname, hello_qual_threshold);
system(buf);
/* Check result */
m = fopen("/proc/modules", "r");
while (fgets(buf, sizeof(buf), m)) {
l = strtok(buf, " \t");
if (!strcmp(l, "kaodv"))
found++;
if (!strcmp(l, "ip_queue"))
found++;
if (!strcmp(l, "ipchains")) {
fprintf(stderr,
"The ipchains kernel module is loaded and prevents AODV-UU from functioning properly.\n");
exit(-1);
}
}
fclose(m);
if (found != 2) {
fprintf(stderr,
"A kernel module could not be loaded, check your installation...\n");
exit(-1);
}
}