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

📄 fa_reply.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	    (ext->ext_dyn->opts & REG_EXT_OWN_TEAR_DOWN) == 0) {		forward_reply(binding, ext, 1, unc);	} else {		DEBUG(DEBUG_FLAG, "handle_reply_disconnect: tear down reply "		      "not forwarded to MN\n");	}	/* Delay binding removal in tear down processing */	if (t_data->confirmed == 1) {		DEBUG(DEBUG_FLAG, "Tear down/disconnect: Delay binding "		      "removal\n");		/* eliminate old session key so that all the new requests will		 * be forwarded upwards */		memset(&binding->key, 0, MAX_SK_LEN);		binding->keylen = 0;#ifdef REMOVE_BINDING_OPTIM		binding->timeout = 0;		binding->exp_time = time(NULL);		if (update_binding(bindings_hash, binding, &bcounters) != 0)			LOG2(LOG_WARNING, "binding removal: "			     "update_binding failed\n");#else		/* Leave the disconnect binding up for		 * DELAY_BINDING_TIME seconds so that possible queued		 * data can still be forwarded.  The tear down message		 * does not change the binding timeout in order to		 * avoid DoS attacks with tear down messages. The		 * session key is still reset, so the returning MN		 * does not cause problems. */		if (ext->ext_dyn == NULL ||		    (ext->ext_dyn->opts & REG_EXT_OWN_TEAR_DOWN) == 0) {			if (binding->timeout > 2) {				DEBUG(DEBUG_FLAG, "Deregistration reply - "				      "setting tunnel lifetime to 2 secs\n");				binding->timeout = 2;			}			binding->exp_time = time(NULL) + binding->timeout;			if (update_binding(bindings_hash, binding,					   &bcounters) != 0)				LOG2(LOG_WARNING, "delay binding removal: "				     "update_binding failed\n");		} else {#ifdef SHORT_BINDING_DELAY_TIME /* ONLY FOR TESTING */			if (binding->timeout != DELAY_BINDING_TIME) {				DEBUG(DEBUG_FLAG, "Deregistration reply - "				      "setting tunnel lifetime to 2 secs\n");				binding->timeout = DELAY_BINDING_TIME;			}			binding->exp_time = time(NULL) + binding->timeout;			if (update_binding(bindings_hash, binding,					   &bcounters) != 0)				LOG2(LOG_WARNING, "delay binding removal: "				     "update_binding failed\n");#endif /* SHORT_BINDING_DELAY_TIME */			DEBUG(DEBUG_FLAG, "Teardown - only resetting the "			      "session key\n");		}		return 0;#endif	}	/* NOTE: With lazy tunnel deletion the tunnel will be up long 	   enough (make sure that tunnel.c:PURGE_TUNNEL_TIME >= 2) */	/* remove the tunnels associated to this binding */	remove_binding_tunnels(binding, tunnels_hash, &bcounters);	return 0;}static intforward_reply(struct bindingentry *binding, struct msg_extensions *ext,	      int error_reply, struct unconfirmed_request *unc){	char msg[MAXMSG];	int len, ret;	struct tunnel_data *t_data;	struct reg_rep *reply;	struct msg_key *key;	struct fa_spi_entry *fa_spi;	struct packet_from_info *dst;	assert(binding != NULL && binding->data != NULL);	if (ext->rep == NULL) return 1;	t_data = binding->data;	if (!t_data->confirmed)		error_reply = TRUE;	if (error_reply && !IS_REGREP_ACCEPTED(ext->rep->code))		DEBUG(DEBUG_FLAG, "Forwarding error reply - code=%i - %s\n",		      ext->rep->code, reply_code_str(ext->rep->code));	else		DEBUG(DEBUG_FLAG, "Forwarding reply\n");	if (ext->mh_auth != NULL) {		/* copy the MAC protected area directly from the received		 * message. This area should include at least the reply		 * header, mn_keyrep and mh_auth. */		len = (__u8 *) ext->mh_auth - (__u8 *) ext->rep +			GET_AUTH_EXT_LEN(ext->mh_auth);		if (len < sizeof(struct reg_rep) +		    GET_AUTH_EXT_LEN(ext->mh_auth) || len > MAXMSG) {			LOG2(LOG_WARNING, "forward_reply: invalid length %i\n",			     len);			return 1;		}		memcpy(msg, ext->rep, len);		DEBUG(DEBUG_FLAG, " * copying up to and including mh_auth "		      "(len ==> %i)\n", len);	} else {		/* no mh_auth - copy only the reply header */		memcpy(msg, ext->rep, sizeof(struct reg_rep));		len = sizeof(struct reg_rep);		DEBUG(DEBUG_FLAG, " * copying reply header (len=%i)\n", len);	}	reply = (struct reg_rep *) msg;	if (!error_reply && binding->fa_spi != 0 &&	    ntohs(ext->rep->lifetime) > 0) {		fa_spi = get_fa_spi(binding->fa_spi,				    (unc ? unc->info.src.sin_addr :				     binding->lower_addr), 0);		if (fa_spi == NULL) {			LOG2(LOG_WARNING, "unknown FA SPI %i, IP=%s\n",			     binding->fa_spi,			     inet_ntoa(binding->lower_addr));			return 1;		}		key = (struct msg_key *) (msg + len);		if (((char *) MSG_KEY_DATA(key)) + MAX_SK_LEN > msg + MAXMSG) {			LOG2(LOG_WARNING, "not enough space for SK to FA\n");			return 1;		}		len += auth_encrypt(fa_spi->alg, fa_spi->shared_secret,				    fa_spi->shared_secret_len, binding->key,				    key, reply, VENDOR_EXT_DYNAMICS_FA_KEYREP,				    htonl(fa_spi->spi));	} else if (!error_reply && t_data->fa_pubkey &&		   ntohs(ext->rep->lifetime) > 0) {		/* encrypt the SK with lower FA pubkey */		if (t_data->last_sent_fa_pubkeyrep == NULL) {			t_data->last_sent_fa_pubkeyrep =				dynamics_do_rsa_encrypt(binding->key,							binding->keylen,							t_data->fa_pubkey);			if (t_data->last_sent_fa_pubkeyrep == NULL) {				LOG2(LOG_WARNING, "RSA encrypt failed\n");				return 1;			}		}		if (len + GET_KEY_EXT_LEN(t_data->last_sent_fa_pubkeyrep) >		    MAXMSG) {			LOG2(LOG_WARNING, "Message buffer overflow\n");			return 1;		}		memcpy(msg + len, t_data->last_sent_fa_pubkeyrep,		       GET_KEY_EXT_LEN(t_data->last_sent_fa_pubkeyrep));		DEBUG(DEBUG_FLAG,		      " * adding fa_pubkeyrep extension: pos=%i, len=%i\n",		      len, GET_KEY_EXT_LEN(t_data->last_sent_fa_pubkeyrep));		len += GET_KEY_EXT_LEN(t_data->last_sent_fa_pubkeyrep);	} else if (!error_reply) {		DEBUG(DEBUG_FLAG,		      " * no pubkey known - FA encrypt session key not "		      "added\n");	}	if (ext->ext_dyn != NULL) {		int elen = ext->ext_dyn->length + 2;		if (len + elen > MAXMSG) {			LOG2(LOG_WARNING, "Message buffer overflow\n");			return 1;		}		memcpy(msg + len, ext->ext_dyn, elen);		DEBUG(DEBUG_FLAG, " * copying ext_dyn: pos=%i, len=%i\n",		      len, elen);		len += elen;	}	if (ext->sfa_debug != NULL) {		int elen = GET_SFA_DEBUG_EXT_LEN(ext->sfa_debug);		if (len + elen > MAXMSG) {			LOG2(LOG_WARNING, "Message buffer overflow\n");			return 1;		}		memcpy(msg + len, ext->sfa_debug, elen);		DEBUG(DEBUG_FLAG, " * copying sfa_debug: pos=%i, len=%i\n",		      len, elen);		len += elen;	}	if (len + sizeof(struct msg_auth) + MD5_MAC_LEN > MAXMSG) {		LOG2(LOG_WARNING, "Message buffer overflow\n");		return 1;	}	if (!error_reply && ext->sk_auth != NULL) {		DEBUG(DEBUG_FLAG,		      " * adding sk_auth extension: pos=%i, len=%i\n",		      len, MD5_MAC_LEN + SPI_LEN);		len += auth_add_vendor(AUTH_ALG_MD5, binding->key,				       binding->keylen,				       (unsigned char *) reply,				       (struct vendor_msg_auth *) (msg + len),				       VENDOR_EXT_DYNAMICS_SK_AUTH,				       ext->sk_auth->spi);	}	len += add_fa_auth_ext((unc ? unc->info.src.sin_addr :				binding->lower_addr),			       reply->home_addr, (unsigned char *) reply,			       (unsigned char *) msg + len);	assert(len <= MAXMSG);	dst = NULL;	if (unc && unc->is_lowest_fa)		dst = &unc->info;	else if (!unc && t_data->is_lowest_fa)		dst = &t_data->info;	if (config->packet_socket_mode != PACKET_SOCKET_MODE_ONLY_RECEIVE &&	    dst != NULL) {		DEBUG(DEBUG_FLAG, " * sending %i bytes using packet socket\n",		      len);		ret = packet_socket_send(dst, msg, len);	} else if (unc) {		DEBUG(DEBUG_FLAG, " * sending %i bytes to %s:%i (unc)\n",		      len, inet_ntoa(unc->info.src.sin_addr),		      ntohs(unc->info.src.sin_port));		assert(unc->info.iface != NULL);		ret = own_sendto(unc->info.iface->udp_sock,				 unc->info.src.sin_addr,				 unc->info.src.sin_port, msg, len);	} else {		DEBUG(DEBUG_FLAG, " * sending %i bytes to %s:%i\n",		      len, inet_ntoa(binding->lower_addr),		      ntohs(binding->lower_port));		assert(t_data->info.iface != NULL);		ret = own_sendto(t_data->info.iface->udp_sock,				 binding->lower_addr,				 binding->lower_port, msg, len);	}	return dynamics_check_sendto(ret, len, "Forward reply");}/* try to confirm an unconfirmed binding */static inthandle_unconfirmed_reply(struct bindingentry *binding,			 struct msg_extensions *ext, unsigned char *sk,			 int sk_len, struct unconfirmed_request *unc){	struct tunnel_data *t_data = (struct tunnel_data *) binding->data;	/* check that the session key and sk_auth extension match */	if ((ext->fa_pubkeyrep != NULL || ext->fa_keyrep) && ext->sk_auth) {		if (!auth_check_vendor(AUTH_ALG_MD5, sk, sk_len,				       (unsigned char *) ext->rep,				       ext->sk_auth)) {			LOG2(LOG_WARNING, "Invalid sk_auth in reply\n");			return 1;		}	} else if (t_data->dynamics_extensions) {		/* this should not be reached as dynamics_extensions implies		 * both fa_pubkeyrep and sk_auth extensions */		LOG2(LOG_WARNING, "Extensions fa_pubkeyrep, fa_keyrep and/or "		     "sk_auth missing\n");		return 1;	}	/* okay, match found - fill the binding with confirmed data */	unconfirmed_to_binding(binding, unc);	t_data->confirmed = TRUE;	DEBUG(DEBUG_FLAG, "\tconfirming the binding\n");	bcounters.bindingcount++;	bcounters.pendingcount--;	free_unconfirmed_data(t_data->unc_req);	t_data->unc_req = NULL;	return 0;}/** * update_reply_binding_info: * @binding: * @unc:  *  * Update binding info based on request data */static voidupdate_reply_binding_info(struct bindingentry *binding, 			  const struct unconfirmed_request *unc){	struct tunnel_data *t_data = (struct tunnel_data *) binding->data;	/* update down interface pointer */	memcpy(&t_data->info, &unc->info, sizeof(unc->info));	t_data->old_if_index = unc->info.iface->if_index;	/* update lower end type (MN/FA) */	t_data->is_lowest_fa = unc->is_lowest_fa;	/* update MN/FA decapsulation mode */	t_data->fa_decapsulation = unc->fa_decapsulation;	/* update encapsulating delivery mode */	t_data->encaps_delivery = 		!t_data->is_lowest_fa || unc->encaps_delivery;	/* update down_type and down_key */	t_data->down_type = unc->tunnel_type;	t_data->down_key = unc->tunnel_key;	/* update binding lower address and port */	binding->lower_addr = unc->info.src.sin_addr;	binding->lower_port = unc->info.src.sin_port;	binding->fa_spi = 0;	setup_device_forcing(t_data);	/* update tunnel mode */	t_data->tunnel_mode = unc->tunnel_mode;#ifdef USE_TEARDOWN	/* FIX-JM: update t_data->upper_id ?? */#endif}/* handle a reply to an unconfirmed requests of a confirmed binding and switch * the lower side of the tunnel if needed * Returns: 0 = success, 1 = failure */static inthandle_confirmed_reply(struct bindingentry *binding,		       struct msg_extensions *ext,		       struct unconfirmed_request *unc){	struct tunnel_data *t_data = (struct tunnel_data *) binding->data;	assert(unc != NULL);	/* replace the binding data with the previously unconfirmed data */

⌨️ 快捷键说明

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