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

📄 mn.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (mn.current_adv != NULL) {		if (mn.current_adv->addr.s_addr != mn.fa_addr.s_addr) {			DEBUG(DEBUG_INFO, "fa_addr=%s != ",			      inet_ntoa(mn.fa_addr));			DEBUG(DEBUG_INFO, "current_adv->addr=%s\n",			      inet_ntoa(mn.current_adv->addr));		}		mn.current_adv->in_use = 1;		/* This FA works, so don't degrade priority: */		mn.current_adv->prio_degrade_percent = 0; 	} else {		LOG2(LOG_WARNING, "connected - current_adv == NULL\n");		mn.warn_str = "connected - current_adv == NULL";	}	/* HA MUST NOT use larger lifetime and the FAs cannot change the	 * requested lifetime - force the lifetime to be at maximum the	 * configured time */	if (lifetime > config.mn_default_tunnel_lifetime) {		LOG2(LOG_WARNING, "Lifetime in the reply (%i sec) larger than "		     "expected (%i sec) - lowering it\n", lifetime,		     config.mn_default_tunnel_lifetime);		mn.warn_str = "lifetime in the reply larger than expected";		lifetime = config.mn_default_tunnel_lifetime;	}	if (config.enable_fa_decapsulation &&	    mn.fa_addr.s_addr != mn.tunnel_addr.s_addr &&	    mn.tunnel_addr.s_addr != 0 &&	    mn.current_adv != NULL)		remove_fa_host_routes(0);        /* if tunnel endpoint has changed, or tunnel is down, create tunnel to	 * FA */	if (mn.fa_addr.s_addr != mn.tunnel_addr.s_addr || !real_tunnel_up) {	        if (real_tunnel_up) {			DEBUG(DEBUG_STATES, "Restart tunneling\n");			restart_tunneling();		} else {			DEBUG(DEBUG_STATES, "Start tunneling\n");			start_tunneling();		}	}	/* set lifetime timer */	timers[TIMER_LIFETIME].tv_sec = timers[TIMER_REQUEST].tv_sec +		lifetime;	timers[TIMER_LIFETIME].tv_usec = timers[TIMER_REQUEST].tv_usec;	  /* If connection was approved by HA,	   * reset timer for reregistering the tunnel */	if (type == CON_HA) {		set_reregistration_time(lifetime);	}	if (mn.state != MN_CONNECTED && type == CON_HA) {		LOG2(LOG_INFO, "Connection established.\n");		mn.info_str = "connection established";	}	DEBUG(DEBUG_TIMERS, "setting TIMER_GEN = TIMER_REREG %li.%06li (in %li"	      " sec)\n",	      timers[TIMER_REREG].tv_sec, timers[TIMER_REREG].tv_usec,	      timers[TIMER_REREG].tv_sec - time(NULL));	timers[TIMER_GEN] = timers[TIMER_REREG];        mn.state = MN_CONNECTED;	mn.tunnel_up = 1;        DEBUG(DEBUG_STATES, "State: Connected\n");}/* Send registration request and set timer */static void reregister(void){	struct timeval now;        DEBUG(DEBUG_INFO, "Reregistering..\n");        /* if tunnel has expired, switch to find agent */	gettimeofday(&now, NULL);        if (cmp_timeval(&timers[TIMER_LIFETIME], &now) <= 0) {		DEBUG(DEBUG_INFO, "Binding expired - trying to find another "		      "FA and re-establish binding\n");		mn_remove_dynamic_home_addr();				/* make sure that closest FA won't take next reg_req		 * as locupd. */		if (mn.session_key != NULL) free(mn.session_key);		mn.session_key = NULL;		mn.session_key_len = 0;                find_agent(STATE_INIT);		return;        }	if (send_registration(REG_REREG) < 0) {		mn.warn_str = "Registration failed, trying to find another FA";		DEBUG(DEBUG_INFO,		      "Registration failed - trying to find another FA\n");		if (mn.session_key != NULL) free(mn.session_key);		mn.session_key = NULL;		mn.session_key_len = 0;                find_agent(STATE_INIT);		return;	}	set_reregistration_time(0);	if (cmp_timeval(&timers[TIMER_REREG], &timers[TIMER_LIFETIME]) < 0) {		DEBUG(DEBUG_TIMERS, "setting TIMER_GEN = TIMER_REREG %li.%06li"		      " (in %li sec)\n", timers[TIMER_REREG].tv_sec,		      timers[TIMER_REREG].tv_usec,		      timers[TIMER_REREG].tv_sec - time(NULL));		timers[TIMER_GEN] = timers[TIMER_REREG];	} else {		DEBUG(DEBUG_TIMERS, "setting TIMER_GEN = TIMER_LIFETIME "		      "%li.%06li (in %li sec)\n",		      timers[TIMER_LIFETIME].tv_sec,		      timers[TIMER_LIFETIME].tv_usec,		      timers[TIMER_REREG].tv_sec - time(NULL));		timers[TIMER_GEN] = timers[TIMER_LIFETIME];	}}/* Stop tunneling and send deregistering message to the home agent. * We'll advance to next state when reply arrives. If the message is lost, it * will be resent after an interval. * Parameters: *  entry - STATE_INIT to move to this state *          STATE_TIMEOUT to indicate timeout in this state */void close_for_home(int entry){	int retry_time;	DEBUG(DEBUG_INFO, "close_for_home(%i)\n", entry);	if (mn.current_adv == NULL) {		LOG2(LOG_ALERT, "close_for_home - current_adv == NULL\n");	}	if (entry == STATE_INIT) {		mn.state = MN_CLOSE_FOR_HOME;		if (real_tunnel_up)			stop_tunneling();		else if (config.shared_secret_len < 0 ||			 config.mn_home_ip_addr.s_addr == 0) {			DEBUG(DEBUG_INFO,			      "close_for_home - not registered; going directly"			      " to home\n");			at_home();			return;		} else {			DEBUG(DEBUG_INFO,			      "close_for_home - not registered, but trying to "			      "deregister possible old bindings at HA\n");			if (mn.co_addr.s_addr == 0)				mn.co_addr.s_addr = mn.local_addr.s_addr;		}		if (mn.current_adv != NULL) {			DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: "			      "%i => %i (close_for_home)\n",			      inet_ntoa(mn.current_adv->addr),			      mn.current_adv->reg_retry_time,			      MIN_REGISTRATION_TIME);			mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;		} else			mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;		/* drop the previous session key so that locupd to FA with the		 * old binding goes to the HA */		if (mn.session_key != NULL)			free(mn.session_key);		mn.session_key = NULL;		mn.session_key_len = 0;	} else if (mn.current_adv == NULL ||		   mn.current_adv->reg_retry_time >= MAX_REGISTRATION_TIME) {		DEBUG(DEBUG_MESSAGES,		      "Could not get reply from HA - assuming deregistration "		      "worked\n");		at_home();		return;	} else if (mn.current_adv != NULL) {		DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: %i => ",		      inet_ntoa(mn.current_adv->addr),		      mn.current_adv->reg_retry_time);		if (mn.current_adv->reg_retry_time == 0)			mn.current_adv->reg_retry_time = 1;		else			mn.current_adv->reg_retry_time *= 2;		DEBUG(DEBUG_TIMERS, "%i\n", mn.current_adv->reg_retry_time);	}	send_gratuitous_arp(config.ha_ip_addr, config.mn_home_ip_addr);	/* send deregistration message to HA */	mn.fa_addr = config.ha_ip_addr;	send_registration(REG_DISC);	/* at least full retry time should be waited */	gettimeofday(&timers[TIMER_GEN], NULL);	retry_time = mn.current_adv ? mn.current_adv->reg_retry_time :		mn.HA_reg_retry_time;	DEBUG(DEBUG_TIMERS, "close_for_home - TIMER_GEN: set now+%i sec\n",	      retry_time);	timers[TIMER_GEN].tv_sec += retry_time;        DEBUG(DEBUG_STATES, "State: Close for home\n");}/* We have successfully deregistered from HA and wait for IP address change * signal to start tunneling again. */void at_home(void){	DEBUG(DEBUG_INFO, "at_home()\n");	send_gratuitous_arp(config.ha_ip_addr, config.mn_home_ip_addr);        mn.state = MN_AT_HOME;        DEBUG(DEBUG_STATES, "State: At home\n");	DEBUG(DEBUG_TIMERS, "Clearing TIMER_GEN\n");	timerclear(&timers[TIMER_GEN]);	mn_remove_dynamic_home_addr();}/* We are disconnected from tunneling system and nothing is done until * connection is asked. */void disconnect(void){	DEBUG(DEBUG_INFO, "disconnect()\n");	mn.cur_route_info.known = 0;	/* if we are connected, we'd better throw out a	 * deregistration message */	if (mn.state == MN_CONNECTED) {		send_registration(REG_DISC);		DEBUG(DEBUG_MESSAGES, "Deregistration message sent\n");	}	if (real_tunnel_up) stop_tunneling();	/* free session key */	if (mn.session_key) {		free(mn.session_key);		mn.session_key = NULL;		mn.session_key_len = 0;	}	DEBUG(DEBUG_TIMERS, "Clearing TIMER_GEN\n");	timerclear(&timers[TIMER_GEN]);        mn.state = MN_DISCONNECTED;        DEBUG(DEBUG_STATES, "State: Disconnected\n");	syslog(LOG_INFO, "Disconnected.");	mn_remove_dynamic_home_addr();}/* handle reregistration when the not supported request option can be fixed */static void reinitiate_state(void){	DEBUG(DEBUG_INFO, "reinitiate_state()\n");	if (mn.current_adv == NULL) {		DEBUG(DEBUG_INFO, "reinitiate_state - current_adv == NULL\n");		mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;	} else {		DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: "		      "%i => %i (reinitiate_state)\n",		      inet_ntoa(mn.current_adv->addr),		      mn.current_adv->reg_retry_time,		      MIN_REGISTRATION_TIME);		mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;	}	switch (mn.state) {	case MN_REQUEST_TUNNEL:		request_tunnel(STATE_INIT, 0, 0);		break;	case MN_CONNECTED:		reregister();		break;	default:		break;	}}static int check_sol_reply(struct node *node, void *data){	struct agentadv_data *adv;	struct timeval *tv;		adv = (struct agentadv_data *) node;	tv = (struct timeval *) data;	if (timerisset(tv) && cmp_timeval(&adv->last, tv) < 0 &&	    usec_passed(&adv->last, tv) > MAX_AGENTSOL_REPLY_WAIT) {		DEBUG(DEBUG_INFO, "  timediff=%u\n",		      usec_passed(&adv->last, tv));		DEBUG(DEBUG_INFO, "No reply from MA (addr=%s) to "		      "agent solicitation within %i usec",		      inet_ntoa(adv->addr), MAX_AGENTSOL_REPLY_WAIT);		adv->prio_degrade_percent += SOLICITATION_PRIO_DEGRADE;		if (adv->prio_degrade_percent > 100)			adv->prio_degrade_percent = 100;		DEBUG(DEBUG_INFO, " - prio to %i\n",		      adv->prio_degrade_percent);	}	return TRUE;}static void handle_timeout(void){	struct timeval tv;        DEBUG(DEBUG_TIMERS, "Timeout\n");	gettimeofday(&tv, NULL);#ifdef WITH_WIRELESS	if (config.wlan_ap_poll_interval > -1 &&	    timerisset(&timers[TIMER_WLAN_AP_POLL]) &&	    cmp_timeval(&tv, &timers[TIMER_WLAN_AP_POLL]) >= 0) {		DEBUG(DEBUG_TIMERS, "\tTIMER_WLAN_AP_POLL\n");		/* poll AP addresses and send agentsol if handoff has		 * occured (do this for each interface supporting wireless		 * extensions) */		monitor_poll_ap_addresses(&mn);		timers[TIMER_WLAN_AP_POLL].tv_sec = tv.tv_sec;		timers[TIMER_WLAN_AP_POLL].tv_usec = tv.tv_usec;		add_usecs(&timers[TIMER_WLAN_AP_POLL],			  config.wlan_ap_poll_interval);	}#endif /* WITH_WIRELESS */	if (config.solicitation_interval > -1 &&	    timerisset(&timers[TIMER_SOLICITATION]) &&	    cmp_timeval(&tv, &timers[TIMER_SOLICITATION]) >= 0) {		DEBUG(DEBUG_TIMERS, "\tTIMER_SOLICITATION\n");		/* check whether some FAs did not reply previous solicitation		 */		hashtable_iterator(mn.agentadv, check_sol_reply,				   &mn.last_scheduled_solicitation);		/* send agentsol to all interfaces */		send_solicitations(&mn);		timers[TIMER_SOLICITATION].tv_sec = tv.tv_sec;		timers[TIMER_SOLICITATION].tv_usec = tv.tv_usec;		add_usecs(&timers[TIMER_SOLICITATION],			  config.solicitation_interval +			  get_rand32() % MAX_RANDOM_SOLICITATION_DELAY);		mn.last_scheduled_solicitation = tv;	}	if (!timerisset(&timers[TIMER_GEN])) {		DEBUG(DEBUG_TIMERS, "\tTIMER_GEN is not set\n");		return;	}	if (cmp_timeval(&tv, &timers[TIMER_GEN]) < 0) {		DEBUG(DEBUG_TIMERS, "\tTIMER_GEN not yet reached - ignoring "		      "timeout\n");		return;	}	/* disable timer */	DEBUG(DEBUG_TIMERS, "\tdisabling TIMER_GEN\n");        timerclear(&timers[TIMER_GEN]);        switch (mn.state) {        case MN_DISCONNECTED:        case MN_AT_HOME:                break;        case MN_CLOSE_FOR_HOME:                close_for_home(STATE_TIMEOUT);                break;        case MN_FIND_AGENT:                find_agent(STATE_TIMEOUT);		break;        case MN_PASSIVE_FIND:                break;        case MN_REQUEST_TUNNEL:                request_tunnel(STATE_TIMEOUT, 0, 0);                break;        case MN_CONNECTED:                reregister();                break;	default:		break;	}}int main(int argc, char *argv[]){	int n, i;	fd_set set;	struct timeval tv;	memset(&mn, 0, sizeof(mn));	mn.info_str = "initialization in progress";	program_name = parse_long_options(argc, argv, "mobile node",					     PACKAGE, VERSION, dynamics_usage);	mn_parse_command_line(argc, argv);	if (!mn_init()) {		fprintf(stderr, "Initialization failed.\n");		exit(0);	}	if (mn.opt_connect) {		/* try to connect to a FA if MN is using FA decapsulation (i.e.		 * its own home IP addr also in the foreign network) or if the		 * home address is not assigned to a local interface with MN		 * decapsulation */		mn.info_str = "trying to connect";		if (config.enable_fa_decapsulation || is_coloc_addr_foreign())		{			mn.tunnel_mode = API_TUNNEL_FULL;			find_agent(STATE_INIT);		} else at_home();	}	/* MN main loop */	while (mn.state != MN_STOP) {		check_old_tunnel_expiration();		FD_ZERO(&set);		FD_SET(mn.registration_socket, &set);		for (i = 0; i < MAX_INTERFACES; i++) {			if (mn.iface[i].s_adv > -1)				FD_SET(mn.iface[i].s_adv, &set);		}		if (mn.api_rw_socket > -1)			FD_SET(mn.api_rw_socket, &set);		if (mn.api_ro_socket > -1)			FD_SET(mn.api_ro_socket, &set);#ifdef INCLUDE_IPAY		FD_SET(mn.ipay_sock, &set);		FD_SET(mn.ipay_sock_fa, &set);#endif		if (mn.rtnetlink_socket > -1)			FD_SET(mn.rtnetlink_socket, &set);		if (get_next_timeout(&tv))			n = select(FD_SETSIZE, &set, NULL, NULL, &tv);		else n = select(FD_SETSIZE, &set, NULL, NULL, NULL);		if (n == 0) {			handle_timeout();			continue;		} else if (n == -1) {		        switch (errno) {			case EINTR:			        break;			default:			        LOG2(LOG_ERR, "main - select: %s\n",				     strerror(errno));				/* this used to exit dynmnd with				 * mn.state = MN_STOP;				 * but this might be a temporary problem, so				 * try agains; use a small delay to prevent				 * hogging all the CPU in case of select()				 * returning error all the time */				sleep(1);			}			continue;		}		if (FD_ISSET(mn.registration_socket, &set) &&		    handle_registration(mn.registration_socket)) {			/* try to reregister */			reinitiate_state();		}		for (i = 0; i < MAX_INTERFACES; i++) {			if (mn.iface[i].s_adv > -1 &&			    FD_ISSET(mn.iface[i].s_adv, &set))				handle_icmp(&mn.iface[i]);		}		if (mn.rtnetlink_socket > -1 &&		    FD_ISSET(mn.rtnetlink_socket, &set)) {			int res = dyn_ip_monitor_get(				mn.rtnetlink_socket,				(config.enforce_routes &&				 mn.state != MN_DISCONNECTED) ?				&mn.cur_route_info : NULL);			if (res == 1 || res == 2)				check_interfaces(mn.iface, MAX_INTERFACES);		}		if (mn.api_rw_socket > -1 && FD_ISSET(mn.api_rw_socket, &set))			handle_api(mn.api_rw_socket, 1);		if (mn.api_ro_socket > -1 && FD_ISSET(mn.api_ro_socket, &set))			handle_api(mn.api_ro_socket, 0);#ifdef INCLUDE_IPAY		if (FD_ISSET(mn.ipay_sock, &set))			handle_ipay(mn.ipay_sock);		if (FD_ISSET(mn.ipay_sock_fa, &set))			handle_ipay(mn.ipay_sock_fa);#endif		/* check expired agent advs. If current FA's agent                   adv. has expired move to FIND_AGENT state */		if (check_expired_agent_advs())			find_agent(STATE_INIT);	}	clean_up(0);	return 0;}

⌨️ 快捷键说明

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