Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/libalias/alias_db.c
Show First 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | |||||
#include <net/if.h> | #include <net/if.h> | ||||
#else | #else | ||||
#include "alias.h" | #include "alias.h" | ||||
#include "alias_local.h" | #include "alias_local.h" | ||||
#include "alias_mod.h" | #include "alias_mod.h" | ||||
#endif | #endif | ||||
static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead); | static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead); | ||||
int LibAliasTime; | |||||
/* | /* | ||||
Constants (note: constants are also defined | Constants (note: constants are also defined | ||||
near relevant functions or structs) | near relevant functions or structs) | ||||
*/ | */ | ||||
/* Parameters used for cleanup of expired links */ | |||||
/* NOTE: ALIAS_CLEANUP_INTERVAL_SECS must be less then LINK_TABLE_OUT_SIZE */ | |||||
#define ALIAS_CLEANUP_INTERVAL_SECS 64 | |||||
#define ALIAS_CLEANUP_MAX_SPOKES (LINK_TABLE_OUT_SIZE/5) | |||||
/* Timeouts (in seconds) for different link types */ | /* Timeouts (in seconds) for different link types */ | ||||
#define ICMP_EXPIRE_TIME 60 | #define ICMP_EXPIRE_TIME 60 | ||||
#define UDP_EXPIRE_TIME 60 | #define UDP_EXPIRE_TIME 60 | ||||
#define PROTO_EXPIRE_TIME 60 | #define PROTO_EXPIRE_TIME 60 | ||||
#define FRAGMENT_ID_EXPIRE_TIME 10 | #define FRAGMENT_ID_EXPIRE_TIME 10 | ||||
#define FRAGMENT_PTR_EXPIRE_TIME 30 | #define FRAGMENT_PTR_EXPIRE_TIME 30 | ||||
/* TCP link expire time for different cases */ | /* TCP link expire time for different cases */ | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | #define LINK_UNFIREWALLED 0x08 | ||||
int timestamp; /* Time link was last accessed */ | int timestamp; /* Time link was last accessed */ | ||||
int expire_time; /* Expire time for link */ | int expire_time; /* Expire time for link */ | ||||
#ifndef NO_USE_SOCKETS | #ifndef NO_USE_SOCKETS | ||||
int sockfd; /* socket descriptor */ | int sockfd; /* socket descriptor */ | ||||
#endif | #endif | ||||
/* Linked list of pointers for input and output lookup tables */ | /* Linked list of pointers for input and output lookup tables */ | ||||
LIST_ENTRY (alias_link) list_out; | LIST_ENTRY (alias_link) list_out; | ||||
LIST_ENTRY (alias_link) list_in; | LIST_ENTRY (alias_link) list_in; | ||||
TAILQ_ENTRY (alias_link) list_expire; | |||||
/* Auxiliary data */ | /* Auxiliary data */ | ||||
union { | union { | ||||
char *frag_ptr; | char *frag_ptr; | ||||
struct in_addr frag_addr; | struct in_addr frag_addr; | ||||
struct tcp_dat *tcp; | struct tcp_dat *tcp; | ||||
} data; | } data; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | |||||
/* Internal routines for finding, deleting and adding links | /* Internal routines for finding, deleting and adding links | ||||
Port Allocation: | Port Allocation: | ||||
GetNewPort() -- find and reserve new alias port number | GetNewPort() -- find and reserve new alias port number | ||||
GetSocket() -- try to allocate a socket for a given port | GetSocket() -- try to allocate a socket for a given port | ||||
Link creation and deletion: | Link creation and deletion: | ||||
CleanupAliasData() - remove all link chains from lookup table | CleanupAliasData() - remove all link chains from lookup table | ||||
IncrementalCleanup() - look for stale links in a single chain | CleanupLink() - look for a stale link | ||||
DeleteLink() - remove link | DeleteLink() - remove link | ||||
AddLink() - add link | AddLink() - add link | ||||
ReLink() - change link | ReLink() - change link | ||||
Link search: | Link search: | ||||
FindLinkOut() - find link for outgoing packets | FindLinkOut() - find link for outgoing packets | ||||
FindLinkIn() - find link for incoming packets | FindLinkIn() - find link for incoming packets | ||||
Port search: | Port search: | ||||
FindNewPortGroup() - find an available group of ports | FindNewPortGroup() - find an available group of ports | ||||
*/ | */ | ||||
/* Local prototypes */ | /* Local prototypes */ | ||||
static int GetNewPort(struct libalias *, struct alias_link *, int); | static int GetNewPort(struct libalias *, struct alias_link *, int); | ||||
#ifndef NO_USE_SOCKETS | #ifndef NO_USE_SOCKETS | ||||
static u_short GetSocket(struct libalias *, u_short, int *, int); | static u_short GetSocket(struct libalias *, u_short, int *, int); | ||||
#endif | #endif | ||||
static void CleanupAliasData(struct libalias *); | static void CleanupAliasData(struct libalias *); | ||||
static void IncrementalCleanup(struct libalias *); | static void CleanupLink(struct libalias *, struct alias_link **); | ||||
static void DeleteLink(struct alias_link *); | static void DeleteLink(struct alias_link **); | ||||
static struct alias_link * | static struct alias_link * | ||||
ReLink(struct alias_link *, | ReLink(struct alias_link *, | ||||
struct in_addr, struct in_addr, struct in_addr, | struct in_addr, struct in_addr, struct in_addr, | ||||
u_short, u_short, int, int); | u_short, u_short, int, int); | ||||
static struct alias_link * | static struct alias_link * | ||||
FindLinkOut(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); | FindLinkOut(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
CleanupAliasData(struct libalias *la) | CleanupAliasData(struct libalias *la) | ||||
{ | { | ||||
struct alias_link *lnk; | struct alias_link *lnk, *lnk_tmp; | ||||
int i; | |||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { | |||||
lnk = LIST_FIRST(&la->linkTableOut[i]); | |||||
while (lnk != NULL) { | |||||
struct alias_link *link_next = LIST_NEXT(lnk, list_out); | |||||
DeleteLink(lnk); | |||||
lnk = link_next; | |||||
} | |||||
} | |||||
la->cleanupIndex = 0; | /* permanent entries may stay */ | ||||
TAILQ_FOREACH_SAFE(lnk, &la->checkExpire, list_expire, lnk_tmp) | |||||
DeleteLink(&lnk); | |||||
} | } | ||||
static void | static void | ||||
IncrementalCleanup(struct libalias *la) | CleanupLink(struct libalias *la, struct alias_link **lnk) | ||||
{ | { | ||||
struct alias_link *lnk, *lnk_tmp; | |||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
LIST_FOREACH_SAFE(lnk, &la->linkTableOut[la->cleanupIndex++], | |||||
list_out, lnk_tmp) { | if (lnk == NULL || *lnk == NULL) | ||||
if (la->timeStamp - lnk->timestamp > lnk->expire_time) | return; | ||||
if (LibAliasTime - (*lnk)->timestamp > (*lnk)->expire_time) { | |||||
DeleteLink(lnk); | DeleteLink(lnk); | ||||
if ((*lnk) == NULL) | |||||
return; | |||||
} | } | ||||
if (la->cleanupIndex == LINK_TABLE_OUT_SIZE) | /* move to end, swap may fail on a single entry list */ | ||||
la->cleanupIndex = 0; | TAILQ_REMOVE(&la->checkExpire, (*lnk), list_expire); | ||||
TAILQ_INSERT_TAIL(&la->checkExpire, (*lnk), list_expire); | |||||
} | } | ||||
static void | static void | ||||
DeleteLink(struct alias_link *lnk) | DeleteLink(struct alias_link **plnk) | ||||
{ | { | ||||
struct alias_link *lnk = *plnk; | |||||
struct libalias *la = lnk->la; | struct libalias *la = lnk->la; | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
/* Don't do anything if the link is marked permanent */ | /* Don't do anything if the link is marked permanent */ | ||||
if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) | if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) | ||||
return; | return; | ||||
#ifndef NO_FW_PUNCH | #ifndef NO_FW_PUNCH | ||||
Show All 11 Lines | do { | ||||
free(curr); | free(curr); | ||||
} while ((curr = next) != head); | } while ((curr = next) != head); | ||||
} | } | ||||
/* Adjust output table pointers */ | /* Adjust output table pointers */ | ||||
LIST_REMOVE(lnk, list_out); | LIST_REMOVE(lnk, list_out); | ||||
/* Adjust input table pointers */ | /* Adjust input table pointers */ | ||||
LIST_REMOVE(lnk, list_in); | LIST_REMOVE(lnk, list_in); | ||||
/* remove from housekeeping */ | |||||
TAILQ_REMOVE(&la->checkExpire, lnk, list_expire); | |||||
#ifndef NO_USE_SOCKETS | #ifndef NO_USE_SOCKETS | ||||
/* Close socket, if one has been allocated */ | /* Close socket, if one has been allocated */ | ||||
if (lnk->sockfd != -1) { | if (lnk->sockfd != -1) { | ||||
la->sockCount--; | la->sockCount--; | ||||
close(lnk->sockfd); | close(lnk->sockfd); | ||||
} | } | ||||
#endif | #endif | ||||
/* Link-type dependent cleanup */ | /* Link-type dependent cleanup */ | ||||
Show All 23 Lines | case LINK_ADDR: | ||||
break; | break; | ||||
default: | default: | ||||
la->protoLinkCount--; | la->protoLinkCount--; | ||||
break; | break; | ||||
} | } | ||||
/* Free memory */ | /* Free memory */ | ||||
free(lnk); | free(lnk); | ||||
*plnk = NULL; | |||||
/* Write statistics, if logging enabled */ | /* Write statistics, if logging enabled */ | ||||
if (la->packetAliasMode & PKT_ALIAS_LOG) { | if (la->packetAliasMode & PKT_ALIAS_LOG) { | ||||
ShowAliasStats(la); | ShowAliasStats(la); | ||||
} | } | ||||
} | } | ||||
struct alias_link * | struct alias_link * | ||||
Show All 18 Lines | if (lnk != NULL) { | ||||
lnk->proxy_port = 0; | lnk->proxy_port = 0; | ||||
lnk->server = NULL; | lnk->server = NULL; | ||||
lnk->link_type = link_type; | lnk->link_type = link_type; | ||||
#ifndef NO_USE_SOCKETS | #ifndef NO_USE_SOCKETS | ||||
lnk->sockfd = -1; | lnk->sockfd = -1; | ||||
#endif | #endif | ||||
lnk->flags = 0; | lnk->flags = 0; | ||||
lnk->pflags = 0; | lnk->pflags = 0; | ||||
lnk->timestamp = la->timeStamp; | lnk->timestamp = LibAliasTime; | ||||
/* Expiration time */ | /* Expiration time */ | ||||
switch (link_type) { | switch (link_type) { | ||||
case LINK_ICMP: | case LINK_ICMP: | ||||
lnk->expire_time = ICMP_EXPIRE_TIME; | lnk->expire_time = ICMP_EXPIRE_TIME; | ||||
break; | break; | ||||
case LINK_UDP: | case LINK_UDP: | ||||
lnk->expire_time = UDP_EXPIRE_TIME; | lnk->expire_time = UDP_EXPIRE_TIME; | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | #endif | ||||
/* Set up pointers for output lookup table */ | /* Set up pointers for output lookup table */ | ||||
start_point = StartPointOut(src_addr, dst_addr, | start_point = StartPointOut(src_addr, dst_addr, | ||||
src_port, dst_port, link_type); | src_port, dst_port, link_type); | ||||
LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out); | LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out); | ||||
/* Set up pointers for input lookup table */ | /* Set up pointers for input lookup table */ | ||||
start_point = StartPointIn(alias_addr, lnk->alias_port, link_type); | start_point = StartPointIn(alias_addr, lnk->alias_port, link_type); | ||||
LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in); | LIST_INSERT_HEAD(&la->linkTableIn[start_point], lnk, list_in); | ||||
/* Include the element into the housekeeping list */ | |||||
TAILQ_INSERT_TAIL(&la->checkExpire, lnk, list_expire); | |||||
} else { | } else { | ||||
#ifdef LIBALIAS_DEBUG | #ifdef LIBALIAS_DEBUG | ||||
fprintf(stderr, "PacketAlias/AddLink(): "); | fprintf(stderr, "PacketAlias/AddLink(): "); | ||||
fprintf(stderr, "malloc() call failed.\n"); | fprintf(stderr, "malloc() call failed.\n"); | ||||
#endif | #endif | ||||
} | } | ||||
if (la->packetAliasMode & PKT_ALIAS_LOG) { | if (la->packetAliasMode & PKT_ALIAS_LOG) { | ||||
ShowAliasStats(la); | ShowAliasStats(la); | ||||
Show All 24 Lines | new_lnk = AddLink(la, src_addr, dst_addr, alias_addr, | ||||
link_type); | link_type); | ||||
#ifndef NO_FW_PUNCH | #ifndef NO_FW_PUNCH | ||||
if (new_lnk != NULL && | if (new_lnk != NULL && | ||||
old_lnk->link_type == LINK_TCP && | old_lnk->link_type == LINK_TCP && | ||||
old_lnk->data.tcp->fwhole > 0) { | old_lnk->data.tcp->fwhole > 0) { | ||||
PunchFWHole(new_lnk); | PunchFWHole(new_lnk); | ||||
} | } | ||||
#endif | #endif | ||||
DeleteLink(old_lnk); | DeleteLink(&old_lnk); | ||||
return (new_lnk); | return (new_lnk); | ||||
} | } | ||||
static struct alias_link * | static struct alias_link * | ||||
_FindLinkOut(struct libalias *la, struct in_addr src_addr, | _FindLinkOut(struct libalias *la, struct in_addr src_addr, | ||||
struct in_addr dst_addr, | struct in_addr dst_addr, | ||||
u_short src_port, | u_short src_port, | ||||
u_short dst_port, | u_short dst_port, | ||||
int link_type, | int link_type, | ||||
int replace_partial_links) | int replace_partial_links) | ||||
{ | { | ||||
u_int i; | u_int i; | ||||
struct alias_link *lnk; | struct alias_link *lnk; | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); | i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); | ||||
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) { | LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) { | ||||
if (lnk->dst_addr.s_addr == dst_addr.s_addr && | if (lnk->dst_addr.s_addr == dst_addr.s_addr && | ||||
lnk->src_addr.s_addr == src_addr.s_addr && | lnk->src_addr.s_addr == src_addr.s_addr && | ||||
lnk->src_port == src_port && | lnk->src_port == src_port && | ||||
lnk->dst_port == dst_port && | lnk->dst_port == dst_port && | ||||
lnk->link_type == link_type && | lnk->link_type == link_type && | ||||
lnk->server == NULL) { | lnk->server == NULL) | ||||
lnk->timestamp = la->timeStamp; | |||||
break; | break; | ||||
} | } | ||||
} | |||||
CleanupLink(la, &lnk); | |||||
if (lnk != NULL) | |||||
lnk->timestamp = LibAliasTime; | |||||
/* Search for partially specified links. */ | /* Search for partially specified links. */ | ||||
if (lnk == NULL && replace_partial_links) { | if (lnk == NULL && replace_partial_links) { | ||||
if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) { | if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) { | ||||
lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0, | lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0, | ||||
link_type, 0); | link_type, 0); | ||||
if (lnk == NULL) | if (lnk == NULL) | ||||
lnk = _FindLinkOut(la, src_addr, ANY_ADDR, src_port, | lnk = _FindLinkOut(la, src_addr, ANY_ADDR, src_port, | ||||
dst_port, link_type, 0); | dst_port, link_type, 0); | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | if (!(flags & LINK_PARTIALLY_SPECIFIED)) { | ||||
&& lnk->link_type == link_type | && lnk->link_type == link_type | ||||
&& lnk->dst_addr.s_addr == dst_addr.s_addr) { | && lnk->dst_addr.s_addr == dst_addr.s_addr) { | ||||
if (lnk_unknown_dst_port == NULL) | if (lnk_unknown_dst_port == NULL) | ||||
lnk_unknown_dst_port = lnk; | lnk_unknown_dst_port = lnk; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
CleanupLink(la, &lnk_fully_specified); | |||||
if (lnk_fully_specified != NULL) { | if (lnk_fully_specified != NULL) { | ||||
lnk_fully_specified->timestamp = la->timeStamp; | lnk_fully_specified->timestamp = LibAliasTime; | ||||
lnk = lnk_fully_specified; | lnk = lnk_fully_specified; | ||||
} else if (lnk_unknown_dst_port != NULL) | } else if (lnk_unknown_dst_port != NULL) | ||||
lnk = lnk_unknown_dst_port; | lnk = lnk_unknown_dst_port; | ||||
else if (lnk_unknown_dst_addr != NULL) | else if (lnk_unknown_dst_addr != NULL) | ||||
lnk = lnk_unknown_dst_addr; | lnk = lnk_unknown_dst_addr; | ||||
else if (lnk_unknown_all != NULL) | else if (lnk_unknown_all != NULL) | ||||
lnk = lnk_unknown_all; | lnk = lnk_unknown_all; | ||||
else | else | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, | ||||
i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); | i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); | ||||
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) | LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) | ||||
if (lnk->link_type == LINK_PPTP && | if (lnk->link_type == LINK_PPTP && | ||||
lnk->src_addr.s_addr == src_addr.s_addr && | lnk->src_addr.s_addr == src_addr.s_addr && | ||||
lnk->dst_addr.s_addr == dst_addr.s_addr && | lnk->dst_addr.s_addr == dst_addr.s_addr && | ||||
lnk->src_port == src_call_id) | lnk->src_port == src_call_id) | ||||
break; | break; | ||||
CleanupLink(la, &lnk); | |||||
return (lnk); | return (lnk); | ||||
} | } | ||||
struct alias_link * | struct alias_link * | ||||
FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, | FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, | ||||
struct in_addr dst_addr, | struct in_addr dst_addr, | ||||
u_int16_t dst_call_id) | u_int16_t dst_call_id) | ||||
{ | { | ||||
u_int i; | u_int i; | ||||
struct alias_link *lnk; | struct alias_link *lnk; | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); | i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP); | ||||
LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) | LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) | ||||
if (lnk->link_type == LINK_PPTP && | if (lnk->link_type == LINK_PPTP && | ||||
lnk->src_addr.s_addr == src_addr.s_addr && | lnk->src_addr.s_addr == src_addr.s_addr && | ||||
lnk->dst_addr.s_addr == dst_addr.s_addr && | lnk->dst_addr.s_addr == dst_addr.s_addr && | ||||
lnk->dst_port == dst_call_id) | lnk->dst_port == dst_call_id) | ||||
break; | break; | ||||
CleanupLink(la, &lnk); | |||||
return (lnk); | return (lnk); | ||||
} | } | ||||
struct alias_link * | struct alias_link * | ||||
FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, | FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, | ||||
struct in_addr alias_addr, | struct in_addr alias_addr, | ||||
u_int16_t dst_call_id) | u_int16_t dst_call_id) | ||||
{ | { | ||||
u_int i; | u_int i; | ||||
struct alias_link *lnk; | struct alias_link *lnk; | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
i = StartPointIn(alias_addr, 0, LINK_PPTP); | i = StartPointIn(alias_addr, 0, LINK_PPTP); | ||||
LIST_FOREACH(lnk, &la->linkTableIn[i], list_in) | LIST_FOREACH(lnk, &la->linkTableIn[i], list_in) | ||||
if (lnk->link_type == LINK_PPTP && | if (lnk->link_type == LINK_PPTP && | ||||
lnk->dst_addr.s_addr == dst_addr.s_addr && | lnk->dst_addr.s_addr == dst_addr.s_addr && | ||||
lnk->alias_addr.s_addr == alias_addr.s_addr && | lnk->alias_addr.s_addr == alias_addr.s_addr && | ||||
lnk->dst_port == dst_call_id) | lnk->dst_port == dst_call_id) | ||||
break; | break; | ||||
CleanupLink(la, &lnk); | |||||
return (lnk); | return (lnk); | ||||
} | } | ||||
struct alias_link * | struct alias_link * | ||||
FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, | FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, | ||||
struct in_addr alias_addr, | struct in_addr alias_addr, | ||||
u_int16_t alias_call_id) | u_int16_t alias_call_id) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 410 Lines • ▼ Show 20 Lines | else | ||||
lnk->data.tcp->state.index = i; | lnk->data.tcp->state.index = i; | ||||
} | } | ||||
void | void | ||||
SetExpire(struct alias_link *lnk, int expire) | SetExpire(struct alias_link *lnk, int expire) | ||||
{ | { | ||||
if (expire == 0) { | if (expire == 0) { | ||||
lnk->flags &= ~LINK_PERMANENT; | lnk->flags &= ~LINK_PERMANENT; | ||||
DeleteLink(lnk); | DeleteLink(&lnk); | ||||
} else if (expire == -1) { | } else if (expire == -1) { | ||||
lnk->flags |= LINK_PERMANENT; | lnk->flags |= LINK_PERMANENT; | ||||
} else if (expire > 0) { | } else if (expire > 0) { | ||||
lnk->expire_time = expire; | lnk->expire_time = expire; | ||||
} else { | } else { | ||||
#ifdef LIBALIAS_DEBUG | #ifdef LIBALIAS_DEBUG | ||||
fprintf(stderr, "PacketAlias/SetExpire(): "); | fprintf(stderr, "PacketAlias/SetExpire(): "); | ||||
fprintf(stderr, "error in expire parameter\n"); | fprintf(stderr, "error in expire parameter\n"); | ||||
Show All 39 Lines | /* | ||||
every 60 seconds. | every 60 seconds. | ||||
(prototype in alias_local.h) | (prototype in alias_local.h) | ||||
*/ | */ | ||||
void | void | ||||
HouseKeeping(struct libalias *la) | HouseKeeping(struct libalias *la) | ||||
{ | { | ||||
int i, n; | struct alias_link * lnk = TAILQ_FIRST(&la->checkExpire); | ||||
#ifndef _KERNEL | static int packets = 0; | ||||
struct timeval tv; | |||||
#endif | |||||
/* | |||||
* User space time/gettimeofday/... is very expensive. | |||||
* Kernel space cache trashing is unnecessary. | |||||
* | |||||
* Reduce the amount of house keeping work substantially by | |||||
* sampling over the packets. | |||||
* | |||||
* TODO: choose a dynamic sampling interval. | |||||
*/ | |||||
if (packets++ < 1000) | |||||
return; | |||||
packets = 0; | |||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
/* | /* | ||||
* Save system time (seconds) in global variable timeStamp for use | * Save system time (seconds) in global variable LibAliasTime | ||||
* by other functions. This is done so as not to unnecessarily | * for use by other functions. This is done so as not to | ||||
* waste timeline by making system calls. | * unnecessarily waste timeline by making system calls. | ||||
*/ | */ | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
la->timeStamp = time_uptime; | LibAliasTime = time_uptime; | ||||
#else | #else | ||||
gettimeofday(&tv, NULL); | LibAliasTime = time(NULL); | ||||
la->timeStamp = tv.tv_sec; | |||||
#endif | #endif | ||||
CleanupLink(la, &lnk); | |||||
/* Compute number of spokes (output table link chains) to cover */ | |||||
n = LINK_TABLE_OUT_SIZE * (la->timeStamp - la->lastCleanupTime); | |||||
n /= ALIAS_CLEANUP_INTERVAL_SECS; | |||||
/* Handle different cases */ | |||||
if (n > 0) { | |||||
if (n > ALIAS_CLEANUP_MAX_SPOKES) | |||||
n = ALIAS_CLEANUP_MAX_SPOKES; | |||||
la->lastCleanupTime = la->timeStamp; | |||||
for (i = 0; i < n; i++) | |||||
IncrementalCleanup(la); | |||||
} else if (n < 0) { | |||||
#ifdef LIBALIAS_DEBUG | |||||
fprintf(stderr, "PacketAlias/HouseKeeping(): "); | |||||
fprintf(stderr, "something unexpected in time values\n"); | |||||
#endif | |||||
la->lastCleanupTime = la->timeStamp; | |||||
} | } | ||||
} | |||||
/* Init the log file and enable logging */ | /* Init the log file and enable logging */ | ||||
static int | static int | ||||
InitPacketAliasLog(struct libalias *la) | InitPacketAliasLog(struct libalias *la) | ||||
{ | { | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
if (~la->packetAliasMode & PKT_ALIAS_LOG) { | if (~la->packetAliasMode & PKT_ALIAS_LOG) { | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | |||||
/* This is a dangerous function to put in the API, | /* This is a dangerous function to put in the API, | ||||
because an invalid pointer can crash the program. */ | because an invalid pointer can crash the program. */ | ||||
void | void | ||||
LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) | LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) | ||||
{ | { | ||||
LIBALIAS_LOCK(la); | LIBALIAS_LOCK(la); | ||||
la->deleteAllLinks = 1; | la->deleteAllLinks = 1; | ||||
DeleteLink(lnk); | DeleteLink(&lnk); | ||||
la->deleteAllLinks = 0; | la->deleteAllLinks = 0; | ||||
LIBALIAS_UNLOCK(la); | LIBALIAS_UNLOCK(la); | ||||
} | } | ||||
void | void | ||||
LibAliasSetAddress(struct libalias *la, struct in_addr addr) | LibAliasSetAddress(struct libalias *la, struct in_addr addr) | ||||
{ | { | ||||
LIBALIAS_LOCK(la); | LIBALIAS_LOCK(la); | ||||
Show All 30 Lines | finishoff(void) | ||||
while (!LIST_EMPTY(&instancehead)) | while (!LIST_EMPTY(&instancehead)) | ||||
LibAliasUninit(LIST_FIRST(&instancehead)); | LibAliasUninit(LIST_FIRST(&instancehead)); | ||||
} | } | ||||
struct libalias * | struct libalias * | ||||
LibAliasInit(struct libalias *la) | LibAliasInit(struct libalias *la) | ||||
{ | { | ||||
int i; | int i; | ||||
#ifndef _KERNEL | |||||
struct timeval tv; | |||||
#endif | |||||
if (la == NULL) { | if (la == NULL) { | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
#undef malloc /* XXX: ugly */ | #undef malloc /* XXX: ugly */ | ||||
la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO); | la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO); | ||||
#else | #else | ||||
la = calloc(sizeof *la, 1); | la = calloc(sizeof *la, 1); | ||||
if (la == NULL) | if (la == NULL) | ||||
return (la); | return (la); | ||||
#endif | #endif | ||||
#ifndef _KERNEL | #ifndef _KERNEL | ||||
/* kernel cleans up on module unload */ | /* kernel cleans up on module unload */ | ||||
if (LIST_EMPTY(&instancehead)) | if (LIST_EMPTY(&instancehead)) | ||||
atexit(finishoff); | atexit(finishoff); | ||||
#endif | #endif | ||||
LIST_INSERT_HEAD(&instancehead, la, instancelist); | LIST_INSERT_HEAD(&instancehead, la, instancelist); | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
la->timeStamp = time_uptime; | LibAliasTime = time_uptime; | ||||
la->lastCleanupTime = time_uptime; | |||||
#else | #else | ||||
gettimeofday(&tv, NULL); | LibAliasTime = time(NULL); | ||||
la->timeStamp = tv.tv_sec; | |||||
la->lastCleanupTime = tv.tv_sec; | |||||
#endif | #endif | ||||
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) | for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) | ||||
LIST_INIT(&la->linkTableOut[i]); | LIST_INIT(&la->linkTableOut[i]); | ||||
for (i = 0; i < LINK_TABLE_IN_SIZE; i++) | for (i = 0; i < LINK_TABLE_IN_SIZE; i++) | ||||
LIST_INIT(&la->linkTableIn[i]); | LIST_INIT(&la->linkTableIn[i]); | ||||
TAILQ_INIT(&la->checkExpire); | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
AliasSctpInit(la); | AliasSctpInit(la); | ||||
#endif | #endif | ||||
LIBALIAS_LOCK_INIT(la); | LIBALIAS_LOCK_INIT(la); | ||||
LIBALIAS_LOCK(la); | LIBALIAS_LOCK(la); | ||||
} else { | } else { | ||||
LIBALIAS_LOCK(la); | LIBALIAS_LOCK(la); | ||||
la->deleteAllLinks = 1; | la->deleteAllLinks = 1; | ||||
▲ Show 20 Lines • Show All 387 Lines • Show Last 20 Lines |