mn_util.c

Go to the documentation of this file.
00001 /* $Id: mn_util.c,v 1.89 2001/10/20 14:20:38 jm Exp $
00002  * Mobile Node - help functions
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  * Copyright (C) 1998-2001, Dynamics group
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation. See README and COPYING for
00010  * more details.
00011  */
00012 
00013 #ifdef HAVE_CONFIG_H
00014 #include <config.h>
00015 #endif
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <unistd.h>
00019 #include <errno.h>
00020 #include <getopt.h>
00021 #include <signal.h>
00022 #include <sys/socket.h>
00023 #include <netinet/in.h>
00024 #include <arpa/inet.h>
00025 #include <string.h>
00026 #include <assert.h>
00027 #ifdef DYN_TARGET_WINDOWS
00028 #include <fcntl.h>
00029 #endif
00030 
00031 #include "debug.h"
00032 #include "dyn_ip.h"
00033 #include "proxyarp.h"
00034 #include "agentapi.h"
00035 #include "util.h"
00036 #ifdef WITH_WIRELESS
00037 #include "monitor.h"
00038 #endif
00039 #include "mn_handler.h"
00040 #include "mn.h"
00041 #include "mn_tunnel.h"
00042 #ifdef INCLUDE_IPAY
00043 #include "mn_ipay.h"
00044 #endif
00045 #include "device_info.h"
00046 
00047 
00048 
00049 extern struct mn_data mn;
00050 extern struct mn_config config;
00051 extern struct timeval timers[TIMER_COUNT];
00052 extern char* program_name;
00053 extern char *opt_config;
00054 extern int opt_foreground;
00055 extern int real_tunnel_up; /* from mn_tunnel */
00056 
00057 static int wireless_extensions;
00058 
00067 static int check_ignore_iface(const char *ifname)
00068 {
00069         struct ignore_iflist_entry *i;
00070         struct node *node;
00071 
00072         if (strcmp(ifname, TUNNEL_DEVICE) == 0) 
00073                 return 1;
00074         if (strcmp(ifname, TUNNEL_DEVICE_B) == 0) 
00075                 return 1;
00076 
00077         for (node = list_get_first(&config.ignore_iflist); node != NULL;
00078              node = list_get_next(node)) {
00079                 i = (struct ignore_iflist_entry *)node;
00080                 if (strncmp(ifname, i->ifname, IFNAMSIZ) == 0) 
00081                         return 1;
00082         }
00083 
00084         return 0;
00085 }
00086 
00087 
00088 struct fa_spi_entry* get_fa_spi(int spi, struct in_addr addr)
00089 {
00090         struct fa_spi_entry *s;
00091         struct node *node;
00092         time_t now;
00093 
00094         time(&now);
00095 
00096         node = list_get_first(&config.fa_spi_list);
00097         while (node != NULL) {
00098                 s = (struct fa_spi_entry *) node;
00099                 node = list_get_next(node);
00100 
00101                 /* Expire dynamic entries that are not infinite (lifetime=0) */
00102                 if (s->created != 0 && s->lifetime != 0 &&
00103                     now > s->created + s->lifetime) {
00104                         DEBUG(DEBUG_INFO, "get_fa_spi: dynamic "
00105                               "security association (SPI=%i, addr=%s) "
00106                               "expired\n", s->spi, inet_ntoa(s->addr));
00107                         list_remove((struct node *) s);
00108                         free(s);
00109                         continue;
00110                 }
00111 
00112                 if ((spi != 0 && s->spi != spi) ||
00113                     s->addr.s_addr != addr.s_addr)
00114                         continue;
00115 
00116                 return s;
00117         }
00118         return NULL;
00119 }
00120 
00121 
00122 int add_fa_spi(struct fa_spi_entry *spi, int replace_any_spi)
00123 {
00124         struct fa_spi_entry *old;
00125 
00126         old = get_fa_spi(replace_any_spi ? 0 : spi->spi, spi->addr);
00127         if (old != NULL) {
00128                 if (old->created == 0) {
00129                         DEBUG(DEBUG_INFO, "add_fa_spi: trying to replace "
00130                               "static security association - aborting "
00131                               "operation\n");
00132                         return -1;
00133                 }
00134 
00135                 DEBUG(DEBUG_INFO, "add_fa_spi: overwriting previous dynamic "
00136                       "security association\n");
00137                 remove_fa_spi(old);
00138                 free(old);
00139                 old = NULL;
00140         }
00141 
00142         DEBUG(DEBUG_INFO, "add_fa_spi: adding dynamic security association "
00143               "(SPI=%i, addr=%s)\n", spi->spi, inet_ntoa(spi->addr));
00144         list_init_node(&spi->node);
00145         list_add_tail(&config.fa_spi_list, &spi->node);
00146         return 0;
00147 }
00148 
00149 
00150 void remove_fa_spi(struct fa_spi_entry *spi)
00151 {
00152         DEBUG(DEBUG_INFO, "remove_fa_spi: removing security association "
00153               "(SPI=%i, addr=%s)\n", spi->spi, inet_ntoa(spi->addr));
00154         list_remove(&spi->node);
00155 }
00156 
00157 
00166 void send_gratuitous_arp(struct in_addr route_addr, 
00167                          struct in_addr gratuitous_addr)
00168 {
00169         char arp_if[IFNAMSIZ];
00170 
00171         if (dyn_ip_route_get(route_addr, arp_if, IFNAMSIZ) != 0) {
00172                 DEBUG(DEBUG_INFO, "Could not get ARP interface\n");
00173                 return;
00174         }
00175         proxyarp_gratuitous(gratuitous_addr, arp_if);
00176 }
00177 
00178 
00179 #ifdef MN_LOCUPD_PROFILER
00180 void write_profiler(const char *msg)
00181 {
00182         struct timeval tv;
00183         gettimeofday(&tv, NULL);
00184         fprintf(mn.profile, "%s %u.%06u (%li usec)\n", msg,
00185                 (unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec,
00186                 (tv.tv_sec - mn.last_api.tv_sec) * 1000000 +
00187                 tv.tv_usec - mn.last_api.tv_usec);
00188 }
00189 #endif
00190 
00191 
00206 int update_fa_decaps_routes(const char *ifname, int ifindex, 
00207                             struct in_addr fa_addr, 
00208                             struct in_addr home_net_addr, 
00209                             int home_net_addr_plen)
00210 {
00211         DEBUG(DEBUG_INFO, "FA decapsulation - setting default route to "
00212               "%s via %s\n", ifname, inet_ntoa(fa_addr));
00213 
00214         mn.cur_route_info.known = 1;
00215         mn.cur_route_info.via.s_addr = fa_addr.s_addr;
00216         mn.cur_route_info.ifindex = ifindex;
00217         memcpy(mn.cur_route_info.ifname, ifname, IFNAMSIZ);
00218         mn.cur_route_info.ifindex_net = -1;
00219 
00220         if (dyn_ip_route_replace_default(ifname, &fa_addr,
00221                                          &config.mn_home_ip_addr) != 0) {
00222                 LOG2(LOG_ERR, "Set default route (to %s via %s) failed\n",
00223                      ifname, inet_ntoa(fa_addr));
00224                 return -1;
00225         }
00226         if (home_net_addr_plen > -1) {
00227                 int count;
00228                 DEBUG(DEBUG_INFO, "Deleting home net route (%s/%i)\n",
00229                       inet_ntoa(home_net_addr), home_net_addr_plen);
00230                 count = dyn_ip_route_delete_net_routes(&home_net_addr,
00231                                                        home_net_addr_plen);
00232                 if (count < 0) {
00233                         LOG2(LOG_ERR, "Home net route (%s/%i) delete failed\n",
00234                              inet_ntoa(home_net_addr), home_net_addr_plen);
00235 #ifdef DYN_TARGET_WINDOWS
00236                         /* at least Win98 does not seem to like to remove
00237                          * home net route.. */
00238                         DEBUG(DEBUG_INFO, "Trying to set net route via the FA "
00239                               "to circumvent failed net route removal\n");
00240 
00241                         if (dyn_ip_route_set_net(ifname, &home_net_addr,
00242                                                  home_net_addr_plen,
00243                                                  NULL, 2) < 0) {
00244                                 DEBUG(DEBUG_INFO, "Could not increase home "
00245                                       "net route metric\n");
00246                         }
00247 
00248                         if (dyn_ip_route_set_net(ifname, &home_net_addr,
00249                                                  home_net_addr_plen,
00250                                                  &fa_addr, 1) < 0) {
00251                                 DEBUG(DEBUG_INFO, "Could not set net route via"
00252                                       " FA\n");
00253                         } else
00254                                 mn.home_net_route_set_via_fa = 1;
00255 #endif /* DYN_TARGET_WINDOWS */
00256                 } else {
00257                         DEBUG(DEBUG_INFO,
00258                               "   %i net route%s deleted\n", count,
00259                               count != 1 ? "s" : "");
00260                 }
00261         }
00262 
00263         return 0;
00264 }
00265 
00271 static void modify_new_interface(struct interface_data *iface, 
00272                                  struct idxmap *idx)
00273 {
00274         struct event_INTERFACE data;
00275         int ret;
00276 
00277         DEBUG(DEBUG_INFO, "modify_new_interface (start): device_count %d\n",
00278               mn.device_count);
00279         if (config.enable_fa_decapsulation) {
00280                 ret = dyn_ip_iface_address(idx->index, 
00281                                            &config.mn_home_ip_addr);
00282                 if ((ret == 2 || ret == 0) &&
00283                     config.use_aaa &&
00284                     config.mn_home_ip_addr.s_addr == 0 &&
00285                     config.enable_fa_decapsulation) {
00286                         DEBUG(DEBUG_INFO, "modify_interface: interface with no"
00287                               " addresses - using AAA to obtain a home "
00288                               "address\n");
00289                 } else {
00290 
00291                         if (ret == 0) {
00292                                 DEBUG(DEBUG_INFO, "FA decapsulation and an "
00293                                       "interface does not have the home "
00294                                       "address\n");
00295                                 mn.warn_str = "FA decapsulation and an "
00296                                         "interface does not have the home "
00297                                         "address";
00298                                 return;
00299                         }
00300 
00301                         /* continue only if the interface has a correct
00302                          * address */
00303                         if (ret != 1) {
00304                                 DEBUG(DEBUG_INFO, "modify_interface: no "
00305                                       "addresses found (ret=%i)\n", ret);
00306                                 return;
00307                         }
00308                 }
00309         }
00310 
00311         if (iface->handlers_off == 1) {
00312                 DEBUG(DEBUG_INFO, "modify_interface: interface up\n");
00313                 memset(&data, 0, sizeof(data));
00314                 data.iface = iface;
00315                 data.ifname = iface->device;
00316                 data.index = &iface->index;
00317                 data.icmp_sock = &iface->s;
00318                 data.icmp_sock_adv = &iface->s_adv;
00319                 assert(idx != NULL);
00320                 data.idx = idx;
00321                 data.last_reg_send_time = &mn.last_reg_send_time;
00322                 data.current_adv = &mn.current_adv;
00323                 data.priority = &iface->priority;
00324                 ret = handler_call_all(INTERFACE_INIT, &data);
00325                 if (ret == -1) {
00326                         DEBUG(DEBUG_INFO, "modify_interface: interface "
00327                               "initialization failed\n");
00328                         return;
00329                 }
00330                 iface->handlers_off = 0;
00331                 if (config.enable_fa_decapsulation &&
00332                     mn.current_adv != NULL &&
00333                     real_tunnel_up) {
00334                         DEBUG(DEBUG_INFO, "modify_new_interface: fix possibly "
00335                               "changed routing entries\n");
00336                         update_fa_decaps_routes(mn.current_adv->ifname,
00337                                                 mn.current_adv->ifindex,
00338                                                 mn.fa_addr,
00339                                                 config.home_net_addr,
00340                                                 config.home_net_addr_plen);
00341                 }
00342         } 
00343         mn.device_count++;
00344 
00345         DEBUG(DEBUG_INFO, "modify_new_interface (end): device_count %d\n",
00346               mn.device_count);
00347 
00348         /* go from passive find to find agent state if a new interface is up
00349          * and there was previously no interfaces available OR if the current 
00350          * adv. was removed */
00351         if ((mn.device_count == 1 && mn.state == MN_PASSIVE_FIND) ||
00352             (mn.current_adv == NULL && mn.state != MN_DISCONNECTED)) {
00353                 find_agent(STATE_INIT);
00354         }
00355 }
00356 
00361 static void modify_removed_interface(struct interface_data *iface)
00362 {
00363         struct event_INTERFACE data;
00364         int ret;
00365 
00366         DEBUG(DEBUG_INFO, "modify_remved_interface (start): device_count %d\n",
00367               mn.device_count);
00368 
00369         if (iface->handlers_off != 1) {
00370                 DEBUG(DEBUG_INFO, "modify_removed_interface: interface down\n");
00371                 memset(&data, 0, sizeof(data));
00372                 data.ifname = iface->device;
00373                 data.index = &iface->index;
00374                 data.icmp_sock = &iface->s;
00375                 data.icmp_sock_adv = &iface->s_adv;
00376                 ret = handler_call_all(INTERFACE_DOWN, &data);
00377                 if (ret == -1) {
00378                         DEBUG(DEBUG_INFO, "modify_interface: interface "
00379                               "down failed\n");
00380                         return;
00381                 }
00382                 iface->handlers_off = 1;
00383         } 
00384         mn.device_count--;
00385         if (mn.device_count < 0) {
00386                 DEBUG(DEBUG_INFO, "modify_interface: device "
00387                       "count < 0!\n");
00388                 mn.device_count = 0;
00389         }
00390 
00391         DEBUG(DEBUG_INFO, "modify_remived_interface (end): device_count %d\n",
00392               mn.device_count);
00393 
00394         /* go from passive find to find agent state if the current 
00395          * adv. was removed */
00396         if (mn.current_adv == NULL && mn.state != MN_DISCONNECTED) {
00397                 find_agent(STATE_INIT);
00398         }
00399 }
00400 
00411 int check_interfaces(struct interface_data *iface, int iface_num)
00412 {
00413         int i;
00414         struct idxmap *idxmap, *idx;
00415 
00416         idxmap = dyn_ip_get_interface_map();
00417         if (idxmap == NULL) {
00418                 DEBUG(DEBUG_INFO, "check_interfaces: interface map could "
00419                       "not be created\n");
00420                 return 1;
00421         }
00422 
00423         /* remove the ignored interfaces */
00424         /* FIX: add list of interfaces to be ignored to dynmnd.conf and try to
00425          * eliminate 'virtual' interfaces like tunnels etc. */
00426         idx = idxmap;
00427         while (idx != NULL) {
00428                 if (check_ignore_iface(idx->name) ||
00429                     (dyn_ip_get_ifflags(idx->name) & IFF_UP) == 0)
00430                         idx->index = -1;
00431                 idx = idx->next;
00432         }
00433 
00434         /* check removed interfaces */
00435         for (i = 0; i < iface_num; i++) {
00436                 idx = idxmap;
00437                 while (idx != NULL) {
00438                         if (iface[i].index == idx->index)
00439                                 break;
00440                         idx = idx->next;
00441                 }
00442                 
00443                 if (iface[i].s > -1) {
00444                         if (idx != NULL) {
00445                                 /* mark the interface used */
00446                                 idx->index = -1;
00447                         } else {                        
00448                                 DEBUG(DEBUG_INFO, "check_interfaces: "
00449                                       "removed interface\n");
00450                                 /* this interface has been removed */
00451                                 modify_removed_interface(&iface[i]);
00452                         }
00453                 }
00454         }
00455         
00456         /* check new interfaces */
00457         idx = idxmap;
00458         while (idx != NULL) {
00459                 if (idx->index == -1) {
00460                         idx = idx->next;
00461                         continue;
00462                 }
00463 
00464                 /* find a free slot */
00465                 i = 0;
00466                 while (i < iface_num && iface[i].s > -1) i++;
00467                 if (i >= iface_num) {
00468                         DEBUG(DEBUG_INFO, "Not enough space for all "
00469                               "the interfaces\n");
00470                         break;
00471                 }
00472 
00473                 /* call handlers for INTERFACE_INIT event */
00474                 DEBUG(DEBUG_INFO, "check_interfaces: new interface\n");
00475                 modify_new_interface(&iface[i], idx);
00476                 idx = idx->next;
00477         }
00478 
00479         dyn_ip_free_interface_map(idxmap);
00480 
00481         return 0;
00482 }
00483 
00484 
00492 int create_registration_socket(void)
00493 {
00494         int s;
00495         unsigned char ttl;
00496 #ifdef BIND_UDP_SOCKET
00497         struct sockaddr_in addr;
00498 #endif
00499 
00500         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00501                 LOG2(LOG_ERR, "create_reg_socket - socket: %s\n",
00502                      strerror(errno));
00503                 return -1;
00504         }
00505 #ifdef BIND_UDP_SOCKET
00506         memset(&addr, 0, sizeof(addr));
00507         addr.sin_family = AF_INET;
00508         addr.sin_addr.s_addr = config.bind_addr.s_addr;
00509         addr.sin_port = config.bind_port;
00510         DEBUG(DEBUG_INFO, "binding UDP socket to %s:%i\n",
00511               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
00512         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00513                 LOG2(LOG_ERR, "create_reg_socket - bind: %s\n",
00514                      strerror(errno));
00515                 return -1;
00516         }
00517 #endif
00518 
00519         if (config.socket_priority > -1 &&
00520             setsockopt(s, SOL_SOCKET, SO_PRIORITY,
00521                        (char *)&config.socket_priority,
00522                        sizeof(config.socket_priority)) < 0) {
00523                 LOG2(LOG_ERR,
00524                      "create_reg_socket - setsockopt SO_PRIORITY: %s\n",
00525                      strerror(errno));
00526                 /* continue without SO_PRIORITY set */
00527         }
00528 
00529         /* send registration request with TTL 255 [RFC 2344, Chap. 3.2] */
00530         ttl = 255;
00531         if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
00532                 LOG2(LOG_ERR, "setsockopt: IP_TTL failed: %s\n",
00533                      strerror(errno));
00534                 /* continue with the default setting anyway */
00535 #ifdef DYN_TARGET_WINDOWS
00536                 if (dyn_ip_set_ttl(255) < 0) {
00537                         DEBUG(DEBUG_INFO, "Also dyn_ip_set_ttl() failed\n");
00538                 }
00539 #endif /* DYN_TARGET_WINDOWS */
00540         }
00541 
00542         return s;
00543 }
00544 
00545 
00546 static void show_usage(void)
00547 {
00548         printf("      --wireless_policy <integer>\n"
00549                "\t\tset wireless handoff policy (1=on, 0=off):\n"
00550                "\t\t  bit 0: rely on MN's agent adv. expiration\n"
00551                "\t\t  bit 1: use shorter agent adv. expiration interval\n"
00552                "\t\t  bit 2: use FA with newest agent advertisement\n"
00553                "\t\t  bit 3: eager switching\n"
00554                "\t\t  bit 4: use newest agent advertisement\n"
00555                "      --no-wireless\tdisable wireless extensions\n"
00556                "      --disconnect\tstart in disconnected state\n");
00557 }
00558 
00559 
00560 int mn_parse_command_line(int argc, char *argv[])
00561 {
00562         int c, oindex = 0;
00563 
00564         static struct option long_options[] = {
00565                 {"help", no_argument, NULL, 'h'},
00566                 {"version", no_argument, NULL, 'v'},
00567                 {"debug", no_argument, NULL, 0},
00568                 {"fg", no_argument, NULL, 0},
00569                 {"config", required_argument, NULL, 'c'},
00570                 /* MN specific arguments */
00571                 {"no-wireless", no_argument, NULL, 'n'},
00572                 {"wireless_policy", required_argument, NULL, 'p'},
00573                 {"disconnect", no_argument, NULL, 'd'},
00574                 /* end of arguments */
00575                 {0, 0, 0, 0}
00576         };
00577 
00578         mn.opt_connect = 1;
00579         mn.policy_bits = 0;
00580 
00581         /* parse mn specific options */
00582         wireless_extensions = 1;
00583         while ((c = getopt_long(argc, argv, "+hv", long_options, &oindex)) !=
00584                EOF) {
00585                 switch (c) {
00586                 case 'n':
00587                         wireless_extensions = 0;
00588                         break;
00589                 case 'p':
00590                         mn.policy_bits = atoi(optarg);
00591                         /* 0: no timestamps */
00592                         /* 1: with timestamps */
00593                         DEBUG(DEBUG_INFO, "Option: %s"
00594                               " 0x%02x (wireless policy)\n",
00595                               long_options[oindex].name,
00596                               mn.policy_bits);
00597                         break;
00598                 case 'h':
00599                         /* show MN specific parameters */
00600                         show_usage();
00601                         exit(1);
00602                         break;
00603 
00604                 case 'd':
00605                         mn.opt_connect = 0;
00606                         break;
00607 
00608                 case '?':
00609                         printf("Command line parsing failed - aborting\n");
00610                         exit(1);
00611 
00612                 case 'v':
00613                 case 'c':
00614                 case 0:
00615                         break;
00616 
00617                 default:
00618                         printf("getopt returned character code 0%o\n", c);
00619                         exit(1);
00620                 }
00621         }
00622 
00623         return 0;
00624 }
00625 
00626 
00627 #ifdef DYN_TARGET_WINDOWS
00628 /* FIX: currently using local UDP socket on Windows because there is no support
00629  * for UNIX domain socket.. maybe something else would be better for IPC on
00630  * Windows platform(?) */
00631 static int windows_api_socket(int admin)
00632 {
00633         int s;
00634         struct sockaddr_in addr;
00635         int flags;
00636 
00637         s = socket(AF_INET, SOCK_DGRAM, 0);
00638         if (s < 0) {
00639                 DEBUG(DEBUG_INFO, "API socket opening failed: %s\n",
00640                       strerror(errno));
00641                 return -1;
00642         }
00643 
00644         flags = fcntl(s, F_GETFL, 0);
00645         if (flags == -1 || fcntl(s, F_SETFL, flags | O_NDELAY) == -1) {
00646                 DEBUG(DEBUG_INFO, "API rw fcntl F_SETFL failed: %s\n",
00647                       strerror(errno));
00648                 close(s);
00649                 return -1;
00650         }
00651 
00652         memset(&addr, 0, sizeof(addr));
00653         addr.sin_family = AF_INET;
00654         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
00655         addr.sin_port = htons(admin ? API_UDP_PORT_RW : API_UDP_PORT_RO);
00656         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00657                 LOG2(LOG_ERR, "API socket - bind: %s\n", strerror(errno));
00658                 close(s);
00659                 return -1;
00660         }
00661 
00662         return s;
00663 }
00664 #endif
00665 
00666 
00667 /* Initialization routines. Setup sockets and variables.
00668  * Returns 1 on success else 0. */
00669 int mn_init(void)
00670 {
00671         int i;
00672 
00673         /* Load configuration */
00674         DEBUG(DEBUG_INFO, "Load config\n");
00675         if (!load_mn(&config, program_name,
00676                      opt_config == NULL ? MN_GLOBAL_CONF_FILE : opt_config)) {
00677                 LOG2(LOG_ERR, "init: unable to load configuration\n");
00678                 
00679                 return 0;
00680         }
00681         mn.use_auth_alg = config.auth_alg;
00682         mn.agentadv = hashtable_init(256);
00683         if (mn.agentadv == NULL) {
00684                 LOG2(LOG_ERR, "init: unable to init agentadv hashtable\n");
00685                 return 0;
00686         }
00687         mn.last_req_FA_NAI = (struct fa_nai_ext *) malloc(MAX_FA_NAI_LEN);
00688         if (mn.last_req_FA_NAI == NULL) {
00689                 LOG2(LOG_ERR, "init: not enough memory\n");
00690                 return 0;
00691         }
00692         memset(mn.last_req_FA_NAI, 0, MAX_FA_NAI_LEN);
00693 
00694         if (!config.enable_fa_decapsulation)
00695                 check_kernel_support(CHECK_KERNEL_IPIP);
00696         check_kernel_support(CHECK_KERNEL_NETLINK);
00697 
00698 #ifdef DYN_TARGET_LINUX
00699         if (getuid() || geteuid()) {
00700                 fprintf(stderr, "This program must be run by root.\n");
00701                 return 0;
00702         }
00703 #endif
00704 #ifdef DYN_TARGET_WINDOWS
00705         /* FIX: on Windows NT and Windows 2000 check for Administrator
00706          * privileges */
00707 #endif
00708 
00709         if ((mn.registration_socket = create_registration_socket()) < 0)
00710                 return 0;
00711 
00712         mn_handlers_init();
00713         mn.dev_info_addr.sun_family = AF_LOCAL;
00714         /* initialize default socket info path */
00715         dynamics_strlcpy(mn.dev_info_addr.sun_path, DEFAULT_DEVICE_INFO_PATH,
00716                          sizeof(mn.dev_info_addr.sun_path));
00717 
00718 #ifdef WITH_WIRELESS
00719         /* If wireless extensions enabled, monitor will register it's own
00720            handlers also */
00721         DEBUG(DEBUG_INFO, "REGISTER MODULE(S)\n");
00722         if (wireless_extensions)
00723                 MONITOR_register_module();
00724 #endif
00725 
00726         /* Check interfaces */
00727         for (i = 0; i < MAX_INTERFACES; i++) {
00728                 mn.iface[i].s = -1;
00729                 mn.iface[i].s_adv = -1;
00730                 mn.iface[i].handlers_off = 1;
00731         }
00732 
00733 #ifdef INCLUDE_IPAY
00734         /* register Ipay handlers after monitor */
00735         ipay_init();
00736 #endif
00737 
00738         if (config.home_net_addr_plen < 0 ||
00739             dyn_ip_route_get(config.home_net_addr, mn.start_default_device,
00740                              IFNAMSIZ) != 0)
00741                 mn.start_default_device[0] = '\0';
00742         else
00743                 DEBUG(DEBUG_INFO, "Initial default device: %s\n",
00744                       mn.start_default_device);
00745 
00746 #ifdef DYN_TARGET_LINUX
00747         if ((mn.api_ro_socket =
00748              api_open_socket(config.mn_api_read_socket_path,
00749                              config.mn_api_read_socket_group,
00750                              config.mn_api_read_socket_owner,
00751                              config.mn_api_read_socket_permissions)) < 0) {
00752                 LOG2(LOG_ERR, "init - open_api_ro_socket: %s\n",
00753                      strerror(errno));
00754                 return 0;
00755         }
00756 
00757         if ((mn.api_rw_socket =
00758              api_open_socket(config.mn_api_admin_socket_path,
00759                              config.mn_api_admin_socket_group,
00760                              config.mn_api_admin_socket_owner,
00761                              config.mn_api_admin_socket_permissions)) < 0) {
00762                 LOG2(LOG_ERR, "init - open api_rw_socket: %s\n",
00763                      strerror(errno));
00764                 return 0;
00765         }
00766 #endif
00767 #ifdef DYN_TARGET_WINDOWS
00768         mn.api_ro_socket = windows_api_socket(0);
00769         mn.api_rw_socket = windows_api_socket(1);
00770 #endif
00771 
00772 #ifdef INCLUDE_IPAY
00773         mn.ipay_sock = socket(AF_INET, SOCK_DGRAM, 0);
00774         if (mn.ipay_sock < 0) {
00775                 LOG2(LOG_ERR, "init - open ipay_sock: %s\n", strerror(errno));
00776                 return 0;
00777         }
00778         if (config.ipay_mn_port > 0) {
00779                 struct sockaddr_in addr;
00780                 memset(&addr, 0, sizeof(addr));
00781                 addr.sin_family = AF_INET;
00782                 addr.sin_addr = config.ipay_mn_addr;
00783                 addr.sin_port = htons(config.ipay_mn_port);
00784                 if (bind(mn.ipay_sock, (struct sockaddr *) &addr,
00785                     sizeof(addr)) < 0) {
00786                         LOG2(LOG_ERR, "init - bind ipay_sock: %s\n",
00787                              strerror(errno));
00788                         return 0;
00789                 }
00790         }
00791         mn.ipay_sock_fa = socket(AF_INET, SOCK_DGRAM, 0);
00792         if (mn.ipay_sock_fa < 0) {
00793                 LOG2(LOG_ERR, "init - open ipay_sock_fa: %s\n",
00794                      strerror(errno));
00795                 return 0;
00796         }
00797         if (config.ipay_fa_port > 0) {
00798                 struct sockaddr_in addr;
00799                 memset(&addr, 0, sizeof(addr));
00800                 addr.sin_family = AF_INET;
00801                 addr.sin_addr.s_addr = INADDR_ANY;
00802                 addr.sin_port = htons(config.ipay_fa_port);
00803                 if (bind(mn.ipay_sock_fa, (struct sockaddr *) &addr,
00804                     sizeof(addr)) < 0) {
00805                         LOG2(LOG_ERR, "init - bind ipay_sock_fa: %s\n",
00806                              strerror(errno));
00807                         return 0;
00808                 }
00809         }
00810 #endif
00811 
00812         mn.rtnetlink_socket = dyn_ip_monitor_open();
00813         if (mn.rtnetlink_socket < 0)
00814                 DEBUG(DEBUG_INFO, "init - rtnetlink socket opening failed\n");
00815 
00816         /* set own ip-addr */
00817         mn.local_addr = config.mn_home_ip_addr;
00818 
00819         init_tunneling();
00820 
00821         /* init variables */
00822         mn.registration_id[0] = 0;
00823         mn.registration_id[1] = 0;
00824         mn.last_nonce = 0;
00825         mn.clock_correction = 0;
00826         mn.state = MN_DISCONNECTED;
00827         mn.fa_addr.s_addr = 0;
00828         mn.current_adv = NULL;
00829         mn.force_fa_addr.s_addr = 0;
00830         mn.session_key = NULL;
00831         mn.session_key_len = 0;
00832         mn.tunnel_up = 0;
00833         mn.tunnel_mode = API_TUNNEL_NONE;
00834         mn.ha_error_count = 0;
00835         memset(&mn.cur_route_info, 0, sizeof(mn.cur_route_info));
00836         mn.cur_route_info.net.s_addr = config.home_net_addr.s_addr;
00837         mn.cur_route_info.prefix_len = config.home_net_addr_plen;
00838 
00839         timerclear(&mn.last_reg_send_time);
00840 
00841         for (i = 0; i < TIMER_COUNT; i++) timerclear(&timers[i]);
00842         if (config.wlan_ap_poll_interval > -1)
00843                 gettimeofday(&timers[TIMER_WLAN_AP_POLL], NULL);
00844         if (config.solicitation_interval > -1)
00845                 gettimeofday(&timers[TIMER_SOLICITATION], NULL);
00846 
00847         openlog(SYSLOG_IDENT, SYSLOG_OPTIONS, config.syslog_facility);
00848 
00849         dyn_ip_route_save_default(config.home_net_gateway.s_addr != 0 ?
00850                 &config.home_net_gateway : NULL);
00851 
00852 #ifdef MN_LOCUPD_PROFILER
00853         mn.profile = fopen("mn.prof.log", "a");
00854         if (mn.profile == NULL) {
00855                 fprintf(stderr, "Cannot open mn.prof.log\n");
00856                 return 0;
00857         }
00858         gettimeofday(&mn.last_api, NULL);
00859         fprintf(mn.profile, "START %u.%06u\n",
00860                 (unsigned int) mn.last_api.tv_sec,
00861                 (unsigned int) mn.last_api.tv_usec);
00862 #endif
00863 
00864         /* Setup signals */
00865         signal(SIGTERM, clean_up);
00866         signal(SIGINT, clean_up);
00867         signal(SIGHUP, SIG_IGN);
00868         signal(SIGPIPE, SIG_IGN);
00869 
00870 /*      if (!opt_foreground && dynamics_fork_daemon() == -1)
00871                 clean_up(0);
00872         dynamics_write_pid_file(MN_PID_FILE);
00873 */
00874         DEBUG(DEBUG_INFO, " MN initialized to %sconnected state,\n"
00875               "  SPI: %d, HA: %s,\n", (mn.opt_connect ? "" : "dis"),
00876               config.spi, inet_ntoa(config.ha_ip_addr));
00877         DEBUG(DEBUG_INFO, "  HomeAddr: %s",
00878               inet_ntoa(config.mn_home_ip_addr));
00879         DEBUG(DEBUG_INFO, ", CurrentAddr: %s\n", inet_ntoa(mn.local_addr));
00880 
00881 
00882         syslog(LOG_INFO, "Started.");
00883 
00884         check_interfaces(mn.iface, MAX_INTERFACES);
00885 
00886 #ifdef DYN_TARGET_WINDOWS
00887         mn.pcap_capturer = init_pcap_for_advs();
00888 #else
00889         mn.pcap_capturer = -1;
00890 #endif /* DYN_TARGET_WINDOWS */
00891 
00892         return 1;
00893 }
00894 
00895 /* Perform clean up: close sockets and log. */
00896 void clean_up(int sig)
00897 {
00898         int i;
00899 
00900         DEBUG(DEBUG_INFO, "cleaning up..\n");
00901 
00902         /* try to disconnect if connected */
00903         if (mn.state == MN_CONNECTED) {
00904                 send_registration(REG_DISC);
00905                 DEBUG(DEBUG_MESSAGES, "Deregistration message sent\n");
00906         }
00907 
00908         if (mn.pcap_capturer > -1) {
00909                 DEBUG(DEBUG_INFO, "Terminating pcap capturer\n");
00910                 kill(mn.pcap_capturer, SIGTERM);
00911                 usleep(100000);
00912                 kill(mn.pcap_capturer, SIGKILL);
00913         }
00914 
00915         if (mn.agentadv != NULL) {
00916                 hashtable_iterator(mn.agentadv, clean_agentadv, NULL);
00917                 hashtable_destroy(mn.agentadv);
00918         }
00919 
00920         /* close sockets */
00921         close(mn.registration_socket);
00922         for (i = 0; i < MAX_INTERFACES; i++) {
00923                 if (mn.iface[i].s > -1)
00924                         close(mn.iface[i].s);
00925                 if (mn.iface[i].s_adv > -1)
00926                         close(mn.iface[i].s_adv);
00927         }
00928         if (mn.api_ro_socket > -1)
00929                 close(mn.api_ro_socket);
00930         if (mn.api_rw_socket > -1)
00931                 close(mn.api_rw_socket);
00932 #ifdef INCLUDE_IPAY
00933         close(mn.ipay_sock);
00934         ipay_cleanup();
00935 #endif
00936         if (mn.rtnetlink_socket > -1)
00937                 close(mn.rtnetlink_socket);
00938 
00939 #ifdef WITH_WIRELESS
00940         /* Remove iwspy entries */
00941         MONITOR_unregister_module();
00942 #endif
00943 
00944         /* stop to any waiting api call */
00945         reply_waiting_api(API_FAILED, NULL, 0);
00946         /* close tunneling device */
00947         close_tunneling();
00948         mn_remove_dynamic_home_addr();
00949 
00950         /* free session key */
00951         if (mn.session_key != NULL)
00952                 free(mn.session_key);
00953 
00954         if (mn.last_req_FA_NAI != NULL)
00955                 free(mn.last_req_FA_NAI);
00956 
00957         /* unlink api domain sockets */
00958         unlink(config.mn_api_read_socket_path);
00959         unlink(config.mn_api_admin_socket_path);
00960 
00961         unlink(MN_PID_FILE);
00962 
00963         /* unregister all handlers */
00964         /* FA_ADV_RECEIVE */
00965         i = handler_unregister_all(FA_ADV_RECEIVE);
00966         DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) "
00967               "removed\n", i, event_type_str(FA_ADV_RECEIVE));
00968         /* FA_ADV_EXPIRE  */
00969         i = handler_unregister_all(FA_ADV_EXPIRE);
00970         DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) "
00971               "removed\n", i, event_type_str(FA_ADV_EXPIRE));
00972         /* FA_GET */
00973         i = handler_unregister_all(FA_GET);
00974         DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) "
00975               "removed\n", i, event_type_str(FA_GET));
00976         /* INTERFACE_INIT */
00977         i = handler_unregister_all(INTERFACE_INIT);
00978         DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) "
00979               "removed\n", i, event_type_str(INTERFACE_INIT));
00980         /* INTERFACE_DOWN */
00981         i = handler_unregister_all(INTERFACE_DOWN);
00982         DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) "
00983               "removed\n", i, event_type_str(INTERFACE_DOWN));
00984 
00985         syslog(LOG_INFO, "stopped");
00986         closelog();
00987 
00988 #ifdef MN_LOCUPD_PROFILER
00989         fclose(mn.profile);
00990 #endif
00991 
00992         DEBUG(DEBUG_INFO, "cleaned up\n");
00993 
00994         exit(0);
00995 }
00996 
00997 
00998 void add_fa_host_route(char *dev, struct hashtable *adv_hash, 
00999                        int ifindex, struct in_addr addr)
01000 {
01001         struct agentadv_data *adv;
01002         adv = adv_fetch(adv_hash, &addr, ifindex);
01003 
01004         if (dyn_ip_route_replace(addr, dev) != 0) {
01005                 if (adv != NULL && adv->routeentry)
01006                         DEBUG(DEBUG_INFO, "Route entry already added for the "
01007                               "FA (%s=>%s)\n", inet_ntoa(addr), dev);
01008                 else
01009                         DEBUG(DEBUG_INFO, "Could not add a route to the FA "
01010                               "(%s=>%s), but trying to register anyway\n",
01011                               inet_ntoa(addr), dev);
01012         } else {
01013                 if (adv != NULL)
01014                         adv->routeentry = 1;
01015                 else
01016                         DEBUG(DEBUG_INFO, "No agentadv for FA %s\n",
01017                               inet_ntoa(addr));
01018         }
01019 }
01020 
01021 
01022 static int clean_routes(struct node *node, void *data)
01023 {
01024         struct agentadv_data *adv, *current;
01025         adv = (struct agentadv_data *) node;
01026         current = (struct agentadv_data *) data;
01027 
01028         if (current == adv) return TRUE; /* do not remove current FA's entry */
01029         if (!adv->routeentry) return TRUE;
01030 
01031         DEBUG(DEBUG_INFO, "Removing FA route (%s,%s)\n",
01032               inet_ntoa(adv->addr), adv->ifname);
01033         if (dyn_ip_route_del(adv->addr, adv->ifname) != 0)
01034                 LOG2(LOG_ERR, "FA route removing failed (addr=%s, dev=%s)\n",
01035                      inet_ntoa(adv->addr), adv->ifname);
01036 
01037         adv->routeentry = 0;
01038         return TRUE;
01039 }
01040 
01041 
01042 void remove_fa_host_routes(int all)
01043 {
01044         DEBUG(DEBUG_INFO, "remove_fa_host_routes(%i)\n", all);
01045         hashtable_iterator(mn.agentadv, clean_routes,
01046                            all ? NULL: mn.current_adv);
01047 }
01048 
01049 
01050 
01051 int is_coloc_addr_foreign(void)
01052 {
01053         char dev[IFNAMSIZ];
01054         if (dyn_ip_route_get(config.mn_home_ip_addr, dev, IFNAMSIZ) != 0 ||
01055             strcmp(dev, "lo") != 0)
01056                 return 1;
01057         return 0;
01058 }
01059 
01060 
01061 int device_up(int ifindex)
01062 {
01063         int i;
01064         for (i = 0; i < MAX_INTERFACES; i++) {
01065                 if (mn.iface[i].s > -1 &&
01066                     mn.iface[i].index == ifindex)
01067                         return 1;
01068         }
01069         return 0;
01070 }
01071 
01072 
01073 char *event_type_str(int event_type)
01074 {
01075         switch (event_type) {
01076         case FA_ADV_RECEIVE:
01077                 return "FA Advertisement receive";
01078         case FA_ADV_EXPIRE:
01079                 return "FA Advertisement expire";
01080         case FA_GET:
01081                 return "Get best FA";
01082         case INTERFACE_INIT:
01083                 return "Initialize interface";
01084         case INTERFACE_DOWN:
01085                 return "Interface down";
01086         default:
01087                 return "Unknown event type!";
01088         }
01089 }
01090 
01091 
01092 
01102 int mn_remove_dynamic_home_addr(void)
01103 {
01104         if (mn.dynamic_home_addr.s_addr == 0)
01105                 return 0;
01106 
01107         if (dyn_ip_addr_del(mn.dynamic_home_addr_dev, mn.dynamic_home_addr) ==
01108             0) {
01109                 DEBUG(DEBUG_INFO, "Dynamic home address '%s' removed from "
01110                       "interface '%s'\n", inet_ntoa(mn.dynamic_home_addr),
01111                       mn.dynamic_home_addr_dev);
01112                 if (config.mn_home_ip_addr.s_addr ==
01113                     mn.dynamic_home_addr.s_addr) {
01114                         DEBUG(DEBUG_INFO, "\treset home address to 0 (use "
01115                               "discovery)\n");
01116                         config.mn_home_ip_addr.s_addr =
01117                                 mn.local_addr.s_addr = 0;
01118                         if (config.ha_ip_addr_orig.s_addr == 0) {
01119                                 DEBUG(DEBUG_INFO, "\treset home agent address "
01120                                       "to 0 (use discovery)\n");
01121                                 config.ha_ip_addr.s_addr = 0;
01122                         }
01123                 } else {
01124                         DEBUG(DEBUG_INFO, "\tDEBUG: config: %s, ",
01125                               inet_ntoa(config.mn_home_ip_addr));
01126                         DEBUG(DEBUG_INFO, "obtained: %s\n",
01127                               inet_ntoa(mn.dynamic_home_addr));
01128                 }
01129 
01130                 mn.dynamic_home_addr.s_addr = 0;
01131                 return 1;
01132         }
01133 
01134         DEBUG(DEBUG_INFO, "Could not remove dynamic home address '%s' "
01135               "from interface '%s'\n", inet_ntoa(mn.dynamic_home_addr),
01136               mn.dynamic_home_addr_dev);
01137         return -1;
01138 }
01139 
01140 
01141 int monitor_check_policy(int bit)
01142 {
01143         return POLICY(bit);
01144 }
01145 
01146 
01147 int copy_str(char *buffer, int len, int *curr, char *str, char *attr)
01148 {
01149         int l;
01150 
01151         l = strlen(str) + strlen(attr) + 1;
01152         if (*curr+l > len) {
01153                 DEBUG(DEBUG_INFO, "copy_str: Not enough room (%d/%d)\n", 
01154                       l, len);
01155                 return 1;
01156         }
01157         sprintf(buffer+*curr, "%s%s\n", str, attr);
01158         *curr += l;
01159 
01160         return 0;
01161 }

Generated on Tue Jan 15 08:50:43 2008 for Virtual foreign agent generator version 0.1 by  doxygen 1.5.1