NETWORK ATTACKS FRAMEWORK
1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
|
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 }