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

📄 mn_agentadv.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: mn_agentadv.c,v 1.76 2001/09/29 18:42:07 jm Exp $ * Mobile Node agentadv module * * 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 <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <assert.h>#include <errno.h>#include <stddef.h>#include <features.h>    /* for the glibc version number */#include <unistd.h>#ifdef DYN_TARGET_LINUX#include <net/if_arp.h>#ifndef __GLIBC__/* get struct iphdr */#include <linux/ip.h>#endif#endif#include "hashtable.h"#include "debug.h"#include "fileio.h"#include "proxyarp.h"#ifdef WITH_WIRELESS#include "monitor.h"#endif#include "dyn_ip.h"#include "agentapi.h"#include "util.h"#include "mn_agentadv.h"#include "mn_handler.h"#include "mn.h"/* fa decision .. */static struct agentadv_data *max_adv;static int max_priority;static struct timeval max_adv_time;extern struct mn_data mn; extern struct mn_config config;extern struct timeval timers[TIMER_COUNT];extern int real_tunnel_up; /* from mn_tunnel */int adv_ok_fa(struct agentadv_data *adv){	int opts;	if (mn.force_fa_addr.s_addr != 0 &&	    mn.force_fa_addr.s_addr != adv->addr.s_addr)		return 0;	if (adv->adv.ext == NULL)		return 0;	opts = ntohs(adv->adv.ext->opts);	if ((opts & AGENT_ADV_BUSY) || !(opts & AGENT_ADV_FOREIGN_AGENT))		return 0;	if (config.tunneling_mode == TUNMODE_REVERSE &&	    !(opts & AGENT_ADV_BIDIR_TUNNELING))		return 0;	if (config.tunneling_mode == TUNMODE_TRIANGLE &&	    adv->adv.own_ext != NULL &&	    !(adv->adv.own_ext->opts & AGENT_ADV_OWN_TRIANGLE_TUNNELING))		return 0;	return 1;}static int addr_cmp(void *key, struct node *cmprd){	struct agentadv_data *entry = (struct agentadv_data *) cmprd;	struct agentadv_key *akey = (struct agentadv_key *) key;	if (akey->addr.s_addr == entry->addr.s_addr &&	    (akey->ifindex == 0 || akey->ifindex == entry->ifindex))		return TRUE;	return FALSE;}static int addr_hash(void *key, const int tablesize){	unsigned char *addr;	struct agentadv_key *akey = (struct agentadv_key *) key;	addr = (unsigned char *) &akey->addr;	return (int) (addr[0] ^ addr[1] ^ addr[2] ^ addr[3]);}/** * adv_fetch: * @adv_hash: hash of agent advertisements * @addr: address of agent * @ifindex: 0 to accept any interface, or index of a given *           interface * * fetch an agent advertisement from the @adv_hash. * addr: the source IP address of the agent advertisment packet * * Returns: the matching advertisement */struct agentadv_data *adv_fetch(struct hashtable *adv_hash, struct in_addr *addr, int ifindex){	struct agentadv_data *adv;	struct agentadv_key key;	key.addr.s_addr = addr->s_addr;	key.ifindex = ifindex;	adv = (struct agentadv_data *)		hashtable_fetch(adv_hash, addr_hash, &key, addr_cmp);	return (adv);}static int current_agent_expired;/* remove hashtable entry, if the current time (data as struct timeval *) is * NULL (forced cleaning) or if the entry has expired */int clean_agentadv(struct node *node, void *data){	struct agentadv_data *adv;	struct timeval *tval;	struct event_FA dat;	adv = (struct agentadv_data *) node;	tval = (struct timeval *) data;	if (tval != NULL && cmp_timeval(tval, &adv->expire) < 0)		return TRUE; /* not expired */	if (tval != NULL && adv->in_use) {		/* in use and removal not forced */		current_agent_expired = TRUE;		return TRUE;	}	DEBUG(DEBUG_AGENTADV, "clean_agentadv: removing %s\n",	      inet_ntoa(adv->addr));	/* call handlers registered for FA_ADV_EXPIRE event */	dat.adv = adv;	dat.hash = mn.agentadv;	handler_call_all(FA_ADV_EXPIRE, &dat);	/* remove the possible ARP entries etc. */	if (adv->arpentry == 1 &&	    arp_del_permanent_item(adv->addr, adv->ifname) < 0) {		if (device_up(adv->ifindex)) {			LOG2(LOG_WARNING,			     "arp_del_permanent_item(%s, %s) failed\n",			     inet_ntoa(adv->addr), adv->ifname);		} else {			DEBUG(DEBUG_INFO, "arp_del_permanent_item(%s, %s) "			      "failed (device down)\n",			      inet_ntoa(adv->addr), adv->ifname);		}	}	/* remove the possible host route to FA */	if (adv->routeentry == 1) {		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)			DEBUG(DEBUG_INFO, "FA route removing failed\n");	}	if (mn.current_adv == adv) {		DEBUG(DEBUG_AGENTADV, "clean_agentadv: removed current_adv\n");		mn.current_adv = NULL;	}	hashtable_remove(node);	free(adv);	return TRUE;}static void handle_home_adv(struct agentadv_data *adv){	struct in_addr addr;        DEBUG(DEBUG_AGENTADV, "Home advertisement\n");	if (config.priv_ha_ip_addr.s_addr != 0)		addr = config.priv_ha_ip_addr;	else		addr = config.ha_ip_addr;	if (addr.s_addr != adv->addr.s_addr) {		struct node *iter;		int found = 0;		for (iter = list_get_first(&config.alt_ha_ip_addrs);		     iter != NULL; iter = list_get_next(iter)) {			struct alt_ha_entry *alt =				(struct alt_ha_entry *) iter;			if (alt->addr.s_addr == adv->addr.s_addr) {				found = 1;				break;			}		}		if (!found) {			DEBUG(DEBUG_AGENTADV, "\tnot our HA\n");			return;		}	}	if (config.ha_nai_len > 0) {		struct fa_nai_ext *fa_nai =			(struct fa_nai_ext *) adv->adv.fa_nai;		if (fa_nai == NULL) {			DEBUG(DEBUG_AGENTADV, "\tno NAI extension in agent adv"			      " - ignoring packet\n");			return;		}		if (config.ha_nai_len != GET_NAI_LEN(fa_nai)) {			DEBUG(DEBUG_AGENTADV, "\tNAI length mismatch - "			      "ignoring packet\n");			return;		}		if (memcmp(config.ha_nai, MSG_NAI_DATA(fa_nai),			   config.ha_nai_len) != 0) {			DEBUG(DEBUG_AGENTADV, "\tNAI mismatch - ignoring "			      "packet\n");			return;		}			}	if (mn.current_adv != NULL && mn.current_adv->in_use)		mn.current_adv->in_use = 0;	mn.current_adv = adv;	mn.current_adv->in_use = 1;	mn.cur_route_info.ifindex = mn.cur_route_info.ifindex_net =		adv->ifindex;	memcpy(mn.cur_route_info.ifname, adv->ifname, IFNAMSIZ);	memcpy(mn.cur_route_info.ifname_net, adv->ifname, IFNAMSIZ);	mn.cur_route_info.known = 1;	mn.cur_route_info.via.s_addr = config.home_net_gateway.s_addr;	adv->adv_type = MN_ADV_TYPE_OWN_HA;	DEBUG(DEBUG_AGENTADV, "\tfrom our own HA - MN is at home\n");	if (mn.state == MN_FIND_AGENT || mn.state == MN_PASSIVE_FIND ||	    mn.state == MN_REQUEST_TUNNEL || mn.state == MN_CONNECTED) {		/* FIX: if the co-loc. COA was used, the address of the		 * interface must be set to the home network settings.		 * Currently it is assumed that some external program		 * handles the IP addresses if co-loc. COA is used. */		DEBUG(DEBUG_INFO, "Deregistering due to the heard "		      "own HA agent advertisement\n");		close_for_home(STATE_INIT);	}}/* hashtable iterator for update_fa_decision() * searches the entry with largest priority */static int find_fa_with_priority(struct node *node, void *data){	struct agentadv_data *adv;	adv = (struct agentadv_data *) node;	if (monitor_check_policy(NEWEST_ADV_BIT)) {		/* special case for Newest-ADV policy: just select the latest		 * received advertisement */		if (!timerisset(&max_adv_time) ||		    cmp_timeval(&max_adv_time, &adv->last) < 0) {			max_adv_time = adv->last;			max_adv = adv;		}		return TRUE;	}	adv->priority_degraded = adv->priority;	DEBUG(DEBUG_HANDLERS, "%s priority %i", inet_ntoa(adv->addr), 	      adv->priority_degraded);	/* degrade priority by degrade percent */	if (adv->prio_degrade_percent > 0 && adv->priority_degraded > 0) {		adv->priority_degraded = (int)			(adv->priority_degraded *			 ((100.0 - adv->prio_degrade_percent) / 100.0));		/* do not totally deny this FA */		if (adv->priority_degraded == 0)			adv->priority_degraded = 1;		DEBUG(DEBUG_HANDLERS, " => %i (-%i%%)", adv->priority_degraded,		      adv->prio_degrade_percent);	}	DEBUG(DEBUG_HANDLERS, "\n");	if (adv->priority_degraded > max_priority && !adv->reg_failed &&	    (adv_ok_fa(adv) || adv == mn.current_adv)) {		max_priority = adv->priority_degraded;		max_adv = adv;	}	return TRUE;}/* Called after FA_GET handlers */static int update_fa_decision(struct agentadv_data *adv){	int same_prio;	struct timeval now;	gettimeofday(&now, NULL);	/* (A) 	 * if we are at home and the HA's agentadv has not expired, do not try	 * to change the FA */	if ((mn.state == MN_AT_HOME || mn.state == MN_CLOSE_FOR_HOME) &&	    mn.current_adv != NULL &&	    mn.current_adv->addr.s_addr == config.ha_ip_addr.s_addr &&	    mn.current_adv->adv.ext != NULL &&	    ntohs(mn.current_adv->adv.ext->opts) & AGENT_ADV_HOME_AGENT &&	    cmp_timeval(&mn.current_adv->expire, &now) >= 0 &&	    !monitor_check_policy(NEWEST_ADV_BIT)) {		DEBUG(DEBUG_AGENTADV,		      "HA agentadv still valid - staying at home\n");

⌨️ 快捷键说明

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