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

📄 fa_request.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			VENDOR_EXT_DYNAMICS_FF_AUTH,			htonl(fa_spi->spi));	}	msglen = msgpos - msg;	assert(iface != NULL);	result = own_sendto(iface->udp_sock, lower_addr, lower_port,			    msg, msglen);	dynamics_check_sendto(result, msglen, "send_tear_down - registration "			      "reply");	if (result != msglen)		return 1;	DEBUG(DEBUG_FLAG, "send_tear_down: sent %d bytes (of %d) to %s:%i, "	      "dev[%s]\n", result, msglen, inet_ntoa(lower_addr),	      ntohs(lower_port), iface->dev);	return 0;}#endif/* list structure for denial reply records */struct denial_dst_data {	struct in_addr home_addr;	struct in_addr ha_addr;	__u32 priv_ha;	struct timeval last;	struct denial_dst_data *next;};static struct denial_dst_data *denials = NULL;/** * expire_denial_records: * @force: 1 = remove all entries, 0 = remove entries that are older than one * second * * Cleanup routine for denial reply records. */voidexpire_denial_records(int force){	struct denial_dst_data *tmp, *tmp2, *prev = NULL;	struct timeval tv;	static time_t last_check_sec = 0;	gettimeofday(&tv, NULL);	/* do not expire entries more often than once per 10 seconds */	if (!force && tv.tv_sec < last_check_sec + 10 &&	    tv.tv_sec > last_check_sec)		return;	last_check_sec = tv.tv_sec;	tmp = denials;	while (tmp != NULL) {		int diff = (tv.tv_sec - tmp->last.tv_sec) * 1000000 +			tv.tv_usec - tmp->last.tv_usec;		if (force || diff >= 1000000) {			DEBUG(DEBUG_FLAG, "Removing expired denial reply "			      "record for MN <%s,", inet_ntoa(tmp->home_addr));			DEBUG(DEBUG_FLAG, "%s,%u>\n",			      inet_ntoa(tmp->ha_addr), tmp->priv_ha);			if (prev == NULL)				denials = tmp->next;			else				prev->next = tmp->next;			tmp2 = tmp;			tmp = tmp->next;			free(tmp2);		} else {			prev = tmp;			tmp = tmp->next;		}	}}/** * send_failure_reply: * @code: the error code to be used in the denial reply * @ext: pointer to the parsed message that caused the denial reply * @info: source data of the request for which the denial reply is to be sent * @sk: pointer to the session key if available; NULL = no session key * @sk_len: length of the session key if @sk != NULL * * Send a failure reply to the mobile node (or the lower foreign agent if this * foreign agent is not the lowest one) * * Returns: 0 if successfully sent, 1 if message was not sent (error in * sending, more than one denial per second, or invalid destination address) */intsend_failure_reply(int code, struct msg_extensions *ext,		   struct packet_from_info *info, unsigned char *sk,		   int sk_len){	struct denial_dst_data *tmp;	unsigned char msg[MAXMSG];	struct reg_rep *reply;	int msglen = 0;	int result;	__u32 priv_ha = 0;	struct timeval tv;	reply = (struct reg_rep *) msg;	memset(reply, 0, sizeof(struct reg_rep));	if (code == REGREP_LONG_LIFETIME_FA)		reply->lifetime = htons(config->fa_default_tunnel_lifetime);	else		reply->lifetime = 0;	reply->type = REG_REP;	reply->code = code;	if (ext != NULL && ext->req != NULL) {		reply->home_addr.s_addr = ext->req->home_addr.s_addr;		reply->ha_addr.s_addr = ext->req->ha_addr.s_addr;		memcpy(reply->id, ext->req->id, sizeof(reply->id));	} else if (ext != NULL && ext->rep != NULL) {		reply->home_addr.s_addr = ext->rep->home_addr.s_addr;		reply->ha_addr.s_addr = ext->rep->ha_addr.s_addr;		memcpy(reply->id, ext->rep->id, sizeof(reply->id));	}	msglen += sizeof(struct reg_rep);	if (ext != NULL && ext->priv_ha != NULL)		priv_ha = ntohl(ext->priv_ha->priv_ha);	/* check whether the last denial was sent less than a second ago */	gettimeofday(&tv, NULL);	tmp = denials;	while (tmp != NULL) {		int diff = (tv.tv_sec - tmp->last.tv_sec) * 1000000 +			tv.tv_usec - tmp->last.tv_usec;		if (tmp->home_addr.s_addr == reply->home_addr.s_addr &&		    tmp->ha_addr.s_addr == reply->ha_addr.s_addr &&		    tmp->priv_ha == priv_ha) {			if (diff < 1000000 && diff >= 0) {				DEBUG(DEBUG_FLAG, "More than one denial reply "				      "per second for MN <%s,",				      inet_ntoa(tmp->home_addr));				DEBUG(DEBUG_FLAG, "%s,%u> - skipping this "				      "denial\n", inet_ntoa(tmp->ha_addr),				      tmp->priv_ha);				return 1;			}			tmp->last.tv_sec = tv.tv_sec;			tmp->last.tv_usec = tv.tv_usec;			break;		}		tmp = tmp->next;	}	if (tmp == NULL) {		DEBUG(DEBUG_FLAG, "Adding denial reply record for MN <%s,",		      inet_ntoa(reply->home_addr));		DEBUG(DEBUG_FLAG, "%s,%u>\n", inet_ntoa(reply->ha_addr),		      priv_ha);		tmp = (struct denial_dst_data *)			malloc(sizeof(struct denial_dst_data));		if (tmp == NULL) {			DEBUG(DEBUG_FLAG, "\tcould not add record (out of "			      "memory)\n");			return 1;		}		tmp->home_addr.s_addr = reply->home_addr.s_addr;		tmp->ha_addr.s_addr = reply->ha_addr.s_addr;		tmp->priv_ha = priv_ha;		tmp->last.tv_sec = tv.tv_sec;		tmp->last.tv_usec = tv.tv_usec;		tmp->next = denials;		denials = tmp;	}	DEBUG(DEBUG_FLAG, "Sending failure reply code %i to %s:%i\n",	      code, inet_ntoa(info->src.sin_addr), ntohs(info->src.sin_port));#if 0	/* FIX: currently challenge extension adding to denial replies is	 * commented out do to possibly missing binding (see below) and	 * ambiguous information in RFC 3012 */	if (config->enable_challenge_response &&	    config->challenge_in_reg_reply) {		struct challenge_ext *challenge;		/* FIX: in hierarchical FA network only the lowest FA should		 * add the challenge extension */		challenge = create_challenge_ext(config, MN_FA_CHALLENGE_EXT);		if (challenge != NULL) {			int n = GET_CHALLENGE_EXT_LEN(challenge);			if (msglen + n > MAXMSG) {				free(challenge);				return 1;			}			memcpy(msg + msglen, challenge, n);			msglen += n;			/* FIX: this challenge must be recorded for the MN,			 * but there may not be a binding for it yet.. */		}	}#endif	if (sk != NULL &&	    msglen + MAX_SK_LEN + sizeof(struct vendor_msg_auth) <= MAXMSG) {		msglen += auth_add_vendor(			AUTH_ALG_MD5, sk, sk_len, msg,			(struct vendor_msg_auth *) (msg + msglen),			VENDOR_EXT_DYNAMICS_SK_AUTH,			ext != NULL && ext->mh_auth != NULL ?			ext->mh_auth->spi : 0);	}	if (msglen + MAX_SK_LEN + sizeof(struct msg_auth) <= MAXMSG)		msglen += add_fa_auth_ext(info->src.sin_addr, reply->home_addr,					  msg, msg + msglen);	if (config->packet_socket_mode == PACKET_SOCKET_MODE_ONLY_RECEIVE ||	    (ext != NULL && !is_sender_mobile(ext))) {		if (!send_address_ok(info->src.sin_addr))			return 1;		result = sendto(info->iface->udp_sock, msg, msglen, 0,				(struct sockaddr *) &info->src,				sizeof(info->src));	} else		result = packet_socket_send(info, msg, msglen);	dynamics_check_sendto(result, msglen, "send_failure_reply");	return 0;}/* forward unconfirmed request or deregistration to upper FA or HA   returns:      0 if successful      1 on error*/static intforward_request(struct bindingentry *binding, struct msg_extensions *ext){	char msg[MAXMSG];	int len, len2, sent;	struct fa_spi_entry *fa_spi;	struct tunnel_data *t_data;	char *auth_ext;	char *copy_end; /* pointer to the ext following the copied area */	int auth_len;	const char *auth_txt;	t_data = binding->data;	DEBUG(DEBUG_FLAG, "Forwarding request upwards\n");	if (ext->req == NULL || ext->mh_auth == NULL) {		LOG2(LOG_WARNING, "forward_request: not req or mh_auth\n");		return 1;	}	/* copy the MAC protected area directly from the received message */	if (ext->mn_aaa_auth != NULL) {		auth_ext = (char *) ext->mn_aaa_auth;		auth_len = GET_GEN_AUTH_EXT_LEN(ext->mn_aaa_auth);		auth_txt = "mn_aaa_auth";	} else {		auth_ext = (char *) ext->mh_auth;		auth_len = GET_AUTH_EXT_LEN(ext->mh_auth);		auth_txt = "mh_auth";	}	assert(auth_ext > (char *) ext->req);	len = (__u8 *) auth_ext - (__u8 *) ext->req + auth_len;	if (len < sizeof(struct reg_req) + auth_len || len > MAXMSG) {		LOG2(LOG_WARNING, "forward_request: invalid length %i\n",		     len);		return 1;	}	memcpy(msg, ext->req, len);	copy_end = (char *) ext->req + len;	DEBUG(DEBUG_FLAG, " * copying up to and including %s (len ==> %i)\n",	      auth_txt, len);	if (ext->sk_auth && !config->highest_FA) {		/* if we came here, this FA could not check the session key		 * based authentication - so, just copy the data to the upper		 * mobility agent */		if ((void *) ext->sk_auth <= (void *) ext->mh_auth) {			LOG2(LOG_WARNING, "forward_request: sk_auth before "			     "mh_auth - dropping message\n");			return 1;		}		len2 = (char *) ext->sk_auth - (char *) ext->mh_auth -			GET_AUTH_EXT_LEN(ext->mh_auth) +			GET_VENDOR_AUTH_EXT_LEN(ext->sk_auth);		if (len + len2 > MAXMSG || len2 < 0) {			LOG2(LOG_WARNING, "forward_request: message overflow "			     "(len=%i, len2=%i)\n", len, len2);			return 1;		}		memcpy(msg + len, ((char *) ext->mh_auth) +		       GET_AUTH_EXT_LEN(ext->mh_auth), len2);		len += len2;		copy_end += len2;		DEBUG(DEBUG_FLAG, " * copying up to and including sk_auth "		      "(len ==> %i)\n", len);	}	if (config->highest_FA)		fa_spi = get_fa_spi(0, ext->req->ha_addr, SPI_AGENT_HA);	else		fa_spi = get_fa_spi(0, upper_fa_addr.sin_addr, SPI_AGENT_FA);	/* FIX: add key request even to deregistration messages if this FA is	 * not the highest FA	 * The keyreq is needed to know whether the lower end is MN or FA */	if (ntohs(ext->req->lifetime) != 0 || !config->highest_FA) {		if (add_key_request(fa_spi, ext, &len, msg) != 0)			return 1;	}	/* add GRE key ext. if it is needed (duplicate private address) */	if (t_data->up_type == TUNNEL_GRE) {		struct gre_key_ext *gre;		if (len + sizeof(struct gre_key_ext) > MAXMSG)			return 1;		gre = (struct gre_key_ext *) (msg + len);		gre->type = VENDOR_EXT_TYPE2;		gre->length = sizeof(struct gre_key_ext) - 2;		gre->reserved = 0;		gre->vendor_id = htonl(VENDOR_ID_DYNAMICS);		gre->sub_type = htons(VENDOR_EXT_DYNAMICS_GRE_KEY);		gre->key = htonl(t_data->up_key);		len += sizeof(struct gre_key_ext);		DEBUG(DEBUG_FLAG, " * adding GRE ext\n");	}	if (ext->challenge != NULL && (char *) ext->challenge >= copy_end) {		int n = GET_CHALLENGE_EXT_LEN(ext->challenge);		if (len + n > MAXMSG)			return 1;		memcpy(msg + len, ext->challenge, n);		len += n;		DEBUG(DEBUG_FLAG, " * adding Challenge ext (len=%i)\n", n);	}	/* Add the FA->FA or FA->HA authentication extension if a security	 * association is configured and send the message */	if (config->highest_FA) {		if (fa_spi != NULL) {			len += auth_add(				fa_spi->alg, fa_spi->shared_secret,				fa_spi->shared_secret_len,				(unsigned char *) msg,				(struct msg_auth *) (msg + len),				FH_AUTH, htonl(fa_spi->spi));		}		DEBUG(DEBUG_FLAG, "forward_request ==> HA %s:%i\n",		      inet_ntoa(ext->req->ha_addr), config->ha_udp_port);		sent = own_sendto(up_interface->udp_sock, ext->req->ha_addr,				  htons(config->ha_udp_port), msg, len);	} else {		if (fa_spi != NULL) {			len += auth_add_vendor(				AUTH_ALG_MD5, fa_spi->shared_secret,				fa_spi->shared_secret_len,				(unsigned char *) msg,				(struct vendor_msg_auth *) (msg + len),				VENDOR_EXT_DYNAMICS_FF_AUTH,				htonl(fa_spi->spi));		}		DEBUG(DEBUG_FLAG,		      "forward_request ==> upper FA %s:%i\n",		      inet_ntoa(upper_fa_addr.sin_addr),		      ntohs(upper_fa_addr.sin_port));		if (!send_address_ok(upper_fa_addr.sin_addr))			return 1;		sent = sendto(up_interface->udp_sock, msg, len, 0,			      (struct sockaddr *) &upper_fa_addr,			      sizeof(upper_fa_addr));	}	assert(len < MAXMSG);	dynamics_check_sendto(sent, len, "forward_request");	if (sent != len)		return 1;	return 0;}/* reply to authenticated request   returns:      0 if successful      1 on error*/static intreply_message(struct bindingentry *binding, struct msg_extensions *ext){	struct tunnel_data *t_data;	unsigned char msg[MAXMSG];	int len, ret, timeout;	struct reg_rep *reply;	struct msg_key *key;	struct fa_spi_entry *fa_spi;	time_t now;	t_data = binding->data;	DEBUG(DEBUG_FLAG, "Reply to authenticated request\n");	memset(msg, 0, MAXMSG);	len = 0;	reply = (struct reg_rep *) msg;	reply->type = REG_REP;	reply->code = REGREP_ACCEPTED;	time(&now);	timeout = binding->exp_time - now;	if (timeout < 0)		timeout = 0;	if (timeout > ntohs(ext->req->lifetime)) {		/* FIX: should this kind of request be forward upwards to		 * lower the binding in all the agents? */		DEBUG(DEBUG_FLAG, "Request lifetime=%i < timeout=%i\n",		      ntohs(ext->req->lifetime), timeout);		timeout = ntohs(ext->req->lifetime);

⌨️ 快捷键说明

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