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

📄 tunnel.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		DEBUG(DEBUG_FLAG, "Marking tunnel %s to %s removable\n",		      data->device, inet_ntoa(data->dst_addr));		data->do_not_remove = 0;	}	return 1;}/** * tunnel_set_remove_all: * @hash:	The pointer to the tunnel hash table * @dst_addr:	The remote end-point of the tunnels to be modified * * Mark all the tunnels to @dst_addr removable. */void tunnel_set_remove_all(HASH *hash, struct in_addr dst_addr){	hashtable_iterator(hash, set_remove_iter, &dst_addr);}/* Help function for tunnel_connect() */static int new_table_to_ha(char *dev){	int i;	i = 0;	while (i < MAX_TABLE_COUNT && DYN_BIT(table_numbers, i)) i++;	if (i >= MAX_TABLE_COUNT) {		LOG2(LOG_WARNING, "tunnel_connect: "		     "no space for a new routing table\n");		return -1;	}	if (dyn_ip_route_add_table(dev, i, NULL) != 0) {		LOG2(LOG_WARNING, "tunnel_connect: "		     "dyn_ip_route_add_table failed\n");		return -1;	}	DEBUG(DEBUG_FLAG, "\treserving to HA table %i\n", i);	DYN_SET_BIT(table_numbers, i);	debug_print_bitfield("TABLE_NUMBERS", table_numbers, MAX_TABLE_INTS);	return i;}/* Help function for tunnel_connect() */static int new_table_to_mn(char *dev){	int i;	i = 0;	while (i < MAX_TABLE_COUNT && DYN_BIT(table_numbers, i)) i++;	if (i >= MAX_TABLE_COUNT) {		DEBUG(DEBUG_FLAG, "\tno space for new routing table\n");		return -1;	}	DEBUG(DEBUG_FLAG, "\treserving to MN table %i\n", i);	DYN_SET_BIT(table_numbers, i);	debug_print_bitfield("TABLE_NUMBERS", table_numbers, MAX_TABLE_INTS);	/* add default blackhole */	if (dyn_ip_route_add_blackhole(i) != 0) {		LOG2(LOG_WARNING, "tunnel_connect: Could not "		     "initialize a routing table for MNs\n");		return -1;	}	/* add rule for MN host routes */	if (dyn_ip_rule_add_table(NULL, NULL, i, dev) != 0) {		LOG2(LOG_WARNING, "tunnel_connect: "		     "could not add rule for the MN routing table\n");		return -1;	}	return i;}/** * tunnel_connect: * @up:       The pointer to the upwards tunnel device * @down:     The pointer to the downwards tunnel device * @mn_addr:  The home address of the mobile node * @reverse:  1 = add reverse tunneling rule, 0 = no reverse tunneling * @force_route_dev:	a device name forced to the routing entry (to be used *                      with FA decaps and encapsulating delivery) or *			%NULL to not force the device name * @force_reverse_dev:	a device name forced to the reverse routing rule (to be *                      used with MN decaps without encapsulating delivery) or *			%NULL to not force the device name * * Connect two tunnels (@up and @down) to each other, i.e., set the routing * entries and rules to forward the packets between these tunnels for the * given @mn_addr. * * Returns: -1 on failure or 0 on success */inttunnel_connect(TUNNEL *up, TUNNEL *down, struct in_addr mn_addr, int reverse,	       char *force_route_dev, char *force_reverse_dev){	struct delayed_connection_deletion *tmp;	char *dev;	if (up == NULL || down == NULL)		return -1;	DEBUG(DEBUG_FLAG, "tunnel_connect: %s => %s\n", down->device,	      up->device);	down->direction = TUNNEL_DOWN;	up->direction = TUNNEL_UP;	if (up->to_ha_table_id == -1) {		/* make a default route to a tunnel device to a new routing		 * table */		up->to_ha_table_id = new_table_to_ha(up->device);		if (up->to_ha_table_id < 0)			return -1;	}	if (up->to_mn_table_id == -1) {		/* make the routing table for MN host routes */		up->to_mn_table_id = new_table_to_mn(up->device);		if (up->to_mn_table_id < 0)			return -1;	}	/* add host route to the MN */	dev = (force_route_dev && force_route_dev[0] != '\0')		? force_route_dev : down->device;	DEBUG(DEBUG_FLAG, "\troute replace: addr=%s, dev=%s, table=%i\n",	      inet_ntoa(mn_addr), dev, up->to_mn_table_id);	if (dyn_ip_route_replace_table(mn_addr, dev, up->to_mn_table_id) == -1)	{		LOG2(LOG_WARNING, "tunnel_connect: could not add host route to"		     " the MN\n");		return -1;	}	/* remove the deletion of the possible replaced routing entry from the	 * delayed unconnect priority queue */	tmp = delayed;	while (tmp != NULL) {		if (tmp->delete_route &&		    tmp->mn_addr.s_addr == mn_addr.s_addr &&		    tmp->to_mn_table_id == up->to_mn_table_id) {			DEBUG(DEBUG_FLAG,			      "\tremoved delayed route deletion (addr=%s, "			      "to_mn_table_id=%i, route_dev=%s, "			      "reverse_dev=%s\n",			      inet_ntoa(tmp->mn_addr), tmp->to_mn_table_id,			      tmp->route_dev, tmp->reverse_dev);			tmp->delete_route = 0;		}			   		tmp = tmp->next;	}	if (reverse) {		/* set reverse tunnel - use source routing		 * (MN->HA direction data) */		dev = (force_reverse_dev && force_reverse_dev[0] != '\0')			? force_reverse_dev : down->device;		DEBUG(DEBUG_FLAG, "\tdyn_ip_rule_add_table: "		      "addr=%s, table_id=%i, dev=%s\n",		      inet_ntoa(mn_addr), up->to_ha_table_id, dev);		if (dyn_ip_rule_add_table(&mn_addr, NULL, up->to_ha_table_id,					  dev) != 0) {			DEBUG(DEBUG_FLAG, "\tdyn_ip_rule_add_table failed!\n");			return -1;		}	}	return 0;}/* The local function to remove the real tunnel connection after some delay * (or immediately if the unconnect is forced) */static inttunnel_unconnect_real(struct delayed_connection_deletion *entry){	int ret = 0;	if (entry == NULL)		return -1;	DEBUG(DEBUG_FLAG, "tunnel_unconnect_real - MN=%s, reverse=%i, "	      "to_ha_table_id=%i, to_mn_table_id=%i, "	      "route_dev=%s, reverse_dev=%s\n",	      inet_ntoa(entry->mn_addr), entry->reverse, entry->to_ha_table_id,	      entry->to_mn_table_id, entry->route_dev, entry->reverse_dev);	if (entry->reverse && entry->to_ha_table_id != -1 &&	    dyn_ip_rule_del_table(&entry->mn_addr, NULL, entry->to_ha_table_id,				  entry->reverse_dev) != 0) {		DEBUG(DEBUG_FLAG, "tunnel_unconnect_real: could not remove "		      "associated rule\n");		ret = -1;	}	/* remove the host route from to_mn_table_id (down tunnels) */	if (entry->delete_route && entry->to_mn_table_id != -1) {		DEBUG(DEBUG_FLAG, "\tdelete route: addr=%s, dev=%s, "		      "table=%i\n", inet_ntoa(entry->mn_addr),		      entry->route_dev, entry->to_mn_table_id);	}	if (entry->delete_route && entry->to_mn_table_id != -1 &&	    dyn_ip_route_del_table(entry->route_dev, entry->to_mn_table_id,				   &entry->mn_addr) == -1) {		LOG2(LOG_WARNING, "tunnel_unconnect_real: could not remove "		     "host route to the MN\n");		ret = -1;	}	return ret;}/** * tunnel_unconnect: * @up:       The pointer to the upwards tunnel device * @down:     The pointer to the downwards tunnel device * @mn_addr:  The home address of the mobile node * @reverse:  1 = add reverse tunneling rule, 0 = no reverse tunneling * @force:   0 = delayed unconnect, 1 = forced unconnect  * @force_route_dev:	a device name forced to the routing entry (to be used *                      with FA decaps and encapsulating delivery) or *			%NULL to not force the device name * @force_reverse_dev:	a device name forced to the reverse routing rule (to be *                      used with MN decaps without encapsulating delivery) or *			%NULL to not force the device name * * Unconnect the tunnels connected with tunnel_connect(). *  * Returns: -1 on failure or 0 on success  */inttunnel_unconnect(TUNNEL *up, TUNNEL *down, struct in_addr mn_addr, int reverse,		 int force, char *force_route_dev, char *force_reverse_dev){	struct delayed_connection_deletion *entry, *tmp;	if (up == NULL || down == NULL)		return -1;	DEBUG(DEBUG_FLAG, "tunnel_unconnect - up[dev=%s,tables=%i,%i], "	      "down[dev=%s,tables=%i,%i], MN=%s, reverse=%i, force=%i\n",	      up->device, up->to_ha_table_id, up->to_mn_table_id,	      down->device, down->to_ha_table_id, down->to_mn_table_id,	      inet_ntoa(mn_addr), reverse, force);	entry = (struct delayed_connection_deletion *)		malloc(sizeof(struct delayed_connection_deletion));	if (entry == NULL) {		LOG2(LOG_WARNING, "tunnel_unconnect - out of memory\n");		return -1;	}	memset(entry, 0, sizeof(struct delayed_connection_deletion));	gettimeofday(&entry->timeout, NULL);	entry->timeout.tv_usec += DELAY_UNCONNECTION_USEC;	if (entry->timeout.tv_usec > 999999) {		entry->timeout.tv_usec += entry->timeout.tv_usec / 1000000;		entry->timeout.tv_usec %= 1000000;	}	entry->mn_addr = mn_addr;	entry->reverse = reverse;	entry->delete_route = 1;	entry->to_ha_table_id = up->to_ha_table_id;	entry->to_mn_table_id = up->to_mn_table_id;	memcpy(entry->route_dev,	       (force_route_dev && force_route_dev[0] != '\0')	       ? force_route_dev : down->device, IFNAMSIZ);	memcpy(entry->reverse_dev,	       (force_reverse_dev && force_reverse_dev[0] != '\0')	       ? force_reverse_dev : down->device, IFNAMSIZ);#ifdef REMOVE_BINDING_OPTIM	/* remove delayed unconnect optimization for comparison measurements */	force = 1;#endif	if (force) {		int ret = tunnel_unconnect_real(entry);		free(entry);		return ret;	}	/* add the entry to the priority queue to be removed after some time */	if (delayed == NULL) {		/* first entry in the priority queue */		delayed = entry;		return 0;	}	if (cmp_timeval(&delayed->timeout, &entry->timeout) > 0) {		/* replaces the head of the priority queue */		entry->next = delayed;		delayed = entry;		return 0;	}	tmp = delayed;	while (tmp->next != NULL &&	       cmp_timeval(&tmp->next->timeout, &entry->timeout) <= 0)		tmp = tmp->next;	entry->next = tmp->next;	tmp->next = entry;	return 0;}/** * tunnel_check_delayed: * @hash:	The pointer to the tunnel hash table * @force: *    0 = do not force the deletion, *    1 = force deletion even if the entries have not timed out yet, *    2 = force only the deletion of not yet timed out connections * * Check and remove the delayed connection and tunnel deletions that have * expired. */voidtunnel_check_delayed(HASH *hash, int force){	static time_t prev_check = 0;	struct timeval now;	gettimeofday(&now, NULL);	/* check delayed priority queue */	while (delayed != NULL &&	       (force || cmp_timeval(&delayed->timeout, &now) <= 0)) {		struct delayed_connection_deletion *prev;		DEBUG(DEBUG_FLAG, "tunnel_check_delayed - deleting entry - "		      "now=%li.%li, timeout=%li.%li\n", now.tv_sec,		      now.tv_usec, delayed->timeout.tv_sec,		      delayed->timeout.tv_usec);		tunnel_unconnect_real(delayed);		prev = delayed;		delayed = delayed->next;		free(prev);	}	/* check the tunnels if enought time has passed from the previous	 * check */	if (force != 1 && prev_check <= now.tv_sec &&	    now.tv_sec < prev_check + PURGE_TUNNEL_TIME)		return;	prev_check = now.tv_sec;	hashtable_iterator(hash, check_tunnel, force == 1 ? NULL : &now);}/**  * tunnel_delete_ptr: * @data:	The pointer to the tunnel entry to be deleted. * @force:	1 = the tunnel will be removed immediately, *		0 = the deletion is delayed * * Remove the given tunnel. * * Returns:	-1 on error, 0 if the tunnel was not deleted *		(i.e., still in use), 1 if the tunnel was deleted */int tunnel_delete_ptr(TUNNEL *data, int force){	int ret = 1;	if (data == NULL) {		DEBUG(DEBUG_FLAG, "tunnel_delete_ptr: no such entry\n");		return -1;	}	DEBUG(DEBUG_FLAG, "tunnel_delete_ptr %s,%i,%i, force=%i\n",	      inet_ntoa(data->dst_addr), data->type, data->key, force);	DEBUG(DEBUG_FLAG, "\treference count: %i => %i\n",	      data->ref, data->ref - 1);	data->ref--;	print_tunnel_data(data);	if (data->ref > 0) {		DEBUG(DEBUG_FLAG, "\ttunnel not deleted\n");		return 0;	}#ifdef REMOVE_TUNNEL_OPTIM	force = 1;#endif	if (force) {		ret = tunnel_destroy(data);	} else {		/* Reference count is zero. Delay tunnel deletion */		gettimeofday(&data->zero_ref_tstamp, NULL);	}	return ret;}/** * tunnel_delete: *    @hash:        The pointer to the tunnel hash table *    @dst_addr:    The remote address of the tunnel *    @force:       1 = Remove tunnel immediately if reference count is zero, *                  0 = Use delayed tunnel deletion *    @type:        Tunnel type (IPIP / GRE) *    @key:         Key for GRE tunnels * * Delete tunnel from the hash table and decrease the tunnel reference count. * If the reference count is zero remove the kernel tunnel device. * * Returns: *    0		Reference count decreased, *    1		The tunnel was destroyed, *   -1		Error */inttunnel_delete(HASH *hash, struct in_addr dst_addr, int force, int type,	      __u32 key){	TUNNEL *data;	struct tunnel_key tkey;	DEBUG(DEBUG_FLAG, "tunnel_delete %s,%i,%i\n", inet_ntoa(dst_addr),	      type, key);	tkey.dst_addr = dst_addr;	tkey.type = type;	tkey.key = key;	data = (struct tunnel *) hashtable_fetch(hash, hashfunc, &tkey,						 cmpfunc);	return tunnel_delete_ptr(data, force);}/** * tunnel_fetch: * @hash:	The pointer to the tunnel hash table * @dst_addr:	The remote address ot the tunnel * @type:	The tunnel type (#TUNNEL_NO_ENCAPS, #TUNNEL_IPIP, #TUNNEL_GRE) * @key:	The key used with the tunnel * * Fetch the tunnel data from the hash table. * * Returns:	A pointer to the tunnel entry or NULL on failure */TUNNEL *tunnel_fetch(HASH *hash, struct in_addr dst_addr, int type, __u32 key){	TUNNEL *entry;	struct tunnel_key tkey;	DEBUG(DEBUG_FLAG, "tunnel_fetch: %s\n", inet_ntoa(dst_addr));	tkey.dst_addr = dst_addr;	tkey.type = type;	tkey.key = key;	entry = (TUNNEL *) hashtable_fetch(hash, hashfunc, &tkey, cmpfunc);	if (entry != NULL)		print_tunnel_data(entry);	else		DEBUG(DEBUG_FLAG, "\tno such entry\n");	return entry;}static int find_delayed(struct node *node, void *val){	int *found = (int *) val;	TUNNEL *data = (struct tunnel *) node;		if (data->ref > 0 || data->do_not_remove)		return 1;	*found = 1;	return 0;}/** * tunnel_delayed_exists: * @hash: The pointer to the tunnel hash table * * Checks whether any delayed deletions exists in the tunnel hash table. * * Returns: 0 = no delayed deletions, 1 = at least one delayed deletion found */inttunnel_delayed_exists(HASH *hash){	int found;	if (delayed != NULL)		return 1;	found = 0;	hashtable_iterator(hash, find_delayed, &found);	return found;}

⌨️ 快捷键说明

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