NETWORK ATTACKS FRAMEWORK  1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
main.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * Copyright (C) 2001 Uppsala University and Ericsson AB.
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  *
00019  * Author: Erik Nordström, <erik.nordstrom@it.uu.se>
00020  *
00021  *****************************************************************************/
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <errno.h>
00026 #include <sys/types.h>
00027 #include <sys/socket.h>
00028 #include <sys/stat.h>
00029 #include <linux/sockios.h>
00030 #include <linux/wireless.h>
00031 #include <getopt.h>
00032 #include <ctype.h>
00033 
00034 #include "defs.h"
00035 #include "debug.h"
00036 #include "timer_queue.h"
00037 #include "MA_params.h"
00038 #include "MA_aodv_socket.h"
00039 #include "MA_aodv_timeout.h"
00040 #include "k_route.h"
00041 #include "MA_routing_table.h"
00042 #include "MA_aodv_hello.h"
00043 #include "MA_nl.h"
00044 
00045 #ifdef LLFEEDBACK
00046 #include "MA_llf.h"
00047 #endif
00048 
00049 /* Global variables: */
00050 int log_to_file = 0;
00051 int rt_log_interval = 0;        /* msecs between routing table logging 0=off */
00052 int unidir_hack = 0;
00053 int rreq_gratuitous = 0;
00054 int expanding_ring_search = 1;
00055 int internet_gw_mode = 0;
00056 int local_repair = 0;
00057 int receive_n_hellos = 0;
00058 int hello_jittering = 1;
00059 int optimized_hellos = 0;
00060 int ratelimit = 1;              /* Option for rate limiting RREQs and RERRs. */
00061 char *progname;
00062 int wait_on_reboot = 1;
00063 int qual_threshold = 0;
00064 int llfeedback = 0;
00065 int gw_prefix = 1;
00066 struct timer worb_timer;        /* Wait on reboot timer */
00067 
00068 /* Dynamic configuration values */
00069 int active_route_timeout = ACTIVE_ROUTE_TIMEOUT_HELLO;
00070 int ttl_start = TTL_START_HELLO;
00071 int delete_period = DELETE_PERIOD_HELLO;
00072 
00073 static void cleanup();
00074 
00075 struct option longopts[] = {
00076     {"interface", required_argument, NULL, 'i'},
00077     {"hello-jitter", no_argument, NULL, 'j'},
00078     {"log", no_argument, NULL, 'l'},
00079     {"n-hellos", required_argument, NULL, 'n'},
00080     {"daemon", no_argument, NULL, 'd'},
00081     {"force-gratuitous", no_argument, NULL, 'g'},
00082     {"opt-hellos", no_argument, NULL, 'o'},
00083     {"quality-threshold", required_argument, NULL, 'q'},
00084     {"log-rt-table", required_argument, NULL, 'r'},
00085     {"unidir_hack", no_argument, NULL, 'u'},
00086     {"gateway-mode", no_argument, NULL, 'w'},
00087     {"help", no_argument, NULL, 'h'},
00088     {"no-expanding-ring", no_argument, NULL, 'x'},
00089     {"no-worb", no_argument, NULL, 'D'},
00090     {"local-repair", no_argument, NULL, 'L'},
00091     {"rate-limit", no_argument, NULL, 'R'},
00092     {"version", no_argument, NULL, 'V'},
00093     {"llfeedback", no_argument, NULL, 'f'},
00094     {0}
00095 };
00096 
00097 void usage(int status)
00098 {
00099     if (status != 0) {
00100         fprintf(stderr, "Try `%s --help' for more information.\n", progname);
00101         exit(status);
00102     }
00103 
00104     printf
00105         ("\nUsage: %s [-dghjlouwxLDRV] [-i if0,if1,..] [-r N] [-n N] [-q THR]\n\n"
00106          "-d, --daemon            Daemon mode, i.e. detach from the console.\n"
00107          "-g, --force-gratuitous  Force the gratuitous flag to be set on all RREQ's.\n"
00108          "-h, --help              This information.\n"
00109          "-i, --interface         Network interfaces to attach to. Defaults to first\n"
00110          "                        wireless interface.\n"
00111          "-j, --hello-jitter      Toggle hello jittering (default ON).\n"
00112          "-l, --log               Log debug output to %s.\n"
00113          "-o, --opt-hellos        Send HELLOs only when forwarding data (experimental).\n"
00114          "-r, --log-rt-table      Log routing table to %s every N secs.\n"
00115          "-n, --n-hellos          Receive N hellos from host before treating as neighbor.\n"
00116          "-u, --unidir-hack       Detect and avoid unidirectional links (experimental).\n"
00117          "-w, --gateway-mode      Enable experimental Internet gateway support.\n"
00118          "-x, --no-expanding-ring Disable expanding ring search for RREQs.\n"
00119          "-D, --no-worb           Disable 15 seconds wait on reboot delay.\n"
00120          "-L, --local-repair      Enable local repair.\n"
00121          "-f, --llfeedback        Enable link layer feedback.\n"
00122          "-R, --rate-limit        Toggle rate limiting of RREQs and RERRs (default ON).\n"
00123          "-q, --quality-threshold Set a minimum signal quality threshold for control packets.\n"
00124          "-V, --version           Show version.\n\n"
00125          "Erik Nordström, <erik.nordstrom@it.uu.se>\n\n",
00126          progname, AODV_LOG_PATH, AODV_RT_LOG_PATH);
00127 
00128     exit(status);
00129 }
00130 
00131 int set_kernel_options()
00132 {
00133     int i, fd = -1;
00134     char on = '1';
00135     char off = '0';
00136     char command[64];
00137 
00138     if ((fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY)) < 0)
00139         return -1;
00140     if (write(fd, &on, sizeof(char)) < 0)
00141     {
00142         close(fd);
00143         return -1;
00144     }
00145     close(fd);
00146 
00147     if ((fd = open("/proc/sys/net/ipv4/route/max_delay", O_WRONLY)) < 0)
00148         return -1;
00149     if (write(fd, &off, sizeof(char)) < 0)
00150     {
00151         close(fd);
00152         return -1;
00153     }
00154     close(fd);
00155 
00156     if ((fd = open("/proc/sys/net/ipv4/route/min_delay", O_WRONLY)) < 0)
00157         return -1;
00158     if (write(fd, &off, sizeof(char)) < 0)
00159     {
00160         close(fd);
00161         return -1;
00162     }
00163     close(fd);
00164 
00165     /* Disable ICMP redirects on all interfaces: */
00166 
00167     for (i = 0; i < MAX_NR_INTERFACES; i++) {
00168         if (!DEV_NR(i).enabled)
00169             continue;
00170 
00171         memset(command, '\0', 64);
00172         sprintf(command, "/proc/sys/net/ipv4/conf/%s/send_redirects",
00173                 DEV_NR(i).ifname);
00174         if ((fd = open(command, O_WRONLY)) < 0)
00175             return -1;
00176         if (write(fd, &off, sizeof(char)) < 0)
00177     {
00178         close(fd);
00179         return -1;
00180     }
00181         close(fd);
00182         memset(command, '\0', 64);
00183         sprintf(command, "/proc/sys/net/ipv4/conf/%s/accept_redirects",
00184                 DEV_NR(i).ifname);
00185         if ((fd = open(command, O_WRONLY)) < 0)
00186             return -1;
00187         if (write(fd, &off, sizeof(char)) < 0)
00188     {
00189         close(fd);
00190         return -1;
00191     }
00192         close(fd);
00193     }
00194     memset(command, '\0', 64);
00195     sprintf(command, "/proc/sys/net/ipv4/conf/all/send_redirects");
00196     if ((fd = open(command, O_WRONLY)) < 0)
00197         return -1;
00198     if (write(fd, &off, sizeof(char)) < 0)
00199     {
00200         close(fd);
00201         return -1;
00202     }
00203     close(fd);
00204 
00205 
00206     memset(command, '\0', 64);
00207     sprintf(command, "/proc/sys/net/ipv4/conf/all/accept_redirects");
00208     if ((fd = open(command, O_WRONLY)) < 0)
00209         return -1;
00210     if (write(fd, &off, sizeof(char)) < 0)
00211     {
00212         close(fd);
00213         return -1;
00214     }
00215     close(fd);
00216 
00217     return 0;
00218 }
00219 
00220 int find_default_gw(void)
00221 {
00222     FILE *route;
00223     char buf[100], *l;
00224 
00225     route = fopen("/proc/net/route", "r");
00226 
00227     if (route == NULL) {
00228         perror("open /proc/net/route");
00229         exit(-1);
00230     }
00231 
00232     while (fgets(buf, sizeof(buf), route)) {
00233         l = strtok(buf, " \t");
00234         l = strtok(NULL, " \t");
00235         if (l != NULL) {
00236             if (strcmp("00000000", l) == 0) {
00237                 l = strtok(NULL, " \t");
00238                 l = strtok(NULL, " \t");
00239                 if (strcmp("0003", l) == 0) {
00240                     fclose(route);
00241                     return 1;
00242                 }
00243             }
00244         }
00245     }
00246     fclose(route);
00247     return 0;
00248 }
00249 
00250 /*
00251  * Returns information on a network interface given its name...
00252  */
00253 struct sockaddr_in *get_if_info(char *ifname, int type)
00254 {
00255     int skfd;
00256     struct sockaddr_in *ina;
00257     static struct ifreq ifr;
00258 
00259     /* Get address of interface... */
00260     skfd = socket(AF_INET, SOCK_DGRAM, 0);
00261 
00262     strcpy(ifr.ifr_name, ifname);
00263     if (ioctl(skfd, type, &ifr) < 0) {
00264         alog(LOG_ERR, errno, __FUNCTION__,
00265              "Could not get address of %s ", ifname);
00266         close(skfd);
00267         return NULL;
00268     } else {
00269         ina = (struct sockaddr_in *) &ifr.ifr_addr;
00270         close(skfd);
00271         return ina;
00272     }
00273 }
00274 
00275 /* This will limit the number of handler functions we can have for
00276    sockets and file descriptors and so on... */
00277 #define CALLBACK_FUNCS 5
00278 static struct callback {
00279     int fd;
00280     callback_func_t func;
00281 } callbacks[CALLBACK_FUNCS];
00282 
00283 static int nr_callbacks = 0;
00284 
00285 int attach_callback_func(int fd, callback_func_t func)
00286 {
00287     if (nr_callbacks >= CALLBACK_FUNCS) {
00288         fprintf(stderr, "callback attach limit reached!!\n");
00289         exit(-1);
00290     }
00291     callbacks[nr_callbacks].fd = fd;
00292     callbacks[nr_callbacks].func = func;
00293     nr_callbacks++;
00294     return 0;
00295 }
00296 
00297 /* Here we find out how to load the kernel modules... If the modules
00298    are located in the current directory. use those. Otherwise fall
00299    back to modprobe. */
00300 
00301 void load_modules(char *ifname)
00302 {
00303     struct stat st;
00304     char buf[1024], *l = NULL;
00305     int found = 0;
00306     FILE *m;
00307 
00308     memset(buf, '\0', 64);
00309 
00310     if (stat("./kaodv.ko", &st) == 0)
00311         sprintf(buf, "/sbin/insmod kaodv.ko ifname=%s &>/dev/null", ifname);
00312     else if (stat("./kaodv.o", &st) == 0)
00313         sprintf(buf, "/sbin/insmod kaodv.o ifname=%s &>/dev/null", ifname);
00314     else
00315         sprintf(buf, "/sbin/modprobe kaodv ifname=%s &>/dev/null", ifname);
00316 
00317     system(buf);
00318 
00319     usleep(100000);
00320 
00321     /* Check result */
00322     m = fopen("/proc/modules", "r");
00323     while (fgets(buf, sizeof(buf), m)) {
00324         l = strtok(buf, " \t");
00325         if (!strcmp(l, "kaodv"))
00326             found++;
00327         if (!strcmp(l, "ipchains")) {
00328             fprintf(stderr,
00329                     "The ipchains kernel module is loaded and prevents AODV-UU from functioning properly.\n");
00330             exit(-1);
00331         }
00332     }
00333     fclose(m);
00334 
00335     if (found < 1) {
00336         fprintf(stderr,
00337                 "A kernel module could not be loaded, check your installation... %d\n",
00338                 found);
00339         exit(-1);
00340     }
00341 }
00342 
00343 void remove_modules(void)
00344 {
00345     system("/sbin/rmmod kaodv &>/dev/null");
00346 }
00347 
00348 void host_init(char *ifname)
00349 {
00350     struct sockaddr_in *ina;
00351     char buf[1024], tmp_ifname[IFNAMSIZ],
00352         ifnames[(IFNAMSIZ + 1) * MAX_NR_INTERFACES], *iface;
00353     struct ifconf ifc;
00354     struct ifreq ifreq, *ifr;
00355     int i, iw_sock, if_sock = 0;
00356 
00357     memset(&this_host, 0, sizeof(struct host_info));
00358     memset(dev_indices, 0, sizeof(unsigned int) * MAX_NR_INTERFACES);
00359 
00360     if (!ifname) {
00361         /* No interface was given... search for first wireless. */
00362         iw_sock = socket(PF_INET, SOCK_DGRAM, 0);
00363         ifc.ifc_len = sizeof(buf);
00364         ifc.ifc_buf = buf;
00365         if (ioctl(iw_sock, SIOCGIFCONF, &ifc) < 0) {
00366             fprintf(stderr, "Could not get wireless info\n");
00367             exit(-1);
00368         }
00369         ifr = ifc.ifc_req;
00370         for (i = ifc.ifc_len / sizeof(struct ifreq); i >= 0; i--, ifr++) {
00371             struct iwreq req;
00372 
00373             strcpy(req.ifr_name, ifr->ifr_name);
00374             if (ioctl(iw_sock, SIOCGIWNAME, &req) >= 0) {
00375                 strcpy(tmp_ifname, ifr->ifr_name);
00376                 break;
00377             }
00378         }
00379         /* Did we find a wireless interface? */
00380         if (!strlen(tmp_ifname)) {
00381             fprintf(stderr, "\nCould not find a wireless interface!\n");
00382             fprintf(stderr, "Use -i <interface> to override...\n\n");
00383             exit(-1);
00384         }
00385         strcpy(ifreq.ifr_name, tmp_ifname);
00386         if (ioctl(iw_sock, SIOCGIFINDEX, &ifreq) < 0) {
00387             alog(LOG_ERR, errno, __FUNCTION__,
00388                  "Could not get index of %s", tmp_ifname);
00389             close(if_sock);
00390             exit(-1);
00391         }
00392         close(iw_sock);
00393 
00394         ifname = tmp_ifname;
00395 
00396         alog(LOG_NOTICE, 0, __FUNCTION__,
00397              "Attaching to %s, override with -i <if1,if2,...>.", tmp_ifname);
00398     }
00399 
00400     strcpy(ifnames, ifname);
00401 
00402     /* Intitialize the local sequence number an rreq_id to zero */
00403     this_host.seqno = 1;
00404     this_host.rreq_id = 0;
00405 
00406     /* Zero interfaces enabled so far... */
00407     this_host.nif = 0;
00408 
00409     gettimeofday(&this_host.bcast_time, NULL);
00410 
00411     /* Find the indices of all interfaces to broadcast on... */
00412     if_sock = socket(AF_INET, SOCK_DGRAM, 0);
00413 
00414     iface = strtok(ifname, ",");
00415 
00416     /* OK, now lookup interface information, and store it... */
00417     do {
00418         strcpy(ifreq.ifr_name, iface);
00419         if (ioctl(if_sock, SIOCGIFINDEX, &ifreq) < 0) {
00420             alog(LOG_ERR, errno, __FUNCTION__, "Could not get index of %s",
00421                  iface);
00422             close(if_sock);
00423             exit(-1);
00424         }
00425         this_host.devs[this_host.nif].ifindex = ifreq.ifr_ifindex;
00426 
00427         dev_indices[this_host.nif++] = ifreq.ifr_ifindex;
00428 
00429         strcpy(DEV_IFINDEX(ifreq.ifr_ifindex).ifname, iface);
00430 
00431         /* Get IP-address of interface... */
00432         ina = get_if_info(iface, SIOCGIFADDR);
00433         if (ina == NULL)
00434             exit(-1);
00435 
00436         DEV_IFINDEX(ifreq.ifr_ifindex).ipaddr = ina->sin_addr;
00437 
00438         /* Get netmask of interface... */
00439         ina = get_if_info(iface, SIOCGIFNETMASK);
00440         if (ina == NULL)
00441             exit(-1);
00442 
00443         DEV_IFINDEX(ifreq.ifr_ifindex).netmask = ina->sin_addr;
00444 
00445         ina = get_if_info(iface, SIOCGIFBRDADDR);
00446         if (ina == NULL)
00447             exit(-1);
00448 
00449         DEV_IFINDEX(ifreq.ifr_ifindex).broadcast = ina->sin_addr;
00450 
00451         DEV_IFINDEX(ifreq.ifr_ifindex).enabled = 1;
00452 
00453         if (this_host.nif >= MAX_NR_INTERFACES)
00454             break;
00455 
00456     } while ((iface = strtok(NULL, ",")));
00457 
00458     close(if_sock);
00459 
00460     /* Load kernel modules */
00461     load_modules(ifnames);
00462 
00463     /* Enable IP forwarding and set other kernel options... */
00464     if (set_kernel_options() < 0) {
00465         fprintf(stderr, "Could not set kernel options!\n");
00466         exit(-1);
00467     }
00468 }
00469 
00470 /* This signal handler ensures clean exits */
00471 void signal_handler(int type)
00472 {
00473 
00474     switch (type) {
00475     case SIGSEGV:
00476         alog(LOG_ERR, 0, __FUNCTION__, "SEGMENTATION FAULT!!!! Exiting!!! "
00477              "To get a core dump, compile with DEBUG option.");
00478     case SIGINT:
00479     case SIGHUP:
00480     case SIGTERM:
00481     default:
00482         exit(0);
00483     }
00484 }
00485 
00486 int main(int argc, char **argv)
00487 {
00488     static char *ifname = NULL; /* Name of interface to attach to */
00489     fd_set rfds, readers;
00490     int n, nfds = 0, i;
00491     int daemonize = 0;
00492     struct timeval *timeout;
00493 
00494     /* Remember the name of the executable... */
00495     progname = strrchr(argv[0], '/');
00496 
00497     if (progname)
00498         progname++;
00499     else
00500         progname = argv[0];
00501 
00502     /* Use debug output as default */
00503     debug = 1;
00504 
00505     /* Parse command line: */
00506 
00507     while (1) {
00508         int opt;
00509 
00510         opt = getopt_long(argc, argv, "i:fjln:dghoq:r:s:uwxDLRV", longopts, 0);
00511 
00512         if (opt == EOF)
00513             break;
00514 
00515         switch (opt) {
00516         case 0:
00517             break;
00518         case 'd':
00519             debug = 0;
00520             daemonize = 1;
00521             break;
00522         case 'f':
00523             llfeedback = 1;
00524             active_route_timeout = ACTIVE_ROUTE_TIMEOUT_LLF;
00525             break;
00526         case 'g':
00527             rreq_gratuitous = !rreq_gratuitous;
00528             break;
00529         case 'i':
00530             ifname = optarg;
00531             break;
00532         case 'j':
00533             hello_jittering = !hello_jittering;
00534             break;
00535         case 'l':
00536             log_to_file = !log_to_file;
00537             break;
00538         case 'n':
00539             if (optarg && isdigit(*optarg)) {
00540                 receive_n_hellos = atoi(optarg);
00541                 if (receive_n_hellos < 2) {
00542                     fprintf(stderr, "-n should be at least 2!\n");
00543                     exit(-1);
00544                 }
00545             }
00546             break;
00547         case 'o':
00548             optimized_hellos = !optimized_hellos;
00549             break;
00550         case 'q':
00551             if (optarg && isdigit(*optarg))
00552                 qual_threshold = atoi(optarg);
00553             break;
00554         case 'r':
00555             if (optarg && isdigit(*optarg))
00556                 rt_log_interval = atof(optarg) * 1000;
00557             break;
00558         case 'u':
00559             unidir_hack = !unidir_hack;
00560             break;
00561         case 'w':
00562             internet_gw_mode = !internet_gw_mode;
00563             break;
00564         case 'x':
00565             expanding_ring_search = !expanding_ring_search;
00566             break;
00567         case 'L':
00568             local_repair = !local_repair;
00569             break;
00570         case 'D':
00571             wait_on_reboot = !wait_on_reboot;
00572             break;
00573         case 'R':
00574             ratelimit = !ratelimit;
00575             break;
00576         case 'V':
00577             printf
00578                 ("\nAODV-UU v%s, %s © Uppsala University & Ericsson AB.\nAuthor: Erik Nordström, <erik.nordstrom@it.uu.se>\n\n",
00579                  AODV_UU_VERSION, DRAFT_VERSION);
00580             exit(0);
00581             break;
00582         case '?':
00583         case ':':
00584             exit(0);
00585         default:
00586             usage(0);
00587         }
00588     }
00589     /* Check that we are running as root */
00590     if (geteuid() != 0) {
00591         fprintf(stderr, "must be root\n");
00592         exit(1);
00593     }
00594 
00595     /* Detach from terminal */
00596     if (daemonize) {
00597         if (fork() != 0)
00598             exit(0);
00599         /* Close stdin, stdout and stderr... */
00600         /*  close(0); */
00601         close(1);
00602         close(2);
00603         setsid();
00604     }
00605     /* Make sure we cleanup at exit... */
00606     atexit((void *) &cleanup);
00607 
00608     /* Initialize data structures and services... */
00609     rt_table_init();
00610     log_init();
00611     /*   packet_queue_init(); */
00612     host_init(ifname);
00613     /*   packet_input_init(); */
00614     nl_init();
00615     nl_send_conf_msg();
00616     aodv_socket_init();
00617 #ifdef LLFEEDBACK
00618     if (llfeedback) {
00619         llf_init();
00620     }
00621 #endif
00622 
00623     /* Catch SIGHUP, SIGINT and SIGTERM type signals */
00624     signal(SIGHUP, signal_handler);
00625     signal(SIGINT, signal_handler);
00626     signal(SIGTERM, signal_handler);
00627 
00628     /* Only capture segmentation faults when we are not debugging... */
00629 #ifndef DEBUG
00630     signal(SIGSEGV, signal_handler);
00631 #endif
00632     /* Set sockets to watch... */
00633     FD_ZERO(&readers);
00634     for (i = 0; i < nr_callbacks; i++) {
00635         FD_SET(callbacks[i].fd, &readers);
00636         if (callbacks[i].fd >= nfds)
00637             nfds = callbacks[i].fd + 1;
00638     }
00639 
00640     /* Set the wait on reboot timer... */
00641     if (wait_on_reboot) {
00642         timer_init(&worb_timer, wait_on_reboot_timeout, &wait_on_reboot);
00643         timer_set_timeout(&worb_timer, DELETE_PERIOD);
00644         alog(LOG_NOTICE, 0, __FUNCTION__,
00645              "In wait on reboot for %d milliseconds. Disable with \"-D\".",
00646              DELETE_PERIOD);
00647     }
00648 
00649     /* Schedule the first Hello */
00650     if (!optimized_hellos && !llfeedback)
00651         hello_start();
00652 
00653     if (rt_log_interval)
00654         log_rt_table_init();
00655 
00656     while (1) {
00657         memcpy((char *) &rfds, (char *) &readers, sizeof(rfds));
00658 
00659         timeout = timer_age_queue();
00660 
00661         if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
00662             if (errno != EINTR)
00663                 alog(LOG_WARNING, errno, __FUNCTION__,
00664                      "Failed select (main loop)");
00665             continue;
00666         }
00667 
00668         if (n > 0) {
00669             for (i = 0; i < nr_callbacks; i++) {
00670                 if (FD_ISSET(callbacks[i].fd, &rfds)) {
00671                     /* We don't want any timer SIGALRM's while executing the
00672                        callback functions, therefore we block the timer... */
00673                     (*callbacks[i].func) (callbacks[i].fd);
00674                 }
00675             }
00676         }
00677     }                           /* Main loop */
00678     return 0;
00679 }
00680 
00681 static void cleanup(void)
00682 {
00683     DEBUG(LOG_DEBUG, 0, "CLEANING UP!");
00684     remove_modules();
00685     rt_table_destroy();
00686     /*  packet_input_cleanup(); */
00687 /*     packet_queue_destroy(); */
00688     aodv_socket_cleanup();
00689     nl_cleanup();
00690 #ifdef LLFEEDBACK
00691     if (llfeedback)
00692         llf_cleanup();
00693 #endif
00694     log_cleanup();
00695 }
 All Classes Files Functions Variables Typedefs Enumerator Defines