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

📄 mn_reg.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: mn_reg.c,v 1.64 2001/09/29 14:56:23 jm Exp $ * Mobile Node - registration * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include "config.h"#include <stdlib.h>#include <assert.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#ifdef DYN_TARGET_LINUX#include <net/if_arp.h>#endif#include <string.h>#include <time.h>#include "agentapi.h"#include "auth.h"#include "debug.h"#include "msgparser.h"#include "proxyarp.h"#include "util.h"#include "mn.h"#ifdef INCLUDE_IPAY#include "mn_ipay.h"#endifextern struct mn_data mn;extern struct mn_config config;extern struct timeval timers[TIMER_COUNT];static int fill_req_header(char *pos, int request_type, int use_reverse){        struct reg_req *req;	int new_reg_time;	unsigned int new_reg_rand;	static int last_reg_time = 0;	static unsigned int last_reg_rand = 0;	struct timeval tv;        req = (struct reg_req *) pos;        req->type = REG_REQ;        req->opts = 0;	/* Note: the agent adv should be checked for allowed tunneling modes	 * and req->opts should be adjusted with that information if needed	 * (i.e. do not request unsupported mode) */	if (!config.enable_fa_decapsulation)		req->opts |= REGREQ_MN_DECAPS;	if (use_reverse)		req->opts |= REGREQ_REVERSE_TUNNEL;	if (request_type != REG_DISC) {		if (mn.tunnel_mode == API_TUNNEL_FULL_HA)			req->lifetime =				htons(config.mn_default_tunnel_lifetime);		else			req->lifetime =				htons(MIN(mn.req_lifetime,					  config.mn_default_tunnel_lifetime));		if (ntohs(req->lifetime) == 0) {			LOG2(LOG_INFO, "send_registration - trying to register"			     ", but lifetime=0 - aborting\n");			return -1;		}	} else req->lifetime = 0;        req->home_addr.s_addr = config.mn_home_ip_addr.s_addr;	if (config.ha_ip_addr.s_addr == 0 && config.use_aaa) {		req->ha_addr.s_addr = config.allow_home_addr_from_foreign_net ?			0 : -1;	} else if (config.ha_ip_addr.s_addr == 0 &&		   config.home_net_addr_plen > -1) {		/* dynamic HA address resolution */		req->ha_addr.s_addr = config.home_net_subnet_bc.s_addr;	} else		req->ha_addr.s_addr = config.ha_ip_addr.s_addr;	req->co_addr.s_addr = mn.co_addr.s_addr;	switch (config.replay_meth) {	case REPLAY_PROTECTION_NONE:		req->id[0] = 0;		req->id[1] = get_rand32();		break;	case REPLAY_PROTECTION_TIMESTAMP:		/* set the timestamp according to RFC 2002, 5.6.1 (NTP format):		 * high-order 32 bits: time in seconds from year 1900,		 * low-order 32 bits: fractional seconds (1/256 sec resolution,		 * i.e., 8 bits, used) and the last bits random */		gettimeofday(&tv, NULL);		new_reg_time = tv.tv_sec + mn.clock_correction;		new_reg_rand = ((tv.tv_usec * 256 / 1000000) << 24) |			(get_rand32() & 0xffffff);		if (new_reg_time == last_reg_time &&		    new_reg_rand <= last_reg_rand) {			/* id must always increase - forcing a larger id */			new_reg_rand = last_reg_rand + 1;		}		req->id[0] = htonl(new_reg_time + UNIX_NTP_DIFF);		req->id[1] = htonl(new_reg_rand);		last_reg_time = new_reg_time;		last_reg_rand = new_reg_rand;		break;	case REPLAY_PROTECTION_NONCE:		req->id[0] = mn.last_nonce;		req->id[1] = get_rand32();		break;	}        return sizeof(struct reg_req);}static int nai_equal(struct fa_nai_ext *nai1, struct fa_nai_ext *nai2){	int len = GET_NAI_LEN(nai1);	if (nai2 == NULL || GET_NAI_LEN(nai2) != len)		return 0;	if (memcmp(MSG_NAI_DATA(nai1), MSG_NAI_DATA(nai2), len) == 0)		return 1;	return 0;}static int add_localized_reg_extensions(char *pos, int left, char *start){	static int last_req_seq_num = 0;	struct registration_ext_dynamics *dyn_ext;	int n, added = 0, add_auth = 1;	if (mn.current_adv == NULL || mn.current_adv->adv.fa_nai == NULL ||	    mn.last_req_FA_NAI->type == 0 ||	    (!mn.prev_req_replied &&	     !nai_equal(mn.last_req_FA_NAI, mn.current_adv->adv.fa_nai))) {		if (mn.current_adv == NULL)			DEBUG(DEBUG_INFO, "\tmn.current_adv == NULL\n");		if (mn.current_adv != NULL &&		    mn.current_adv->adv.fa_nai == NULL)			DEBUG(DEBUG_INFO,			      "\tcurrent_adv->fa_nai == NULL\n");		if (mn.last_req_FA_NAI->type == 0)			DEBUG(DEBUG_INFO, "\tlast_req_FA_NAI->type == 0\n");		if (!mn.prev_req_replied)			DEBUG(DEBUG_INFO, "\t!mn.prev_req_replied\n");		if (mn.current_adv != NULL &&		    !nai_equal(mn.last_req_FA_NAI, mn.current_adv->adv.fa_nai))			DEBUG(DEBUG_INFO, "\t!nai_equal()\n");		if (mn.current_adv == NULL ||		    mn.current_adv->adv.fa_nai != NULL) {			DEBUG(DEBUG_INFO, "Not adding SK auth because "			      "current_adv == NULL or FA NAI advertised and "			      "forcing req. to HA\n");			add_auth = 0;		}		DEBUG(DEBUG_INFO, "Excluding previous FA NAI extension "		      "(forcing request to HA)\n");		mn.last_req_FA_NAI->type = 0;	}	if (left < sizeof(struct registration_ext_dynamics))		return -1;	DEBUG(DEBUG_MESSAGES, " * ext_dynamics\n");	dyn_ext = (struct registration_ext_dynamics *) pos;	dyn_ext->type = VENDOR_EXT_TYPE2;	dyn_ext->length = sizeof(struct registration_ext_dynamics) - 2;	dyn_ext->reserved = 0;	dyn_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS);	dyn_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_OPTIONS);	dyn_ext->version = VENDOR_EXT_VERSION;	dyn_ext->opts = 0;	dyn_ext->seq = htonl(++last_req_seq_num);	added += sizeof(struct registration_ext_dynamics);	left -= sizeof(struct registration_ext_dynamics);	if (mn.current_adv != NULL && mn.current_adv->adv.fa_nai != NULL) {		/* previous FA NAI ext. */		if (mn.prev_req_replied && mn.last_req_FA_NAI->type != 0) {			n = GET_NAI_EXT_LEN(mn.last_req_FA_NAI);			if (left < n)				return -1;			mn.last_req_FA_NAI->sub_type =				htons(VENDOR_EXT_DYNAMICS_PREVIOUS_FA_NAI);			memcpy(pos + added, mn.last_req_FA_NAI, n);			added += n;			left -= n;			DEBUG(DEBUG_MESSAGES, " * previous FA NAI (len=%i)\n",			      n);		}		/* current FA NAI ext. */		n = GET_NAI_EXT_LEN(mn.current_adv->adv.fa_nai);		memcpy(mn.last_req_FA_NAI, mn.current_adv->adv.fa_nai, n);		if (left < n)			return -1;		memcpy(pos + added, mn.last_req_FA_NAI, n);		added += n;		left -= n;		DEBUG(DEBUG_MESSAGES, " * current FA NAI (len=%i)\n", n);	}	if (add_auth) {		if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)			return -1;		DEBUG(DEBUG_MESSAGES, " * sk_auth\n");		n = auth_add_vendor(			config.auth_alg, mn.session_key, mn.session_key_len,			(unsigned char *) start,			(struct vendor_msg_auth *) (pos + added),			VENDOR_EXT_DYNAMICS_SK_AUTH, htonl(config.spi));		added += n;		left -= n;	}	return added;}static int add_req_extensions(char *pos, int left, char *start,			      int request_type, int use_reverse){	int use_dynamics_ext, n;	struct fa_spi_entry *fa_spi = NULL;	struct msg_key *mn_keyreq;	struct challenge_ext *challenge = NULL;	char *orig = pos;	int add_mn_aaa_auth_ext = 0;	int send_to_ha = 0;	if (request_type == REG_DISC &&	    mn.fa_addr.s_addr == config.ha_ip_addr.s_addr)		send_to_ha = 1;	if (config.priv_ha > 0) {		struct priv_ha_ext *priv = (struct priv_ha_ext *) pos;		if (left < sizeof(struct priv_ha_ext))			return -1;		memset(priv, 0, sizeof(struct priv_ha_ext));		priv->type = VENDOR_EXT_TYPE2;		priv->length = sizeof(struct priv_ha_ext) - 2;		priv->vendor_id = htonl(VENDOR_ID_DYNAMICS);		priv->sub_type = htons(VENDOR_EXT_DYNAMICS_PRIV_HA);		priv->priv_ha = htonl(config.priv_ha);		pos += GET_PRIV_HA_EXT_LEN(priv);		left -= GET_PRIV_HA_EXT_LEN(priv);		DEBUG(DEBUG_MESSAGES, " * priv_ha\n");	}	if (config.mn_nai_len > 0) {		struct mn_nai_ext *nai;		if (left < sizeof(struct mn_nai_ext) + config.mn_nai_len)			return -1;		nai = (struct mn_nai_ext *) pos;		nai->type = MN_NAI_EXT;		nai->length = config.mn_nai_len;		memcpy(nai + 1, config.mn_nai, config.mn_nai_len);		pos += GET_MN_NAI_EXT_LEN(nai);		left -= GET_MN_NAI_EXT_LEN(nai);		DEBUG(DEBUG_MESSAGES, " * mn_nai\n");	}#ifdef INCLUDE_IPAY	if (config.mn_nai_len == 0 && mn.nai.nai != NULL) {		struct mn_nai_ext *nai;		if (left < sizeof(struct mn_nai_ext) + mn.nai.len)			return -1;		nai = (struct mn_nai_ext *) pos;		nai->type = MN_NAI_EXT;		nai->length = mn.nai.len;		memcpy(nai + 1, mn.nai.nai, mn.nai.len);		pos += GET_MN_NAI_EXT_LEN(nai);		left -= GET_MN_NAI_EXT_LEN(nai);		DEBUG(DEBUG_MESSAGES, " * mn_nai (Ipay)\n");	}#endif	/* add Dynamics extensions if the Foreign Agent advertised support for	 * them or if the registration is made directly to the Home Agent */	use_dynamics_ext = mn.fa_dynamics_ext.type != 0 ||		mn.tunnel_mode == API_TUNNEL_FULL_HA;	if (use_dynamics_ext) {		/* add mn_keyreq extension */		if (left < MIN_KEY_EXT_LEN)			return -1;		DEBUG(DEBUG_MESSAGES, " * mn_keyreq\n");		mn_keyreq = (struct msg_key *) pos;		init_key_extension(mn_keyreq, VENDOR_EXT_DYNAMICS_MN_KEYREQ,				   htonl(config.spi), 0);		pos += GET_KEY_EXT_LEN(mn_keyreq);		left -= GET_KEY_EXT_LEN(mn_keyreq);		/* add HFA public key hash extension if the hash is available		 * from the agent advertisement */		if (mn.current_adv != NULL) {			struct msg_key *hashext =				mn.current_adv->adv.pubkey_hash;			if (hashext != NULL && hashext->type != 0) {				if (left < GET_KEY_EXT_LEN(hashext))					return -1;				DEBUG(DEBUG_MESSAGES, " * pubkey_hash\n");				memcpy(pos, hashext, GET_KEY_EXT_LEN(hashext));				pos += GET_KEY_EXT_LEN(hashext);				left -= GET_KEY_EXT_LEN(hashext);			}		}	} else {		DEBUG(DEBUG_INFO, "FA did not advertise support for Dynamics "		      "extensions - not using them\n");	}	if (config.use_aaa &&	    config.mn_ha_key_timestamp != 0 &&	    config.mn_ha_key_lifetime != 0 &&	    config.mn_ha_key_timestamp + config.mn_ha_key_lifetime <	    time(NULL)) {		DEBUG(DEBUG_INFO, "Dynamic MN-HA security association (from "		      "AAA) expired\n");		config.shared_secret_len = -1;	}	if (config.shared_secret_len >= 0) {		/* add MN->HA authentication extension */		if (left < sizeof(struct msg_auth) + MAX_SK_LEN)			return -1;		DEBUG(DEBUG_MESSAGES, " * mh_auth\n");		n = auth_add(mn.use_auth_alg, config.shared_secret,			     config.shared_secret_len, (unsigned char *) start,			     (struct msg_auth *) pos, MH_AUTH,			     htonl(config.spi));		pos += n;		left -= n;	}	/* Add encapsulating delivery extension if MN decaps and reverse	 * tunnel is in use [RFC 2344, Chap. 3.3] */	if (!config.enable_fa_decapsulation && use_reverse) {		struct encaps_delivery_ext *edel =			(struct encaps_delivery_ext *) pos;		if (left < sizeof(struct encaps_delivery_ext))			return -1;		DEBUG(DEBUG_MESSAGES, " * encaps_delivery\n");		edel->type = ENCAPS_DELIVERY_EXT;		edel->length = 0;		pos += sizeof(struct encaps_delivery_ext);		left -= sizeof(struct encaps_delivery_ext);	}	/* add FA NAI extensions and session key based MN->FA authentication	 * if Dynamics extensions are used and the session key is available	 * and this is not a reregistration */	if (use_dynamics_ext && mn.session_key != NULL &&	    request_type != REG_REREG) {		n = add_localized_reg_extensions(pos, left, start);		if (n < 0)			return -1;		pos += n;		left -= n;	} else if (mn.current_adv != NULL &&		   mn.current_adv->adv.fa_nai != NULL) {		/* current FA NAI ext. */		memcpy(mn.last_req_FA_NAI, mn.current_adv->adv.fa_nai,		       MAX_FA_NAI_LEN);		n = GET_NAI_EXT_LEN(mn.last_req_FA_NAI);		if (left < n)			return -1;		memcpy(pos, mn.last_req_FA_NAI, n);		pos += n;		left -= n;		DEBUG(DEBUG_MESSAGES, " * current FA NAI (len=%i)\n", n);	}	/* if the agent advertisement from the FA has a Challenge extension,	 * copy it to the registration request or if the previous registration	 * reply had a more recent Challenge ext, use it */	/* FIX: MN must not use the same challenge again, so if no new	 * challenge is available, it is no use sending this registration	 * without first acquiring a new challenge fron an agent advertisement.	 * MN could send an agent soliciation in that case. Now the request	 * will be denied by FA and MN might get a new challenge from that	 * denial reply. */	if (mn.last_challenge_ext != NULL &&	    (mn.current_adv == NULL ||	     cmp_timeval(&mn.current_adv->last, &mn.last_challenge_time) < 0))	{		DEBUG(DEBUG_INFO, "Using challenge from last reg. reply\n");		challenge = mn.last_challenge_ext;	} else if (mn.current_adv != NULL &&		   mn.current_adv->adv.challenge != NULL) {		DEBUG(DEBUG_INFO, "Using challenge from last agentadv\n");		challenge = mn.current_adv->adv.challenge;	} else		challenge = NULL;	if (!send_to_ha)		fa_spi = get_fa_spi(0, mn.fa_addr);	if (challenge != NULL && (fa_spi != NULL || config.use_aaa)) {		n = GET_CHALLENGE_EXT_LEN(challenge);		DEBUG(DEBUG_MESSAGES, " * challenge (len=%i)\n", n);		if (left < n)			return -1;		memcpy(pos, challenge, n);		challenge = (struct challenge_ext *) pos;		challenge->type = MN_FA_CHALLENGE_EXT;		pos += n;		left -= n;		add_mn_aaa_auth_ext = 1;	}	/* add shared secret based MN->FA authentication if the security	 * association is configured */	if (!send_to_ha && fa_spi != NULL && !mn.aaa_rekey) {		if (left < sizeof(struct msg_auth) + MAX_SK_LEN)			return -1;		DEBUG(DEBUG_MESSAGES, " * mf_auth\n");		n = auth_add(fa_spi->alg, fa_spi->shared_secret,			     fa_spi->shared_secret_len,			     (unsigned char *) start, (struct msg_auth *) pos,			     MF_AUTH, htonl(fa_spi->spi));		pos += n;		left -= n;		add_mn_aaa_auth_ext = 0;	} else if (!send_to_ha && config.use_aaa) {		struct generalized_mn_fa_key_req_ext *keyreq;		add_mn_aaa_auth_ext = 1;		/* add MN-FA key req. from AAA */		keyreq = (struct generalized_mn_fa_key_req_ext *) pos;		if (left < sizeof(*keyreq))			return -1;		DEBUG(DEBUG_MESSAGES, " * MN-FA Key Req from AAA\n");		keyreq->type = GENERALIZED_MN_FA_KEY_REQ_EXT;		keyreq->subtype = GEN_MN_FA_KEY_REQ_FROM_AAA;		keyreq->length = htons(4);		/* FIX: mn_spi is the SPI that MN will assign for the security		 * association; this may need to be uniquely selected for some		 * cases(?) */		keyreq->mn_spi = htonl(1000);		pos += GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);		left -= GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);	}	if ((config.shared_secret_len < 0 || mn.aaa_rekey) &&	    config.use_aaa) {		struct generalized_mn_ha_key_req_ext *keyreq;		add_mn_aaa_auth_ext = 1;		/* add MN-HA key req. from AAA */		keyreq = (struct generalized_mn_ha_key_req_ext *) pos;		if (left < sizeof(*keyreq))			return -1;		DEBUG(DEBUG_MESSAGES, " * MN-HA Key Req from AAA\n");		keyreq->type = GENERALIZED_MN_HA_KEY_REQ_EXT;		keyreq->subtype = GEN_MN_HA_KEY_REQ_FROM_AAA;

⌨️ 快捷键说明

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