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

📄 ha.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		binding = api_fetch_binding(&recv_msg);		if (!binding) {			send_msg.code = API_FAILED;			break;		}		binding_remove(binding);		remove_tunnel(binding);		destroy_binding(binding);		send_msg.length = 0;		send_msg.code = API_SUCCESS;		LOG2(LOG_NOTICE, "API call removed binding for MN %s\n",		     inet_ntoa(binding->mn_addr));		break;	case API_GET_STATUS:		DEBUG(DEBUG_FLAG, "Received API_GET_STATUS\n");		if (recv_msg.length != 0) {			LOG2(LOG_ERR, "API_GET_STATUS message has wrong "			     "length\n");			break;		}		status = (struct dynamics_ha_status *) send_msg.params;		memcpy(status, &stats, sizeof(struct dynamics_ha_status));		UNALIGNED_(&status->tunnel_count, &bindingcount);		send_msg.length = sizeof(struct dynamics_ha_status);		send_msg.code = API_SUCCESS;		break;	case API_RELOAD_CONFIG:		/* Force a reload of the configuration */		DEBUG(DEBUG_FLAG, "Received API_RELOAD_CONFIG\n");		if (!priv) {			send_msg.code = API_NOT_PERMITTED;			break;		}		reload_config(1);		DEBUG(DEBUG_FLAG, "Configuration_reloaded\n");		send_msg.code = API_SUCCESS;		break;	default:		LOG2(LOG_ERR, "Received unknown API command: %d\n",		     recv_msg.code);		send_msg.code = API_NOT_SUPPORTED;		break;	}	return api_send(socket, &cli_addr, cli_len, &send_msg);}/********************************************************************** * Registration request handling **********************************************************************//** * pubkey_hash_ok: * @pubkey: pointer to public key extension * @hash: pointer to public key hash extension * * Check whether public key @pubkey matches with its @hash value. * * Returns: *   1 if key hash is correct or 0 if check failed */static intpubkey_hash_ok(struct msg_key *pubkey, struct msg_key *hash){	unsigned char mac[MD5_MAC_LEN];	if (GET_KEY_LEN(hash) != MD5_MAC_LEN) {		DEBUG(DEBUG_FLAG, "pubkey_hash_ok: invalid hash length: %i, "		      "expected %i\n", GET_KEY_LEN(hash), MD5_MAC_LEN);		return 0;	}	md5_mac((unsigned char *) "", 0, (unsigned char *) pubkey,		GET_KEY_EXT_LEN(pubkey), mac);	return (memcmp(mac, MSG_KEY_DATA(hash), MD5_MAC_LEN) == 0);}/** * check_fa_auth_ext: * @addr: source IP address of the registration message * @ext: registration message extensions * * Check whether registration message FA/SHA-HA authentication is valid. * * Returns: *   0 if auth. ext. okay or 1 if fh_auth missing/invalid */static intcheck_fa_auth_ext(struct in_addr addr, const struct msg_extensions *ext){	struct fa_spi_entry *fa_spi;	fa_spi = get_fa_spi(0, addr);	if (fa_spi == NULL) {		/* no security association with the sender - authentication		 * extension not required */		if (ext->fh_auth != NULL) {			DEBUG(DEBUG_FLAG, "No FA-HA security association, but "			      "request had FA-HA authentication extension\n");			return 1;		}		return 0;	}	if (ext->fh_auth == NULL && ext->sha_ha_auth != NULL &&	    config.sha_addr.s_addr != 0) {		DEBUG(DEBUG_FLAG, "Checking sha_ha_auth\n");		if (auth_check_vendor(fa_spi->alg, fa_spi->shared_secret,				      fa_spi->shared_secret_len,				      (unsigned char *) ext->req,				      ext->sha_ha_auth))			return 0;		return 1;	}	DEBUG(DEBUG_FLAG, "Checking fh_auth\n");	if (ext->fh_auth == NULL ||	    !auth_check(fa_spi->alg, fa_spi->shared_secret,			fa_spi->shared_secret_len, (unsigned char *) ext->req,			ext->fh_auth))		return 1;	else		return 0;}/** * validate_request: * @binding: binding entry of the MN from which the registration message is * originating or %NULL if no binding for this MN available * @faaddr: source IP address of the registration message * @msg: pointer to the start of registration message * @msg_len: length of the registration message * @ext: received message extensions * @code: pointer to buffer for failure code * @auth_type: pointer to buffer for used MN-HA authentication type * * Validate registration request. Check that it: * - has the necessary extensions * - comes from an authorized mobile node * - has a valid MAC in the authentication extension * - has the right HA address * * Returns: *  If everything is OK a pointer to the used SPI entry will be *  returned, and code will be REGREP_ACCEPTED or REGREP_ACCEPTED_NO_SB. * *  On failure @code is set to the value that should be sent in the failure *  reply. If code is negative no reply is to be sent. The returned value *  is %NULL if the SPI entry for MN is not found, otherwise it points to the *  SPI entry. * *  The auth_type is set to a special code AUTH_MAC_RFC2002 if *  the MAC of the mh_auth did not included the SPI field (RFC 2002). */#define AUTH_MAC_RFC2002 -100static struct spi_entry *validate_request(struct bindingentry *binding, struct in_addr faaddr,		 const char *msg, int msg_len,		 const struct msg_extensions *ext, int *code, int *auth_type){	struct node *node;	struct spi_entry *spi = NULL;	time_t current_time;	enum { NOT_FOUND, UNICAST_FOUND, BROADCAST_FOUND } own_addr_found;	struct authorized_entry *auth = NULL;	char faaddrstr[16];	char mnaddrstr[16];	struct ha_tunnel_data *t_data = NULL;	if (binding != NULL)		t_data = (struct ha_tunnel_data *) binding->data;	dynamics_strlcpy(faaddrstr, inet_ntoa(faaddr), sizeof(faaddrstr));	*code = REGREP_ACCEPTED;	*auth_type = 0;	/* check that it has the right extensions */	if (ext->req == NULL || ext->mh_auth == NULL) {		LOG2(LOG_WARNING,		     "FA %s: message does not contain either request "		     "and/or message authentication\n", faaddrstr);		if (ext->mh_auth == NULL)			*code = REGREP_MN_FAILED_AUTH_HA;		else			*code = REGREP_BAD_REQUEST_HA;		return NULL;	}		dynamics_strlcpy(mnaddrstr, inet_ntoa(ext->req->home_addr),			 sizeof(mnaddrstr));	/* check that the MN is authorized */	for (node = list_get_first(&config.authorized_list); node != NULL;	     node = list_get_next(node)) {		auth = (struct authorized_entry *) node;		if (ntohl(ext->mh_auth->spi) >= auth->spi_low &&		    ntohl(ext->mh_auth->spi) <= auth->spi_high &&		    (ext->req->home_addr.s_addr & auth->netmask.s_addr) ==		    auth->network.s_addr) {			break;		}	}	if (node == NULL) {		LOG2(LOG_WARNING, "FA %s, MN %s: Not authorized\n", 		     faaddrstr, mnaddrstr);		*code = REGREP_ADMIN_PROHIBITED_HA;		return NULL;	}	/* check MAC (MN-HA authentication extension) */	spi = get_mn_spi(ntohl(ext->mh_auth->spi));	if (spi == NULL) {		LOG2(LOG_WARNING, "FA %s, MN %s: SPI %d not found\n", 		     faaddrstr, mnaddrstr, ntohl(ext->mh_auth->spi));		*code = REGREP_MN_FAILED_AUTH_HA;		return NULL;	}	if (!auth_check(spi->auth_alg, spi->shared_secret,			spi->shared_secret_len,			(unsigned char *) msg, ext->mh_auth)) {		if (spi->auth_alg != AUTH_ALG_MD5 ||		    !auth_check(AUTH_ALG_MD5_RFC2002, spi->shared_secret,				spi->shared_secret_len,				(unsigned char *) msg, ext->mh_auth)) {			LOG2(LOG_WARNING, "FA %s, MN %s, SPI %d: Invalid MN-HA"			     " authentication extension\n",			     faaddrstr, mnaddrstr, spi->spi);			*code = REGREP_MN_FAILED_AUTH_HA;			return spi;		} else {			/* non-standard authentication method used */			DEBUG(DEBUG_FLAG, "RFC 2002 MAC calculation "			      "detected - trying to use the same method\n");			*auth_type = AUTH_MAC_RFC2002;		}	}	if (ext->double_auth_ext > 0) {		LOG2(LOG_WARNING, "FA %s, MN %s: duplicate authentication "		     "extension\n", faaddrstr, mnaddrstr);		if (ext->double_auth_ext & DOUBLE_MH_AUTH)			*code = REGREP_MN_FAILED_AUTH_HA;		else if (ext->double_auth_ext & DOUBLE_FH_AUTH)			*code = REGREP_FA_FAILED_AUTH_HA;		else			*code = REGREP_REASON_UNSPEC_HA;		return spi;	}	/* check possible Foreign-Home Authentication Extension */	if (check_fa_auth_ext(faaddr, ext) != 0) {		LOG2(LOG_WARNING, "FA %s, MN %s: invalid/missing fh_auth\n",		     faaddrstr, mnaddrstr);		*code = REGREP_FA_FAILED_AUTH_HA;		return spi;	}	/* check that MN-HA auth. ext. protects correct extensions */	if (!auth_is_protected(ext->pubkey_hash, ext->mh_auth) ||	    !auth_is_protected(ext->priv_ha, ext->mh_auth) ||	    !auth_is_protected(ext->mn_keyreq, ext->mh_auth) ||	    !auth_is_protected(ext->mn_nai, ext->mh_auth)) {		LOG2(LOG_WARNING, "FA %s, MN %s: MN-HA auth. ext. does not "		     "protect all the required extensions\n",		     faaddrstr, mnaddrstr);		*code = REGREP_MN_FAILED_AUTH_HA;	}	/* check that MN-AAA auth. ext. protects correct extensions */	if (ext->mn_fa_key_req_aaa != NULL &&	    (ext->mn_aaa_auth == NULL ||	     !auth_is_protected(ext->mn_fa_key_req_aaa, ext->mn_aaa_auth))) {		LOG2(LOG_WARNING, "FA %s, MN %s: MN-AAA auth. ext. does not "		     "protect MN-FA keyreq from AAA extensions\n",		     faaddrstr, mnaddrstr);		*code = REGREP_MN_FAILED_AUTH_HA;	}	if (ext->mn_ha_key_req_aaa != NULL &&	    (ext->mn_aaa_auth == NULL ||	     !auth_is_protected(ext->mn_ha_key_req_aaa, ext->mn_aaa_auth))) {		LOG2(LOG_WARNING, "FA %s, MN %s: MN-AAA auth. ext. does not "		     "protect MN-HA keyreq from AAA extensions\n",		     faaddrstr, mnaddrstr);		*code = REGREP_MN_FAILED_AUTH_HA;	}	if (ext->fh_auth != NULL &&	    !auth_is_protected(ext->challenge, ext->fh_auth)) {		LOG2(LOG_WARNING, "FA %s, MN %s: FA-HA auth. ext. does not "		     "protect all the required extensions\n",		     faaddrstr, mnaddrstr);		*code = REGREP_FA_FAILED_AUTH_HA;	}	/* check own (HA) address */	own_addr_found = NOT_FOUND;	for (node = list_get_first(&config.interfaces); node != NULL;	     node = list_get_next(node)) {		struct interface_entry *iface =			(struct interface_entry *) node;		if (iface->addr.s_addr == ext->req->ha_addr.s_addr) {			own_addr_found = UNICAST_FOUND;			break;		}		if (iface->ha_disc &&		    iface->bcaddr.s_addr == ext->req->ha_addr.s_addr) {			own_addr_found = BROADCAST_FOUND;			break;		}	}	if (own_addr_found != 1 &&	    (config.sha_addr.s_addr == 0 ||	     ext->req->ha_addr.s_addr != config.sha_addr.s_addr)) {		if (own_addr_found == BROADCAST_FOUND)			DEBUG(DEBUG_FLAG,			      "==> HA discovery, deny with unknown HA\n");		else			LOG2(LOG_WARNING, "FA %s, MN %s: HA address does not "			     "match\n", faaddrstr, mnaddrstr);		*code = REGREP_UNKNOWN_HA_HA;		return spi;	}	/* check option bits */	if (ext->req->opts & REGREQ_SIMULTANEOUS_BINDINGS) {		LOG2(LOG_INFO,		     "FA %s, MN %s: Received request for unsupported "		    "simultaneous_bindings\n", faaddrstr, mnaddrstr);		/* this is ok, but inform the MN */		*code = REGREP_ACCEPTED_NO_SB;	}	current_time = time(NULL);	if (spi->replay_method == REPLAY_PROTECTION_TIMESTAMP &&	    (ntohl(ext->req->id[0]) < current_time + UNIX_NTP_DIFF -	     spi->timestamp_tolerance ||	     ntohl(ext->req->id[0]) > current_time + UNIX_NTP_DIFF +	     spi->timestamp_tolerance)) {		time_t t;		t = ntohl(ext->req->id[0]) - UNIX_NTP_DIFF;		LOG2(LOG_WARNING, "ID mismatch - timestamp difference=%i, "		     "tolerance=%i\n", abs(t - current_time),		     spi->timestamp_tolerance);		*code = REGREP_ID_MISMATCH_HA;	} else if (spi->replay_method == REPLAY_PROTECTION_NONCE &&		   t_data != NULL && ext->req->id[0] != t_data->nonce) {		LOG2(LOG_WARNING, "ID mismatch (nonce)\n");		DEBUG(DEBUG_FLAG, "\treq->id: %08x, expected nonce %08x\n",		      ext->req->id[0], t_data->nonce);		*code = REGREP_ID_MISMATCH_HA;	}	if (ext->req->opts & REGREQ_BROADCAST_DATAGRAMS) {		DEBUG(LOG_INFO,		      "FA %s, MN %s: Received request for unsupported "		    "broadcast message forwarding\n", faaddrstr, mnaddrstr);		/* this is not yet implemented in Dynamics HA, but accept the		 * connection anyway; there is no accepted reply code that		 * would indicate this situation, so MN will think that the		 * request was accepted.. */	}	/* REGREQ_VJ_HC is ignored in HA, see RFC 2002, 3.8.2 */	if (ext->req->opts & (REGREQ_MINIMAL_ENCAPS | REGREQ_GRE_ENCAPS)) {		LOG2(LOG_INFO, "FA %s, MN %s: Received unsupported option "		     "request (opts=0x%02x)\n", faaddrstr, mnaddrstr,		     ext->req->opts);		/* RFC 2344 defines new denial code for unavailable		 * encapsulation */		if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0)			*code = REGREP_ENCAP_UNAVAIL_HA;		else			*code = REGREP_REASON_UNSPEC_HA;		return spi;	}	if (!config.enable_reverse_tunneling &&	    (ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0) {		LOG2(LOG_INFO,		     "FA %s, MN %s: Asked forbidden reverse tunneling\n",		     faaddrstr, mnaddrstr);		*code = REGREP_REVERSE_TUNNEL_UNAVAIL_HA;		return spi;	}	if (!config.enable_triangle_tunneling &&	    (ext->req->opts & REGREQ_REVERSE_TUNNEL) == 0) {		LOG2(LOG_INFO,		     "FA %s, MN %s: Reverse tunneling mandatory\n",		     faaddrstr, mnaddrstr);		*code = REGREP_REVERSE_TUNNEL_MANDATORY_HA;		return spi;	}	if (ext->req->opts & REGREQ_RESERVED) {		LOG2(LOG_INFO, "FA %s, MN %s: Received a request with non-zero"		     " reserved field\n", faaddrstr, mnaddrstr);		*code = REGREP_BAD_REQUEST_HA;		return spi;	}	if (config.pubkey_hash_method == HASH_METHOD_REQUIRE &&	    ext->fa_pubkey != NULL && ext->pubkey_hash == NULL) {		LOG2(LOG_INFO, "FA %s, MN %s: Received a request with public "		     "key, but without public key hash extension\n",		     faaddrstr, mnaddrstr);		*code = REGREP_ADMIN_PROHIBITED_HA;		return spi;	}	if (config.pubkey_hash_method != HASH_METHOD_NONE &&	    ext->fa_pubkey != NULL &&	    ext->pubkey_hash != NULL &&	    !pubkey_hash_ok(ext->fa_pubkey, ext->pubkey_hash)) {		LOG2(LOG_INFO, "FA %s, MN %s: Received a request with public "		     "key and mismatching public key hash extension\n",		     faaddrstr, mnaddrstr);		*code = REGREP_ADMIN_PROHIBITED_HA;		return spi;	}	/* request is OK */	return spi;}/** * new_session_key: * @binding: pointer to bindingentry * @mn_spi: pointer to SPI entry for the MN * * Generate a new session key for the given MN (@binding,@mn_spi). * * Returns: *  0 on success or -1 on failure

⌨️ 快捷键说明

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