⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mn_util.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: mn_util.c,v 1.89 2001/10/20 14:20:38 jm Exp $ * Mobile Node - help functions * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <getopt.h>#include <signal.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <assert.h>#ifdef DYN_TARGET_WINDOWS#include <fcntl.h>#endif#include "debug.h"#include "dyn_ip.h"#include "proxyarp.h"#include "agentapi.h"#include "util.h"#ifdef WITH_WIRELESS#include "monitor.h"#endif#include "mn_handler.h"#include "mn.h"#include "mn_tunnel.h"#ifdef INCLUDE_IPAY#include "mn_ipay.h"#endif#include "device_info.h"extern struct mn_data mn;extern struct mn_config config;extern struct timeval timers[TIMER_COUNT];extern char* program_name;extern char *opt_config;extern int opt_foreground;extern int real_tunnel_up; /* from mn_tunnel */static int wireless_extensions;/** * check_ignore_iface: * @ifname: Interface name * * Check whether an interface is to be ignored * * Returns: 1 if it should be ignored, else 0 */static int check_ignore_iface(const char *ifname){	struct ignore_iflist_entry *i;	struct node *node;	if (strcmp(ifname, TUNNEL_DEVICE) == 0)			return 1;	if (strcmp(ifname, TUNNEL_DEVICE_B) == 0) 		return 1;	for (node = list_get_first(&config.ignore_iflist); node != NULL;	     node = list_get_next(node)) {		i = (struct ignore_iflist_entry *)node;		if (strncmp(ifname, i->ifname, IFNAMSIZ) == 0) 			return 1;	}	return 0;}struct fa_spi_entry* get_fa_spi(int spi, struct in_addr addr){	struct fa_spi_entry *s;	struct node *node;	time_t now;	time(&now);	node = list_get_first(&config.fa_spi_list);	while (node != NULL) {		s = (struct fa_spi_entry *) node;		node = list_get_next(node);		/* Expire dynamic entries that are not infinite (lifetime=0) */		if (s->created != 0 && s->lifetime != 0 &&		    now > s->created + s->lifetime) {			DEBUG(DEBUG_INFO, "get_fa_spi: dynamic "			      "security association (SPI=%i, addr=%s) "			      "expired\n", s->spi, inet_ntoa(s->addr));			list_remove((struct node *) s);			free(s);			continue;		}		if ((spi != 0 && s->spi != spi) ||		    s->addr.s_addr != addr.s_addr)			continue;		return s;	}	return NULL;}int add_fa_spi(struct fa_spi_entry *spi, int replace_any_spi){	struct fa_spi_entry *old;	old = get_fa_spi(replace_any_spi ? 0 : spi->spi, spi->addr);	if (old != NULL) {		if (old->created == 0) {			DEBUG(DEBUG_INFO, "add_fa_spi: trying to replace "			      "static security association - aborting "			      "operation\n");			return -1;		}		DEBUG(DEBUG_INFO, "add_fa_spi: overwriting previous dynamic "		      "security association\n");		remove_fa_spi(old);		free(old);		old = NULL;	}	DEBUG(DEBUG_INFO, "add_fa_spi: adding dynamic security association "	      "(SPI=%i, addr=%s)\n", spi->spi, inet_ntoa(spi->addr));	list_init_node(&spi->node);	list_add_tail(&config.fa_spi_list, &spi->node);	return 0;}void remove_fa_spi(struct fa_spi_entry *spi){	DEBUG(DEBUG_INFO, "remove_fa_spi: removing security association "	      "(SPI=%i, addr=%s)\n", spi->spi, inet_ntoa(spi->addr));	list_remove(&spi->node);}/**  * send_gratuitous_arp: * @route_addr:  * @gratuituous_addr: * * A gratuituous arp message for address @gratuitous_addr will be sent  * on the interface where there is a route to @route_addr. */void send_gratuitous_arp(struct in_addr route_addr, 			 struct in_addr gratuitous_addr){	char arp_if[IFNAMSIZ];	if (dyn_ip_route_get(route_addr, arp_if, IFNAMSIZ) != 0) {		DEBUG(DEBUG_INFO, "Could not get ARP interface\n");		return;	}	proxyarp_gratuitous(gratuitous_addr, arp_if);}#ifdef MN_LOCUPD_PROFILERvoid write_profiler(const char *msg){	struct timeval tv;	gettimeofday(&tv, NULL);	fprintf(mn.profile, "%s %u.%06u (%li usec)\n", msg,		(unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec,		(tv.tv_sec - mn.last_api.tv_sec) * 1000000 +		tv.tv_usec - mn.last_api.tv_usec);}#endif/** * update_fa_decsps_routes: * @ifname: interface name * @ifindex: interface index @ifname * @fa_addr: foreign agent addres * @home_net_addr: home network addres * @home_net_addr_plen: home network prefix length, -1 if no *   home network * * Set the default route to @ifname via @fa_addr and delete all * routes to @home_net_addr/@home_net_addr_plen. * * Returns: 0 if successful */int update_fa_decaps_routes(const char *ifname, int ifindex, 			    struct in_addr fa_addr, 			    struct in_addr home_net_addr, 			    int home_net_addr_plen){	DEBUG(DEBUG_INFO, "FA decapsulation - setting default route to "	      "%s via %s\n", ifname, inet_ntoa(fa_addr));	mn.cur_route_info.known = 1;	mn.cur_route_info.via.s_addr = fa_addr.s_addr;	mn.cur_route_info.ifindex = ifindex;	memcpy(mn.cur_route_info.ifname, ifname, IFNAMSIZ);	mn.cur_route_info.ifindex_net = -1;	if (dyn_ip_route_replace_default(ifname, &fa_addr,					 &config.mn_home_ip_addr) != 0) {		LOG2(LOG_ERR, "Set default route (to %s via %s) failed\n",		     ifname, inet_ntoa(fa_addr));		return -1;	}	if (home_net_addr_plen > -1) {		int count;		DEBUG(DEBUG_INFO, "Deleting home net route (%s/%i)\n",		      inet_ntoa(home_net_addr), home_net_addr_plen);		count = dyn_ip_route_delete_net_routes(&home_net_addr,						       home_net_addr_plen);		if (count < 0) {			LOG2(LOG_ERR, "Home net route (%s/%i) delete failed\n",			     inet_ntoa(home_net_addr), home_net_addr_plen);#ifdef DYN_TARGET_WINDOWS			/* at least Win98 does not seem to like to remove			 * home net route.. */			DEBUG(DEBUG_INFO, "Trying to set net route via the FA "			      "to circumvent failed net route removal\n");			if (dyn_ip_route_set_net(ifname, &home_net_addr,						 home_net_addr_plen,						 NULL, 2) < 0) {				DEBUG(DEBUG_INFO, "Could not increase home "				      "net route metric\n");			}			if (dyn_ip_route_set_net(ifname, &home_net_addr,						 home_net_addr_plen,						 &fa_addr, 1) < 0) {				DEBUG(DEBUG_INFO, "Could not set net route via"				      " FA\n");			} else				mn.home_net_route_set_via_fa = 1;#endif /* DYN_TARGET_WINDOWS */		} else {			DEBUG(DEBUG_INFO,			      "   %i net route%s deleted\n", count,			      count != 1 ? "s" : "");		}	}	return 0;}/** * modify_new_interface: * @iface: new or removed interface * @idx: interface map */static void modify_new_interface(struct interface_data *iface, 				 struct idxmap *idx){	struct event_INTERFACE data;	int ret;	DEBUG(DEBUG_INFO, "modify_new_interface (start): device_count %d\n",	      mn.device_count);	if (config.enable_fa_decapsulation) {		ret = dyn_ip_iface_address(idx->index, 					   &config.mn_home_ip_addr);		if ((ret == 2 || ret == 0) &&		    config.use_aaa &&		    config.mn_home_ip_addr.s_addr == 0 &&		    config.enable_fa_decapsulation) {			DEBUG(DEBUG_INFO, "modify_interface: interface with no"			      " addresses - using AAA to obtain a home "			      "address\n");		} else {			if (ret == 0) {				DEBUG(DEBUG_INFO, "FA decapsulation and an "				      "interface does not have the home "				      "address\n");				mn.warn_str = "FA decapsulation and an "					"interface does not have the home "					"address";				return;			}			/* continue only if the interface has a correct			 * address */			if (ret != 1) {				DEBUG(DEBUG_INFO, "modify_interface: no "				      "addresses found (ret=%i)\n", ret);				return;			}		}	}	if (iface->handlers_off == 1) {		DEBUG(DEBUG_INFO, "modify_interface: interface up\n");		memset(&data, 0, sizeof(data));		data.iface = iface;		data.ifname = iface->device;		data.index = &iface->index;		data.icmp_sock = &iface->s;		data.icmp_sock_adv = &iface->s_adv;		assert(idx != NULL);		data.idx = idx;		data.last_reg_send_time = &mn.last_reg_send_time;		data.current_adv = &mn.current_adv;		data.priority = &iface->priority;		ret = handler_call_all(INTERFACE_INIT, &data);		if (ret == -1) {			DEBUG(DEBUG_INFO, "modify_interface: interface "			      "initialization failed\n");			return;		}		iface->handlers_off = 0;		if (config.enable_fa_decapsulation &&		    mn.current_adv != NULL &&		    real_tunnel_up) {			DEBUG(DEBUG_INFO, "modify_new_interface: fix possibly "			      "changed routing entries\n");			update_fa_decaps_routes(mn.current_adv->ifname,						mn.current_adv->ifindex,						mn.fa_addr,						config.home_net_addr,						config.home_net_addr_plen);		}	} 	mn.device_count++;	DEBUG(DEBUG_INFO, "modify_new_interface (end): device_count %d\n",	      mn.device_count);	/* go from passive find to find agent state if a new interface is up	 * and there was previously no interfaces available OR if the current 	 * adv. was removed */	if ((mn.device_count == 1 && mn.state == MN_PASSIVE_FIND) ||	    (mn.current_adv == NULL && mn.state != MN_DISCONNECTED)) {		find_agent(STATE_INIT);	}}/** * modify_removed_interface: * @iface: interface */static void modify_removed_interface(struct interface_data *iface){	struct event_INTERFACE data;	int ret;	DEBUG(DEBUG_INFO, "modify_remved_interface (start): device_count %d\n",	      mn.device_count);	if (iface->handlers_off != 1) {		DEBUG(DEBUG_INFO, "modify_removed_interface: interface down\n");		memset(&data, 0, sizeof(data));		data.ifname = iface->device;		data.index = &iface->index;		data.icmp_sock = &iface->s;		data.icmp_sock_adv = &iface->s_adv;		ret = handler_call_all(INTERFACE_DOWN, &data);		if (ret == -1) {			DEBUG(DEBUG_INFO, "modify_interface: interface "			      "down failed\n");			return;		}		iface->handlers_off = 1;	} 	mn.device_count--;	if (mn.device_count < 0) {		DEBUG(DEBUG_INFO, "modify_interface: device "		      "count < 0!\n");		mn.device_count = 0;	}	DEBUG(DEBUG_INFO, "modify_remived_interface (end): device_count %d\n",	      mn.device_count);	/* go from passive find to find agent state if the current 	 * adv. was removed */	if (mn.current_adv == NULL && mn.state != MN_DISCONNECTED) {		find_agent(STATE_INIT);	}}/** * check_interfaces: * @iface: array of interfaces * @iface_num: number of interfaces in @iface *  * Check whether new interfaces can be detected or if an interface  * has been removed * * Returns: 0 if successfully executed, 1 on error */int check_interfaces(struct interface_data *iface, int iface_num){	int i;	struct idxmap *idxmap, *idx;	idxmap = dyn_ip_get_interface_map();	if (idxmap == NULL) {		DEBUG(DEBUG_INFO, "check_interfaces: interface map could "		      "not be created\n");		return 1;	}	/* remove the ignored interfaces */	/* FIX: add list of interfaces to be ignored to dynmnd.conf and try to	 * eliminate 'virtual' interfaces like tunnels etc. */	idx = idxmap;	while (idx != NULL) {		if (check_ignore_iface(idx->name) ||		    (dyn_ip_get_ifflags(idx->name) & IFF_UP) == 0)			idx->index = -1;		idx = idx->next;	}	/* check removed interfaces */	for (i = 0; i < iface_num; i++) {		idx = idxmap;		while (idx != NULL) {			if (iface[i].index == idx->index)				break;			idx = idx->next;		}				if (iface[i].s > -1) {			if (idx != NULL) {				/* mark the interface used */				idx->index = -1;			} else {							DEBUG(DEBUG_INFO, "check_interfaces: "				      "removed interface\n");				/* this interface has been removed */				modify_removed_interface(&iface[i]);			}		}	}		/* check new interfaces */	idx = idxmap;	while (idx != NULL) {		if (idx->index == -1) {			idx = idx->next;			continue;		}		/* find a free slot */		i = 0;		while (i < iface_num && iface[i].s > -1) i++;		if (i >= iface_num) {			DEBUG(DEBUG_INFO, "Not enough space for all "			      "the interfaces\n");			break;		}		/* call handlers for INTERFACE_INIT event */		DEBUG(DEBUG_INFO, "check_interfaces: new interface\n");		modify_new_interface(&iface[i], idx);		idx = idx->next;	}	dyn_ip_free_interface_map(idxmap);	return 0;}/** * create_registration_socket: * * Create registration socket and bind it to specified port. * * Returns: created socket or -1 on error.  */int create_registration_socket(void){	int s;	unsigned char ttl;#ifdef BIND_UDP_SOCKET	struct sockaddr_in addr;#endif	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {		LOG2(LOG_ERR, "create_reg_socket - socket: %s\n",		     strerror(errno));		return -1;	}#ifdef BIND_UDP_SOCKET	memset(&addr, 0, sizeof(addr));	addr.sin_family = AF_INET;	addr.sin_addr.s_addr = config.bind_addr.s_addr;	addr.sin_port = config.bind_port;	DEBUG(DEBUG_INFO, "binding UDP socket to %s:%i\n",	      inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		LOG2(LOG_ERR, "create_reg_socket - bind: %s\n",		     strerror(errno));		return -1;	}#endif	if (config.socket_priority > -1 &&	    setsockopt(s, SOL_SOCKET, SO_PRIORITY,		       (char *)&config.socket_priority,		       sizeof(config.socket_priority)) < 0) {		LOG2(LOG_ERR,		     "create_reg_socket - setsockopt SO_PRIORITY: %s\n",		     strerror(errno));		/* continue without SO_PRIORITY set */	}	/* send registration request with TTL 255 [RFC 2344, Chap. 3.2] */	ttl = 255;	if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {		LOG2(LOG_ERR, "setsockopt: IP_TTL failed: %s\n",		     strerror(errno));		/* continue with the default setting anyway */#ifdef DYN_TARGET_WINDOWS		if (dyn_ip_set_ttl(255) < 0) {			DEBUG(DEBUG_INFO, "Also dyn_ip_set_ttl() failed\n");		}#endif /* DYN_TARGET_WINDOWS */	}	return s;}static void show_usage(void){	printf("      --wireless_policy <integer>\n"	       "\t\tset wireless handoff policy (1=on, 0=off):\n"	       "\t\t  bit 0: rely on MN's agent adv. expiration\n"	       "\t\t  bit 1: use shorter agent adv. expiration interval\n"	       "\t\t  bit 2: use FA with newest agent advertisement\n"	       "\t\t  bit 3: eager switching\n"	       "\t\t  bit 4: use newest agent advertisement\n"	       "      --no-wireless\tdisable wireless extensions\n"	       "      --disconnect\tstart in disconnected state\n");}int mn_parse_command_line(int argc, char *argv[]){	int c, oindex = 0;	static struct option long_options[] = {		{"help", no_argument, NULL, 'h'},		{"version", no_argument, NULL, 'v'},		{"debug", no_argument, NULL, 0},		{"fg", no_argument, NULL, 0},		{"config", required_argument, NULL, 'c'},		/* MN specific arguments */		{"no-wireless", no_argument, NULL, 'n'},		{"wireless_policy", required_argument, NULL, 'p'},		{"disconnect", no_argument, NULL, 'd'},		/* end of arguments */		{0, 0, 0, 0}	};	mn.opt_connect = 1;	mn.policy_bits = 0;	/* parse mn specific options */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -