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

📄 fa_reply.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	DEBUG(DEBUG_FLAG,	      "Confirmed binding data - old lower_addr: %s, ",	      inet_ntoa(binding->lower_addr));	DEBUG(DEBUG_FLAG, "new lower_addr: %s\n",	      inet_ntoa(unc->info.src.sin_addr));	if (unc->info.src.sin_addr.s_addr != binding->lower_addr.s_addr ||	    unc->info.src.sin_port != binding->lower_port ||	    unc->tunnel_mode != t_data->tunnel_mode ||	    unc->is_lowest_fa != t_data->is_lowest_fa ||	    unc->fa_decapsulation != t_data->fa_decapsulation ||	    unc->encaps_delivery != t_data->encaps_delivery ||	    unc->info.iface != t_data->info.iface) {		struct saved_binding_info old;		/* the iface argument is NULL because the reply may not come		 * from the same interface as the request */		save_binding_info(&old, binding);		update_reply_binding_info(binding, unc);		if (handle_lower_switch(binding, &old, ext,					&unc->info.src.sin_addr,					FALSE) != 0)			return 1;	}	unconfirmed_to_binding(binding, unc);	free_unconfirmed_data(t_data->unc_req);	t_data->unc_req = NULL;	return 0;}static intget_fa_session_key_sec(unsigned char *sk, int *sk_len, struct reg_rep *reply,		       struct msg_key *fa_keyrep, struct in_addr addr){	struct fa_spi_entry *fa_spi;	unsigned char *tmp_sk;#ifndef NODEBUGMODE	int i;#endif	fa_spi = get_fa_spi(ntohl(fa_keyrep->spi), addr, 0);	if (fa_spi == NULL) {		LOG2(LOG_WARNING, "Could not handle fa_keyrep with "		     "SPI %i\n", ntohl(fa_keyrep->spi));		return 1;	}	tmp_sk = auth_decrypt(fa_spi->alg, fa_spi->shared_secret,			      fa_spi->shared_secret_len,			      fa_keyrep, reply, sk_len);	if (*sk_len < 0) {		LOG2(LOG_WARNING, "Could not decrypt fa_keyrep with "		     "SPI %i\n", ntohl(fa_keyrep->spi));		return 1;	}	if (*sk_len > MAX_SK_LEN) {		LOG2(LOG_WARNING, "Too long session key\n");		free(tmp_sk);		return 1;	}	memcpy(sk, tmp_sk, *sk_len);	free(tmp_sk);#ifndef NODEBUGMODE	DEBUG(DEBUG_FLAG, "Session key (MD5): ");	for (i = 0; i < *sk_len; i++)		DEBUG(DEBUG_FLAG, "%02x", sk[i]);	DEBUG(DEBUG_FLAG, "\n");#endif	return 0;}static intget_fa_session_key_pub(unsigned char *sk, int *sk_len,		       struct tunnel_data *t_data,		       struct msg_key *fa_pubkeyrep){	if (t_data->last_sent_fa_pubkeyrep != NULL) {		free(t_data->last_sent_fa_pubkeyrep);		t_data->last_sent_fa_pubkeyrep = NULL;	}	if (t_data->last_recv_fa_pubkeyrep != NULL)		free(t_data->last_recv_fa_pubkeyrep);	t_data->last_recv_fa_pubkeyrep =		(struct msg_key *) malloc(GET_KEY_EXT_LEN(fa_pubkeyrep));	if (t_data->last_recv_fa_pubkeyrep == NULL)		return 1;	memcpy(t_data->last_recv_fa_pubkeyrep, fa_pubkeyrep,	       GET_KEY_EXT_LEN(fa_pubkeyrep));	*sk_len = MD5_SK_LEN;	if (do_rsa_decrypt(fa_pubkeyrep, sk, *sk_len) != 0)		return 1;	return 0;}/**  * get_fa_session_key: * @sk:  * @sk_len: * @ext: * @addr: * @binding: * * Extract the session key from @ext (distributed either by symmetric  * secret encryption, or public key encryption). If the @ext does not * contain a key use an already decrypted key in @binding. * * The key is placed in @sk, and its length in @sk_len. * * Returns: 0 if successful */static intget_fa_session_key(unsigned char *sk, int *sk_len, struct msg_extensions *ext,		   struct in_addr addr, struct bindingentry *binding){	struct tunnel_data *t_data = (struct tunnel_data *) binding->data;	if (ext->fa_keyrep) {		/* shared secret based session key distribution */		return get_fa_session_key_sec(sk, sk_len, ext->rep,					      ext->fa_keyrep, addr);	}	/* public key based session key distribution */	if (ext->fa_pubkeyrep != NULL && ntohs(ext->rep->lifetime) > 0 &&	    !equal_pubkey(ext->fa_pubkeyrep, t_data->last_recv_fa_pubkeyrep)) {		/* new key */		return get_fa_session_key_pub(sk, sk_len, t_data,					       ext->fa_pubkeyrep);	}	/* use already decrypted key */	memcpy(sk, binding->key, binding->keylen);	*sk_len = binding->keylen;	return 0;}struct binding_search_data {	struct in_addr mn_addr;	__u32 id1;};static struct binding_search_data bsearch_data;/* returns 1 if bsearch_data matches with the given binding or 0 if it does * not match; to be used with binding_fetch_func() */static intbinding_search_check(struct bindingentry *binding){	struct tunnel_data *t_data;	struct unconfirmed_request *unc;	if (binding->mn_addr.s_addr != bsearch_data.mn_addr.s_addr)		return 0;	if (binding->data == NULL)		return 0;	t_data = (struct tunnel_data *) binding->data;	if (t_data->confirmed && bsearch_data.id1 == binding->id[1])		return 1;	unc = t_data->unc_req;	while (unc != NULL) {		if (unc->id[1] == bsearch_data.id1)			return 1;		unc = unc->next;	}	return 0;}/** * handle_reply: * @ext: * @info: source of reply message * @iface: interface where reply arrived * * Process a registration reply message. * * Returns: 0 if OK, else 1 */inthandle_reply(struct msg_extensions *ext, struct packet_from_info *info){	struct bindingentry *binding;	struct tunnel_data *t_data;	unsigned char sk[MAX_SK_LEN];	int prev_confirmed, sk_len, i, idtype;	struct unconfirmed_request *unc;	char tmp[30];	struct bindingkey bkey;	DEBUG(DEBUG_FLAG, "Handling reply\n");	memcpy(&bkey.mn_addr, &(ext->rep->home_addr), sizeof(bkey.mn_addr));	memcpy(&bkey.ha_addr, &(ext->rep->ha_addr), sizeof(bkey.ha_addr));	if (ext->priv_ha != NULL)		bkey.priv_ha = ntohl(ext->priv_ha->priv_ha);	else		bkey.priv_ha = 0;	if (ext->rep->code == REGREP_UNKNOWN_HA_HA) {		bsearch_data.mn_addr.s_addr = ext->rep->home_addr.s_addr;		bsearch_data.id1 = ntohl(ext->rep->id[1]);		binding = binding_fetch_func(bindings_hash,					     binding_search_check);	} else		binding = binding_fetch(bindings_hash, &bkey);	if (binding == NULL) {		dynamics_strlcpy(tmp, inet_ntoa(info->src.sin_addr),				 sizeof(tmp));		LOG2(LOG_WARNING, "Received reply from %s:%i for MN %s, but "		     "no binding found\n", tmp, ntohs(info->src.sin_port),		     inet_ntoa(ext->rep->home_addr));		return 1;	}	t_data = binding->data;	t_data->pending_request = FALSE;	unc = find_matching_request(binding, ntohl(ext->rep->id[1]), &idtype);	if (idtype == ID_NOT_FOUND || (t_data->info.iface == NULL &&				       unc == NULL)) {		LOG2(LOG_WARNING, "Could not found a matching request for the "		     "reply - dropping it\n");		return 1;	}	assert(t_data->confirmed || unc != NULL);	i = validate_reply(ext, binding, info, unc);	if (i < 0) {		LOG2(LOG_WARNING, "Reply validation failed - dropping it\n");		return 1;	}	if (i == 1) {		DEBUG(DEBUG_FLAG, "Reply did not have Dynamics extensions - "		      "assuming that HA/upper FA does not support them\n");		t_data->dynamics_extensions = 0;	} else {		t_data->dynamics_extensions = 1;	}	if (get_fa_session_key(sk, &sk_len, ext, info->src.sin_addr,			       binding) != 0)		return 1;	if (!IS_REGREP_ACCEPTED(ext->rep->code)) {		/* Note: RFC 2002 - chapter 3.7.2:		 * "If the Registration Reply indicates that the Request (for		 * registration or deregistration) was denied by the home		 * agent, the existing visitor list entry for the mobile node		 * MUST NOT be modified as a result of receiving the		 * Registration Reply." */		return forward_reply(binding, ext, 1, unc);	}	if (ntohs(ext->rep->lifetime) == 0) {		/* Tear down or disconnect */		return handle_reply_disconnect(binding, unc, ext, idtype);	}	prev_confirmed = t_data->confirmed;	if (!t_data->confirmed) {		if (handle_unconfirmed_reply(binding, ext, sk, sk_len, unc) !=		    0) {			LOG2(LOG_WARNING, "Reply to an unconfirmed binding "			     "could not be confirmed - dropping reply\n");			return 1;		}	} else {		if (idtype == ID_NEW &&		    handle_confirmed_reply(binding, ext, unc) != 0) {			LOG2(LOG_WARNING, "Reply to a confirmed binding - "			     "confirming request data failed\n");			return 1;		}	}	assert(t_data->confirmed);	/* update the session key */	memcpy(binding->key, sk, sk_len);	binding->keylen = sk_len;	time(&binding->mod_time);	if (ntohs(ext->rep->lifetime) > t_data->req_lifetime) {		/* RFC 2002, sec. 3.4:		 * The home agent MUST NOT increase the Lifetime selected by		 * the mobile node in the Registration Request, since doing so		 * could increase it beyond the maximum Registration Lifetime		 * allowed by the foreign agent. If the Lifetime received in		 * the Registration Reply is greater than that in the		 * Registration Request, the Lifetime in the Request MUST be		 * used. */		LOG2(LOG_WARNING, "Lifetime too long in reply (%i) - using the"		     " lifetime of the request (%i)\n",		     ntohs(ext->rep->lifetime), t_data->req_lifetime);		binding->timeout = t_data->req_lifetime;	} else		binding->timeout = ntohs(ext->rep->lifetime);	if (binding->timeout > config->fa_default_tunnel_lifetime) {		DEBUG(DEBUG_FLAG, "Lifetime too long - using max lifetime\n");		binding->timeout = config->fa_default_tunnel_lifetime;	}	/* increase timeout with one second so that the one second timer	 * resolution doesn't cause too early expirations */	binding->timeout++;	binding->exp_time = time(NULL) + binding->timeout;	if (update_binding(bindings_hash, binding, &bcounters) != 0) {		LOG2(LOG_WARNING, "handle_reply: update_binding failed\n");		return 1;	}	/* In LFA prepare the tunnels first but in IFA send the reply first	 * and do the tunnel stuff afterwards. This speeds up the location	 * update time when using IFAs */	if (!t_data->is_lowest_fa) {		DEBUG(DEBUG_FLAG, "handle_reply: not lowest FA: forwarding "		      "reply first and then create_tunnels\n");		i = forward_reply(binding, ext, 0, NULL);	}	/* create the tunnels if the binding was confirmed */	if (!prev_confirmed && t_data->confirmed &&	    create_tunnels(binding, tunnels_hash, config->highest_FA) != 0) {		LOG2(LOG_WARNING, "handle_reply: create_tunnels failed\n");		return 1;	}	if (t_data->is_lowest_fa) {		DEBUG(DEBUG_FLAG, "handle_reply: lowest FA: forwarding reply "		      "after create_tunnels ok\n");		i = forward_reply(binding, ext, 0, NULL);	}	return i;	}

⌨️ 快捷键说明

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