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

📄 fa_request.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 4 页
字号:
static intmake_preliminary_data_path(struct bindingentry *binding,			   struct unconfirmed_request *unc,			   struct interface_entry *iface){	struct tunnel_data *t_data;	struct tunnel *down, *up;	/* Highest FA MUST NOT do this optimization or there may be some	 * security problems (data transfered before getting a reply from the	 * HA) */	if (config->highest_FA)		return 0;	t_data = binding->data;	/* tunnel downwards (if FA decaps is used, this will be just a dummy	 * entry for the non-capsulated connection) */	down = tunnel_add(tunnels_hash, unc->info.src.sin_addr,			  binding->tun_dev, iface->addr, 1, unc->tunnel_type,			  unc->tunnel_key);	if (down == NULL) {		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "tunnel_add failed (down)\n");		return 1;	}	up = tunnel_add(tunnels_hash, upper_fa_addr.sin_addr,			t_data->ha_tun_dev, up_interface->addr, 1,			t_data->up_type, t_data->up_key);	if (up == NULL) {		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "tunnel_add failed (up)\n");		tunnel_delete_ptr(down, 0);		return 1;	}	/* FIX-JM: what about force_route_dev? should it be != NULL when	 * FA decaps is used with encaps. del.? */	/* FIX-JM: what about force_reverse_dev? should it be != NULL when	 * MN decaps is used without encaps. del.? */	/* Route for HA->MN direction - this enables routing of downstream	 * packets to the MN. Note that this does not make the reverse	 * connection. */	if (tunnel_connect(up, down, binding->mn_addr, 0, NULL, NULL) < 0) {		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "tunnel_connect failed\n");	}	/* With lazy tunnel deletion the tunnel will be up long enough.	 * If no reply is received, the tunnel is removed automatically.	 * Additionally the reference count will be ok. When reply is	 * received the tunnels are remade which means that the reference	 * counts are increased. */	if (tunnel_unconnect(up, down, binding->mn_addr, 0, 0, NULL, NULL) < 0)	{		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "tunnel_unconnect failed\n");	}	if (tunnel_delete_ptr(down, 0) == -1) {		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "lazy tunnel delete failed (down).\n");	}	if (tunnel_delete_ptr(up, 0) == -1) {		LOG2(LOG_WARNING, "make_preliminary_data_path: "		     "lazy tunnel delete failed (up).\n");	}	return 0;}static int check_mn_challenge(struct tunnel_data *t_data,			      struct msg_extensions *ext){	int i, found = 0;	/* check whether the MN has already used this challenge; if yes and	 * this is not a replay of request with same id, send denial reg. reply	 * with code REGREP_STALE_CHALLENGE_FA */	for (i = 0; i < 2 * config->challenge_window; i++) {		if (equal_challenge(t_data->used_challenges[i],				    ext->challenge)) {			found = 1;			break;		}	}	if (found && (i != t_data->used_challenges_pos ||		      memcmp(ext->req->id, t_data->used_challenges_id,			     sizeof(ext->req->id)) != 0))		return REGREP_STALE_CHALLENGE_FA;	/* check whether the used challenge is known */	found = 0;	for (i = 0; i < config->challenge_window; i++) {		if (equal_challenge(last_challenges[i], ext->challenge)) {			found = 1;			break;		}	}	if (!found && equal_challenge(t_data->last_challenge,				      ext->challenge)) {		/* let the MN use the same challenge only once by freeing the		 * stored challenge */		free(t_data->last_challenge);		t_data->last_challenge = NULL;		found = 1;	}	if (!found)		return REGREP_UNKNOWN_CHALLENGE_FA;	return 0;}/** * handle_request: * @ext: the request with extensions * @info: source of the request * @dst_addr: destination address of the request * @iface: interface that the request arrived on * @config: configuration file parameters * @ttl: TTL of the request * * Handle registration request. * * Returns: *     0 if successful, *     1 on error */inthandle_request(struct msg_extensions *ext, struct packet_from_info *info,	       struct fa_config *config){	struct bindingentry *binding;	int auth_ok, ret = 0;	int lower_mode_changed = 0;	struct tunnel_data *t_data;	struct unconfirmed_request *unc = NULL;	struct bindingkey bkey;	struct interface_entry *prev_iface;	int iface_ok;	DEBUG(DEBUG_FLAG, "Handling request from MN %s",	      inet_ntoa(ext->req->home_addr));	DEBUG(DEBUG_FLAG, " (%s:%d)\n", inet_ntoa(info->src.sin_addr),	      ntohs(info->src.sin_port));	if (validate_request(ext, info))		return 1;	memcpy(&bkey.mn_addr, &(ext->req->home_addr), sizeof(bkey.mn_addr));	memcpy(&bkey.ha_addr, &(ext->req->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;	binding = binding_fetch(bindings_hash, &bkey);	if (binding == NULL) {		int type, added_addr = 0;		DEBUG(DEBUG_FLAG, "No binding for MN => making new binding\n");		if (config->max_pending > 0 &&		    bcounters.pendingcount >= config->max_pending) {			LOG2(LOG_ALERT, "Too many pending registration "			     "requests - refusing new ones\n");			send_failure_reply(REGREP_NO_RESOURCES_FA, ext,					   info, NULL, 0);			return 1;		}		if (config->enable_challenge_response && ext->challenge) {			int i, found = 0;			for (i = 0; i < config->challenge_window; i++) {				if (equal_challenge(last_challenges[i],						    ext->challenge)) {					found = 1;					break;				}			}			if (!found) {				send_failure_reply(REGREP_UNKNOWN_CHALLENGE_FA,						   ext, info, NULL, 0);				return 1;			}		}		if (config->highest_FA && ext->priv_ha == NULL)			type = MN_ADDR_TUNNEL_IPIP;		else {			type = mn_addr_add(&ext->req->home_addr);			DEBUG(DEBUG_FLAG, "mn_addr_add(%s) => %i\n",			      inet_ntoa(ext->req->home_addr), type);			added_addr = 1;		}		if (type != MN_ADDR_TUNNEL_ERROR) {			int max_time = config->fa_default_tunnel_lifetime;			if (config->delete_pending_after > 0 &&			    config->delete_pending_after < max_time)				max_time = config->delete_pending_after;			binding = make_new_binding(				bindings_hash, ext, max_time, &bcounters);		}		if (binding == NULL) {			LOG2(LOG_WARNING, type > -2 ?			     "Could not make new binding\n" :			     "Out of resources while checking MN address");			send_failure_reply(REGREP_NO_RESOURCES_FA, ext,					   info, NULL, 0);			if (added_addr)				mn_addr_remove(&ext->req->home_addr, type);			return 1;		}		t_data = (struct tunnel_data *) binding->data;		if (type == MN_ADDR_TUNNEL_IPIP) {			t_data->up_type = TUNNEL_IPIP;			t_data->up_key = 0;		} else {			t_data->up_type = TUNNEL_GRE;			t_data->up_key = type;		}		if (added_addr)			t_data->mn_addr_added = 1;	} else {		check_unconfirmed_timeout(binding);		t_data = (struct tunnel_data *) binding->data;		if (config->enable_challenge_response && ext->challenge) {			int ret = check_mn_challenge(t_data, ext);			if (ret != 0) {				send_failure_reply(ret, ext, info, NULL, 0);				return 1;			}		}	}	if (ext->challenge) {		int n = t_data->used_challenges_pos + 1;		if (n >= 2 * config->challenge_window)			n = 0;		t_data->used_challenges_pos = n;		if (t_data->used_challenges[n] != NULL)			free(t_data->used_challenges[n]);		t_data->used_challenges[n] = (struct challenge_ext *)			malloc(GET_CHALLENGE_EXT_LEN(ext->challenge));		if (t_data->used_challenges[n] == NULL) {			DEBUG(DEBUG_FLAG, "malloc failed for "			      "used_challenges\n");		} else {			memcpy(t_data->used_challenges[n], ext->challenge,			       GET_CHALLENGE_EXT_LEN(ext->challenge));		}	}	auth_ok = FALSE;	if (!t_data->confirmed) {		DEBUG(DEBUG_FLAG, "\tunconfirmed binding\n");		if (check_resources()) {			LOG2(LOG_ALERT,			     "FA: Not enough resources to accept "			     "registration\n");			send_failure_reply(REGREP_NO_RESOURCES_FA, ext,					   info, NULL, 0);			return 1;		}		unc = add_unconfirmed_data(bindings_hash, &bcounters,					   binding, ext, info, config);	} else {		DEBUG(DEBUG_FLAG, "\tconfirmed binding\n");		if (ext->sk_auth != NULL) {#ifdef DEBUG_SIMULATED_TEST			/* for debuging only - accept any sk_auth extension */			if (0) {			}#else			if (!auth_check_vendor(AUTH_ALG_MD5, binding->key,					       binding->keylen,					       (unsigned char *) ext->req,					       ext->sk_auth)) {				DEBUG(DEBUG_FLAG,				      "handle_request: sk_auth not valid\n");			}#endif			else if (ext->ext_dyn == NULL) {				DEBUG(DEBUG_FLAG,				      "handle_request: missing ext_dyn\n");			} else if ((void *) ext->ext_dyn >				   (void *) ext->sk_auth) {				DEBUG(DEBUG_FLAG, "handle_request: ext_dyn "				      "after sk_auth\n");			} else if (ntohl(ext->ext_dyn->seq) <=				   t_data->last_used_seq_num) {				LOG2(LOG_WARNING, "handle_request: seq# did "				     "not increase\n");			} else {				auth_ok = TRUE;				t_data->last_used_seq_num =					ntohl(ext->ext_dyn->seq);			}		}	}	/* check, whether this FA is the switching FA */	iface_ok = 0;	if (ext->prev_fa_nai) {		prev_iface = fa_hash_check(ext->prev_fa_nai);		if (GET_NAI_LEN(ext->prev_fa_nai) == config->fa_nai_len &&		    memcmp(MSG_NAI_DATA(ext->prev_fa_nai), config->fa_nai,			   config->fa_nai_len) == 0) {			iface_ok = 1;			DEBUG(DEBUG_FLAG,			      "This FA was the previous FA - okay to reply\n");		} else if (prev_iface == NULL) {			DEBUG(DEBUG_FLAG, "Unknown previous FA NAI - "			      "forwarding request upwards\n");		} else {			DEBUG(DEBUG_FLAG, "Request from a known FA below us - "			      "okay to reply\n");			iface_ok = 1;		}	} else {		DEBUG(DEBUG_FLAG, "No FA NAI ext - using only session key "		      "based SFA detection\n");		iface_ok = 1;	}	if (ext->fa_nai) {		prev_iface = fa_hash_check(ext->fa_nai);		if (prev_iface != NULL && prev_iface != info->iface) {			LOG2(LOG_ALERT, "Request coming from different "			     "interface - forcing forwarding of the "			     "request\n");			LOG2(LOG_ALERT, "old iface '%s', now iface '%s'\n",			     prev_iface->dev, info->iface->dev);		}	}	/* handle authorized messages self and forward unauthorized messages	 * and disconnect requests to upper mobility agent */	if (auth_ok && ntohs(ext->req->lifetime) > 0 && iface_ok) {		/* check whether FA decapsulation to MN has changed */		if (t_data->fa_decapsulation !=		    (is_sender_mobile(ext) &&		     (ext->req->opts & REGREQ_MN_DECAPS) == 0)) {			DEBUG(DEBUG_FLAG, "FA decaps changed (old=%i) => "			      "forcing lower switch\n",			      t_data->fa_decapsulation);			lower_mode_changed = 1;		}		/* check whether MN encapsulation to FA has changed */ 		if (t_data->encaps_delivery !=		    (!is_sender_mobile(ext) || ext->encaps_del != NULL)) {			DEBUG(DEBUG_FLAG, "Encaps. delivery changed (old=%i) "			      "=> forcing lower switch\n",			      t_data->encaps_delivery);			lower_mode_changed = 1;		}		if (unc != NULL && (t_data->down_type != unc->tunnel_type ||				    t_data->down_key != unc->tunnel_key)) {			DEBUG(DEBUG_FLAG, "Down tunnel mode changed "			      "(%i,%i => %i,%i) => forcing lower switch\n",			      t_data->down_type, t_data->down_key,			      unc->tunnel_type, unc->tunnel_key);			lower_mode_changed = 1;		}		if (unc != NULL && t_data->info.iface != unc->info.iface) {			DEBUG(DEBUG_FLAG, "Down interface changed (%s => %s) "			      "=> forcing lower switch\n",			      t_data->info.iface->dev, unc->info.iface->dev);			lower_mode_changed = 1;		}		if (binding->lower_addr.s_addr != info->src.sin_addr.s_addr ||		    lower_mode_changed) {			struct saved_binding_info old;			save_binding_info(&old, binding);			update_request_binding_info(binding, ext, info);			handle_lower_switch(binding, &old, ext,					    &info->src.sin_addr, TRUE);		}		else			reply_message(binding, ext);		time(&binding->mod_time);		binding->id[0] = ntohl(ext->req->id[0]);		binding->id[1] = ntohl(ext->req->id[1]);#ifdef USE_TEARDOWN		/* Note: t_data->upper_id is left unchanged because upper		 * FAs/HA do not get this id */#endif	} else {		/* unauthorized message or disconnect request */		int use_prelim = 0;		if (t_data->confirmed)			unc = add_unconfirmed_data(bindings_hash, 						   &bcounters,						   binding, ext, info, config);		/* use preliminary data path optimization when there is not		 * yet a tunnel downwards or the lower end has changed */		if (!t_data->confirmed)			use_prelim = 1;		else if (auth_ok && binding->lower_addr.s_addr !=			 info->src.sin_addr.s_addr)			use_prelim = 1;		if (ntohs(ext->req->lifetime) > 0 && use_prelim && unc != NULL		    && make_preliminary_data_path(binding, unc,						  info->iface) != 0) {			DEBUG(DEBUG_FLAG, "preliminary data path optimization "			      "failed\n");			ret = 1;		}		t_data->pending_request = TRUE;		/* forward request first */		forward_request(binding, ext);	} 		return ret;}

⌨️ 快捷键说明

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