00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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;
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
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
00237
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
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
00302
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
00349
00350
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
00395
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
00424
00425
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
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
00446 idx->index = -1;
00447 } else {
00448 DEBUG(DEBUG_INFO, "check_interfaces: "
00449 "removed interface\n");
00450
00451 modify_removed_interface(&iface[i]);
00452 }
00453 }
00454 }
00455
00456
00457 idx = idxmap;
00458 while (idx != NULL) {
00459 if (idx->index == -1) {
00460 idx = idx->next;
00461 continue;
00462 }
00463
00464
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
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
00527 }
00528
00529
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
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
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
00571 {"no-wireless", no_argument, NULL, 'n'},
00572 {"wireless_policy", required_argument, NULL, 'p'},
00573 {"disconnect", no_argument, NULL, 'd'},
00574
00575 {0, 0, 0, 0}
00576 };
00577
00578 mn.opt_connect = 1;
00579 mn.policy_bits = 0;
00580
00581
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
00592
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
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
00629
00630
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
00668
00669 int mn_init(void)
00670 {
00671 int i;
00672
00673
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
00706
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
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
00720
00721 DEBUG(DEBUG_INFO, "REGISTER MODULE(S)\n");
00722 if (wireless_extensions)
00723 MONITOR_register_module();
00724 #endif
00725
00726
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
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
00817 mn.local_addr = config.mn_home_ip_addr;
00818
00819 init_tunneling();
00820
00821
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
00865 signal(SIGTERM, clean_up);
00866 signal(SIGINT, clean_up);
00867 signal(SIGHUP, SIG_IGN);
00868 signal(SIGPIPE, SIG_IGN);
00869
00870
00871
00872
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
00891
00892 return 1;
00893 }
00894
00895
00896 void clean_up(int sig)
00897 {
00898 int i;
00899
00900 DEBUG(DEBUG_INFO, "cleaning up..\n");
00901
00902
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
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
00941 MONITOR_unregister_module();
00942 #endif
00943
00944
00945 reply_waiting_api(API_FAILED, NULL, 0);
00946
00947 close_tunneling();
00948 mn_remove_dynamic_home_addr();
00949
00950
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
00958 unlink(config.mn_api_read_socket_path);
00959 unlink(config.mn_api_admin_socket_path);
00960
00961 unlink(MN_PID_FILE);
00962
00963
00964
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
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
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
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
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;
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 }