📄 sha_utils.c
字号:
/* $Id: sha_utils.c,v 1.6 2001/02/25 09:38:34 jm Exp $ * Surrogate Home Agent - independent help routines * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Jouni Malinen * * 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 <stdlib.h>#include <unistd.h>#include <syslog.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include "dyn_ip.h"#include "binding.h"#include "debug.h"#include "tunnel.h"#include "sha.h"#include "sha_utils.h"static voidfree_unconfirmed_data(struct unconfirmed_request *unc){ struct unconfirmed_request *prev; while (unc != NULL) { prev = unc; unc = unc->next; free(prev); }}static voidfree_binding(struct bindingentry *binding, int *count){ struct tunnel_data *t_data; if (binding == NULL || binding->data == NULL) return; t_data = (struct tunnel_data *) binding->data; free_unconfirmed_data(t_data->unc_req); if (t_data->confirmed && count != NULL) *count -= 1; free(binding->data); free(binding);}static intelim_binding(struct node *node, void *data, int force){ struct bindingentry *binding; int *count, type; struct tunnel_data *t_data; binding = (struct bindingentry *) node; t_data = (struct tunnel_data *) binding->data; count = (int *) data; if (t_data->confirmed) { if (tunnel_unconnect(t_data->up_tunl, t_data->down_tunl, binding->mn_addr, 1, force, NULL, NULL) < 0) { LOG2(LOG_WARNING, "tunnel unconnect failed " "(tun_dev=%s)\n", binding->tun_dev); } if (tunnel_delete_ptr(t_data->down_tunl, force) == -1) { LOG2(LOG_WARNING, "tunnel down - tunnel_delete failed\n"); } if (tunnel_delete_ptr(t_data->up_tunl, force) == -1) { LOG2(LOG_WARNING, "tunnel up - tunnel_delete failed\n"); } } if (t_data->up_type == TUNNEL_IPIP) type = -1; else type = t_data->up_key; binding_remove(binding); free_binding(binding, count); return TRUE;}inteliminate_binding_entry(struct node *node, void *data){ return elim_binding(node, data, 0);}inteliminate_binding_entry_force(struct node *node, void *data){ return elim_binding(node, data, 1);}static voidremove_binding_tunnels(struct bindingentry *binding, struct hashtable *thash, int *bindingcount){ struct tunnel_data *t_data; struct in_addr dst_addr, mn_addr, ha_addr; int up_type; __u32 up_key ; t_data = binding->data; up_type = t_data->up_type; up_key = t_data->up_key; if (t_data->up_tunl) dst_addr = t_data->up_tunl->dst_addr; else dst_addr.s_addr = 0; /* Remove possible tunnel upwards to HA also */ mn_addr.s_addr = binding->mn_addr.s_addr; ha_addr.s_addr = binding->ha_addr.s_addr; eliminate_binding_entry((struct node *) binding, bindingcount);}/* Check and remove expired bindings */voidcheck_bindings(struct bindingtable *bhash, struct hashtable *thash, int *bindingcount, time_t now){ static time_t prev_check; static int first = 1; struct bindingentry *binding; static time_t advance_expire_time; int diff; time_t time_check; if (first) { time(&prev_check); time(&advance_expire_time); first = 0; } /* don't check too frequently */ if (now - prev_check < 1) return; prev_check = now; time(&time_check); diff = time_check - advance_expire_time; advance_expire_time = time_check; if (diff < 0) { LOG2(LOG_WARNING, "check_bindings: diff(%i) < 0 - system time changed?\n", diff); diff = 0; } binding = binding_getexpired(bhash, diff); while (binding != NULL) { struct tunnel_data *t_data; t_data = (struct tunnel_data *) binding->data; DEBUG(DEBUG_FLAG, "check_bindings: binding expired\n"); DEBUG(DEBUG_FLAG, "\tdiff = %d, expiretime = %d\n", diff, binding->timeout); DEBUG(DEBUG_FLAG, "\tbinding->mn_addr = %s\n", inet_ntoa(binding->mn_addr)); DEBUG(DEBUG_FLAG, "\tbinding->lower_addr = %s\n", inet_ntoa(binding->lower_addr)); remove_binding_tunnels(binding, thash, bindingcount); binding = binding_getexpired(bhash, 0); }}struct bindingentry *make_new_binding(struct bindingtable *bhash, struct msg_extensions *ext, struct sockaddr_in *addr, int max_lifetime){ struct bindingentry *binding; struct tunnel_data *t_data; binding = (struct bindingentry *) malloc(sizeof(struct bindingentry)); if (binding == NULL) return NULL; t_data = (struct tunnel_data *) malloc(sizeof(struct tunnel_data)); if (t_data == NULL) { free(binding); return NULL; } memset(binding, 0, sizeof(struct bindingentry)); memset(t_data, 0, sizeof(struct tunnel_data)); binding->data = t_data; time(&binding->create_time); time(&binding->mod_time); binding->mn_addr.s_addr = ext->req->home_addr.s_addr; binding->ha_addr.s_addr = ext->req->ha_addr.s_addr; if (ext->priv_ha != NULL) binding->priv_ha = ntohl(ext->priv_ha->priv_ha); else binding->priv_ha = 0; t_data->confirmed = FALSE; /* add default values for upper tunnel - changed if needed */ t_data->up_type = TUNNEL_IPIP; t_data->up_key = 0; if (ntohs(ext->req->lifetime) < max_lifetime) binding->timeout = ntohs(ext->req->lifetime); else binding->timeout = max_lifetime; if (!binding_add(bhash, binding)) { free_binding(binding, NULL); return NULL; } DEBUG(DEBUG_FLAG, "Created binding (MN=%s, ", inet_ntoa(binding->mn_addr)); DEBUG(DEBUG_FLAG, "HA=%s, priv_ha=%i)\n", inet_ntoa(binding->ha_addr), binding->priv_ha); return binding;}/* check if given binding has unconfirmed requests that have timeouted and * remove them */voidcheck_unconfirmed_timeout(struct bindingentry *binding){ time_t now; struct tunnel_data *t_data; struct unconfirmed_request *unc, *prev; time(&now); t_data = binding->data; unc = t_data->unc_req; prev = NULL; while (unc != NULL) { if (now - unc->created > UNCONFIRMED_TIMEOUT) { DEBUG(DEBUG_FLAG, "Freeing unconfirmed requests that " "have timed out\n"); free_unconfirmed_data(unc); if (prev == NULL) t_data->unc_req = NULL; else prev->next = NULL; break; } prev = unc; unc = unc->next; }}intupdate_binding(struct bindingtable *hash, struct bindingentry *binding, int *count){ if (!binding_update(hash, binding)) { LOG2(LOG_WARNING, "binding_update failed\n"); free_binding(binding, count); return 1; } return 0;}/* try to avoid looping messages to own addresses, return TRUE if the address * is okay or FALSE if it is not */intsend_address_ok(struct in_addr to_addr){ char dev[IFNAMSIZ]; /* check that destionation interface != lo */ if (dyn_ip_route_get(to_addr, dev, IFNAMSIZ) == 0 && strcmp(dev, "lo") == 0) { LOG2(LOG_ALERT, "send_address_ok: destination to 'lo' " "interface - possible loop => refusing\n"); return FALSE; } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -