Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/libalias/alias_db.c
Show First 20 Lines • Show All 568 Lines • ▼ Show 20 Lines | ReLink(struct alias_link *, | ||||
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); | ||||
static struct alias_link * | static struct alias_link * | ||||
FindLinkIn(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); | FindLinkIn(struct libalias *, struct in_addr, struct in_addr, u_short, u_short, int, int); | ||||
#define ALIAS_PORT_BASE 0x08000 | static u_short _RandomPort(struct libalias *la); | ||||
#define ALIAS_PORT_MASK 0x07fff | |||||
#define ALIAS_PORT_MASK_EVEN 0x07ffe | |||||
#define GET_NEW_PORT_MAX_ATTEMPTS 20 | #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_uniform(la->aliasPortLength); | |||||
return ntohs(port); | |||||
} | |||||
/* GetNewPort() allocates port numbers. Note that if a port number | /* GetNewPort() allocates port numbers. Note that if a port number | ||||
is already in use, that does not mean that it cannot be used by | is already in use, that does not mean that it cannot be used by | ||||
another link concurrently. This is because GetNewPort() looks for | another link concurrently. This is because GetNewPort() looks for | ||||
unused triplets: (dest addr, dest port, alias port). */ | unused triplets: (dest addr, dest port, alias port). */ | ||||
static int | static int | ||||
GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) | GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) | ||||
{ | { | ||||
int i; | int i; | ||||
int max_trials; | int max_trials; | ||||
u_short port_sys; | u_short port; | ||||
u_short port_net; | |||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
/* | /* | ||||
* Description of alias_port_param for GetNewPort(). When | * Description of alias_port_param for GetNewPort(). When | ||||
* this parameter is zero or positive, it precisely specifies | * this parameter is zero or positive, it precisely specifies | ||||
* the port number. GetNewPort() will return this number | * the port number. GetNewPort() will return this number | ||||
* without check that it is in use. | * 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 | * When this parameter is GET_ALIAS_PORT, it indicates to get | ||||
* a randomly selected port number. | * a randomly selected port number. | ||||
*/ | */ | ||||
if (alias_port_param == GET_ALIAS_PORT) { | if (alias_port_param >= 0 && alias_port_param < 0x10000) { | ||||
/* | |||||
* 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) { | |||||
lnk->alias_port = (u_short) alias_port_param; | lnk->alias_port = (u_short) alias_port_param; | ||||
return (0); | return (0); | ||||
} else { | } | ||||
if (alias_port_param != GET_ALIAS_PORT) { | |||||
#ifdef LIBALIAS_DEBUG | #ifdef LIBALIAS_DEBUG | ||||
fprintf(stderr, "PacketAlias/GetNewPort(): "); | fprintf(stderr, "PacketAlias/GetNewPort(): "); | ||||
fprintf(stderr, "input parameter error\n"); | fprintf(stderr, "input parameter error\n"); | ||||
#endif | #endif | ||||
return (-1); | 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 */ | /* Port number search */ | ||||
for (i = 0; i < max_trials; i++) { | for (i = 0; i < max_trials; i++, port = _RandomPort(la)) { | ||||
int go_ahead; | struct group_in *grp; | ||||
struct alias_link *search_result; | struct alias_link *search_result; | ||||
search_result = FindLinkIn(la, lnk->dst_addr, lnk->alias_addr, | grp = StartPointIn(la, lnk->alias_addr, port, lnk->link_type, 0); | ||||
lnk->dst_port, port_net, | if (grp == NULL) | ||||
lnk->link_type, 0); | 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) | if (search_result == NULL) | ||||
go_ahead = 1; | break; | ||||
else if (!(lnk->flags & LINK_PARTIALLY_SPECIFIED) | |||||
&& (search_result->flags & LINK_PARTIALLY_SPECIFIED)) | |||||
go_ahead = 1; | |||||
else | |||||
go_ahead = 0; | |||||
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 { | |||||
#endif | |||||
lnk->alias_port = port_net; | |||||
return (0); | |||||
#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 (i >= max_trials) { | |||||
#ifdef LIBALIAS_DEBUG | #ifdef LIBALIAS_DEBUG | ||||
fprintf(stderr, "PacketAlias/GetNewPort(): "); | fprintf(stderr, "PacketAlias/GetNewPort(): "); | ||||
fprintf(stderr, "could not find free port\n"); | fprintf(stderr, "could not find free port\n"); | ||||
#endif | #endif | ||||
return (-1); | |||||
} | |||||
#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, &lnk->sockfd, lnk->link_type)) { | |||||
return (-1); | return (-1); | ||||
} | } | ||||
} | |||||
#endif | |||||
lnk->alias_port = port; | |||||
return (0); | |||||
} | |||||
#ifndef NO_USE_SOCKETS | #ifndef NO_USE_SOCKETS | ||||
static u_short | static u_short | ||||
GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) | GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) | ||||
{ | { | ||||
int err; | int err; | ||||
int sock; | int sock; | ||||
struct sockaddr_in sock_addr; | struct sockaddr_in sock_addr; | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | FindNewPortGroup(struct libalias *la, | ||||
u_short src_port, | u_short src_port, | ||||
u_short dst_port, | u_short dst_port, | ||||
u_short port_count, | u_short port_count, | ||||
u_char proto, | u_char proto, | ||||
u_char align) | u_char align) | ||||
{ | { | ||||
int i, j; | int i, j; | ||||
int max_trials; | int max_trials; | ||||
u_short port_sys; | u_short port; | ||||
int link_type; | int link_type; | ||||
LIBALIAS_LOCK_ASSERT(la); | LIBALIAS_LOCK_ASSERT(la); | ||||
/* | /* | ||||
* Get link_type from protocol | * Get link_type from protocol | ||||
*/ | */ | ||||
switch (proto) { | switch (proto) { | ||||
Show All 15 Lines | FindNewPortGroup(struct libalias *la, | ||||
max_trials = GET_NEW_PORT_MAX_ATTEMPTS; | max_trials = GET_NEW_PORT_MAX_ATTEMPTS; | ||||
if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { | if (la->packetAliasMode & PKT_ALIAS_SAME_PORTS) { | ||||
/* | /* | ||||
* When the ALIAS_SAME_PORTS option is chosen, the first | * When the ALIAS_SAME_PORTS option is chosen, the first | ||||
* try will be the actual source port. If this is already | * try will be the actual source port. If this is already | ||||
* in use, the remainder of the trials will be random. | * in use, the remainder of the trials will be random. | ||||
*/ | */ | ||||
port_sys = ntohs(src_port); | port = src_port; | ||||
} else { | } else { | ||||
/* First trial and all subsequent are random. */ | port = _RandomPort(la); | ||||
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 number search */ | /* 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; | 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, | 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) | link_type, 0)) != NULL) | ||||
break; | break; | ||||
} | |||||
/* Found a good range, return base */ | /* Found a good range, return base */ | ||||
if (j == port_count) | if (j == port_count) | ||||
return (htons(port_sys)); | return (port); | ||||
/* 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; | |||||
} | } | ||||
#ifdef LIBALIAS_DEBUG | #ifdef LIBALIAS_DEBUG | ||||
fprintf(stderr, "PacketAlias/FindNewPortGroup(): "); | fprintf(stderr, "PacketAlias/FindNewPortGroup(): "); | ||||
fprintf(stderr, "could not find free port(s)\n"); | fprintf(stderr, "could not find free port(s)\n"); | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 1,714 Lines • ▼ Show 20 Lines | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
AliasSctpTerm(la); | AliasSctpTerm(la); | ||||
AliasSctpInit(la); | AliasSctpInit(la); | ||||
#endif | #endif | ||||
} | } | ||||
la->aliasAddress.s_addr = INADDR_ANY; | la->aliasAddress.s_addr = INADDR_ANY; | ||||
la->targetAddress.s_addr = INADDR_ANY; | la->targetAddress.s_addr = INADDR_ANY; | ||||
la->aliasPortLower = 0x8000; | |||||
la->aliasPortLength = 0x8000; | |||||
la->icmpLinkCount = 0; | la->icmpLinkCount = 0; | ||||
la->udpLinkCount = 0; | la->udpLinkCount = 0; | ||||
la->tcpLinkCount = 0; | la->tcpLinkCount = 0; | ||||
la->sctpLinkCount = 0; | la->sctpLinkCount = 0; | ||||
la->pptpLinkCount = 0; | la->pptpLinkCount = 0; | ||||
la->protoLinkCount = 0; | la->protoLinkCount = 0; | ||||
la->fragmentIdLinkCount = 0; | la->fragmentIdLinkCount = 0; | ||||
▲ Show 20 Lines • Show All 367 Lines • Show Last 20 Lines |