Page MenuHomeFreeBSD

D30283.diff
No OneTemporary

D30283.diff

Index: sys/netinet/libalias/alias_db.c
===================================================================
--- sys/netinet/libalias/alias_db.c
+++ sys/netinet/libalias/alias_db.c
@@ -220,9 +220,8 @@
#define NO_DEST_PORT 1
#define NO_SRC_PORT 1
-/* Dummy address used for FindLinkIn/Out() and AddLink().
- The value of this variable is never used. */
-static struct in_addr const NO_ADDR;
+/* Matches any/unknown address in FindLinkIn/Out() and AddLink(). */
+static struct in_addr const ANY_ADDR = { INADDR_ANY };
/* Data Structures
@@ -319,14 +318,23 @@
#define LINK_UNFIREWALLED 0x08
int timestamp; /* Time link was last accessed */
- int expire_time; /* Expire time for link */
#ifndef NO_USE_SOCKETS
int sockfd; /* socket descriptor */
#endif
/* Linked list of pointers for input and output lookup tables */
- LIST_ENTRY (alias_link) list_out;
- LIST_ENTRY (alias_link) list_in;
- TAILQ_ENTRY (alias_link) list_expire;
+ union {
+ struct {
+ LIST_ENTRY(alias_link) in;
+ LIST_ENTRY(alias_link) out;
+ } all;
+ struct {
+ LIST_ENTRY(alias_link) list;
+ } pptp;
+ };
+ struct {
+ TAILQ_ENTRY(alias_link) list;
+ int timeout; /* Expire time for link */
+ } expire;
/* Auxiliary data */
union {
char *frag_ptr;
@@ -379,12 +387,10 @@
*/
/* Local prototypes */
-static u_int StartPointIn(struct in_addr, u_short, int);
-
-static u_int
-StartPointOut(struct in_addr, struct in_addr,
- u_short, u_short, int);
-
+static struct group_in *
+StartPointIn(struct libalias *, struct in_addr, u_short, int, int);
+static u_int
+StartPointOut(struct in_addr, struct in_addr, u_short, u_short, int);
static int SeqDiff(u_long, u_long);
#ifndef NO_FW_PUNCH
@@ -402,19 +408,46 @@
void SctpShowAliasStats(struct libalias *la);
-static u_int
-StartPointIn(struct in_addr alias_addr,
- u_short alias_port,
- int link_type)
+#define INGUARD \
+ if (grp->alias_port != alias_port || \
+ grp->link_type != link_type || \
+ grp->alias_addr.s_addr != alias_addr.s_addr) \
+ continue;
+
+static struct group_in *
+StartPointIn(struct libalias *la,
+ struct in_addr alias_addr, u_short alias_port, int link_type,
+ int create)
{
u_int n;
+ struct group_in *grp, *tmp;
n = alias_addr.s_addr;
- if (link_type != LINK_PPTP)
- n += alias_port;
+ n += alias_port;
n += link_type;
- return (n % LINK_TABLE_IN_SIZE);
-}
+ n %= LINK_TABLE_IN_SIZE;
+
+ LIST_FOREACH_SAFE(grp, &la->groupTableIn[n], group_in, tmp) {
+ /* Auto cleanup */
+ if (LIST_EMPTY(&grp->full) && LIST_EMPTY(&grp->partial)) {
+ LIST_REMOVE(grp, group_in);
+ free(grp);
+ } else {
+ INGUARD;
+ return (grp);
+ }
+ }
+ if (!create || (grp = malloc(sizeof(*grp))) == NULL)
+ return (grp);
+ grp->alias_addr = alias_addr;
+ grp->alias_port = alias_port;
+ grp->link_type = link_type;
+ LIST_INIT(&grp->full);
+ LIST_INIT(&grp->partial);
+ LIST_INSERT_HEAD(&la->groupTableIn[n], grp, group_in);
+ return (grp);
+}
+#undef INGUARD
static u_int
StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
@@ -424,10 +457,8 @@
n = src_addr.s_addr;
n += dst_addr.s_addr;
- if (link_type != LINK_PPTP) {
- n += src_port;
- n += dst_port;
- }
+ n += src_port;
+ n += dst_port;
n += link_type;
return (n % LINK_TABLE_OUT_SIZE);
@@ -529,6 +560,8 @@
static void CleanupAliasData(struct libalias *);
static void CleanupLink(struct libalias *, struct alias_link **);
static void DeleteLink(struct alias_link **);
+static struct alias_link *
+UseLink(struct libalias *, struct alias_link *);
static struct alias_link *
ReLink(struct alias_link *,
@@ -541,12 +574,20 @@
static struct alias_link *
FindLinkIn(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int);
-#define ALIAS_PORT_BASE 0x08000
-#define ALIAS_PORT_MASK 0x07fff
-#define ALIAS_PORT_MASK_EVEN 0x07ffe
+static u_short _RandomPort(struct libalias *la);
+
#define GET_NEW_PORT_MAX_ATTEMPTS 20
-#define FIND_EVEN_ALIAS_BASE 1
+/* get random port in network byte order */
+static u_short
+_RandomPort(struct libalias *la) {
+ u_short port;
+
+ port = la->aliasPortLower +
+ (arc4random() % la->aliasPortLength);
+
+ return ntohs(port);
+}
/* GetNewPort() allocates port numbers. Note that if a port number
is already in use, that does not mean that it cannot be used by
@@ -558,8 +599,7 @@
{
int i;
int max_trials;
- u_short port_sys;
- u_short port_net;
+ u_short port;
LIBALIAS_LOCK_ASSERT(la);
/*
@@ -567,41 +607,18 @@
* this parameter is zero or positive, it precisely specifies
* the port number. GetNewPort() will return this number
* without check that it is in use.
-
+ *
+ * The aliasing port is automatically selected by one of
+ * two methods below:
+ *
* When this parameter is GET_ALIAS_PORT, it indicates to get
* a randomly selected port number.
*/
- if (alias_port_param == GET_ALIAS_PORT) {
- /*
- * The aliasing port is automatically selected by one of
- * two methods below:
- */
- max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
-
- if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) {
- /*
- * When the PKT_ALIAS_SAME_PORTS option is chosen,
- * the first try will be the actual source port. If
- * this is already in use, the remainder of the
- * trials will be random.
- */
- port_net = lnk->src_port;
- port_sys = ntohs(port_net);
- } else if (la->aliasPortLower) {
- /* First trial is a random port in the aliasing range. */
- port_sys = la->aliasPortLower +
- (arc4random() % la->aliasPortLength);
- port_net = htons(port_sys);
- } else {
- /* First trial and all subsequent are random. */
- port_sys = arc4random() & ALIAS_PORT_MASK;
- port_sys += ALIAS_PORT_BASE;
- port_net = htons(port_sys);
- }
- } else if (alias_port_param >= 0 && alias_port_param < 0x10000) {
+ if (alias_port_param >= 0 && alias_port_param < 0x10000) {
lnk->alias_port = (u_short) alias_port_param;
return (0);
- } else {
+ }
+ if (alias_port_param != GET_ALIAS_PORT) {
#ifdef LIBALIAS_DEBUG
fprintf(stderr, "PacketAlias/GetNewPort(): ");
fprintf(stderr, "input parameter error\n");
@@ -609,58 +626,57 @@
return (-1);
}
+ max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
+
+ /*
+ * When the PKT_ALIAS_SAME_PORTS option is chosen,
+ * the first try will be the actual source port. If
+ * this is already in use, the remainder of the
+ * trials will be random.
+ */
+ port = (la->packetAliasMode & PKT_ALIAS_SAME_PORTS)
+ ? lnk->src_port
+ : _RandomPort(la);
+
/* Port number search */
- for (i = 0; i < max_trials; i++) {
- int go_ahead;
+ for (i = 0; i < max_trials; i++, port = _RandomPort(la)) {
+ struct group_in *grp;
struct alias_link *search_result;
- search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr,
- lnk->dst_port, port_net,
- lnk->link_type, 0);
+ grp = StartPointIn(la, lnk->alias_addr, port, lnk->link_type, 0);
+ if (grp == NULL)
+ break;
+ LIST_FOREACH(search_result, &grp->full, all.in) {
+ if (lnk->dst_addr.s_addr == search_result->dst_addr.s_addr &&
+ lnk->dst_port == search_result->dst_port)
+ break; /* found match */
+ }
if (search_result == NULL)
- go_ahead = 1;
- else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED)
- && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
- go_ahead = 1;
- else
- go_ahead = 0;
+ break;
+ }
- if (go_ahead) {
-#ifndef NO_USE_SOCKETS
- if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS)
- && (lnk->flags & LINK_PARTIALLY_SPECIFIED)
- && ((lnk->link_type == LINK_TCP) ||
- (lnk->link_type == LINK_UDP))) {
- if (GetSocket(la, port_net, &lnk->sockfd, lnk->link_type)) {
- lnk->alias_port = port_net;
- return (0);
- }
- } else {
+ if (i >= max_trials) {
+#ifdef LIBALIAS_DEBUG
+ fprintf(stderr, "PacketAlias/GetNewPort(): ");
+ fprintf(stderr, "could not find free port\n");
#endif
- lnk->alias_port = port_net;
- return (0);
+ return (-1);
+ }
+
#ifndef NO_USE_SOCKETS
- }
-#endif
- }
- if (la->aliasPortLower) {
- port_sys = la->aliasPortLower +
- (arc4random() % la->aliasPortLength);
- port_net = htons(port_sys);
- } else {
- port_sys = arc4random() & ALIAS_PORT_MASK;
- port_sys += ALIAS_PORT_BASE;
- port_net = htons(port_sys);
+ if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS) &&
+ (lnk->flags & LINK_PARTIALLY_SPECIFIED) &&
+ ((lnk->link_type == LINK_TCP) ||
+ (lnk->link_type == LINK_UDP))) {
+ if (!GetSocket(la, port, &lnk->sockfd, lnk->link_type)) {
+ return (-1);
}
}
-
-#ifdef LIBALIAS_DEBUG
- fprintf(stderr, "PacketAlias/GetNewPort(): ");
- fprintf(stderr, "could not find free port\n");
#endif
+ lnk->alias_port = port;
- return (-1);
+ return (0);
}
#ifndef NO_USE_SOCKETS
@@ -727,7 +743,7 @@
{
int i, j;
int max_trials;
- u_short port_sys;
+ u_short port;
int link_type;
LIBALIAS_LOCK_ASSERT(la);
@@ -759,39 +775,31 @@
* try will be the actual source port. If this is already
* in use, the remainder of the trials will be random.
*/
- port_sys = ntohs(src_port);
+ port = src_port;
} else {
- /* First trial and all subsequent are random. */
- if (align == FIND_EVEN_ALIAS_BASE)
- port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
- else
- port_sys = arc4random() & ALIAS_PORT_MASK;
-
- port_sys += ALIAS_PORT_BASE;
+ port = _RandomPort(la);
}
/* Port number search */
- for (i = 0; i < max_trials; i++) {
+ for (i = 0; i < max_trials; i++, port = _RandomPort(la)) {
struct alias_link *search_result;
- for (j = 0; j < port_count; j++)
+ if (align)
+ port &= htons(0xfffe);
+
+ for (j = 0; j < port_count; j++) {
+ u_short port_j = ntohs(port) + j;
+
if ((search_result = FindLinkIn(la, dst_addr,
- alias_addr, dst_port, htons(port_sys + j),
+ alias_addr, dst_port, htons(port_j),
link_type, 0)) != NULL)
break;
+ }
/* Found a good range, return base */
if (j == port_count)
- return (htons(port_sys));
-
- /* Find a new base to try */
- if (align == FIND_EVEN_ALIAS_BASE)
- port_sys = arc4random() & ALIAS_PORT_MASK_EVEN;
- else
- port_sys = arc4random() & ALIAS_PORT_MASK;
-
- port_sys += ALIAS_PORT_BASE;
+ return (port);
}
#ifdef LIBALIAS_DEBUG
@@ -806,12 +814,23 @@
CleanupAliasData(struct libalias *la)
{
struct alias_link *lnk, *lnk_tmp;
+ u_int i;
LIBALIAS_LOCK_ASSERT(la);
/* permanent entries may stay */
- TAILQ_FOREACH_SAFE(lnk, &la->checkExpire, list_expire, lnk_tmp)
+ TAILQ_FOREACH_SAFE(lnk, &la->checkExpire, expire.list, lnk_tmp)
DeleteLink(&lnk);
+
+ for (i = 0; i < LINK_TABLE_IN_SIZE; i++) {
+ struct group_in *grp, *grp_tmp;
+
+ LIST_FOREACH_SAFE(grp, &la->groupTableIn[i], group_in, grp_tmp)
+ if (LIST_EMPTY(&grp->full) && LIST_EMPTY(&grp->partial)) {
+ LIST_REMOVE(grp, group_in);
+ free(grp);
+ }
+ }
}
static void
@@ -822,15 +841,24 @@
if (lnk == NULL || *lnk == NULL)
return;
- if (LibAliasTime - (*lnk)->timestamp > (*lnk)->expire_time) {
+ if (LibAliasTime - (*lnk)->timestamp > (*lnk)->expire.timeout) {
DeleteLink(lnk);
if ((*lnk) == NULL)
return;
}
/* move to end, swap may fail on a single entry list */
- TAILQ_REMOVE(&la->checkExpire, (*lnk), list_expire);
- TAILQ_INSERT_TAIL(&la->checkExpire, (*lnk), list_expire);
+ TAILQ_REMOVE(&la->checkExpire, (*lnk), expire.list);
+ TAILQ_INSERT_TAIL(&la->checkExpire, (*lnk), expire.list);
+}
+
+static struct alias_link *
+UseLink(struct libalias *la, struct alias_link *lnk)
+{
+ CleanupLink(la, &lnk);
+ if (lnk != NULL)
+ lnk->timestamp = LibAliasTime;
+ return (lnk);
}
static void
@@ -849,24 +877,32 @@
ClearFWHole(lnk);
#endif
- /* Free memory allocated for LSNAT server pool */
- if (lnk->server != NULL) {
- struct server *head, *curr, *next;
+ switch (lnk->link_type) {
+ case LINK_PPTP:
+ LIST_REMOVE(lnk, pptp.list);
+ break;
+ default:
+ /* Free memory allocated for LSNAT server pool */
+ if (lnk->server != NULL) {
+ struct server *head, *curr, *next;
+
+ head = curr = lnk->server;
+ do {
+ next = curr->next;
+ free(curr);
+ } while ((curr = next) != head);
+ } else {
+ /* Adjust output table pointers */
+ LIST_REMOVE(lnk, all.out);
+ }
- head = curr = lnk->server;
- do {
- next = curr->next;
- free(curr);
- } while ((curr = next) != head);
+ /* Adjust input table pointers */
+ LIST_REMOVE(lnk, all.in);
+ break;
}
- /* Adjust output table pointers */
- LIST_REMOVE(lnk, list_out);
-
- /* Adjust input table pointers */
- LIST_REMOVE(lnk, list_in);
/* remove from housekeeping */
- TAILQ_REMOVE(&la->checkExpire, lnk, list_expire);
+ TAILQ_REMOVE(&la->checkExpire, lnk, expire.list);
#ifndef NO_USE_SOCKETS
/* Close socket, if one has been allocated */
@@ -924,133 +960,150 @@
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
+
lnk = malloc(sizeof(struct alias_link));
- if (lnk != NULL) {
- /* Basic initialization */
- lnk->la = la;
- lnk->src_addr = src_addr;
- lnk->dst_addr = dst_addr;
- lnk->alias_addr = alias_addr;
- lnk->proxy_addr.s_addr = INADDR_ANY;
- lnk->src_port = src_port;
- lnk->dst_port = dst_port;
- lnk->proxy_port = 0;
- lnk->server = NULL;
- lnk->link_type = link_type;
+ if (lnk == NULL) {
+#ifdef LIBALIAS_DEBUG
+ fprintf(stderr, "PacketAlias/AddLink(): ");
+ fprintf(stderr, "malloc() call failed.\n");
+#endif
+ return (NULL);
+ }
+ /* Basic initialization */
+ lnk->la = la;
+ lnk->src_addr = src_addr;
+ lnk->dst_addr = dst_addr;
+ lnk->alias_addr = alias_addr;
+ lnk->proxy_addr.s_addr = INADDR_ANY;
+ lnk->src_port = src_port;
+ lnk->dst_port = dst_port;
+ lnk->proxy_port = 0;
+ lnk->server = NULL;
+ lnk->link_type = link_type;
#ifndef NO_USE_SOCKETS
- lnk->sockfd = -1;
+ lnk->sockfd = -1;
#endif
- lnk->flags = 0;
- lnk->pflags = 0;
- lnk->timestamp = LibAliasTime;
+ lnk->flags = 0;
+ lnk->pflags = 0;
+ lnk->timestamp = LibAliasTime;
- /* Expiration time */
- switch (link_type) {
- case LINK_ICMP:
- lnk->expire_time = ICMP_EXPIRE_TIME;
- break;
- case LINK_UDP:
- lnk->expire_time = UDP_EXPIRE_TIME;
- break;
- case LINK_TCP:
- lnk->expire_time = TCP_EXPIRE_INITIAL;
- break;
- case LINK_PPTP:
- lnk->flags |= LINK_PERMANENT; /* no timeout. */
- break;
- case LINK_FRAGMENT_ID:
- lnk->expire_time = FRAGMENT_ID_EXPIRE_TIME;
- break;
- case LINK_FRAGMENT_PTR:
- lnk->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
- break;
- case LINK_ADDR:
- break;
- default:
- lnk->expire_time = PROTO_EXPIRE_TIME;
- break;
- }
+ /* Expiration time */
+ switch (link_type) {
+ case LINK_ICMP:
+ lnk->expire.timeout = ICMP_EXPIRE_TIME;
+ break;
+ case LINK_UDP:
+ lnk->expire.timeout = UDP_EXPIRE_TIME;
+ break;
+ case LINK_TCP:
+ lnk->expire.timeout = TCP_EXPIRE_INITIAL;
+ break;
+ case LINK_FRAGMENT_ID:
+ lnk->expire.timeout = FRAGMENT_ID_EXPIRE_TIME;
+ break;
+ case LINK_FRAGMENT_PTR:
+ lnk->expire.timeout = FRAGMENT_PTR_EXPIRE_TIME;
+ break;
+ case LINK_ADDR:
+ break;
+ default:
+ lnk->expire.timeout = PROTO_EXPIRE_TIME;
+ break;
+ }
+
+ /* Determine alias flags */
+ if (dst_addr.s_addr == INADDR_ANY)
+ lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
+ if (dst_port == 0)
+ lnk->flags |= LINK_UNKNOWN_DEST_PORT;
- /* Determine alias flags */
- if (dst_addr.s_addr == INADDR_ANY)
- lnk->flags |= LINK_UNKNOWN_DEST_ADDR;
- if (dst_port == 0)
- lnk->flags |= LINK_UNKNOWN_DEST_PORT;
+ /* Determine alias port */
+ if (GetNewPort(la, lnk, alias_port_param) != 0) {
+ free(lnk);
+ return (NULL);
+ }
+ /* Link-type dependent initialization */
+ switch (link_type) {
+ case LINK_ICMP:
+ la->icmpLinkCount++;
+ break;
+ case LINK_UDP:
+ la->udpLinkCount++;
+ break;
+ case LINK_TCP: {
+ struct tcp_dat *aux_tcp;
+ int i;
- /* Determine alias port */
- if (GetNewPort(la, lnk, alias_port_param) != 0) {
+ aux_tcp = malloc(sizeof(struct tcp_dat));
+ if (aux_tcp != NULL) {
+#ifdef LIBALIAS_DEBUG
+ fprintf(stderr, "PacketAlias/AddLink: ");
+ fprintf(stderr, " cannot allocate auxiliary TCP data\n");
+#endif
free(lnk);
return (NULL);
}
- /* Link-type dependent initialization */
- switch (link_type) {
- struct tcp_dat *aux_tcp;
- case LINK_ICMP:
- la->icmpLinkCount++;
- break;
- case LINK_UDP:
- la->udpLinkCount++;
- break;
- case LINK_TCP:
- aux_tcp = malloc(sizeof(struct tcp_dat));
- if (aux_tcp != NULL) {
- int i;
-
- la->tcpLinkCount++;
- aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
- aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
- aux_tcp->state.index = 0;
- aux_tcp->state.ack_modified = 0;
- for (i = 0; i < N_LINK_TCP_DATA; i++)
- aux_tcp->ack[i].active = 0;
- aux_tcp->fwhole = -1;
- lnk->data.tcp = aux_tcp;
- } else {
-#ifdef LIBALIAS_DEBUG
- fprintf(stderr, "PacketAlias/AddLink: ");
- fprintf(stderr, " cannot allocate auxiliary TCP data\n");
-#endif
- free(lnk);
- return (NULL);
- }
- break;
- case LINK_PPTP:
- la->pptpLinkCount++;
- break;
- case LINK_FRAGMENT_ID:
- la->fragmentIdLinkCount++;
- break;
- case LINK_FRAGMENT_PTR:
- la->fragmentPtrLinkCount++;
- break;
- case LINK_ADDR:
- break;
- default:
- la->protoLinkCount++;
- break;
+ la->tcpLinkCount++;
+ aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
+ aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
+ aux_tcp->state.index = 0;
+ aux_tcp->state.ack_modified = 0;
+ for (i = 0; i < N_LINK_TCP_DATA; i++)
+ aux_tcp->ack[i].active = 0;
+ aux_tcp->fwhole = -1;
+ lnk->data.tcp = aux_tcp;
+ }
+ break;
+ case LINK_PPTP:
+ la->pptpLinkCount++;
+ break;
+ case LINK_FRAGMENT_ID:
+ la->fragmentIdLinkCount++;
+ break;
+ case LINK_FRAGMENT_PTR:
+ la->fragmentPtrLinkCount++;
+ break;
+ case LINK_ADDR:
+ break;
+ default:
+ la->protoLinkCount++;
+ break;
+ }
+
+ switch (link_type) {
+ case LINK_PPTP:
+ LIST_INSERT_HEAD(&la->pptpList, lnk, pptp.list);
+ break;
+ default: {
+ struct group_in *grp;
+
+ grp = StartPointIn(la, alias_addr, lnk->alias_port, link_type, 1);
+ if (grp == NULL) {
+ free(lnk);
+ return (NULL);
}
/* Set up pointers for output lookup table */
start_point = StartPointOut(src_addr, dst_addr,
src_port, dst_port, link_type);
- LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, list_out);
+ LIST_INSERT_HEAD(&la->linkTableOut[start_point], lnk, all.out);
/* Set up pointers for input lookup table */
- start_point = StartPointIn(alias_addr, lnk->alias_port, link_type);
- 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 {
-#ifdef LIBALIAS_DEBUG
- fprintf(stderr, "PacketAlias/AddLink(): ");
- fprintf(stderr, "malloc() call failed.\n");
-#endif
+ if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
+ LIST_INSERT_HEAD(&grp->partial, lnk, all.in);
+ else
+ LIST_INSERT_HEAD(&grp->full, lnk, all.in);
}
- if (la->packetAliasMode & PKT_ALIAS_LOG) {
- ShowAliasStats(la);
+ break;
}
+
+ /* Include the element into the housekeeping list */
+ TAILQ_INSERT_TAIL(&la->checkExpire, lnk, expire.list);
+
+ if (la->packetAliasMode & PKT_ALIAS_LOG)
+ ShowAliasStats(la);
+
return (lnk);
}
@@ -1086,6 +1139,35 @@
return (new_lnk);
}
+
+#define OUTGUARD \
+ if (lnk->src_port != src_port || \
+ lnk->src_addr.s_addr != src_addr.s_addr || \
+ lnk->dst_addr.s_addr != dst_addr.s_addr || \
+ lnk->dst_port != dst_port || \
+ lnk->link_type != link_type) \
+ continue;
+
+static struct alias_link *
+_SearchLinkOut(struct libalias *la, struct in_addr src_addr,
+ struct in_addr dst_addr,
+ u_short src_port,
+ u_short dst_port,
+ int link_type) {
+ u_int i;
+ struct alias_link *lnk;
+
+ i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
+ LIST_FOREACH(lnk, &la->linkTableOut[i], all.out) {
+ OUTGUARD;
+ return (UseLink(la, lnk));
+ }
+
+ return (NULL);
+}
+
+#undef OUTGUARD
+
static struct alias_link *
_FindLinkOut(struct libalias *la, struct in_addr src_addr,
struct in_addr dst_addr,
@@ -1094,45 +1176,31 @@
int link_type,
int replace_partial_links)
{
- u_int i;
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
- LIST_FOREACH(lnk, &la->linkTableOut[i], list_out) {
- if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
- lnk->src_addr.s_addr == src_addr.s_addr &&
- lnk->src_port == src_port &&
- lnk->dst_port == dst_port &&
- lnk->link_type == link_type &&
- lnk->server == NULL)
- break;
- }
-
- CleanupLink(la, &lnk);
- if (lnk != NULL)
- lnk->timestamp = LibAliasTime;
+ lnk = _SearchLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type);
+ if (lnk != NULL || !replace_partial_links)
+ return (lnk);
/* Search for partially specified links. */
- if (lnk == NULL && replace_partial_links) {
- if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
- lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, 0,
- link_type, 0);
- if (lnk == NULL)
- lnk = _FindLinkOut(la, src_addr, NO_ADDR, src_port,
- dst_port, link_type, 0);
- }
- if (lnk == NULL &&
- (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
- lnk = _FindLinkOut(la, src_addr, NO_ADDR, src_port, 0,
- link_type, 0);
- }
- if (lnk != NULL) {
- lnk = ReLink(lnk,
- src_addr, dst_addr, lnk->alias_addr,
- src_port, dst_port, lnk->alias_port,
- link_type);
- }
+ if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
+ lnk = _SearchLinkOut(la, src_addr, dst_addr, src_port, 0,
+ link_type);
+ if (lnk == NULL)
+ lnk = _SearchLinkOut(la, src_addr, ANY_ADDR, src_port,
+ dst_port, link_type);
+ }
+ if (lnk == NULL &&
+ (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
+ lnk = _SearchLinkOut(la, src_addr, ANY_ADDR, src_port, 0,
+ link_type);
+ }
+ if (lnk != NULL) {
+ lnk = ReLink(lnk,
+ src_addr, dst_addr, lnk->alias_addr,
+ src_port, dst_port, lnk->alias_port,
+ link_type);
}
return (lnk);
}
@@ -1160,7 +1228,7 @@
*/
if (la->aliasAddress.s_addr != INADDR_ANY &&
src_addr.s_addr == la->aliasAddress.s_addr) {
- lnk = _FindLinkOut(la, NO_ADDR, dst_addr, src_port, dst_port,
+ lnk = _FindLinkOut(la, ANY_ADDR, dst_addr, src_port, dst_port,
link_type, replace_partial_links);
}
}
@@ -1176,16 +1244,16 @@
int replace_partial_links)
{
int flags_in;
- u_int start_point;
+ struct group_in *grp;
struct alias_link *lnk;
- struct alias_link *lnk_fully_specified;
struct alias_link *lnk_unknown_all;
struct alias_link *lnk_unknown_dst_addr;
struct alias_link *lnk_unknown_dst_port;
+ struct in_addr src_addr;
+ u_short src_port;
LIBALIAS_LOCK_ASSERT(la);
/* Initialize pointers */
- lnk_fully_specified = NULL;
lnk_unknown_all = NULL;
lnk_unknown_dst_addr = NULL;
lnk_unknown_dst_port = NULL;
@@ -1199,79 +1267,78 @@
flags_in |= LINK_UNKNOWN_DEST_PORT;
/* Search loop */
- start_point = StartPointIn(alias_addr, alias_port, link_type);
- LIST_FOREACH(lnk, &la->linkTableIn[start_point], list_in) {
- int flags;
-
- flags = flags_in | lnk->flags;
- if (!(flags & LINK_PARTIALLY_SPECIFIED)) {
- if (lnk->alias_addr.s_addr == alias_addr.s_addr
- && lnk->alias_port == alias_port
- && lnk->dst_addr.s_addr == dst_addr.s_addr
- && lnk->dst_port == dst_port
- && lnk->link_type == link_type) {
- lnk_fully_specified = lnk;
+ grp = StartPointIn(la, alias_addr, alias_port, link_type, 0);
+ if (grp == NULL)
+ return (NULL);
+
+ switch (flags_in) {
+ case 0:
+ LIST_FOREACH(lnk, &grp->full, all.in) {
+ if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
+ lnk->dst_port == dst_port)
+ return (UseLink(la, lnk));
+ }
+ break;
+ case LINK_UNKNOWN_DEST_PORT:
+ LIST_FOREACH(lnk, &grp->full, all.in) {
+ if(lnk->dst_addr.s_addr == dst_addr.s_addr) {
+ lnk_unknown_dst_port = lnk;
break;
}
- } else if ((flags & LINK_UNKNOWN_DEST_ADDR)
- && (flags & LINK_UNKNOWN_DEST_PORT)) {
- if (lnk->alias_addr.s_addr == alias_addr.s_addr
- && lnk->alias_port == alias_port
- && lnk->link_type == link_type) {
- if (lnk_unknown_all == NULL)
- lnk_unknown_all = lnk;
- }
- } else if (flags & LINK_UNKNOWN_DEST_ADDR) {
- if (lnk->alias_addr.s_addr == alias_addr.s_addr
- && lnk->alias_port == alias_port
- && lnk->link_type == link_type
- && lnk->dst_port == dst_port) {
- if (lnk_unknown_dst_addr == NULL)
- lnk_unknown_dst_addr = lnk;
+ }
+ break;
+ case LINK_UNKNOWN_DEST_ADDR:
+ LIST_FOREACH(lnk, &grp->full, all.in) {
+ if(lnk->dst_port == dst_port) {
+ lnk_unknown_dst_addr = lnk;
+ break;
}
- } else if (flags & LINK_UNKNOWN_DEST_PORT) {
- if (lnk->alias_addr.s_addr == alias_addr.s_addr
- && lnk->alias_port == alias_port
- && lnk->link_type == link_type
- && lnk->dst_addr.s_addr == dst_addr.s_addr) {
- if (lnk_unknown_dst_port == NULL)
- lnk_unknown_dst_port = lnk;
+ }
+ break;
+ case LINK_PARTIALLY_SPECIFIED:
+ lnk_unknown_all = LIST_FIRST(&grp->full);
+ break;
+ }
+
+ if (lnk_unknown_dst_port == NULL) {
+ LIST_FOREACH(lnk, &grp->partial, all.in) {
+ int flags = (flags_in | lnk->flags) & LINK_PARTIALLY_SPECIFIED;
+
+ if (flags == LINK_PARTIALLY_SPECIFIED &&
+ lnk_unknown_all == NULL)
+ lnk_unknown_all = lnk;
+ if (flags == LINK_UNKNOWN_DEST_ADDR &&
+ lnk->dst_port == dst_port &&
+ lnk_unknown_dst_addr == NULL)
+ lnk_unknown_dst_addr = lnk;
+ if (flags == LINK_UNKNOWN_DEST_PORT &&
+ lnk->dst_addr.s_addr == dst_addr.s_addr) {
+ lnk_unknown_dst_port = lnk;
+ break;
}
}
}
- CleanupLink(la, &lnk_fully_specified);
- if (lnk_fully_specified != NULL) {
- lnk_fully_specified->timestamp = LibAliasTime;
- lnk = lnk_fully_specified;
- } else if (lnk_unknown_dst_port != NULL)
- lnk = lnk_unknown_dst_port;
- else if (lnk_unknown_dst_addr != NULL)
- lnk = lnk_unknown_dst_addr;
- else if (lnk_unknown_all != NULL)
- lnk = lnk_unknown_all;
- else
- return (NULL);
+ lnk = (lnk_unknown_dst_port != NULL) ? lnk_unknown_dst_port
+ : (lnk_unknown_dst_addr != NULL) ? lnk_unknown_dst_addr
+ : lnk_unknown_all;
- if (replace_partial_links &&
- (lnk->flags & LINK_PARTIALLY_SPECIFIED || lnk->server != NULL)) {
- struct in_addr src_addr;
- u_short src_port;
+ if (lnk == NULL || !replace_partial_links)
+ return (lnk);
- if (lnk->server != NULL) { /* LSNAT link */
- src_addr = lnk->server->addr;
- src_port = lnk->server->port;
- lnk->server = lnk->server->next;
- } else {
- src_addr = lnk->src_addr;
- src_port = lnk->src_port;
- }
+ if (lnk->server != NULL) { /* LSNAT link */
+ src_addr = lnk->server->addr;
+ src_port = lnk->server->port;
+ lnk->server = lnk->server->next;
+ } else {
+ src_addr = lnk->src_addr;
+ src_port = lnk->src_port;
+ }
- if (link_type == LINK_SCTP) {
- lnk->src_addr = src_addr;
- lnk->src_port = src_port;
- return (lnk);
- }
+ if (link_type == LINK_SCTP) {
+ lnk->src_addr = src_addr;
+ lnk->src_port = src_port;
+ } else {
lnk = ReLink(lnk,
src_addr, dst_addr, alias_addr,
src_port, dst_port, alias_port,
@@ -1303,7 +1370,7 @@
*/
if (la->aliasAddress.s_addr != INADDR_ANY &&
alias_addr.s_addr == la->aliasAddress.s_addr) {
- lnk = _FindLinkIn(la, dst_addr, NO_ADDR, dst_port, alias_port,
+ lnk = _FindLinkIn(la, dst_addr, ANY_ADDR, dst_port, alias_port,
link_type, replace_partial_links);
}
}
@@ -1385,7 +1452,7 @@
LINK_FRAGMENT_ID, 0);
if (lnk == NULL) {
- lnk = AddLink(la, NO_ADDR, dst_addr, alias_addr,
+ lnk = AddLink(la, ANY_ADDR, dst_addr, alias_addr,
NO_SRC_PORT, NO_DEST_PORT, ip_id,
LINK_FRAGMENT_ID);
}
@@ -1408,7 +1475,7 @@
u_short ip_id)
{
LIBALIAS_LOCK_ASSERT(la);
- return AddLink(la, NO_ADDR, dst_addr, NO_ADDR,
+ return AddLink(la, ANY_ADDR, dst_addr, ANY_ADDR,
NO_SRC_PORT, NO_DEST_PORT, ip_id,
LINK_FRAGMENT_PTR);
}
@@ -1418,7 +1485,7 @@
u_short ip_id)
{
LIBALIAS_LOCK_ASSERT(la);
- return FindLinkIn(la, dst_addr, NO_ADDR,
+ return FindLinkIn(la, dst_addr, ANY_ADDR,
NO_DEST_PORT, ip_id,
LINK_FRAGMENT_PTR, 0);
}
@@ -1566,20 +1633,16 @@
struct in_addr dst_addr,
u_int16_t src_call_id)
{
- u_int i;
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
- LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
- if (lnk->link_type == LINK_PPTP &&
- lnk->src_addr.s_addr == src_addr.s_addr &&
+ LIST_FOREACH(lnk, &la->pptpList, pptp.list)
+ if (lnk->src_addr.s_addr == src_addr.s_addr &&
lnk->dst_addr.s_addr == dst_addr.s_addr &&
lnk->src_port == src_call_id)
break;
- CleanupLink(la, &lnk);
- return (lnk);
+ return (UseLink(la, lnk));
}
struct alias_link *
@@ -1587,20 +1650,16 @@
struct in_addr dst_addr,
u_int16_t dst_call_id)
{
- u_int i;
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- i = StartPointOut(src_addr, dst_addr, 0, 0, LINK_PPTP);
- LIST_FOREACH(lnk, &la->linkTableOut[i], list_out)
- if (lnk->link_type == LINK_PPTP &&
- lnk->src_addr.s_addr == src_addr.s_addr &&
+ LIST_FOREACH(lnk, &la->pptpList, pptp.list)
+ if (lnk->src_addr.s_addr == src_addr.s_addr &&
lnk->dst_addr.s_addr == dst_addr.s_addr &&
lnk->dst_port == dst_call_id)
break;
- CleanupLink(la, &lnk);
- return (lnk);
+ return (UseLink(la, lnk));
}
struct alias_link *
@@ -1608,20 +1667,17 @@
struct in_addr alias_addr,
u_int16_t dst_call_id)
{
- u_int i;
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- i = StartPointIn(alias_addr, 0, LINK_PPTP);
- LIST_FOREACH(lnk, &la->linkTableIn[i], list_in)
- if (lnk->link_type == LINK_PPTP &&
+
+ LIST_FOREACH(lnk, &la->pptpList, pptp.list)
+ if (lnk->dst_port == dst_call_id &&
lnk->dst_addr.s_addr == dst_addr.s_addr &&
- lnk->alias_addr.s_addr == alias_addr.s_addr &&
- lnk->dst_port == dst_call_id)
+ lnk->alias_addr.s_addr == alias_addr.s_addr)
break;
- CleanupLink(la, &lnk);
- return (lnk);
+ return (UseLink(la, lnk));
}
struct alias_link *
@@ -1632,9 +1688,11 @@
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- lnk = FindLinkIn(la, dst_addr, alias_addr,
- 0 /* any */ , alias_call_id,
- LINK_PPTP, 0);
+ LIST_FOREACH(lnk, &la->pptpList, pptp.list)
+ if (lnk->alias_port == alias_call_id &&
+ lnk->dst_addr.s_addr == dst_addr.s_addr &&
+ lnk->alias_addr.s_addr == alias_addr.s_addr)
+ break;
return (lnk);
}
@@ -1681,7 +1739,7 @@
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- lnk = FindLinkIn(la, NO_ADDR, alias_addr,
+ lnk = FindLinkIn(la, ANY_ADDR, alias_addr,
0, 0, LINK_ADDR, 0);
if (lnk == NULL) {
la->newDefaultLink = 1;
@@ -1713,7 +1771,7 @@
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
- lnk = FindLinkOut(la, original_addr, NO_ADDR,
+ lnk = FindLinkOut(la, original_addr, ANY_ADDR,
0, 0, LINK_ADDR, 0);
if (lnk == NULL) {
return (la->aliasAddress.s_addr != INADDR_ANY) ?
@@ -1772,13 +1830,13 @@
switch (state) {
case ALIAS_TCP_STATE_DISCONNECTED:
if (lnk->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED)
- lnk->expire_time = TCP_EXPIRE_DEAD;
+ lnk->expire.timeout = TCP_EXPIRE_DEAD;
else
- lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
+ lnk->expire.timeout = TCP_EXPIRE_SINGLEDEAD;
break;
case ALIAS_TCP_STATE_CONNECTED:
if (lnk->data.tcp->state.out == ALIAS_TCP_STATE_CONNECTED)
- lnk->expire_time = TCP_EXPIRE_CONNECTED;
+ lnk->expire.timeout = TCP_EXPIRE_CONNECTED;
break;
default:
#ifdef _KERNEL
@@ -1797,13 +1855,13 @@
switch (state) {
case ALIAS_TCP_STATE_DISCONNECTED:
if (lnk->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED)
- lnk->expire_time = TCP_EXPIRE_DEAD;
+ lnk->expire.timeout = TCP_EXPIRE_DEAD;
else
- lnk->expire_time = TCP_EXPIRE_SINGLEDEAD;
+ lnk->expire.timeout = TCP_EXPIRE_SINGLEDEAD;
break;
case ALIAS_TCP_STATE_CONNECTED:
if (lnk->data.tcp->state.in == ALIAS_TCP_STATE_CONNECTED)
- lnk->expire_time = TCP_EXPIRE_CONNECTED;
+ lnk->expire.timeout = TCP_EXPIRE_CONNECTED;
break;
default:
#ifdef _KERNEL
@@ -2052,7 +2110,7 @@
} else if (expire == -1) {
lnk->flags |= LINK_PERMANENT;
} else if (expire > 0) {
- lnk->expire_time = expire;
+ lnk->expire.timeout = expire;
} else {
#ifdef LIBALIAS_DEBUG
fprintf(stderr, "PacketAlias/SetExpire(): ");
@@ -2256,7 +2314,14 @@
LIBALIAS_LOCK(la);
(void)la;
- server = malloc(sizeof(struct server));
+ switch (lnk->link_type) {
+ case LINK_PPTP:
+ server = NULL;
+ break;
+ default:
+ server = malloc(sizeof(struct server));
+ break;
+ }
if (server != NULL) {
struct server *head;
@@ -2265,9 +2330,11 @@
server->port = port;
head = lnk->server;
- if (head == NULL)
+ if (head == NULL) {
server->next = server;
- else {
+ /* not usable for outgoing connections */
+ LIST_REMOVE(lnk, all.out);
+ } else {
struct server *s;
for (s = head; s->next != head; s = s->next)
@@ -2321,7 +2388,7 @@
struct alias_link *lnk;
LIBALIAS_LOCK(la);
- lnk = AddLink(la, src_addr, NO_ADDR, alias_addr,
+ lnk = AddLink(la, src_addr, ANY_ADDR, alias_addr,
0, 0, 0,
LINK_ADDR);
@@ -2439,7 +2506,8 @@
for (i = 0; i < LINK_TABLE_OUT_SIZE; i++)
LIST_INIT(&la->linkTableOut[i]);
for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
- LIST_INIT(&la->linkTableIn[i]);
+ LIST_INIT(&la->groupTableIn[i]);
+ LIST_INIT(&la->pptpList);
TAILQ_INIT(&la->checkExpire);
#ifdef _KERNEL
AliasSctpInit(la);
@@ -2459,6 +2527,8 @@
la->aliasAddress.s_addr = INADDR_ANY;
la->targetAddress.s_addr = INADDR_ANY;
+ la->aliasPortLower = 0x8000;
+ la->aliasPortLength = 0x8000;
la->icmpLinkCount = 0;
la->udpLinkCount = 0;
Index: sys/netinet/libalias/alias_local.h
===================================================================
--- sys/netinet/libalias/alias_local.h
+++ sys/netinet/libalias/alias_local.h
@@ -80,6 +80,14 @@
struct proxy_entry;
+struct group_in {
+ struct in_addr alias_addr;
+ u_short alias_port;
+ int link_type;
+ LIST_ENTRY(group_in) group_in;
+ LIST_HEAD(, alias_link) full, partial;
+};
+
struct libalias {
LIST_ENTRY(libalias) instancelist;
/* Mode flags documented in alias.h */
@@ -92,8 +100,9 @@
/* Lookup table of pointers to chains of link records.
* Each link record is doubly indexed into input and
* output lookup tables. */
- LIST_HEAD (, alias_link) linkTableOut[LINK_TABLE_OUT_SIZE];
- LIST_HEAD (, alias_link) linkTableIn[LINK_TABLE_IN_SIZE];
+ LIST_HEAD (, alias_link) linkTableOut[LINK_TABLE_OUT_SIZE];
+ LIST_HEAD (, group_in) groupTableIn[LINK_TABLE_IN_SIZE];
+ LIST_HEAD (, alias_link) pptpList;
/* HouseKeeping */
TAILQ_HEAD (, alias_link) checkExpire;
/* Link statistics */

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 10, 5:35 PM (14 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15744555
Default Alt Text
D30283.diff (34 KB)

Event Timeline