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

📄 ha.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	return NULL;}/** * get_mn_spi: * @spi: security parameter index (in host byte order) * * Fetches SPI structure for an MN using key @spi. * * Returns: *  pointer to the SPI structure or %NULL if requested item not found */static struct spi_entry *get_mn_spi(int spi){	struct spi_entry *s;	struct node *node;	for (node = list_get_first(&config.spi_list); node != NULL;	     node = list_get_next(node)) {		s = (struct spi_entry *) node;		if (s->spi == spi)			return s;	}	return NULL;}/** * ha_add_ext_start: * @start: pointer to the beginning of the authenticated data * @pos: memory position for the added authentication extension * @left: amount of free base in buffer * @ext: parsed registration request or %NULL if not available * @lifetime: lifetime of the binding; zero for deregistration or failure reply * @mn_spi: SPI structure for the MN or %NULL if not available * @binding: bindingentry for the MN or %NULL if not available * @auth_type: authentication data area (%AUTH_RFC2002 / %AUTH_RFC2002BIS) * * Add private HA extension (if SHA is used), copy MN NAI extension from the * request (if available), add a key reply extension (if requested), and * add MN-HA authentication extension if security associated available. * * Returns: *  Number of used bytes in the buffer or -1 on failure. */static intha_add_ext_start(unsigned char *start, unsigned char *pos, int left,		 struct msg_extensions *ext, int lifetime,		 struct spi_entry *mn_spi, struct bindingentry *binding,		 int auth_type){	int used = 0, n;	if (config.priv_ha > 0) {		struct priv_ha_ext *priv = (struct priv_ha_ext *) (pos + used);		DEBUG(DEBUG_FLAG, " * priv_ha\n");		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);		used += GET_PRIV_HA_EXT_LEN(priv);		left -= GET_PRIV_HA_EXT_LEN(priv);	}	/* RFC 2794 requires that HA copies MN NAI extension to the reply */	if (ext != NULL && ext->mn_nai != NULL) {		DEBUG(DEBUG_FLAG, " * mn_nai\n");		if (left < GET_MN_NAI_EXT_LEN(ext->mn_nai))			return -1;		memcpy(pos + used, ext->mn_nai,		       GET_MN_NAI_EXT_LEN(ext->mn_nai));		used += GET_MN_NAI_EXT_LEN(ext->mn_nai);		left -= GET_MN_NAI_EXT_LEN(ext->mn_nai);	}	/* Add the session key to mobile node, if it requested for a key and	 * the reply is not a deregistration or failure reply */	if (ext && ext->mn_keyreq != NULL && mn_spi && lifetime != 0) {		struct msg_key *key;		DEBUG(DEBUG_FLAG, " * mn_keyrep\n");		if (left < sizeof(struct msg_key) + MAX_SK_LEN)			return -1;		key = (struct msg_key *) (pos + used);		n = auth_encrypt(mn_spi->auth_alg, mn_spi->shared_secret,				 mn_spi->shared_secret_len, binding->key,				 key, (struct reg_rep *) start,				 VENDOR_EXT_DYNAMICS_MN_KEYREP,				 htonl(mn_spi->spi));		used += n;		left -= n;	}	if (ext && mn_spi) {		struct msg_auth *auth;		DEBUG(DEBUG_FLAG, " * mh_auth\n");		if (left < sizeof(struct msg_auth) + MAX_SK_LEN)			return -1;		/* Add message authentication for MN */		auth = (struct msg_auth *) (pos + used);		n = auth_add((auth_type == AUTH_RFC2002BIS ?			      AUTH_ALG_MD5_RFC2002 : mn_spi->auth_alg),			     mn_spi->shared_secret,			     mn_spi->shared_secret_len, start,			     (struct msg_auth *) (pos + used), MH_AUTH,			     htonl(mn_spi->spi));		used += n;		left -= n;	}	/* RFC 3012 requires that HA copies challenge extension to the reply	 * after Mobile-Home auth. ext.; this will be authenticated with	 * FA-HA auth. ext. if security association for this is available */	if (ext != NULL && ext->challenge != NULL) {		DEBUG(DEBUG_FLAG, " * challenge\n");		n = GET_CHALLENGE_EXT_LEN(ext->challenge);		if (left < n)			return -1;		memcpy(pos + used, ext->challenge, n);		used += n;		left -= n;	}	return used;}/** * ha_add_ext_end: * @start: pointer to the beginning of the authenticated data * @pos: memory position for the added authentication extension * @addr: IP address from which the registration request was received * @left: amount of free base in buffer * @ext: parsed registration request or %NULL if not available * * Copy nonce extension from the request (if available) and add an * authentication extension for SHA or FA if a security association is * configured. * * Returns: *  Number of used bytes in the buffer or -1 on failure. */static intha_add_ext_end(unsigned char *start, unsigned char *pos, struct in_addr addr,	       int left, struct msg_extensions *ext){	struct fa_spi_entry *fa_spi;	int used = 0;	if (config.priv_ha && ext && ext->nonce) {		if (ext->nonce->length != sizeof(struct nonce_ext) - 2) {			DEBUG(DEBUG_FLAG, " - invalid nonce ext len\n");		} else {			DEBUG(DEBUG_FLAG, " * nonce\n");			if (left < GET_NONCE_EXT_LEN(ext->nonce))				return -1;			memcpy(pos + used, ext->nonce,			       GET_NONCE_EXT_LEN(ext->nonce));			used += GET_NONCE_EXT_LEN(ext->nonce);			left -= GET_NONCE_EXT_LEN(ext->nonce);		}	}	fa_spi = get_fa_spi(0, addr);	if (fa_spi != NULL && config.priv_ha > 0) {		DEBUG(DEBUG_FLAG, " * sha_ha_auth\n");		if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)			return -1;		used += auth_add_vendor(			AUTH_ALG_MD5, fa_spi->shared_secret,			fa_spi->shared_secret_len, start,			(struct vendor_msg_auth *) (pos + used),			VENDOR_EXT_DYNAMICS_SHA_HA_AUTH, htonl(fa_spi->spi));	} else if (fa_spi != NULL) {		DEBUG(DEBUG_FLAG, " * fh_auth\n");		if (left < sizeof(struct msg_auth) + MAX_SK_LEN)			return -1;		used += auth_add(fa_spi->alg, fa_spi->shared_secret,				 fa_spi->shared_secret_len, start,				 (struct msg_auth *) (pos + used), FH_AUTH,				 htonl(fa_spi->spi));	}	return used;}/** * send_reg_repl: * @s: socket to be used in sending the registration reply * @binding: bindingentry for the MN * @mn_spi: SPI entry for the MN * @ext: parsed registration request or %NULL for teardown reply * @forced_iface: forced destination interface or %NULL for no forcing * @code: registration reply code * * Creates and sends a registration reply message to the foreign agent given * in the binding. This function can also be used for sending a teardown reply * to the old foreign agent by giving %NULL @ext argument. * * Returns: *  0 on success or -1 on failure */static intsend_reg_repl(int s, struct bindingentry *binding, struct spi_entry *mn_spi,	      struct msg_extensions *ext, struct interface_entry *forced_iface,	      int code){	unsigned char msg[MAXMSG];	unsigned char *msgpos = msg;	struct reg_rep *reply;	struct msg_key *key;	struct sockaddr_in dest_addr;	struct fa_spi_entry *fa_spi;#ifdef USE_TEARDOWN	struct registration_ext_dynamics *dyn_ext;#endif	int msglen, result, key_to_fa, left = MAXMSG, n;	struct ha_tunnel_data *t_data;	ASSERT(s >= 0 && binding != NULL && binding->data != NULL &&	       mn_spi != NULL);	t_data = (struct ha_tunnel_data *) binding->data;	/* Create the reply extension */	DEBUG(DEBUG_FLAG, "Reply\n");	reply = (struct reg_rep *) msg;	memset(reply, 0, sizeof(struct reg_rep));	reply->lifetime = htons(binding->timeout);	reply->type = REG_REP;	reply->code = code;	reply->home_addr.s_addr = binding->mn_addr.s_addr;	reply->ha_addr.s_addr = config.sha_addr.s_addr != 0 ?		config.sha_addr.s_addr : binding->ha_addr.s_addr;	memcpy(reply->id, binding->id, REG_REQ_ID_LEN);	if (mn_spi->replay_method == REPLAY_PROTECTION_NONCE)		t_data->nonce = reply->id[0] = get_rand32();	msgpos += sizeof(struct reg_rep);	left -= sizeof(struct reg_rep);	n = ha_add_ext_start(msg, msgpos, left, ext, binding->timeout,			     mn_spi, binding, t_data->auth_type);	if (n < 0)		return -1;	msgpos += n;	left -= n;	/* Encrypt the session key for the FA if it requested the key with	 * fa_keyreq (use shared secret and MD5) or fa_pubkey (use RSA) */	key_to_fa = 0;	if (binding->fa_spi != 0 && ntohs(reply->lifetime) != 0) {		fa_spi = get_fa_spi(binding->fa_spi, t_data->lower_saddr);		if (fa_spi == NULL) {			LOG2(LOG_ERR, "unknown FA SPI %i\n", binding->fa_spi);			return -1;		}		DEBUG(DEBUG_FLAG, " * fa_keyrep\n");		if (left < sizeof(struct msg_key) + MAX_SK_LEN)			return -1;		key = (struct msg_key *) msgpos;		n = 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));		msgpos += n;		left -= n;		key_to_fa = 1;	} else if (binding->fa_pubkey && ntohs(reply->lifetime) != 0 &&		   binding->last_sent_fa_pubkeyrep) {		DEBUG(DEBUG_FLAG, " * fa_pubkeyrep\n");		n = GET_KEY_EXT_LEN(binding->last_sent_fa_pubkeyrep);		if (left < n)			return -1;		/* If the foreign agent included a public key, add an RSA		 * encrypted session key to the FA */		key = (struct msg_key *) msgpos;		memcpy(key, binding->last_sent_fa_pubkeyrep, n);		msgpos += n;		left -= n;		key_to_fa = 1;	}#ifdef USE_TEARDOWN	if (teardown) {		DEBUG(DEBUG_FLAG, " * ext_dynamics (teardown)\n");		if (left < sizeof(struct registration_ext_dynamics))			return -1;		dyn_ext = (struct registration_ext_dynamics *) msgpos;		dyn_ext->type = VENDOR_EXT_TYPE2;		dyn_ext->reserved = 0;		dyn_ext->length = sizeof(struct registration_ext_dynamics) - 2;		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 = REG_EXT_OWN_TEAR_DOWN;		dyn_ext->seq = 0;		msgpos += sizeof(struct registration_ext_dynamics);		left -= sizeof(struct registration_ext_dynamics);	}#endif	if (key_to_fa) {		DEBUG(DEBUG_FLAG, " * sk_auth\n");		if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)			return -1;		/* Add session key-based message authentication for FA */		n = auth_add_vendor(AUTH_ALG_MD5, binding->key,				    binding->keylen, msg,				    (struct vendor_msg_auth *) msgpos,				    VENDOR_EXT_DYNAMICS_SK_AUTH,				    htonl(mn_spi->spi));		msgpos += n;		left -= n;	}	n = ha_add_ext_end(msg, msgpos, t_data->lower_saddr, left, ext);	if (n < 0)		return -1;	msgpos += n;	left -= n;	msglen = msgpos - msg;	dest_addr.sin_family = AF_INET;	dest_addr.sin_addr.s_addr = t_data->lower_saddr.s_addr;	dest_addr.sin_port = binding->lower_port;	if (forced_iface != NULL &&	    setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, forced_iface->dev,		       IFNAMSIZ)) {		DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, SO_BINDTODEVICE): "		      "%s\n", strerror(errno));	}	DEBUG(DEBUG_FLAG, " * total %i bytes to %s:%i\n", msglen,	      inet_ntoa(dest_addr.sin_addr), ntohs(dest_addr.sin_port));	result = sendto(s, msg, msglen, 0,			(struct sockaddr *) &dest_addr,			sizeof(struct sockaddr_in));	if (forced_iface != NULL) {		/* kernel seems to require optlen >= sizeof(int) */		char dummy[sizeof(int)];		memset(dummy, 0, sizeof(dummy));		if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dummy,			       sizeof(dummy)))			DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, "			      "SO_BINDTODEVICE): %s\n", strerror(errno));	}	return dynamics_check_sendto(result, msglen, "send_reg_repl");}/** * send_reg_failure: * @s: socket to be used for sending the registration reply * @sock_addr: destination address (IP address and UDP port) * @mn_spi: pointer to SPI structure for the MN or %NULL if not known * @auth_type: authentication data area (%AUTH_RFC2002 / %AUTH_RFC2002BIS) * @code: failure code for the registration reply (3 .. 255) * @nonce: nonce value to be updated if the MN uses nonce-based replay * protection; @nonce can also be %NULL, when the nonce value is not updated * @ext: parsed registration request * @forced_iface: forced destination interface or %NULL for no forcing * @binding: pointer to MN's binding entry if known, or %NULL if not available * @from_iface: interface from which the registration request was received * * Sends a registration reply with a failure code @code to @sock_addr. * * Returns: *   0 on success or -1 on failure */static intsend_reg_failure(int s, struct sockaddr_in *sock_addr,		 struct spi_entry *mn_spi, int auth_type,		 int code, __u32 *nonce, struct msg_extensions *ext,		 struct interface_entry *forced_iface,		 struct bindingentry *binding,		 struct interface_entry *from_iface){	unsigned char msg[MAXMSG];	unsigned char *msgpos = msg;	struct reg_rep *reply;	int msglen, result, n, left = MAXMSG;	struct ha_tunnel_data *t_data = NULL;	static time_t last_failure_time = 0;	time_t *timer, now;	ASSERT(s >= 0 && sock_addr && ext && ext->req && code > 2);	if (binding) {		/* known binding - use MN's own timer */		t_data = (struct ha_tunnel_data *) binding->data;		timer = &t_data->last_failure_time;	} else {		/* no binding - use general timer */		timer = &last_failure_time;	}	/* do not send failure replys too often */	time(&now);	if (*timer > now) {		DEBUG(DEBUG_FLAG, "send_reg_failure: timed failure in the "		      "future - host time changed?\n");		*timer = now;	} else if (now - *timer < config.reg_error_reply_interval) {		DEBUG(DEBUG_FLAG, "Too frequent error message - skipping\n");		return 0;	}        *timer = now;	if (mn_spi == NULL && ext->mh_auth != NULL)		mn_spi = get_mn_spi(ntohl(ext->mh_auth->spi));		/* Create the reply extension */	DEBUG(DEBUG_FLAG, "Failure reply\n");	reply = (struct reg_rep *) msg;	memset(reply, 0, sizeof(struct reg_rep));	reply->lifetime = 0;	reply->type = REG_REP;	reply->code = code;	reply->home_addr.s_addr = ext->req->home_addr.s_addr;	reply->ha_addr.s_addr = ext->req->ha_addr.s_addr;	if (config.sha_addr.s_addr != 0)		reply->ha_addr.s_addr = config.sha_addr.s_addr;	else if (code == REGREP_UNKNOWN_HA_HA) {		/* use the HA's unicast IP address in case of HA discovery */		struct node *node;		int found = 0;		for (node = list_get_first(&config.interfaces); node != NULL;		     node = list_get_next(node)) {			struct interface_entry *iface =				(struct interface_entry *) node;			if (iface->ha_disc &&			    iface->bcaddr.s_addr == ext->req->ha_addr.s_addr) {				reply->ha_addr.s_addr = iface->addr.s_addr;

⌨️ 快捷键说明

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