PERFORCE change 108766 for review
Paolo Pisati
piso at FreeBSD.org
Mon Oct 30 17:49:37 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=108766
Change 108766 by piso at piso_newluxor on 2006/10/30 17:49:03
Libalias locking: embed a sleep mtx per struct libalias instance,
and grab/drop it at the entrance/exit of every public LibAlias*
function.
Not tested yet...
Affected files ...
.. //depot/projects/soc2005/libalias/sys/netinet/libalias/alias.c#19 edit
.. //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_db.c#13 edit
.. //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_local.h#8 edit
.. //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_proxy.c#9 edit
.. //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_util.c#4 edit
Differences ...
==== //depot/projects/soc2005/libalias/sys/netinet/libalias/alias.c#19 (text+ko) ====
@@ -1138,6 +1138,7 @@
struct alias_link *lnk;
struct ip *pip;
+ LIBALIAS_LOCK(la);
pip = (struct ip *)ptr;
lnk = AddFragmentPtrLink(la, pip->ip_src, pip->ip_id);
iresult = PKT_ALIAS_ERROR;
@@ -1145,6 +1146,7 @@
SetFragmentPtr(lnk, ptr);
iresult = PKT_ALIAS_OK;
}
+ LIBALIAS_UNLOCK(la);
return (iresult);
}
@@ -1156,17 +1158,18 @@
char *fptr;
struct ip *pip;
+ LIBALIAS_LOCK(la);
pip = (struct ip *)ptr;
lnk = FindFragmentPtr(la, pip->ip_src, pip->ip_id);
if (lnk != NULL) {
GetFragmentPtr(lnk, &fptr);
SetFragmentPtr(lnk, NULL);
SetExpire(lnk, 0); /* Deletes link */
+ } else
+ fptr = NULL;
- return (fptr);
- } else {
- return (NULL);
- }
+ LIBALIAS_UNLOCK(la);
+ return (fptr);
}
@@ -1181,6 +1184,7 @@
struct ip *pip;
struct ip *fpip;
+ LIBALIAS_LOCK(la);
(void)la;
pip = (struct ip *)ptr;
fpip = (struct ip *)ptr_fragment;
@@ -1188,6 +1192,7 @@
DifferentialChecksum(&fpip->ip_sum,
&pip->ip_dst, &fpip->ip_dst, 2);
fpip->ip_dst = pip->ip_dst;
+ LIBALIAS_UNLOCK(la);
}
@@ -1198,11 +1203,12 @@
struct ip *pip;
int iresult;
+ LIBALIAS_LOCK(la);
if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
iresult = LibAliasOut(la, ptr, maxpacketsize);
la->packetAliasMode |= PKT_ALIAS_REVERSE;
- return (iresult);
+ goto getout;
}
HouseKeeping(la);
ClearCheckNewLink(la);
@@ -1211,8 +1217,10 @@
/* Defense against mangled packets */
if (ntohs(pip->ip_len) > maxpacketsize
- || (pip->ip_hl << 2) > maxpacketsize)
- return (PKT_ALIAS_IGNORED);
+ || (pip->ip_hl << 2) > maxpacketsize) {
+ iresult = PKT_ALIAS_IGNORED;
+ goto getout;
+ }
iresult = PKT_ALIAS_IGNORED;
if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
@@ -1266,6 +1274,8 @@
iresult = FragmentIn(la, pip);
}
+getout:
+ LIBALIAS_UNLOCK(la);
return (iresult);
}
@@ -1305,11 +1315,12 @@
struct in_addr addr_save;
struct ip *pip;
+ LIBALIAS_LOCK(la);
if (la->packetAliasMode & PKT_ALIAS_REVERSE) {
la->packetAliasMode &= ~PKT_ALIAS_REVERSE;
iresult = LibAliasIn(la, ptr, maxpacketsize);
la->packetAliasMode |= PKT_ALIAS_REVERSE;
- return (iresult);
+ goto getout;
}
HouseKeeping(la);
ClearCheckNewLink(la);
@@ -1317,8 +1328,10 @@
/* Defense against mangled packets */
if (ntohs(pip->ip_len) > maxpacketsize
- || (pip->ip_hl << 2) > maxpacketsize)
- return (PKT_ALIAS_IGNORED);
+ || (pip->ip_hl << 2) > maxpacketsize) {
+ iresult = PKT_ALIAS_IGNORED;
+ goto getout;
+ }
addr_save = GetDefaultAliasAddress(la);
if (la->packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) {
@@ -1380,6 +1393,8 @@
}
SetDefaultAliasAddress(la, addr_save);
+getout:
+ LIBALIAS_UNLOCK(la);
return (iresult);
}
@@ -1395,12 +1410,13 @@
struct alias_link *lnk;
int iresult = PKT_ALIAS_IGNORED;
+ LIBALIAS_LOCK(la);
pip = (struct ip *)ptr;
/* Defense against mangled packets */
if (ntohs(pip->ip_len) > maxpacketsize
|| (pip->ip_hl << 2) > maxpacketsize)
- return (iresult);
+ goto getout;
ud = (struct udphdr *)ip_next(pip);
tc = (struct tcphdr *)ip_next(pip);
@@ -1484,6 +1500,8 @@
iresult = PKT_ALIAS_OK;
}
}
+getout:
+ LIBALIAS_UNLOCK(la);
return (iresult);
}
==== //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_db.c#13 (text+ko) ====
@@ -2273,6 +2273,7 @@
int link_type;
struct alias_link *lnk;
+ LIBALIAS_LOCK(la);
switch (proto) {
case IPPROTO_UDP:
link_type = LINK_UDP;
@@ -2285,7 +2286,8 @@
fprintf(stderr, "PacketAliasRedirectPort(): ");
fprintf(stderr, "only TCP and UDP protocols allowed\n");
#endif
- return (NULL);
+ lnk = NULL;
+ goto getout;
}
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
@@ -2302,6 +2304,8 @@
}
#endif
+getout:
+ LIBALIAS_UNLOCK(la);
return (lnk);
}
@@ -2310,7 +2314,9 @@
LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
{
struct server *server;
+ int res;
+ LIBALIAS_LOCK(la);
(void)la;
server = malloc(sizeof(struct server));
@@ -2332,9 +2338,12 @@
server->next = head;
}
lnk->server = server;
- return (0);
+ res = 0;
} else
- return (-1);
+ res = -1;
+
+ LIBALIAS_UNLOCK(la);
+ return (res);
}
/* Redirect packets of a given IP protocol from a specific
@@ -2346,7 +2355,8 @@
u_char proto)
{
struct alias_link *lnk;
-
+
+ LIBALIAS_LOCK(la);
lnk = AddLink(la, src_addr, dst_addr, alias_addr,
NO_SRC_PORT, NO_DEST_PORT, 0,
proto);
@@ -2361,6 +2371,7 @@
}
#endif
+ LIBALIAS_UNLOCK(la);
return (lnk);
}
@@ -2371,6 +2382,7 @@
{
struct alias_link *lnk;
+ LIBALIAS_LOCK(la);
lnk = AddLink(la, src_addr, la->nullAddress, alias_addr,
0, 0, 0,
LINK_ADDR);
@@ -2385,6 +2397,7 @@
}
#endif
+ LIBALIAS_UNLOCK(la);
return (lnk);
}
@@ -2393,15 +2406,19 @@
int
LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
{
+ int res;
+ LIBALIAS_LOCK(la);
(void)la;
if (lnk->flags & LINK_PARTIALLY_SPECIFIED)
- return (-1);
+ res = -1;
else {
lnk->flags &= ~LINK_PERMANENT;
- return (0);
+ res = 0;
}
+ LIBALIAS_UNLOCK(la);
+ return (res);
}
@@ -2411,27 +2428,35 @@
/* This is a dangerous function to put in the API,
because an invalid pointer can crash the program. */
+ LIBALIAS_LOCK(la);
la->deleteAllLinks = 1;
DeleteLink(lnk);
la->deleteAllLinks = 0;
+ LIBALIAS_UNLOCK(la);
}
void
LibAliasSetAddress(struct libalias *la, struct in_addr addr)
{
+
+ LIBALIAS_LOCK(la);
if (la->packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
&& la->aliasAddress.s_addr != addr.s_addr)
CleanupAliasData(la);
la->aliasAddress = addr;
+ LIBALIAS_UNLOCK(la);
}
void
LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
{
+
+ LIBALIAS_LOCK(la);
la->targetAddress = target_addr;
+ LIBALIAS_UNLOCK(la);
}
static void
@@ -2508,12 +2533,15 @@
#ifndef _KERNEL
LibAliasRefreshModules();
#endif
+ LIBALIAS_LOCK_INIT(la);
return (la);
}
void
LibAliasUninit(struct libalias *la)
{
+
+ LIBALIAS_LOCK(la);
la->deleteAllLinks = 1;
CleanupAliasData(la);
la->deleteAllLinks = 0;
@@ -2522,6 +2550,8 @@
UninitPunchFW(la);
#endif
LIST_REMOVE(la, instancelist);
+ LIBALIAS_UNLOCK(la);
+ LIBALIAS_LOCK_DESTROY(la);
free(la);
}
@@ -2534,11 +2564,15 @@
* do a probe for flag values) */
)
{
+
+ LIBALIAS_LOCK(la);
/* Enable logging? */
if (flags & mask & PKT_ALIAS_LOG) {
/* Do the enable */
- if (InitPacketAliasLog(la) == ENOMEM)
+ if (InitPacketAliasLog(la) == ENOMEM) {
+ LIBALIAS_UNLOCK(la);
return (-1);
+ }
} else
/* _Disable_ logging? */
if (~flags & mask & PKT_ALIAS_LOG) {
@@ -2557,6 +2591,7 @@
/* Other flags can be set/cleared without special action */
la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
+ LIBALIAS_UNLOCK(la);
return (la->packetAliasMode);
}
@@ -2564,7 +2599,12 @@
int
LibAliasCheckNewLink(struct libalias *la)
{
- return (la->newDefaultLink);
+ int res;
+
+ LIBALIAS_LOCK(la);
+ res = la->newDefaultLink;
+ LIBALIAS_UNLOCK(la);
+ return (res);
}
@@ -2819,14 +2859,20 @@
void
LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
{
+
+ LIBALIAS_LOCK(la);
#ifndef NO_FW_PUNCH
la->fireWallBaseNum = base;
la->fireWallNumNums = num;
#endif
+ LIBALIAS_UNLOCK(la);
}
void
LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
{
+
+ LIBALIAS_LOCK(la);
la->skinnyPort = port;
+ LIBALIAS_UNLOCK(la);
}
==== //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_local.h#8 (text+ko) ====
@@ -51,7 +51,10 @@
#ifdef _KERNEL
#include <sys/malloc.h>
+#include <sys/param.h>
#include <sys/lock.h>
+#include <sys/mutex.h>
+
/* XXX: LibAliasSetTarget() uses this constant. */
#define INADDR_NONE 0xffffffff
#endif
@@ -146,11 +149,29 @@
struct in_addr true_addr; /* in network byte order. */
u_short true_port; /* in host byte order. */
-
+#ifdef _KERNEL
+ /*
+ * avoid races in libalias: every pubblic function has to use it.
+ */
+ struct mtx mutex;
+#endif
};
/* Macros */
+#ifdef _KERNEL
+#define LIBALIAS_LOCK_INIT(l) \
+ mtx_init(&l->mutex, "per-instance libalias mutex", NULL, MTX_DEF|MTX_RECURSE)
+#define LIBALIAS_LOCK(l) mtx_lock(&l->mutex)
+#define LIBALIAS_UNLOCK(l) mtx_unlock(&l->mutex)
+#define LIBALIAS_LOCK_DESTROY(l) mtx_destroy(&l->mutex);
+#else
+#define LIBALIAS_LOCK_INIT(l)
+#define LIBALIAS_LOCK(l)
+#define LIBALIAS_UNLOCK(l)
+#define LIBALIAS_LOCK_DESTROY(l)
+#endif
+
/*
* The following macro is used to update an
* internet checksum. "delta" is a 32-bit
==== //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_proxy.c#9 (text+ko) ====
@@ -648,7 +648,7 @@
* then 0 is used, and group 0 rules are always checked before any
* others.
*/
- int i, n, len;
+ int i, n, len, ret;
int cmd_len;
int token_count;
int state;
@@ -668,11 +668,15 @@
struct in_addr dst_addr, dst_mask;
struct proxy_entry *proxy_entry;
+ LIBALIAS_LOCK(la);
+ ret = 0;
/* Copy command line into a buffer */
cmd += strspn(cmd, " \t");
cmd_len = strlen(cmd);
- if (cmd_len > (int)(sizeof(buffer) - 1))
- return (-1);
+ if (cmd_len > (int)(sizeof(buffer) - 1)) {
+ ret = -1;
+ goto getout;
+ }
strcpy(buffer, cmd);
/* Convert to lower case */
@@ -730,8 +734,10 @@
state = STATE_READ_SRC;
else if (strcmp(token, "dst") == 0)
state = STATE_READ_DST;
- else
- return (-1);
+ else {
+ ret = -1;
+ goto getout;
+ }
break;
case STATE_READ_TYPE:
@@ -741,8 +747,10 @@
proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
else if (strcmp(token, "no_encode") == 0)
proxy_type = PROXY_TYPE_ENCODE_NONE;
- else
- return (-1);
+ else {
+ ret = -1;
+ goto getout;
+ }
state = STATE_READ_KEYWORD;
break;
@@ -763,18 +771,24 @@
if (*p != ':') {
err = IpAddr(token, &server_addr);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
} else {
*p = ' ';
n = sscanf(token, "%s %s", s, str_server_port);
- if (n != 2)
- return (-1);
+ if (n != 2) {
+ ret = -1;
+ goto getout;
+ }
err = IpAddr(s, &server_addr);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
}
}
state = STATE_READ_KEYWORD;
@@ -782,8 +796,10 @@
case STATE_READ_RULE:
n = sscanf(token, "%d", &rule_index);
- if (n != 1 || rule_index < 0)
- return (-1);
+ if (n != 1 || rule_index < 0) {
+ ret = -1;
+ goto getout;
+ }
state = STATE_READ_KEYWORD;
break;
@@ -792,16 +808,21 @@
int err;
int rule_to_delete;
- if (token_count != 2)
- return (-1);
+ if (token_count != 2) {
+ ret = -1;
+ goto getout;
+ }
n = sscanf(token, "%d", &rule_to_delete);
- if (n != 1)
- return (-1);
+ if (n != 1) {
+ ret = -1;
+ goto getout;
+ }
err = RuleNumberDelete(la, rule_to_delete);
if (err)
- return (-1);
- return (0);
+ ret = -1;
+ ret = 0;
+ goto getout;
}
case STATE_READ_PROTO:
@@ -809,8 +830,10 @@
proto = IPPROTO_TCP;
else if (strcmp(token, "udp") == 0)
proto = IPPROTO_UDP;
- else
- return (-1);
+ else {
+ ret = -1;
+ goto getout;
+ }
state = STATE_READ_KEYWORD;
break;
@@ -829,24 +852,32 @@
if (*p != '/') {
IpMask(32, &mask);
err = IpAddr(token, &addr);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
} else {
int nbits;
char s[sizeof(buffer)];
*p = ' ';
n = sscanf(token, "%s %d", s, &nbits);
- if (n != 2)
- return (-1);
+ if (n != 2) {
+ ret = -1;
+ goto getout;
+ }
err = IpAddr(s, &addr);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
err = IpMask(nbits, &mask);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
}
if (state == STATE_READ_SRC) {
@@ -861,7 +892,8 @@
break;
default:
- return (-1);
+ ret = -1;
+ goto getout;
break;
}
@@ -887,8 +919,10 @@
int err;
err = IpPort(str_port, proto, &proxy_port);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
} else {
proxy_port = 0;
}
@@ -897,20 +931,26 @@
int err;
err = IpPort(str_server_port, proto, &server_port);
- if (err)
- return (-1);
+ if (err) {
+ ret = -1;
+ goto getout;
+ }
} else {
server_port = 0;
}
/* Check that at least the server address has been defined */
- if (server_addr.s_addr == 0)
- return (-1);
+ if (server_addr.s_addr == 0) {
+ ret = -1;
+ goto getout;
+ }
/* Add to linked list */
proxy_entry = malloc(sizeof(struct proxy_entry));
- if (proxy_entry == NULL)
- return (-1);
+ if (proxy_entry == NULL) {
+ ret = -1;
+ goto getout;
+ }
proxy_entry->proxy_type = proxy_type;
proxy_entry->rule_index = rule_index;
@@ -925,5 +965,7 @@
RuleAdd(la, proxy_entry);
- return (0);
+getout:
+ LIBALIAS_UNLOCK(la);
+ return (ret);
}
==== //depot/projects/soc2005/libalias/sys/netinet/libalias/alias_util.c#4 (text+ko) ====
@@ -76,6 +76,7 @@
{
int sum, oddbyte;
+ LIBALIAS_LOCK(la);
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
@@ -89,6 +90,7 @@
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
+ LIBALIAS_UNLOCK(la);
return (~sum);
}
More information about the p4-projects
mailing list