📄 sha_request.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 + -