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

📄 mn_reg.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * Home Agent */		LOG2(LOG_ALERT, "No authentication in the reply\n");		if (config.use_aaa)			mn.aaa_rekey = 1;		return 0;	}	/* check the possible mf_auth */	fa_spi = get_fa_spi(0, addr.sin_addr);	if (ext->rep->code == REGREP_MN_FAILED_AUTH_FA && config.use_aaa &&	    fa_spi != NULL && fa_spi->created != 0) {		DEBUG(DEBUG_INFO, "FA reported incorrect authentication - "		      "trying to create a new security association\n");		remove_fa_spi(fa_spi);		free(fa_spi);		fa_spi = NULL;		mn.try_to_fix_sec_assoc = 1;	}	if (fa_spi != NULL) {		if (ext->mf_auth == NULL) {			LOG2(LOG_ALERT, "No mf_auth in the reply even though "			     "there is a security association with the FA.\n");			return 0;		} else if (!auth_check(fa_spi->alg, fa_spi->shared_secret,				       fa_spi->shared_secret_len,				       (unsigned char *) ext->rep,				       ext->mf_auth)) {			LOG2(LOG_ALERT, "Incorrect FA->MN authentication "			     "extension received the reply\n");			return 0;		}	} else if (ext->mf_auth != NULL && !mn.try_to_fix_sec_assoc) {		LOG2(LOG_ALERT, "Reply has an MN-FA auth. ext., but there is "		     "no security association with the FA.\n");		return 0;	}        /* verify id */        if (ntohl(ext->rep->id[1]) != mn.registration_id[1]) {                LOG2(LOG_ALERT,		     "Wrong id field in the reply (was %08x, "		     "expected %08x)\n",		     ext->rep->id[1], (u32) htonl(mn.registration_id[1]));                return 0;        }	if (ntohs(ext->rep->lifetime) > 0 &&	    IS_REGREP_ACCEPTED(ext->rep->code) &&	    config.ha_ip_addr.s_addr == 0) {		DEBUG(DEBUG_INFO, "Discovered HA address from reply: %s\n",		      inet_ntoa(ext->rep->ha_addr));		config.ha_ip_addr.s_addr = ext->rep->ha_addr.s_addr;	}	if (ntohs(ext->rep->lifetime) > 0 &&	    IS_REGREP_ACCEPTED(ext->rep->code) &&	    config.mn_home_ip_addr.s_addr == 0) {		DEBUG(DEBUG_INFO, "Discovered MN home address from "		      "reply: %s\n", inet_ntoa(ext->rep->home_addr));		mn.local_addr.s_addr =			config.mn_home_ip_addr.s_addr =			ext->rep->home_addr.s_addr;		if (mn.current_adv != NULL &&		    dyn_ip_iface_address(mn.current_adv->ifindex,					 &config.mn_home_ip_addr) != 1) {			DEBUG(DEBUG_INFO, "Adding assigned home address to the"			      " interface\n");			if (dyn_ip_addr_add(mn.current_adv->ifname,					    config.mn_home_ip_addr) == 0) {				mn.dynamic_home_addr.s_addr =					config.mn_home_ip_addr.s_addr;				memcpy(mn.dynamic_home_addr_dev,				       mn.current_adv->ifname, IFNAMSIZ);			} else				DEBUG(DEBUG_INFO, "dyn_ip_addr_add failed\n");		}	}	/* don't accept any further messages with same id */	mn.registration_id[1]++;        return 1;#endif}/* Handle session key extension. Decrypt and copy to session_key */static void handle_key_ext(struct reg_rep *rep, struct msg_key *key){        ASSERT(rep != NULL && key != NULL);        DEBUG(DEBUG_MESSAGES, "mobile-home key extension received\n");        /* If SPIs are different, something went wrong and we should         * send another registration request to obtain session key. */        if (ntohl(key->spi) != config.spi) {                LOG2(LOG_WARNING, "Wrong SPI in the key reply extension.\n");                return;        }        /* Extract new session key */	if (mn.session_key) free(mn.session_key);	mn.session_key = auth_decrypt(config.auth_alg, config.shared_secret,				   config.shared_secret_len, key, rep,				   (int *) &mn.session_key_len);	if (mn.session_key == NULL) {		LOG2(LOG_ERR,		       "handle_key_ext: session key decryption failed\n");		mn.session_key_len = 0;		return;	}	show_key_dump("Session key", mn.session_key, mn.session_key_len);}/* Handle registration accepting registration reply */static void handle_reg_accept(struct msg_extensions *ext){#ifdef MN_LOCUPD_PROFILER	char tmp[30];#endif        ASSERT(ext != NULL && ext->rep != NULL);	/* Connection succeeded. It's ok to monitor agent adv. expiring */	mn.expire_check = 1;	if (mn.current_adv != NULL) {		/* reset retry wait time for next registration */		DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: "		      "%i => %i (reg. reply ok)\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;	if (ntohs(ext->rep->lifetime) > 0) {		DEBUG(DEBUG_INFO, "Registration accepted\n");#ifdef INCLUDE_IPAY		if (mn.current_adv != NULL)			ipay_new_fa(mn.current_adv);#endif	} else DEBUG(DEBUG_INFO, "Deregistration accepted\n");        switch (mn.state) {        case MN_CLOSE_FOR_HOME:		mn.ha_error_count = 0;                if (ntohs(ext->rep->lifetime) == 0)                        at_home();                break;        case MN_FIND_AGENT:        case MN_PASSIVE_FIND:		/* The answer is coming later than expected,		 * so we just skip it. */		DEBUG(DEBUG_MESSAGES, "handle_reg_accept - in find agent or "		      "passive find state - skipping reg. reply\n");		break;        case MN_REQUEST_TUNNEL:        case MN_CONNECTED:		mn.ha_error_count = 0;                if (ext->mn_keyrep != NULL)                        handle_key_ext(ext->rep, ext->mn_keyrep);		if (ext->rep->lifetime == 0) {			LOG2(LOG_INFO, "Got registration accepted reply with "			     "zero lifetime - aborting registration and going "			     "to passive find state\n");			reply_waiting_api(API_FAILED, NULL, 0);			passive_find();			return;		} else {			connected((ext->mh_auth) ? CON_HA : CON_FA,				  ntohs(ext->rep->lifetime));#ifdef MN_LOCUPD_PROFILER			snprintf(tmp, sizeof(tmp), "CON %s",				 inet_ntoa(mn.fa_addr));			write_profiler(tmp);#endif			reply_waiting_api(API_SUCCESS, NULL, 0);		}                break;	case MN_DISCONNECTED:#ifdef MN_LOCUPD_PROFILER		write_profiler("DIS");#endif		break;	default:		break;        }}/* returns: 1 = try again, 0 = give up */static int handle_id_mismatch_ha(struct msg_extensions *ext){	/* If reply code is 133, id failed and we should resynchronize         * clock/nonce and try again */#ifdef MN_LOCUPD_PROFILER	write_profiler("DENY_ID");#endif	switch (config.replay_meth) {	case REPLAY_PROTECTION_NONE:		LOG2(LOG_INFO, "ID mismatch from HA even with "		     "disabled replay protection\n");		reply_waiting_api(API_FAILED, &ext->rep->code, 1);		disconnect();		break;	case REPLAY_PROTECTION_TIMESTAMP:		mn.clock_correction = ntohl(ext->rep->id[0]) -			UNIX_NTP_DIFF -	time(NULL);		if (mn.ha_error_count++ < MAX_HA_ERRORS) {			LOG2(LOG_INFO, "Clock synchronization %d seconds\n",			     mn.clock_correction);			return 1;		} else {			LOG2(LOG_INFO,			     "Clock resynchronization failed. "			     "Disconnecting.\n");			reply_waiting_api(API_FAILED, &ext->rep->code, 1);			disconnect();		}		break;	case REPLAY_PROTECTION_NONCE:		if (mn.ha_error_count++ < MAX_HA_ERRORS) {			LOG2(LOG_INFO, "Nonce mismatch - syncronizing\n");			return 1;		} else {			LOG2(LOG_INFO, "Nonce mismatch - "			     "syncronization failed\n");			reply_waiting_api(API_FAILED, &ext->rep->code, 1);			disconnect();		}		break;	}	return 0;}/* returns: 1 = try again, 0 = give up */static int handle_long_lifetime(struct msg_extensions *ext){#ifdef MN_LOCUPD_PROFILER	write_profiler("LIFETIME_FA");#endif	if (mn.req_lifetime > ntohs(ext->rep->lifetime) &&		ntohs(ext->rep->lifetime) >= MIN_ALLOWED_LIFETIME) {		LOG2(LOG_INFO, "FA (closest FA %s), "		     "requests smaller lifetime (%d) - retrying\n",		     inet_ntoa(mn.fa_addr), ntohs(ext->rep->lifetime));		mn.req_lifetime = ntohs(ext->rep->lifetime);		return 1;	}	/* this FA failed - try to find another one */	LOG2(LOG_INFO, "FA %s denies requested lifetime %d s with bad "	     "suggestion %d s - changing FA\n",	     inet_ntoa(mn.fa_addr), mn.req_lifetime,	     ntohs(ext->rep->lifetime));	if (mn.current_adv != NULL)		mn.current_adv->reg_failed = 1;	else		LOG2(LOG_INFO, "handle_long_lifetime - current_adv == NULL\n");	find_agent(STATE_INIT);	return 0;}/* returns: 1 = try again, 0 = give up */static int handle_unknown_ha(struct msg_extensions *ext){	int retry_hadisc = 0;	/* dynamic home agent address resolution */	if (config.ha_ip_addr.s_addr != 0 || config.home_net_addr_plen < 0) {		LOG2(LOG_INFO, "HA did not accept HA address %s\n",		     inet_ntoa(config.ha_ip_addr));		retry_hadisc = 1;	}	if (ext->rep->ha_addr.s_addr ==	    config.home_net_subnet_bc.s_addr) {		LOG2(LOG_INFO, "HA returned same subnet-directed broadcast "		     "address in dynamic address resolution\n");		retry_hadisc = 1;	}	if (retry_hadisc) {		if (config.use_hadisc) {			DEBUG(DEBUG_MESSAGES, "Try to discover another HA\n");			mn.info_str = "restarting HA discovery";			config.ha_ip_addr.s_addr = 0;			return 1;		}		return 0;	}	LOG2(LOG_INFO, "Learned HA address (%s) with dynamic address "	     "resolution\n", inet_ntoa(ext->rep->ha_addr));	mn.info_str = "HA discovery completed successfully";	config.ha_ip_addr.s_addr = ext->rep->ha_addr.s_addr;	return 1; /* try to register with the new HA address */}/** * handle_reg_denied: * ext: received and parsed registration reply * * Handle registration reply denying registration. * * Returns 1 if registration should be retried or 0 if registration should be * aborted. */static int handle_reg_denied(struct msg_extensions *ext){        ASSERT(ext != NULL && ext->rep != NULL);	if (mn.state != MN_REQUEST_TUNNEL &&	    mn.state != MN_CLOSE_FOR_HOME &&	    mn.state != MN_CONNECTED) {		DEBUG(DEBUG_MESSAGES, "handle_reg_denied - received denial "		      "reply while not trying to register\n");		return 0;	}	DEBUG(DEBUG_MESSAGES, "Registration denied, code = %d (%s)\n",		     ext->rep->code, reply_code_str(ext->rep->code));	switch (ext->rep->code) {	case REGREP_ID_MISMATCH_HA:		return handle_id_mismatch_ha(ext);	case REGREP_LONG_LIFETIME_FA:		return handle_long_lifetime(ext);	case REGREP_UNKNOWN_HA_HA:		return handle_unknown_ha(ext);	case REGREP_HA_HOST_UNCREACHABLE_FA:	case REGREP_HA_PORT_UNCREACHABLE_FA:	case REGREP_HA_UNREACHABLE_FA:		if (config.use_hadisc && config.ha_ip_addr.s_addr != 0) {			DEBUG(DEBUG_MESSAGES, "HA unreachable => try to "			      "discover another HA\n");			mn.info_str = "restarting HA discovery";			config.ha_ip_addr.s_addr = 0;			return 1;		}		return 0;	case REGREP_UNKNOWN_CHALLENGE_FA:	case REGREP_STALE_CHALLENGE_FA:		return 1; /* try to reregister; FIX: should get a new challenge			   * value, if no new agent advertisement has been			   * received */	case REGREP_MN_FAILED_AUTH_FA:		if (mn.try_to_fix_sec_assoc) {			/* dynamic security association was removed in			 * is_valid_reply() so try to reregister and create a			 * new security association with the FA */			return 1;		}		/* no method for fixing the security association, so just fall		 * through to the default case */        default:#ifdef MN_LOCUPD_PROFILER		write_profiler("DENY");#endif		LOG2(LOG_INFO, "Registration denied, code = %d (%s)\n",		     ext->rep->code, reply_code_str(ext->rep->code));		reply_waiting_api(API_FAILED, &ext->rep->code, 1);		/* Try to change the FA by degrading the priority of the "		   "current FA. */		degrade_current_fa_priority();        }	return 0;}/* Handle registration message from socket s. * Returns 1 if registration should be re-tried */int handle_registration(int s){	char msg[MAXMSG];	unsigned int len;	struct sockaddr_in addr;	int n, res;	struct msg_extensions ext;	len = sizeof(addr);        n = recvfrom(s, msg, MAXMSG, 0, (struct sockaddr*) &addr, &len);        if (n < 0) {		LOG2(LOG_ERR, "registration recv: %s\n", strerror(errno));		return 0;	}        DEBUG(DEBUG_MESSAGES, "Received %d bytes from %s:%d\n", n,               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));	res = parse_msg(msg, n, &ext);        if (res != 0 || ext.double_auth_ext != 0) {		char *reason = "N/A";		DEBUG(DEBUG_MESSAGES, "Dropping invalid message\n");		mn.discarded_msgs++;		if (res == -1)			reason = "unknown extension";		else if (res == -2)			reason = "malformed message";		else if (res == -3 || res == -4 || res == -5)			reason = "unknown vendor extension";		else if (ext.double_auth_ext != 0)			reason = "double authentication extension";		report_discarded_msg(msg, n, &addr, reason);		return 0;	}	mn.try_to_fix_sec_assoc = 0;        if (is_valid_reply(&ext, addr)) {		mn.prev_req_replied = 1;		time(&mn.last_reply_rcvd);		mn.last_reply_code = ext.rep->code;		mn.last_nonce = ext.rep->id[0];		if (ext.challenge != NULL) {			int len;			gettimeofday(&mn.last_challenge_time, NULL);			len = GET_CHALLENGE_EXT_LEN(ext.challenge);			if (mn.last_challenge_ext == NULL ||			    GET_CHALLENGE_EXT_LEN(mn.last_challenge_ext) !=			    len) {				if (mn.last_challenge_ext != NULL)					free(mn.last_challenge_ext);				mn.last_challenge_ext =					(struct challenge_ext *) malloc(len);			}			if (mn.last_challenge_ext != NULL)				memcpy(mn.last_challenge_ext, ext.challenge,				       len);			else				DEBUG(DEBUG_INFO, "Could not malloc() memory "				      "for challenge extension\n");		}                if (IS_REGREP_ACCEPTED(ext.rep->code))                        handle_reg_accept(&ext);                else			return handle_reg_denied(&ext);        } else {		report_discarded_msg(msg, n, &addr, "invalid reply");		mn.discarded_msgs++;	}	return 0;}

⌨️ 快捷键说明

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