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

📄 mn_agentadv.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		return FA_GET_NO;	}	/* if we are using direct connection to the HA, do not try to change	 * the FA */	if (mn.tunnel_mode == API_TUNNEL_FULL_HA) {		DEBUG(DEBUG_AGENTADV, "Direct connection to the HA - ignoring "		      "FA agent advertisement\n");		return FA_GET_NO;	}	/* Get FA with max priority */	max_adv = NULL;	max_priority = 0;	timerclear(&max_adv_time);	if (mn.agentadv == NULL) {		DEBUG(DEBUG_AGENTADV, "update_fa_decision: mn.agentadv == "		      "NULL\n");		return FA_GET_NO;	}	hashtable_iterator(mn.agentadv, find_fa_with_priority, NULL);	if (max_adv == NULL) {		DEBUG(DEBUG_AGENTADV, "update_fa_decision: Can't find FA!\n");		return FA_GET_NO;	}	if (mn.current_adv != NULL) {		DEBUG(DEBUG_AGENTADV, "CURRENT: %s   ",		      inet_ntoa(mn.current_adv->addr));		DEBUG(DEBUG_AGENTADV, "MAX: %s\n",		      inet_ntoa(max_adv->addr));	}	/* (B)          * If same priority, don't change */	/* FIX: How to compare two LFAs. How can we know that they are same	 * JM-FIX: use FA NAI */	if (mn.current_adv != NULL)		same_prio = mn.current_adv->priority_degraded == max_priority;	else		same_prio = FALSE;	/* skip priority check if Newest-ADV policy is used */	if (monitor_check_policy(NEWEST_ADV_BIT))		same_prio = FALSE;	if (mn.current_adv != NULL &&	    (same_prio ||	     mn.current_adv->addr.s_addr == max_adv->addr.s_addr)) {		return FA_GET_SAME; /* no change if same priority or SAME FA */	}	/* Change FA. First update the FA information */	mn.fa_addr.s_addr = max_adv->addr.s_addr;	memcpy(&mn.co_addr, (max_adv->adv.ext) + 1, sizeof(struct in_addr));	mn.req_lifetime = ntohs(max_adv->adv.ext->reg_lifetime);	if (mn.current_adv != NULL)		mn.current_adv->in_use = 0;	mn.current_adv = max_adv;	memcpy(&mn.fa_dynamics_ext, &max_adv->adv.own_ext,	       sizeof(struct agent_adv_dynamics));	gettimeofday(&timers[TIMER_ADV], NULL);	timers[TIMER_ADV].tv_sec += ntohs(max_adv->adv.radv->lifetime);	return FA_GET_CHANGED;}/* Get a FA * Returns: *   0 = FA not found or HA agentadv still valid => do not try to register *   1 = new FA found *   2 = FA found, but it is the same as the current FA */int get_fa(struct agentadv_data *adv){	struct event_FA data;	data.adv = adv;	data.hash = mn.agentadv;	handler_call_all(FA_GET, &data);	return update_fa_decision(adv);}static void handle_fa_adv(struct agentadv_data *adv){	struct in_addr _fa_addr, _highest_fa_addr;	int chg = 0;	struct event_FA data;	UNALIGNED_(&_fa_addr.s_addr, &adv->adv.ip->saddr);	memcpy(&_highest_fa_addr, adv->adv.ext + 1, sizeof(struct in_addr));        DEBUG(DEBUG_AGENTADV, "FA advertisement - fa_addr=%s, ",	      inet_ntoa(_fa_addr));	DEBUG(DEBUG_AGENTADV, "highest_fa_addr=%s\n",	      inet_ntoa(_highest_fa_addr));	/* Call all handlers for this event: FA_ADV_RECEIVE */	data.adv = adv;	data.hash = mn.agentadv;	handler_call_all(FA_ADV_RECEIVE, &data);	if (mn.state == MN_CONNECTED && ntohs(adv->adv.ext->seq) < 256 &&	    adv->last_heard_seqn >= ntohs(adv->adv.ext->seq)) {		adv->last_heard_seqn = ntohs(adv->adv.ext->seq);		DEBUG(DEBUG_INFO, "FA rebooted - trying to reregister\n");		request_tunnel(STATE_INIT, 0, 0);		return;	}        /* update sequence number */	adv->last_heard_seqn = ntohs(adv->adv.ext->seq);        switch (mn.state) {        case MN_DISCONNECTED:		break;        case MN_AT_HOME:        case MN_CLOSE_FOR_HOME:		/* try to register to an FA if the HA's agentadv expires */		if (mn.current_adv == NULL ||		    mn.current_adv->adv_type != MN_ADV_TYPE_OWN_HA ||		    adv->adv_type != MN_ADV_TYPE_FA)			break;                if (cmp_timeval(&adv->last, &mn.current_adv->expire) < 0 &&		    !monitor_check_policy(NEWEST_ADV_BIT))			break;		DEBUG(DEBUG_INFO,		      "HA agentadv expired - trying to use FA (IP=%s)\n",		      inet_ntoa(adv->addr));		/* continue to next case statement.. */        case MN_FIND_AGENT:        case MN_PASSIVE_FIND:        case MN_REQUEST_TUNNEL:		/* FIX: if the real tunnel is not yet up and the MN gets a		 * flood of agentadvs from different FAs, there might not be		 * enough time for the reply to arrive and MN might try to		 * register to yet another FA.. */		chg = get_fa(adv);		if (chg == FA_GET_CHANGED ||		    (chg == FA_GET_SAME && (real_tunnel_up == 0 ||			    mn.state != MN_REQUEST_TUNNEL)))			request_tunnel(STATE_INIT, 0, 1);                break;        case MN_CONNECTED:		chg = get_fa(adv);		/* start requesting the tunnel if the current FA's seq#		 * indicates that the FA has rebooted or if the FA has been		 * changed */                if (chg == FA_GET_CHANGED) {                        request_tunnel(STATE_INIT, 0, 1);		}                break;	default:		break;        }}/* check_expired_agent_advs: * * Remove old agent advertisement datas from the memory  * * Returns: 1 if current agent has expired, else 0 */int check_expired_agent_advs(void){	static time_t prev_check = 0;	struct timeval now;	struct timeval tmp;		gettimeofday(&now, NULL);	if (prev_check <= now.tv_sec &&	    now.tv_sec < prev_check + ADV_CLEANUP_FREQ)		return 0;			prev_check = now.tv_sec;	current_agent_expired = FALSE;	tmp.tv_sec = now.tv_sec - ADV_EXTRA_TIME;	tmp.tv_usec = now.tv_usec;	DEBUG(DEBUG_AGENTADV,	      "\tchecking for expired agentadv data\n");	hashtable_iterator(mn.agentadv, clean_agentadv, &tmp);		if (current_agent_expired) {		DEBUG(DEBUG_AGENTADV, "Current agent's adv. expired - try to "		      "find new FA\n");		return 1;	}		return 0;}/* handle incoming agent advertisement * Returns: *   0 - no extra processing needed *   1 - current agent's advertisement has expired */int handle_icmp(struct interface_data *iface){	char buf[MAX_ADV_MSG];	struct adv_extensions ext;	struct agentadv_key key;	struct agentadv_data *adv;	int res;        /* return, if message was not for us */	res = handle_icmp_adv(iface->s_adv, buf, MAX_ADV_MSG, &ext);	if (res == -1) {		/* network is down - rescan interfaces */		check_interfaces(mn.iface, MAX_INTERFACES);	}	if (res != 1)		return 0;	UNALIGNED_(&key.addr.s_addr, &ext.ip->saddr);#ifndef MN_FA_FORCE_AFTER_AGENTADV_UPDATE	if (mn.force_fa_addr.s_addr != 0 &&	    mn.force_fa_addr.s_addr != key.addr.s_addr) {		DEBUG(DEBUG_AGENTADV,		      "handle_icmp: force_fa set to %s - ignoring this FA(1)",		      inet_ntoa(mn.force_fa_addr));		DEBUG(DEBUG_AGENTADV, " (%s)\n", inet_ntoa(key.addr));		return 0;	}#endif /* MN_FA_FORCE_AFTER_AGENTADV_UPDATE */	key.ifindex = iface->index;	if (ntohs(ext.ext->reg_lifetime) < MIN_ALLOWED_LIFETIME) {		DEBUG(DEBUG_AGENTADV,		      "handle_icmp: too small lifetime advertised (%d) "		      "- ignoring this FA (%s)\n",		      ntohs(ext.ext->reg_lifetime), inet_ntoa(key.addr));		return 0;	}	/* save the last agentadv */	adv = (struct agentadv_data *)		hashtable_fetch(mn.agentadv, addr_hash, &key, addr_cmp);	if (adv == NULL) {		/* we have no previous information on this mobility agent */		adv = (struct agentadv_data *)			malloc(sizeof(struct agentadv_data));		if (adv == NULL) {			DEBUG(DEBUG_AGENTADV,			      "handle_icmp: no memory for agentadv data\n");			return 0;		}		DEBUG(DEBUG_AGENTADV, "Added new agentadv entry for %s\n",		      inet_ntoa(key.addr));		memset(adv, 0, sizeof(struct agentadv_data));		list_init_node(&adv->node);		UNALIGNED_(&adv->addr.s_addr, &ext.ip->saddr);		adv->counter = 1;		adv->prio_degrade_percent = 0; /* don't degrade new FAs! */ 		if (!hashtable_add(mn.agentadv, addr_hash, &key.addr,				   &adv->node)) {			DEBUG(DEBUG_AGENTADV,			      "handle_icmp: hashtable_add failed\n");			free(adv);			return 0;		}	} else {		/* updating information for previously heard mobility agent */		DEBUG(DEBUG_AGENTADV, "Used old agentadv entry for %s\n",		      inet_ntoa(key.addr));		adv->counter++;		/* Let FA become slowly "available" again */		if (adv->prio_degrade_percent > 0)			adv->prio_degrade_percent = (int)				(adv->prio_degrade_percent*				 DEFAULT_PRIO_DEGRADE_DEGRADE);		/* remove the reg_failed flag if the adv. opts has changed */		if (adv->reg_failed && ext.ext->opts != adv->adv.ext->opts) {			DEBUG(DEBUG_AGENTADV,			      "Reseting reg_failed for this FA\n");			adv->reg_failed = 0;		}	}	adv->ifindex = iface->index;	dynamics_strlcpy(adv->ifname, iface->device, sizeof(adv->ifname));	gettimeofday(&adv->last, NULL);	adv->expire.tv_sec = adv->last.tv_sec + ntohs(ext.radv->lifetime) + 1;	adv->expire.tv_usec = adv->last.tv_usec;	DEBUG(DEBUG_AGENTADV, "\tnow=%li.%li, expire=%li.%li\n",	      adv->last.tv_sec, adv->last.tv_usec,	      adv->expire.tv_sec, adv->expire.tv_usec);	memcpy(adv->buf, buf, MAX_ADV_MSG);	memcpy(&adv->adv, &ext, sizeof(struct adv_extensions));	adv->adv.start = adv->buf;	adv->adv.len = ext.len;	adv->adv.coaddrs = ext.coaddrs;	memcpy(&adv->adv.from, &ext.from, sizeof(ext.from));#define UPDATE_OFFSET(n) adv->adv.n = ext.n ? \(typeof(ext.n)) (((char *) ext.n) - ext.start + adv->adv.start) : NULL#ifndef DYN_TARGET_LINUX	UPDATE_OFFSET(eth);#endif	UPDATE_OFFSET(ip);	UPDATE_OFFSET(radv);	UPDATE_OFFSET(ext);	UPDATE_OFFSET(prefix);	UPDATE_OFFSET(own_ext);	UPDATE_OFFSET(pubkey_hash);	UPDATE_OFFSET(fa_nai);	UPDATE_OFFSET(challenge);#ifdef MN_FA_FORCE_AFTER_AGENTADV_UPDATE	if (mn.force_fa_addr.s_addr != 0 &&	    mn.force_fa_addr.s_addr != key.addr.s_addr) {		DEBUG(DEBUG_AGENTADV,		      "handle_icmp: force_fa set to %s - ignoring this FA(2)",		      inet_ntoa(mn.force_fa_addr));		DEBUG(DEBUG_AGENTADV, " (%s)\n", inet_ntoa(key.addr));		return 0;	}#endif /* MN_FA_FORCE_AFTER_AGENTADV_UPDATE */	if (ntohs(ext.ext->opts) & AGENT_ADV_HOME_AGENT) {		adv->adv_type = MN_ADV_TYPE_HA;		handle_home_adv(adv);	}	if (ntohs(ext.ext->opts) & AGENT_ADV_FOREIGN_AGENT) {		if (adv->adv_type != MN_ADV_TYPE_OWN_HA)			adv->adv_type = MN_ADV_TYPE_FA;		if (ext.coaddrs <= 0)			DEBUG(DEBUG_AGENTADV,			      "handle_icmp: FA adv with no COAs - ignoring\n");		else			handle_fa_adv(adv);	}	return 0;}

⌨️ 快捷键说明

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