📄 fa_hash.c
字号:
/* $Id: fa_hash.c,v 1.8 2001/06/23 22:23:51 jm Exp $ * Foreign Agent - lower FA hash * * 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. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stddef.h>#include <assert.h>#include <string.h>#include <time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <syslog.h>#include "debug.h"#include "hashtable.h"#include "agent_utils.h"#include "util.h"#include "tunnel.h"#include "fa.h"#include "fa_hash.h"#define DEBUG_FLAG 'F'#define EXPIRY_CHECK_INTERVAL 10extern struct sockaddr_in upper_fa_addr;extern struct interface_entry *up_interface;extern struct fa_nai_ext *fa_nai;extern struct fa_config *config;extern struct hashtable *tunnels_hash;/* hashtable containing 'struct lower_fa_data's */static struct hashtable *fa_hash = NULL;/* hashtable containing 'struct next_hop_data's */static struct hashtable *next_hash = NULL;/* the nonce value to be used in the next own FA registration request */static __u8 next_send_nonce[FA_REG_NONCE_LEN];/* the nonce value sent in the previous request */static __u8 next_wait_nonce[FA_REG_NONCE_LEN];static time_t last_reg_ok = 0; /* timestamp of the last acknowledged own FA * reg. */static int next_wait_time = 1; /* seconds to wait between own FA reg. retries */static int denial_replies = 0; /* how many denial replies since the last * succesful registration */#define MAX_WAIT_TIME 600time_t fa_reg_next_try = 0; /* next time the FA registration should be done */static int own_req_pending = 0; /* whether this FA waits a reply to its own * request */static void get_new_nonce(__u8 *nonce){ int i; __u32 r; for (i = 0; i < FA_REG_NONCE_LEN / 4; i++) { r = get_rand32(); memcpy(&nonce[i * 4], &r, 4); }}static intlower_fa_hashfunc(void *key, const int hashsize){ __u8 hash; struct lower_fa_data *data; int i; data = (struct lower_fa_data *) key; if (data->nai_len == 0) return 0; hash = data->nai[0]; for (i = 1; i < data->nai_len; i++) { hash ^= data->nai[i]; } return ((int) hash);}static intlower_fa_cmpfunc(void *key, struct node *cmprd){ struct lower_fa_data *data1, *data2; assert(key != NULL && cmprd != NULL); data1 = (struct lower_fa_data *) key; data2 = (struct lower_fa_data *) cmprd; if (data1->nai_len != data2->nai_len) return 0; if (memcmp(data1->nai, data2->nai, data1->nai_len) != 0) return 0; return 1;}static intnext_hop_hashfunc(void *key, const int hashsize){ __u8 *data = (__u8 *) key; return ((int) (data[0] ^ data[1] ^ data[2] ^ data[3]));}static intnext_hop_cmpfunc(void *key, struct node *cmprd){ struct in_addr *addr; struct next_hop_data *data; assert(key != NULL && cmprd != NULL); addr = (struct in_addr *) key; data = (struct next_hop_data *) cmprd; if (addr->s_addr != data->addr.s_addr) return 0; return 1;}int fa_hash_init(void){ fa_hash = hashtable_init(256); if (fa_hash == NULL) return 0; next_hash = hashtable_init(256); if (next_hash == NULL) { hashtable_destroy(fa_hash); fa_hash = NULL; return 0; } return 1;}static intremove_fa_entry(struct node *node, void *data){ struct lower_fa_data *hdata; time_t *now; int i; if (data == NULL) { hashtable_remove(node); free(node); return 1; } hdata = (struct lower_fa_data *) node; now = (time_t *) data; if (hdata->expire + FA_HASH_EXPIRE_TIME < *now || (hdata->expire < *now && !hdata->confirmed)) { DEBUG(DEBUG_FLAG, "FA NAI["); for (i = 0; i < hdata->nai_len; i++) DEBUG(DEBUG_FLAG, "%c", hdata->nai[i]); DEBUG(DEBUG_FLAG, "] expired\n"); hashtable_remove(node); free(node); } return 1;}static intremove_next_hop_entry(struct node *node, void *data){ struct next_hop_data *hdata; time_t *now; hdata = (struct next_hop_data *) node; if (data == NULL) { /* forced deletion at cleanup, do not check tunnel removal * settings */ hashtable_remove(node); free(node); return 1; } now = (time_t *) data; if (hdata->expire < *now) { DEBUG(DEBUG_FLAG, "Next hop FA %s expired\n", inet_ntoa(hdata->addr)); tunnel_set_remove_all(tunnels_hash, hdata->addr); hashtable_remove(node); free(node); } return 1;}void fa_hash_destroy(void){ if (fa_hash != NULL) { DEBUG(DEBUG_FLAG, "Removing dynamic FA information..\n"); hashtable_iterator(fa_hash, remove_fa_entry, NULL); hashtable_destroy(fa_hash); } if (next_hash != NULL) { DEBUG(DEBUG_FLAG, "Removing dynamic next lower FA " "information..\n"); hashtable_iterator(next_hash, remove_next_hop_entry, NULL); hashtable_destroy(next_hash); }}/* Check whether given FA NAI exists in the hashtable * Returns: NULL if NAI not found or pointer to interface_entry if NAI found */struct interface_entry* fa_hash_check(struct fa_nai_ext *nai){ struct lower_fa_data key, *data; time_t now; key.nai_len = GET_NAI_LEN(nai); if (key.nai_len > MAX_NAI_LEN) key.nai_len = MAX_NAI_LEN; memcpy(key.nai, MSG_NAI_DATA(nai), key.nai_len); data = (struct lower_fa_data *) hashtable_fetch(fa_hash, lower_fa_hashfunc, &key, lower_fa_cmpfunc); if (data == NULL || !data->confirmed) return NULL; time(&now); if (now > data->expire) { DEBUG(DEBUG_FLAG, "FA reg. entry expired - marking it " "unconfirmed\n"); data->confirmed = 0; return NULL; } return data->iface;}/* Check whether a valid entry for a given next hop address exists in the * hashtable * Returns: 0 not found, 1 found */int fa_hash_check_next_hop(struct in_addr addr){ struct next_hop_data *data; time_t now; data = (struct next_hop_data *) hashtable_fetch(next_hash, next_hop_hashfunc, &addr, next_hop_cmpfunc); if (data == NULL) return 0; time(&now); if (now > data->expire) { DEBUG(DEBUG_FLAG, "Searched FA reg. entry expired - removing " "it\n"); tunnel_set_remove_all(tunnels_hash, addr); hashtable_remove(&data->node); free(data); return 0; } return 1;}/* Remove expired entries from the hashtable */void fa_hash_expire(void){ static time_t last_check = 0; time_t now; time(&now); if (now < last_check + EXPIRY_CHECK_INTERVAL) return; hashtable_iterator(fa_hash, remove_fa_entry, &now); hashtable_iterator(next_hash, remove_next_hop_entry, &now); last_check = now;}static void update_next_hop(struct in_addr addr, time_t expire){ struct next_hop_data *data; data = (struct next_hop_data *) hashtable_fetch(next_hash, next_hop_hashfunc, &addr, next_hop_cmpfunc); if (data == NULL) { data = (struct next_hop_data *) malloc(sizeof(struct next_hop_data)); if (data == NULL) { DEBUG(DEBUG_FLAG, "update_next_hop - malloc failed\n"); return; } memset(data, 0, sizeof(struct next_hop_data)); list_init_node(&data->node); data->addr = addr; data->expire = expire; hashtable_add(next_hash, next_hop_hashfunc, (void *) &addr, &data->node); DEBUG(DEBUG_FLAG, "\tadded new next hop entry: %s, expire %s", inet_ntoa(addr), ctime(&expire)); return; } if (data->expire < expire) { data->expire = expire; DEBUG(DEBUG_FLAG, "\tupdated next hop entry: %s, expire %s", inet_ntoa(data->addr), ctime(&data->expire)); }}void fa_register(int dereg){ time_t now; char buf[MAXMSG], *pos; struct fa_reg_req *req; struct fa_spi_entry *fa_spi; int res; if (config->highest_FA || fa_nai == NULL) return; time(&now); if (dereg == FA_REGISTER && now < fa_reg_next_try) return; fa_reg_next_try = now + next_wait_time; next_wait_time *= 2; if (next_wait_time > MAX_WAIT_TIME) next_wait_time = MAX_WAIT_TIME; DEBUG(DEBUG_FLAG, "\tnext registration retry: %s", ctime(&fa_reg_next_try)); /* send FA registration request */ req = (struct fa_reg_req *) buf; memset(req, 0, sizeof(struct fa_reg_req)); req->type = FA_REQ; req->lifetime = dereg ? 0 : htons(config->fa_reg_lifetime); get_new_nonce(next_wait_nonce); memcpy(&req->down_nonce, next_wait_nonce, FA_REG_NONCE_LEN); memcpy(&req->up_nonce, next_send_nonce, FA_REG_NONCE_LEN); pos = (char *) (req + 1); memcpy(pos, fa_nai, GET_NAI_EXT_LEN(fa_nai)); pos += GET_NAI_EXT_LEN(fa_nai); fa_spi = get_fa_spi(0, upper_fa_addr.sin_addr, SPI_AGENT_FA); if (fa_spi != NULL) { pos += auth_add_vendor( AUTH_ALG_MD5, fa_spi->shared_secret, fa_spi->shared_secret_len, (unsigned char *) buf, (struct vendor_msg_auth *) pos, VENDOR_EXT_DYNAMICS_FF_AUTH, htonl(fa_spi->spi)); } DEBUG(DEBUG_FLAG, "Sending FA %sreg. request to %s:%i\n", dereg ? "de" : "", inet_ntoa(upper_fa_addr.sin_addr),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -