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

📄 sha_request.c

📁 mobile ip 在linux下的一种实现
💻 C
字号:
/* $Id: sha_request.c,v 1.4 2000/07/05 16:50:18 jm Exp $ * Surrogate Home Agent - request handling * * Dynamic hierarchial IP tunnel * Copyright (C) 2000, 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. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stdio.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <syslog.h>#include <string.h>#include <assert.h>#include "debug.h"#include "tunnel.h"#include "util.h"#include "sha_config.h"#include "sha.h"#include "sha_utils.h"extern int sha_sock;extern struct bindingtable *bindings_hash;extern struct sha_config *config;extern int bindingcount;static struct unconfirmed_request *add_unconfirmed_data(struct bindingtable *bhash, int *bindingcount,		     struct bindingentry *binding, struct msg_extensions *ext,		     struct sockaddr_in *addr){	struct tunnel_data *t_data;	struct unconfirmed_request *unc;	DEBUG(DEBUG_FLAG, "Adding unconfirmed request data\n");	t_data = binding->data;	time(&binding->mod_time);	unc = (struct unconfirmed_request *)		malloc(sizeof(struct unconfirmed_request));	if (unc == NULL)		return NULL;	memset(unc, 0, sizeof(struct unconfirmed_request));	unc->next = t_data->unc_req;	time(&unc->created);	unc->lower_addr = addr->sin_addr;	unc->lower_port = addr->sin_port;	unc->id[0] = ntohl(ext->req->id[0]);	unc->id[1] = ntohl(ext->req->id[1]);	if (ext->mh_auth != NULL)		unc->spi = ntohl(ext->mh_auth->spi);	unc->ha_addr = ext->req->ha_addr;	unc->timeout = ntohs(ext->req->lifetime);	if (ext->gre_key != NULL) {		unc->tunnel_type = TUNNEL_GRE;		unc->tunnel_key = ntohl(ext->gre_key->key);	} else {		unc->tunnel_type = TUNNEL_IPIP;		unc->tunnel_key = 0;	}	if (ext->fa_pubkey != NULL) {		unc->fa_pubkey = (struct msg_key *)			malloc(GET_AUTH_EXT_LEN(ext->fa_pubkey));		if (unc->fa_pubkey == NULL) {			DEBUG(DEBUG_FLAG, "\tmalloc failed\n");			return NULL;		}		memcpy(unc->fa_pubkey, ext->fa_pubkey,		       GET_AUTH_EXT_LEN(ext->fa_pubkey));	} else if (ext->fa_keyreq != NULL) {		unc->fa_spi = ntohl(ext->fa_keyreq->spi);	}	t_data->unc_req = unc;	if (!t_data->confirmed &&	    binding->timeout < ntohs(ext->req->lifetime)) {		/* update the unconfirmed binding timeout so that extra		 * requests will not cause unwanted timeouts */		DEBUG(DEBUG_FLAG, "\tupdated binding lifetime %i => %i\n",		      binding->timeout, ntohs(ext->req->lifetime));		binding->timeout = ntohs(ext->req->lifetime);		binding->exp_time = time(NULL) + binding->timeout;		if (update_binding(bhash, binding, bindingcount) != 0)			return NULL;	}	return unc;}static voidforward_request(struct msg_extensions *ext, struct sha_spi_entry *spi,		struct unconfirmed_request *unc){	char buf[MAXMSG];	int len, res;	struct sockaddr_in dst;	assert(ext != NULL && spi != NULL);	if (ext->req == NULL || ext->mh_auth == NULL) {		LOG2(LOG_WARNING, "forward_request: not req or mh_auth\n");		return;	}	/* copy the MAC protected area directly from the received message */	len = (__u8 *) ext->mh_auth - (__u8 *) ext->req +		GET_AUTH_EXT_LEN(ext->mh_auth);	if (len < sizeof(struct reg_req) + GET_AUTH_EXT_LEN(ext->mh_auth) ||	    len > MAXMSG) {		LOG2(LOG_WARNING, "forward_request: invalid length %i\n",		     len);		return;	}	memcpy(buf, ext->req, len);	DEBUG(DEBUG_FLAG, " * copying up to and including mh_auth "	      "(len ==> %i)\n", len);	if (ext->fa_pubkey != NULL || ext->fa_keyreq != NULL) {		struct msg_key *key;		if (len + sizeof(struct msg_key) > MAXMSG) {			DEBUG(DEBUG_FLAG,			      "\tnot enough space for the message\n");			return;		}		DEBUG(DEBUG_FLAG, " * adding fa_keyreq\n");		key = (struct msg_key *) &buf[len];		memset(key, 0, sizeof(struct msg_key));		key->type = VENDOR_EXT_TYPE2;		key->length = sizeof(struct msg_key) - 2;		key->vendor_id = htonl(VENDOR_ID_DYNAMICS);		key->sub_type = htons(VENDOR_EXT_DYNAMICS_FA_KEYREQ);		key->spi = htonl(spi->spi);		len += sizeof(struct msg_key);	}	if (unc != NULL) {		struct nonce_ext *nonce;		if (len + sizeof(struct nonce_ext) > MAXMSG) {			DEBUG(DEBUG_FLAG,			      "\tnot enough space for the message\n");			return;		}		DEBUG(DEBUG_FLAG, " * adding nonce\n");		nonce = (struct nonce_ext *) &buf[len];		memset(nonce, 0, sizeof(struct nonce_ext));		nonce->type = VENDOR_EXT_TYPE2;		nonce->length = sizeof(struct nonce_ext) - 2;		nonce->vendor_id = htonl(VENDOR_ID_DYNAMICS);		nonce->sub_type = htons(VENDOR_EXT_DYNAMICS_NONCE);		unc->nonce = get_rand32();		nonce->nonce = htonl(unc->nonce);		len += sizeof(struct nonce_ext);	}	/* Add SHA-HA ext. auth. */	if (len + sizeof(struct vendor_msg_auth) + MAX_SK_LEN > MAXMSG) {		DEBUG(DEBUG_FLAG, "\tnot enough space for the message\n");		return;	}	DEBUG(DEBUG_FLAG, " * adding sha_ha_auth\n");	len += auth_add_vendor(spi->alg, spi->shared_secret,			       spi->shared_secret_len, (unsigned char *) buf,			       (struct vendor_msg_auth *) &buf[len],			       VENDOR_EXT_DYNAMICS_SHA_HA_AUTH,			       htonl(spi->spi));	memset(&dst, 0, sizeof(dst));	dst.sin_family = AF_INET;	dst.sin_addr = spi->addr;	dst.sin_port = htons(config->udp_port);	DEBUG(DEBUG_FLAG, "\tforwarding request to %s:%i\n",	      inet_ntoa(dst.sin_addr), dst.sin_port);	if (!send_address_ok(dst.sin_addr)) {		DEBUG(DEBUG_FLAG, "\tinvalid address\n");		return;	}	res = sendto(sha_sock, buf, len, 0, (struct sockaddr *) &dst,		     sizeof(dst));	if (res < 0) {		DEBUG(DEBUG_FLAG, "\tsendto: %s\n", strerror(errno));	}}voidhandle_request(char *msg, int len, struct msg_extensions *ext,	       struct sockaddr_in *addr){	struct bindingentry *binding;	struct bindingkey bkey;	struct sha_spi_entry *spi;	struct in_addr tmpaddr;	struct tunnel_data *t_data;	struct unconfirmed_request *unc;	DEBUG(DEBUG_FLAG, "Handling request from MN %s",	      inet_ntoa(ext->req->home_addr));	DEBUG(DEBUG_FLAG, " (%s:%d)\n", inet_ntoa(addr->sin_addr),	      ntohs(addr->sin_port));	/* Check FA-SHA auth. ext */	spi = get_sha_spi(0, addr->sin_addr, 0);	if (spi != NULL) {		if (ext->fh_auth == NULL) {			DEBUG(DEBUG_FLAG, "\tno FA-HA auth. ext.\n");			return;		}		if (!auth_check(spi->alg, spi->shared_secret,				spi->shared_secret_len, (unsigned char *) msg,				ext->fh_auth)) {			DEBUG(DEBUG_FLAG, "\tinvalid FA-HA auth. ext.\n");			return;		}	}	if (ext->req->ha_addr.s_addr != config->sha_addr.s_addr) {		DEBUG(DEBUG_FLAG, "\tinvalid SHA address %s\n",		      inet_ntoa(ext->req->ha_addr));		return;	}	if (ext->priv_ha == NULL) {		DEBUG(DEBUG_FLAG, "\tno priv_ha ext\n");		return;	}	if (ntohl(ext->priv_ha->priv_ha) == 0) {		DEBUG(DEBUG_FLAG, "\tpriv_ha=0\n");		return;	}	tmpaddr.s_addr = 0;	spi = get_sha_spi(0, tmpaddr, ntohl(ext->priv_ha->priv_ha));	if (spi == NULL) {		DEBUG(DEBUG_FLAG, "\tprivate HA ID %u not found\n",		      ntohl(ext->priv_ha->priv_ha));		return;	}	memcpy(&bkey.mn_addr, &(ext->req->home_addr), sizeof(bkey.mn_addr));	memcpy(&bkey.ha_addr, &(ext->req->ha_addr), sizeof(bkey.ha_addr));	bkey.priv_ha = ntohl(ext->priv_ha->priv_ha);	binding = binding_fetch(bindings_hash, &bkey);	if (binding == NULL) {		DEBUG(DEBUG_FLAG, "No binding for MN => making new binding\n");		binding = make_new_binding(bindings_hash, ext, addr,					   config->max_lifetime);		if (binding == NULL) {			DEBUG(DEBUG_FLAG, "\tbinding creation failed\n");			return;		}	} else		check_unconfirmed_timeout(binding);	t_data = (struct tunnel_data *) binding->data;	if (!t_data->confirmed) {		DEBUG(DEBUG_FLAG, "\tunconfirmed binding\n");		if (bindingcount >= config->max_bindings) {			LOG2(LOG_ALERT, "\ttoo many concurrent "			     "bindings - refusing new ones\n");			return;		}	}	unc = add_unconfirmed_data(bindings_hash, &bindingcount, 				   binding, ext, addr);	forward_request(ext, spi, unc);}

⌨️ 快捷键说明

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