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

📄 fa_request.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	DEBUG(DEBUG_FLAG, "\tbinding->timeout=%i, calculated timeout=%i\n",	      binding->timeout, timeout);	reply->lifetime = htons(timeout);	reply->home_addr.s_addr = ext->req->home_addr.s_addr;	reply->ha_addr.s_addr = ext->req->ha_addr.s_addr;	reply->id[0] = ext->req->id[0];	reply->id[1] = ext->req->id[1];	len += sizeof(struct reg_rep);	if (config->send_sfa_debug_ext) {		struct sfa_debug_ext *sfa_ext = (struct sfa_debug_ext *)			(msg + len);		sfa_ext->type = VENDOR_EXT_TYPE2;		sfa_ext->reserved = 0;		sfa_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS);		sfa_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_SFA_DEBUG);		sfa_ext->length = sizeof(struct sfa_debug_ext) - 2;		sfa_ext->sfa_addr = up_interface->addr;		len += GET_SFA_DEBUG_EXT_LEN(sfa_ext);		DEBUG(DEBUG_FLAG, " * added SFA debug ext\n");	}	if (t_data->is_lowest_fa && config->enable_challenge_response &&	    config->challenge_in_reg_reply) {		struct challenge_ext *challenge;		challenge = create_challenge_ext(config, MN_FA_CHALLENGE_EXT);		if (challenge != NULL) {			int n = GET_CHALLENGE_EXT_LEN(challenge);			if (len + n > MAXMSG) {				free(challenge);				return 1;			}			memcpy(msg + len, challenge, n);			len += n;			/* save the last challenge so that MN's registration			 * requests can be checked to contain a valid challenge			 */			if (t_data->last_challenge != NULL)				free(t_data->last_challenge);			t_data->last_challenge = challenge;			DEBUG(DEBUG_FLAG, " * added challenge ext\n");		}	}	if (len + sizeof(struct msg_auth) + MD5_MAC_LEN > MAXMSG)		return 1;	len += auth_add_vendor(		AUTH_ALG_MD5, binding->key, binding->keylen, msg,		(struct vendor_msg_auth *) (msg + len),		VENDOR_EXT_DYNAMICS_SK_AUTH,		ext->sk_auth != NULL ? ext->sk_auth->spi : 0);	/* Foreign Agent key reply - add only if not lowest FA	 * Use shared secret and MD5 if fa_keyreq was used or RSA if	 * fa_pubkey was used */	if (binding->fa_spi != 0) {		fa_spi = get_fa_spi(binding->fa_spi, binding->lower_addr,				    SPI_AGENT_FA);		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 (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 (t_data->fa_pubkey != NULL) {		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)				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));		len += GET_KEY_EXT_LEN(t_data->last_sent_fa_pubkeyrep);	}	len += add_fa_auth_ext(binding->lower_addr, ext->req->home_addr, msg,			       msg + len);	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);	if (config->packet_socket_mode != PACKET_SOCKET_MODE_ONLY_RECEIVE &&	    t_data->is_lowest_fa)		ret = packet_socket_send(&t_data->info, msg, len);	else		ret = own_sendto(t_data->info.iface->udp_sock,				 binding->lower_addr,				 binding->lower_port, msg, len);	dynamics_check_sendto(ret, len, "reply_message");	return 0;}/** * update_request_binding_info: * @binding: * @ext: * @iface: NULL if reply * @info: Source of the request message * @dst_addr: Destination address of the request message * *  */static voidupdate_request_binding_info(struct bindingentry *binding, 			    struct msg_extensions *ext,			    struct packet_from_info *info){	struct tunnel_data *t_data = (struct tunnel_data *) binding->data;	/* update down interface pointer */	memcpy(&t_data->info, info, sizeof(*info));	t_data->old_if_index = info->iface->if_index;	/* update lower end type (MN/FA) */	t_data->is_lowest_fa = is_sender_mobile(ext);	/* update MN/FA decapsulation mode */	t_data->fa_decapsulation = t_data->is_lowest_fa &&		(ext->req->opts & REGREQ_MN_DECAPS) == 0;	/* update encapsulating delivery mode */	t_data->encaps_delivery = !t_data->is_lowest_fa ||		ext->encaps_del != NULL;	/* update down_type and down_key */	if (ext->gre_key != NULL) {		t_data->down_type = TUNNEL_GRE;		t_data->down_key = ntohl(ext->gre_key->key);	} else if (!t_data->fa_decapsulation || t_data->encaps_delivery) {		t_data->down_type = TUNNEL_IPIP;		t_data->down_key = 0;	} else {		t_data->down_type = TUNNEL_NO_ENCAPS;		t_data->down_key = info->iface->if_index;	}	/* update FA public key */	if (!equal_pubkey(t_data->fa_pubkey, ext->fa_pubkey)) {		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->fa_pubkey != NULL) {			DEBUG(DEBUG_FLAG,			      "Removing the previous fa_pubkey\n");			free(t_data->fa_pubkey);			t_data->fa_pubkey = NULL;		}		if (ext->fa_pubkey) {			DEBUG(DEBUG_FLAG, "Adding new fa_pubkey\n");			t_data->fa_pubkey = (struct msg_key *)				malloc(GET_KEY_EXT_LEN(ext->fa_pubkey));			if (t_data->fa_pubkey != NULL) {				memcpy(t_data->fa_pubkey, ext->fa_pubkey,				       GET_KEY_EXT_LEN(ext->fa_pubkey));			} else {				LOG2(LOG_WARNING, "Not enough memory "				     "for fa_pubkey\n");			}		}	}	/* update binding lower address and port */	binding->lower_addr = info->src.sin_addr;	binding->lower_port = info->src.sin_port;	/* update FA keyreq SPI */	if (ext->fa_keyreq)		binding->fa_spi = ntohl(ext->fa_keyreq->spi);	else		binding->fa_spi = 0;	setup_device_forcing(t_data);	/* update tunnel mode */	if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0 || 	    config->force_reverse_tunneling)		t_data->tunnel_mode = TUNNEL_MODE_REVERSE;	else		t_data->tunnel_mode = TUNNEL_MODE_TRIANGLE;	#ifdef USE_TEARDOWN	/* FIX-JM: update t_data->upper_id ?? */#endif}/** * save_binding_information: * @save: Where to copy binding info * @binding: A binding containing the info to copy * * Copies information from @binding to @save. */voidsave_binding_info(struct saved_binding_info *save,		  const struct bindingentry *binding){	struct tunnel_data *t_data;	t_data = binding->data;	save->lower_addr = binding->lower_addr;	save->lower_port = binding->lower_port;	save->is_lowest_fa = t_data->is_lowest_fa;	save->down_type = t_data->down_type;	save->down_key = t_data->down_key;	save->fa_decapsulation = t_data->fa_decapsulation;	save->encaps_delivery = t_data->encaps_delivery;	save->down_tunl = t_data->down_tunl;	save->down_iface = t_data->info.iface;	memcpy(save->force_route_dev, t_data->force_route_dev, IFNAMSIZ);	memcpy(save->force_reverse_dev, t_data->force_reverse_dev, IFNAMSIZ);	save->tunnel_mode = t_data->tunnel_mode;	return;}/** * debug_compare_binding_info: * @old:  * @binding: * * Compare old and changed binding information and print * debug information about it */static voiddebug_compare_binding_info(const struct saved_binding_info *old,			   const struct bindingentry *binding){	struct tunnel_data *t_data;	t_data = binding->data;	if (t_data->info.iface != old->down_iface) {		DEBUG(DEBUG_FLAG, "\tdown interface changed %s => %s\n",		      old->down_iface->dev, t_data->info.iface->dev);	}	if (t_data->is_lowest_fa && !old->is_lowest_fa)		DEBUG(DEBUG_FLAG, "\tlower end changed FA -> MN\n");	else if (!t_data->is_lowest_fa && old->is_lowest_fa)		DEBUG(DEBUG_FLAG, "\tlower end changed MN -> FA\n");	if (old->fa_decapsulation != t_data->fa_decapsulation) {		DEBUG(DEBUG_FLAG, "\tFA decapsulation changed %i => %i\n",		      old->fa_decapsulation, t_data->fa_decapsulation);	}	if (old->encaps_delivery != t_data->encaps_delivery) {		DEBUG(DEBUG_FLAG, "\tencaps. delivery changed: %i => %i\n",		      old->encaps_delivery, t_data->encaps_delivery);	}	if (t_data->down_type != old->down_type ||	    t_data->down_key != old->down_key) {		DEBUG(DEBUG_FLAG, "\ttunnel type changed: %i,%i => %i,%i\n",		      old->down_type, old->down_key, t_data->down_type,		      t_data->down_key);	}	if (binding->lower_addr.s_addr != old->lower_addr.s_addr) {		DEBUG(DEBUG_FLAG, "\tlower addr changed %s => ",		      inet_ntoa(old->lower_addr));		DEBUG(DEBUG_FLAG, "%s\n", inet_ntoa(binding->lower_addr));	}	if (binding->lower_port != old->lower_port) {		DEBUG(DEBUG_FLAG, "\tlower port changed %i => %i\n",		      ntohs(old->lower_port), ntohs(binding->lower_port));	}	if (strcmp(t_data->force_route_dev, old->force_route_dev) != 0) {		DEBUG(DEBUG_FLAG, "\tforce route dev changed %s => %s\n",		      old->force_route_dev, t_data->force_route_dev);	}	if (strcmp(t_data->force_reverse_dev, old->force_reverse_dev) != 0) {		DEBUG(DEBUG_FLAG, "\tforce reverse dev changed %s => %s\n",		      old->force_reverse_dev, t_data->force_reverse_dev);	}}	/** * handle_lower_switch: * @binding: MN's binding entry * @old: saved binding data * @ext: request/reply message data * @info: source of the request message * * Handle registration request as switched FA. * * 1. Send reply * 2. Make tunnel to new lower FA * 3. Connect the new tunnel to upper agent and change route from HA *    to new lower FA/MN * 4. Send Tear Down message * 5. Unconnect old tunnel * 6. Delete old tunnel (delayed) * * Returns: 0 if successful, *          1 on error */inthandle_lower_switch(struct bindingentry *binding, 		    struct saved_binding_info *old,		    struct msg_extensions *ext,		    struct in_addr *addr, int request_auth_ok){	struct tunnel_data *t_data;	int reverse;	assert(binding != NULL && binding->data != NULL);	DEBUG(DEBUG_FLAG, "Lower FA or MN address changed (locupd)\n");	t_data = binding->data;	assert(t_data->info.iface != NULL);	/* tell about the changes made */	debug_compare_binding_info(old, binding);#ifdef DYNAMICS_SET_MAIN_TABLE_MN_ROUTE	if (old->fa_decapsulation && !t_data->fa_decapsulation &&	    dyn_ip_route_del(binding->mn_addr, old->down_iface->dev) != 0) {		LOG2(LOG_WARNING, "dyn_ip_route_del(%s,%s) failed\n",		     inet_ntoa(binding->mn_addr), old->down_iface->dev);	}	/* add/replace host route to MN if in FA decaps mode */	if (t_data->is_lowest_fa && !old->is_lowest_fa &&	    t_data->fa_decapsulation &&	    dyn_ip_route_replace(binding->mn_addr, t_data->info.iface->dev) ==	    -1) {		LOG2(LOG_WARNING, "handle_lower_switch: "		     "dyn_ip_route_replace(%s,%s) failed.\n",		     inet_ntoa(binding->mn_addr), t_data->info.iface->dev);	}#endif /* DYNAMICS_SET_MAIN_TABLE_MN_ROUTE */	/* 1. Send reply */	/* Send reply if the request is valid  	 * (if not valid, the reply is forwarded elsewhere) */	if (request_auth_ok) {		reply_message(binding, ext);	}	/* 2. Make tunnel to new lower FA */	t_data->down_tunl = tunnel_add(		tunnels_hash, *addr, binding->tun_dev,		t_data->info.iface->addr, 1, t_data->down_type,		t_data->down_key);	if (t_data->down_tunl == NULL) {		LOG2(LOG_WARNING, "handle_lower_switch: tunnel_add failed!\n");		return 1;	}	/* 3. Connect the new tunnel to upper agent */	/* Note: "To MN" routing table does not change, so no need to update	 * routing rule for locally generated packets. */	/* Use delayed tunnel unconnect and make a new connect */	reverse = old->tunnel_mode == TUNNEL_MODE_REVERSE ? 1 : 0;	if (tunnel_unconnect(t_data->up_tunl, old->down_tunl, binding->mn_addr,			     reverse, 0, old->force_route_dev,			     old->force_reverse_dev) < 0) {		LOG2(LOG_WARNING,		     "handle_lower_switch: tunnel_unconnect failed!\n");	}	reverse = t_data->tunnel_mode == TUNNEL_MODE_REVERSE ? 1 : 0;	if (tunnel_connect(t_data->up_tunl, t_data->down_tunl,			   binding->mn_addr, reverse, t_data->force_route_dev,			   t_data->force_reverse_dev)	    < 0) {		LOG2(LOG_WARNING,		     "handle_lower_switch: tunnel_connect failed!\n");		return 1;	}#ifdef USE_TEARDOWN	/* 4. Send Tear Down message */	/* Send a tear down message only if this is not the lowest FA */	if (old->lowest_fa == FALSE) {		if (send_tear_down(binding, old->lower_addr, old->lower_port,				   old->down_iface))			DEBUG(DEBUG_FLAG, "send_tear_down failed\n");	} else		DEBUG(DEBUG_FLAG, "Lowest FA - no tear down reply sent\n");#endif	/* 5. Delayed tunnel deletion (6. delete tunnel) */	if (tunnel_delete_ptr(old->down_tunl, 0) < 0) {		LOG2(LOG_WARNING, "handle_lower_switch: tunnel delete "		     "failed\n");		return 1;	}	return 0;}/* Create tunnel and table for the tunnel. The table will get route for MN. * This enables data coming from upper mobility agent to be routed to MN. * --> Lesser packet loss when SFA or HA changes the route (data path is * already made available for downstream packets).  *  * For security reasons, do nothing if this is the HFA. *  * Returns 0 if successful, else 1 */

⌨️ 快捷键说明

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