📄 mn_util.c
字号:
wireless_extensions = 1; while ((c = getopt_long(argc, argv, "+hv", long_options, &oindex)) != EOF) { switch (c) { case 'n': wireless_extensions = 0; break; case 'p': mn.policy_bits = atoi(optarg); /* 0: no timestamps */ /* 1: with timestamps */ DEBUG(DEBUG_INFO, "Option: %s" " 0x%02x (wireless policy)\n", long_options[oindex].name, mn.policy_bits); break; case 'h': /* show MN specific parameters */ show_usage(); exit(1); break; case 'd': mn.opt_connect = 0; break; case '?': printf("Command line parsing failed - aborting\n"); exit(1); case 'v': case 'c': case 0: break; default: printf("getopt returned character code 0%o\n", c); exit(1); } } return 0;}#ifdef DYN_TARGET_WINDOWS/* FIX: currently using local UDP socket on Windows because there is no support * for UNIX domain socket.. maybe something else would be better for IPC on * Windows platform(?) */static int windows_api_socket(int admin){ int s; struct sockaddr_in addr; int flags; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { DEBUG(DEBUG_INFO, "API socket opening failed: %s\n", strerror(errno)); return -1; } flags = fcntl(s, F_GETFL, 0); if (flags == -1 || fcntl(s, F_SETFL, flags | O_NDELAY) == -1) { DEBUG(DEBUG_INFO, "API rw fcntl F_SETFL failed: %s\n", strerror(errno)); close(s); return -1; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl((127 << 24) | 1); addr.sin_port = htons(admin ? API_UDP_PORT_RW : API_UDP_PORT_RO); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { LOG2(LOG_ERR, "API socket - bind: %s\n", strerror(errno)); close(s); return -1; } return s;}#endif/* Initialization routines. Setup sockets and variables. * Returns 1 on success else 0. */int mn_init(void){ int i; /* Load configuration */ DEBUG(DEBUG_INFO, "Load config\n"); if (!load_mn(&config, program_name, opt_config == NULL ? MN_GLOBAL_CONF_FILE : opt_config)) { LOG2(LOG_ERR, "init: unable to load configuration\n"); return 0; } mn.use_auth_alg = config.auth_alg; mn.agentadv = hashtable_init(256); if (mn.agentadv == NULL) { LOG2(LOG_ERR, "init: unable to init agentadv hashtable\n"); return 0; } mn.last_req_FA_NAI = (struct fa_nai_ext *) malloc(MAX_FA_NAI_LEN); if (mn.last_req_FA_NAI == NULL) { LOG2(LOG_ERR, "init: not enough memory\n"); return 0; } memset(mn.last_req_FA_NAI, 0, MAX_FA_NAI_LEN); if (!config.enable_fa_decapsulation) check_kernel_support(CHECK_KERNEL_IPIP); check_kernel_support(CHECK_KERNEL_NETLINK);#ifdef DYN_TARGET_LINUX if (getuid() || geteuid()) { fprintf(stderr, "This program must be run by root.\n"); return 0; }#endif#ifdef DYN_TARGET_WINDOWS /* FIX: on Windows NT and Windows 2000 check for Administrator * privileges */#endif if ((mn.registration_socket = create_registration_socket()) < 0) return 0; mn_handlers_init(); mn.dev_info_addr.sun_family = AF_LOCAL; /* initialize default socket info path */ dynamics_strlcpy(mn.dev_info_addr.sun_path, DEFAULT_DEVICE_INFO_PATH, sizeof(mn.dev_info_addr.sun_path));#ifdef WITH_WIRELESS /* If wireless extensions enabled, monitor will register it's own handlers also */ DEBUG(DEBUG_INFO, "REGISTER MODULE(S)\n"); if (wireless_extensions) MONITOR_register_module();#endif /* Check interfaces */ for (i = 0; i < MAX_INTERFACES; i++) { mn.iface[i].s = -1; mn.iface[i].s_adv = -1; mn.iface[i].handlers_off = 1; }#ifdef INCLUDE_IPAY /* register Ipay handlers after monitor */ ipay_init();#endif if (config.home_net_addr_plen < 0 || dyn_ip_route_get(config.home_net_addr, mn.start_default_device, IFNAMSIZ) != 0) mn.start_default_device[0] = '\0'; else DEBUG(DEBUG_INFO, "Initial default device: %s\n", mn.start_default_device);#ifdef DYN_TARGET_LINUX if ((mn.api_ro_socket = api_open_socket(config.mn_api_read_socket_path, config.mn_api_read_socket_group, config.mn_api_read_socket_owner, config.mn_api_read_socket_permissions)) < 0) { LOG2(LOG_ERR, "init - open_api_ro_socket: %s\n", strerror(errno)); return 0; } if ((mn.api_rw_socket = api_open_socket(config.mn_api_admin_socket_path, config.mn_api_admin_socket_group, config.mn_api_admin_socket_owner, config.mn_api_admin_socket_permissions)) < 0) { LOG2(LOG_ERR, "init - open api_rw_socket: %s\n", strerror(errno)); return 0; }#endif#ifdef DYN_TARGET_WINDOWS mn.api_ro_socket = windows_api_socket(0); mn.api_rw_socket = windows_api_socket(1);#endif#ifdef INCLUDE_IPAY mn.ipay_sock = socket(AF_INET, SOCK_DGRAM, 0); if (mn.ipay_sock < 0) { LOG2(LOG_ERR, "init - open ipay_sock: %s\n", strerror(errno)); return 0; } if (config.ipay_mn_port > 0) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr = config.ipay_mn_addr; addr.sin_port = htons(config.ipay_mn_port); if (bind(mn.ipay_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { LOG2(LOG_ERR, "init - bind ipay_sock: %s\n", strerror(errno)); return 0; } } mn.ipay_sock_fa = socket(AF_INET, SOCK_DGRAM, 0); if (mn.ipay_sock_fa < 0) { LOG2(LOG_ERR, "init - open ipay_sock_fa: %s\n", strerror(errno)); return 0; } if (config.ipay_fa_port > 0) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(config.ipay_fa_port); if (bind(mn.ipay_sock_fa, (struct sockaddr *) &addr, sizeof(addr)) < 0) { LOG2(LOG_ERR, "init - bind ipay_sock_fa: %s\n", strerror(errno)); return 0; } }#endif mn.rtnetlink_socket = dyn_ip_monitor_open(); if (mn.rtnetlink_socket < 0) DEBUG(DEBUG_INFO, "init - rtnetlink socket opening failed\n"); /* set own ip-addr */ mn.local_addr = config.mn_home_ip_addr; init_tunneling(); /* init variables */ mn.registration_id[0] = 0; mn.registration_id[1] = 0; mn.last_nonce = 0; mn.clock_correction = 0; mn.state = MN_DISCONNECTED; mn.fa_addr.s_addr = 0; mn.current_adv = NULL; mn.force_fa_addr.s_addr = 0; mn.session_key = NULL; mn.session_key_len = 0; mn.tunnel_up = 0; mn.tunnel_mode = API_TUNNEL_NONE; mn.ha_error_count = 0; memset(&mn.cur_route_info, 0, sizeof(mn.cur_route_info)); mn.cur_route_info.net.s_addr = config.home_net_addr.s_addr; mn.cur_route_info.prefix_len = config.home_net_addr_plen; timerclear(&mn.last_reg_send_time); for (i = 0; i < TIMER_COUNT; i++) timerclear(&timers[i]); if (config.wlan_ap_poll_interval > -1) gettimeofday(&timers[TIMER_WLAN_AP_POLL], NULL); if (config.solicitation_interval > -1) gettimeofday(&timers[TIMER_SOLICITATION], NULL); openlog(SYSLOG_IDENT, SYSLOG_OPTIONS, config.syslog_facility); dyn_ip_route_save_default(config.home_net_gateway.s_addr != 0 ? &config.home_net_gateway : NULL);#ifdef MN_LOCUPD_PROFILER mn.profile = fopen("mn.prof.log", "a"); if (mn.profile == NULL) { fprintf(stderr, "Cannot open mn.prof.log\n"); return 0; } gettimeofday(&mn.last_api, NULL); fprintf(mn.profile, "START %u.%06u\n", (unsigned int) mn.last_api.tv_sec, (unsigned int) mn.last_api.tv_usec);#endif /* Setup signals */ signal(SIGTERM, clean_up); signal(SIGINT, clean_up); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); if (!opt_foreground && dynamics_fork_daemon() == -1) clean_up(0); dynamics_write_pid_file(MN_PID_FILE); DEBUG(DEBUG_INFO, " MN initialized to %sconnected state,\n" " SPI: %d, HA: %s,\n", (mn.opt_connect ? "" : "dis"), config.spi, inet_ntoa(config.ha_ip_addr)); DEBUG(DEBUG_INFO, " HomeAddr: %s", inet_ntoa(config.mn_home_ip_addr)); DEBUG(DEBUG_INFO, ", CurrentAddr: %s\n", inet_ntoa(mn.local_addr)); syslog(LOG_INFO, "Started."); check_interfaces(mn.iface, MAX_INTERFACES);#ifdef DYN_TARGET_WINDOWS mn.pcap_capturer = init_pcap_for_advs();#else mn.pcap_capturer = -1;#endif /* DYN_TARGET_WINDOWS */ return 1;}/* Perform clean up: close sockets and log. */void clean_up(int sig){ int i; DEBUG(DEBUG_INFO, "cleaning up..\n"); /* try to disconnect if connected */ if (mn.state == MN_CONNECTED) { send_registration(REG_DISC); DEBUG(DEBUG_MESSAGES, "Deregistration message sent\n"); } if (mn.pcap_capturer > -1) { DEBUG(DEBUG_INFO, "Terminating pcap capturer\n"); kill(mn.pcap_capturer, SIGTERM); usleep(100000); kill(mn.pcap_capturer, SIGKILL); } if (mn.agentadv != NULL) { hashtable_iterator(mn.agentadv, clean_agentadv, NULL); hashtable_destroy(mn.agentadv); } /* close sockets */ close(mn.registration_socket); for (i = 0; i < MAX_INTERFACES; i++) { if (mn.iface[i].s > -1) close(mn.iface[i].s); if (mn.iface[i].s_adv > -1) close(mn.iface[i].s_adv); } if (mn.api_ro_socket > -1) close(mn.api_ro_socket); if (mn.api_rw_socket > -1) close(mn.api_rw_socket);#ifdef INCLUDE_IPAY close(mn.ipay_sock); ipay_cleanup();#endif if (mn.rtnetlink_socket > -1) close(mn.rtnetlink_socket);#ifdef WITH_WIRELESS /* Remove iwspy entries */ MONITOR_unregister_module();#endif /* stop to any waiting api call */ reply_waiting_api(API_FAILED, NULL, 0); /* close tunneling device */ close_tunneling(); mn_remove_dynamic_home_addr(); /* free session key */ if (mn.session_key != NULL) free(mn.session_key); if (mn.last_req_FA_NAI != NULL) free(mn.last_req_FA_NAI); /* unlink api domain sockets */ unlink(config.mn_api_read_socket_path); unlink(config.mn_api_admin_socket_path); unlink(MN_PID_FILE); /* unregister all handlers */ /* FA_ADV_RECEIVE */ i = handler_unregister_all(FA_ADV_RECEIVE); DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) " "removed\n", i, event_type_str(FA_ADV_RECEIVE)); /* FA_ADV_EXPIRE */ i = handler_unregister_all(FA_ADV_EXPIRE); DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) " "removed\n", i, event_type_str(FA_ADV_EXPIRE)); /* FA_GET */ i = handler_unregister_all(FA_GET); DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) " "removed\n", i, event_type_str(FA_GET)); /* INTERFACE_INIT */ i = handler_unregister_all(INTERFACE_INIT); DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) " "removed\n", i, event_type_str(INTERFACE_INIT)); /* INTERFACE_DOWN */ i = handler_unregister_all(INTERFACE_DOWN); DEBUG(DEBUG_HANDLERS, "clean_up: %d \"%s\" handler(s) " "removed\n", i, event_type_str(INTERFACE_DOWN)); syslog(LOG_INFO, "stopped"); closelog();#ifdef MN_LOCUPD_PROFILER fclose(mn.profile);#endif DEBUG(DEBUG_INFO, "cleaned up\n"); exit(0);}void add_fa_host_route(char *dev, struct hashtable *adv_hash, int ifindex, struct in_addr addr){ struct agentadv_data *adv; adv = adv_fetch(adv_hash, &addr, ifindex); if (dyn_ip_route_replace(addr, dev) != 0) { if (adv != NULL && adv->routeentry) DEBUG(DEBUG_INFO, "Route entry already added for the " "FA (%s=>%s)\n", inet_ntoa(addr), dev); else DEBUG(DEBUG_INFO, "Could not add a route to the FA " "(%s=>%s), but trying to register anyway\n", inet_ntoa(addr), dev); } else { if (adv != NULL) adv->routeentry = 1; else DEBUG(DEBUG_INFO, "No agentadv for FA %s\n", inet_ntoa(addr)); }}static int clean_routes(struct node *node, void *data){ struct agentadv_data *adv, *current; adv = (struct agentadv_data *) node; current = (struct agentadv_data *) data; if (current == adv) return TRUE; /* do not remove current FA's entry */ if (!adv->routeentry) return TRUE; DEBUG(DEBUG_INFO, "Removing FA route (%s,%s)\n", inet_ntoa(adv->addr), adv->ifname); if (dyn_ip_route_del(adv->addr, adv->ifname) != 0) LOG2(LOG_ERR, "FA route removing failed (addr=%s, dev=%s)\n", inet_ntoa(adv->addr), adv->ifname); adv->routeentry = 0; return TRUE;}void remove_fa_host_routes(int all){ DEBUG(DEBUG_INFO, "remove_fa_host_routes(%i)\n", all); hashtable_iterator(mn.agentadv, clean_routes, all ? NULL: mn.current_adv);}int is_coloc_addr_foreign(void){ char dev[IFNAMSIZ]; if (dyn_ip_route_get(config.mn_home_ip_addr, dev, IFNAMSIZ) != 0 || strcmp(dev, "lo") != 0) return 1; return 0;}int device_up(int ifindex){ int i; for (i = 0; i < MAX_INTERFACES; i++) { if (mn.iface[i].s > -1 && mn.iface[i].index == ifindex) return 1; } return 0;}char *event_type_str(int event_type){ switch (event_type) { case FA_ADV_RECEIVE: return "FA Advertisement receive"; case FA_ADV_EXPIRE: return "FA Advertisement expire"; case FA_GET: return "Get best FA"; case INTERFACE_INIT: return "Initialize interface"; case INTERFACE_DOWN: return "Interface down"; default: return "Unknown event type!"; }}/** * mn_remove_dynamic_home_addr: * * Remove dynamic home address from interface if it is maintained by * Dynamics MN. * * Returns: 1 on success (address removed), 0 if no dynamic home address, or * -1 on failure */int mn_remove_dynamic_home_addr(void){ if (mn.dynamic_home_addr.s_addr == 0) return 0; if (dyn_ip_addr_del(mn.dynamic_home_addr_dev, mn.dynamic_home_addr) == 0) { DEBUG(DEBUG_INFO, "Dynamic home address '%s' removed from " "interface '%s'\n", inet_ntoa(mn.dynamic_home_addr), mn.dynamic_home_addr_dev); if (config.mn_home_ip_addr.s_addr == mn.dynamic_home_addr.s_addr) { DEBUG(DEBUG_INFO, "\treset home address to 0 (use " "discovery)\n"); config.mn_home_ip_addr.s_addr = mn.local_addr.s_addr = 0; if (config.ha_ip_addr_orig.s_addr == 0) { DEBUG(DEBUG_INFO, "\treset home agent address " "to 0 (use discovery)\n"); config.ha_ip_addr.s_addr = 0; } } else { DEBUG(DEBUG_INFO, "\tDEBUG: config: %s, ", inet_ntoa(config.mn_home_ip_addr)); DEBUG(DEBUG_INFO, "obtained: %s\n", inet_ntoa(mn.dynamic_home_addr)); } mn.dynamic_home_addr.s_addr = 0; return 1; } DEBUG(DEBUG_INFO, "Could not remove dynamic home address '%s' " "from interface '%s'\n", inet_ntoa(mn.dynamic_home_addr), mn.dynamic_home_addr_dev); return -1;}int monitor_check_policy(int bit){ return POLICY(bit);}int copy_str(char *buffer, int len, int *curr, char *str, char *attr){ int l; l = strlen(str) + strlen(attr) + 1; if (*curr+l > len) { DEBUG(DEBUG_INFO, "copy_str: Not enough room (%d/%d)\n", l, len); return 1; } sprintf(buffer+*curr, "%s%s\n", str, attr); *curr += l; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -