From 9ddea1329157d5feaa73563a77ab72f0409c9fb9 Mon Sep 17 00:00:00 2001 From: piso Date: Fri, 15 Dec 2006 12:50:06 +0000 Subject: o made in kernel libalias mpsafe o fixed a comment o made in kernel libalias a bit less verbose (disabled automatic logging everytime a new link is added or deleted) Approved by: glebius (mentor) --- sys/netinet/libalias/alias.c | 120 ++++++++++++++++++++++++--------- sys/netinet/libalias/alias_db.c | 132 ++++++++++++++++++++++++++++++++----- sys/netinet/libalias/alias_local.h | 25 ++++++- sys/netinet/libalias/alias_mod.c | 12 ++-- sys/netinet/libalias/alias_proxy.c | 130 ++++++++++++++++++++++++------------ sys/netinet/libalias/alias_util.c | 2 + 6 files changed, 327 insertions(+), 94 deletions(-) diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c index 3e136a7..ed500e1 100644 --- a/sys/netinet/libalias/alias.c +++ b/sys/netinet/libalias/alias.c @@ -283,6 +283,8 @@ static int TcpAliasOut(struct libalias *, struct ip *, int, int create); static int IcmpAliasIn1(struct libalias *la, struct ip *pip) { + + LIBALIAS_LOCK_ASSERT(la); /* De-alias incoming echo and timestamp replies. Alias incoming echo and timestamp requests. @@ -326,6 +328,8 @@ IcmpAliasIn1(struct libalias *la, struct ip *pip) static int IcmpAliasIn2(struct libalias *la, struct ip *pip) { + + LIBALIAS_LOCK_ASSERT(la); /* Alias incoming ICMP error messages containing IP header and first 64 bits of datagram. @@ -429,6 +433,7 @@ IcmpAliasIn(struct libalias *la, struct ip *pip) int iresult; struct icmp *ic; + LIBALIAS_LOCK_ASSERT(la); /* Return if proxy-only mode is enabled */ if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) return (PKT_ALIAS_OK); @@ -468,6 +473,7 @@ IcmpAliasOut1(struct libalias *la, struct ip *pip, int create) struct alias_link *lnk; struct icmp *ic; + LIBALIAS_LOCK_ASSERT(la); ic = (struct icmp *)ip_next(pip); /* Save overwritten data for when echo packet returns */ @@ -515,6 +521,7 @@ IcmpAliasOut2(struct libalias *la, struct ip *pip) struct tcphdr *tc; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); ic = (struct icmp *)ip_next(pip); ip = &ic->icmp_ip; @@ -608,6 +615,7 @@ IcmpAliasOut(struct libalias *la, struct ip *pip, int create) int iresult; struct icmp *ic; + LIBALIAS_LOCK_ASSERT(la); (void)create; /* Return if proxy-only mode is enabled */ @@ -650,6 +658,7 @@ ProtoAliasIn(struct libalias *la, struct ip *pip) */ struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); /* Return if proxy-only mode is enabled */ if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) return (PKT_ALIAS_OK); @@ -681,6 +690,7 @@ ProtoAliasOut(struct libalias *la, struct ip *pip, int create) */ struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); (void)create; /* Return if proxy-only mode is enabled */ @@ -710,6 +720,7 @@ UdpAliasIn(struct libalias *la, struct ip *pip) struct udphdr *ud; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); /* Return if proxy-only mode is enabled */ if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) return (PKT_ALIAS_OK); @@ -775,6 +786,7 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int create) struct alias_link *lnk; int error; + LIBALIAS_LOCK_ASSERT(la); /* Return if proxy-only mode is enabled */ if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) return (PKT_ALIAS_OK); @@ -835,6 +847,7 @@ TcpAliasIn(struct libalias *la, struct ip *pip) struct tcphdr *tc; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); tc = (struct tcphdr *)ip_next(pip); lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, @@ -959,6 +972,7 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) struct tcphdr *tc; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); tc = (struct tcphdr *)ip_next(pip); if (create) @@ -1085,6 +1099,7 @@ FragmentIn(struct libalias *la, struct ip *pip) { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindFragmentIn2(la, pip->ip_src, pip->ip_dst, pip->ip_id); if (lnk != NULL) { struct in_addr original_address; @@ -1105,6 +1120,7 @@ FragmentOut(struct libalias *la, struct ip *pip) { struct in_addr alias_address; + LIBALIAS_LOCK_ASSERT(la); alias_address = FindAliasAddress(la, pip->ip_src); DifferentialChecksum(&pip->ip_sum, &alias_address, &pip->ip_src, 2); @@ -1138,6 +1154,7 @@ LibAliasSaveFragment(struct libalias *la, char *ptr) 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 +1162,7 @@ LibAliasSaveFragment(struct libalias *la, char *ptr) SetFragmentPtr(lnk, ptr); iresult = PKT_ALIAS_OK; } + LIBALIAS_UNLOCK(la); return (iresult); } @@ -1156,17 +1174,18 @@ LibAliasGetFragment(struct libalias *la, char *ptr) 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 +1200,7 @@ LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly struct ip *pip; struct ip *fpip; + LIBALIAS_LOCK(la); (void)la; pip = (struct ip *)ptr; fpip = (struct ip *)ptr_fragment; @@ -1188,21 +1208,40 @@ LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly DifferentialChecksum(&fpip->ip_sum, &pip->ip_dst, &fpip->ip_dst, 2); fpip->ip_dst = pip->ip_dst; + LIBALIAS_UNLOCK(la); } +/* Local prototypes */ +static int +LibAliasOutLocked(struct libalias *la, char *ptr, + int maxpacketsize, int create); +static int +LibAliasInLocked(struct libalias *la, char *ptr, + int maxpacketsize); int LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) { + int res; + + LIBALIAS_LOCK(la); + res = LibAliasInLocked(la, ptr, maxpacketsize); + LIBALIAS_UNLOCK(la); + return (res); +} + +static int +LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize) +{ struct in_addr alias_addr; struct ip *pip; int iresult; if (la->packetAliasMode & PKT_ALIAS_REVERSE) { la->packetAliasMode &= ~PKT_ALIAS_REVERSE; - iresult = LibAliasOut(la, ptr, maxpacketsize); + iresult = LibAliasOutLocked(la, ptr, maxpacketsize, 1); la->packetAliasMode |= PKT_ALIAS_REVERSE; - return (iresult); + goto getout; } HouseKeeping(la); ClearCheckNewLink(la); @@ -1211,8 +1250,10 @@ LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) /* 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 +1307,7 @@ LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) iresult = FragmentIn(la, pip); } +getout: return (iresult); } @@ -1286,19 +1328,32 @@ LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize) #define UNREG_ADDR_C_UPPER 0xc0a8ffff int -LibAliasOut(struct libalias *la, char *ptr, /* valid IP packet */ - int maxpacketsize /* How much the packet data may grow (FTP - * and IRC inline changes) */ -) +LibAliasOut(struct libalias *la, char *ptr, int maxpacketsize) { - return (LibAliasOutTry(la, ptr, maxpacketsize, 1)); + int res; + + LIBALIAS_LOCK(la); + res = LibAliasOutLocked(la, ptr, maxpacketsize, 1); + LIBALIAS_UNLOCK(la); + return (res); } int -LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ +LibAliasOutTry(struct libalias *la, char *ptr, int maxpacketsize, int create) +{ + int res; + + LIBALIAS_LOCK(la); + res = LibAliasOutLocked(la, ptr, maxpacketsize, create); + LIBALIAS_UNLOCK(la); + return (res); +} + +static int +LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */ int maxpacketsize, /* How much the packet data may grow (FTP * and IRC inline changes) */ - int create /* Create new entries ? */ + int create /* Create new entries ? */ ) { int iresult; @@ -1307,9 +1362,9 @@ LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ if (la->packetAliasMode & PKT_ALIAS_REVERSE) { la->packetAliasMode &= ~PKT_ALIAS_REVERSE; - iresult = LibAliasIn(la, ptr, maxpacketsize); + iresult = LibAliasInLocked(la, ptr, maxpacketsize); la->packetAliasMode |= PKT_ALIAS_REVERSE; - return (iresult); + goto getout; } HouseKeeping(la); ClearCheckNewLink(la); @@ -1317,8 +1372,10 @@ LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ /* 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 +1437,7 @@ LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */ } SetDefaultAliasAddress(la, addr_save); +getout: return (iresult); } @@ -1395,12 +1453,13 @@ LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ 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 +1543,8 @@ LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */ iresult = PKT_ALIAS_OK; } } +getout: + LIBALIAS_UNLOCK(la); return (iresult); } @@ -1585,17 +1646,16 @@ LibAliasUnLoadAllModule(void) #ifdef _KERNEL /* - * m_megapullup() function is a big hack (only used in ng_nat and ipfw+nat). + * m_megapullup() - this function is a big hack. + * Thankfully, it's only used in ng_nat and ipfw+nat. + * + * It allocates an mbuf with cluster and copies the whole chain into cluster, + * so that it is all contiguous and the whole packet can be accessed via a + * plain (char *) pointer. This is required, because libalias doesn't know + * how to handle mbuf chains. * - * It allocates an mbuf with cluster and copies the whole - * chain into cluster, so that it is all contigous and the - * whole packet can be accessed via char pointer. - * This is required, because libalias doesn't have idea - * about mbufs. - * - * On success, m_megapullup returns an mbuf with cluster - * containing the input packet, on failure NULL. - * In both cases, the input packet is consumed. + * On success, m_megapullup returns an mbuf with cluster containing the input + * packet, on failure NULL. In both cases, the input packet is consumed. */ struct mbuf * m_megapullup(struct mbuf *m, int len) { diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c index 1061c74..e32a5bd 100644 --- a/sys/netinet/libalias/alias_db.c +++ b/sys/netinet/libalias/alias_db.c @@ -463,7 +463,6 @@ AliasLog(char *str, const char *format, ...) va_start(ap, format); vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap); - log(LOG_SECURITY | LOG_INFO, "%s\n", str); va_end(ap); } #else @@ -482,6 +481,8 @@ AliasLog(FILE *stream, const char *format, ...) static void ShowAliasStats(struct libalias *la) { + + LIBALIAS_LOCK_ASSERT(la); /* Used for debugging */ if (la->logDesc) { int tot = la->icmpLinkCount + la->udpLinkCount + @@ -575,6 +576,7 @@ GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param) u_short port_sys; u_short port_net; + LIBALIAS_LOCK_ASSERT(la); /* Description of alias_port_param for GetNewPort(). When this parameter is zero or positive, it precisely specifies @@ -675,6 +677,7 @@ GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type) int sock; struct sockaddr_in sock_addr; + LIBALIAS_LOCK_ASSERT(la); if (link_type == LINK_TCP) sock = socket(AF_INET, SOCK_STREAM, 0); else if (link_type == LINK_UDP) @@ -733,6 +736,7 @@ FindNewPortGroup(struct libalias *la, u_short port_sys; int link_type; + LIBALIAS_LOCK_ASSERT(la); /* * Get link_type from protocol */ @@ -812,6 +816,7 @@ CleanupAliasData(struct libalias *la) struct alias_link *lnk; int i, icount; + LIBALIAS_LOCK_ASSERT(la); icount = 0; for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { lnk = LIST_FIRST(&la->linkTableOut[i]); @@ -835,6 +840,7 @@ IncrementalCleanup(struct libalias *la) int icount; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); icount = 0; lnk = LIST_FIRST(&la->linkTableOut[la->cleanupIndex++]); while (lnk != NULL) { @@ -875,6 +881,7 @@ DeleteLink(struct alias_link *lnk) { struct libalias *la = lnk->la; + LIBALIAS_LOCK_ASSERT(la); /* Don't do anything if the link is marked permanent */ if (la->deleteAllLinks == 0 && lnk->flags & LINK_PERMANENT) return; @@ -959,6 +966,7 @@ AddLink(struct libalias *la, struct in_addr src_addr, u_int start_point; /* zero, equal to alias port */ struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = malloc(sizeof(struct alias_link)); if (lnk != NULL) { /* Basic initialization */ @@ -1100,6 +1108,7 @@ ReLink(struct alias_link *old_lnk, struct alias_link *new_lnk; /* zero, equal to alias port */ struct libalias *la = old_lnk->la; + LIBALIAS_LOCK_ASSERT(la); new_lnk = AddLink(la, src_addr, dst_addr, alias_addr, src_port, dst_port, alias_port_param, link_type); @@ -1125,6 +1134,7 @@ _FindLinkOut(struct libalias *la, struct in_addr src_addr, 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->src_addr.s_addr == src_addr.s_addr @@ -1172,6 +1182,7 @@ FindLinkOut(struct libalias *la, struct in_addr src_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = _FindLinkOut(la, src_addr, dst_addr, src_port, dst_port, link_type, replace_partial_links); @@ -1208,6 +1219,7 @@ _FindLinkIn(struct libalias *la, struct in_addr dst_addr, struct alias_link *lnk_unknown_dst_addr; struct alias_link *lnk_unknown_dst_port; + LIBALIAS_LOCK_ASSERT(la); /* Initialize pointers */ lnk_fully_specified = NULL; lnk_unknown_all = NULL; @@ -1311,6 +1323,7 @@ FindLinkIn(struct libalias *la, struct in_addr dst_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = _FindLinkIn(la, dst_addr, alias_addr, dst_port, alias_port, link_type, replace_partial_links); @@ -1358,6 +1371,7 @@ FindIcmpIn(struct libalias *la, struct in_addr dst_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkIn(la, dst_addr, alias_addr, NO_DEST_PORT, id_alias, LINK_ICMP, 0); @@ -1381,6 +1395,7 @@ FindIcmpOut(struct libalias *la, struct in_addr src_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkOut(la, src_addr, dst_addr, id, NO_DEST_PORT, LINK_ICMP, 0); @@ -1403,6 +1418,7 @@ FindFragmentIn1(struct libalias *la, struct in_addr dst_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkIn(la, dst_addr, alias_addr, NO_DEST_PORT, ip_id, LINK_FRAGMENT_ID, 0); @@ -1422,6 +1438,8 @@ FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, /* Doesn't add a l struct in_addr alias_addr, /* is not found. */ u_short ip_id) { + + LIBALIAS_LOCK_ASSERT(la); return FindLinkIn(la, dst_addr, alias_addr, NO_DEST_PORT, ip_id, LINK_FRAGMENT_ID, 0); @@ -1432,6 +1450,8 @@ struct alias_link * AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr, u_short ip_id) { + + LIBALIAS_LOCK_ASSERT(la); return AddLink(la, la->nullAddress, dst_addr, la->nullAddress, NO_SRC_PORT, NO_DEST_PORT, ip_id, LINK_FRAGMENT_PTR); @@ -1442,6 +1462,8 @@ struct alias_link * FindFragmentPtr(struct libalias *la, struct in_addr dst_addr, u_short ip_id) { + + LIBALIAS_LOCK_ASSERT(la); return FindLinkIn(la, dst_addr, la->nullAddress, NO_DEST_PORT, ip_id, LINK_FRAGMENT_PTR, 0); @@ -1455,6 +1477,7 @@ FindProtoIn(struct libalias *la, struct in_addr dst_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkIn(la, dst_addr, alias_addr, NO_DEST_PORT, 0, proto, 1); @@ -1478,6 +1501,7 @@ FindProtoOut(struct libalias *la, struct in_addr src_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkOut(la, src_addr, dst_addr, NO_SRC_PORT, NO_DEST_PORT, proto, 1); @@ -1505,6 +1529,7 @@ FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr, int link_type; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); switch (proto) { case IPPROTO_UDP: link_type = LINK_UDP; @@ -1544,6 +1569,7 @@ FindUdpTcpOut(struct libalias *la, struct in_addr src_addr, int link_type; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); switch (proto) { case IPPROTO_UDP: link_type = LINK_UDP; @@ -1578,6 +1604,7 @@ AddPptp(struct libalias *la, struct in_addr src_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = AddLink(la, src_addr, dst_addr, alias_addr, src_call_id, 0, GET_ALIAS_PORT, LINK_PPTP); @@ -1594,6 +1621,7 @@ FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, 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 && @@ -1614,6 +1642,7 @@ FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, 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 && @@ -1634,6 +1663,7 @@ FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, 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 && @@ -1653,6 +1683,7 @@ FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkIn(la, dst_addr, alias_addr, 0 /* any */ , alias_call_id, LINK_PPTP, 0); @@ -1672,6 +1703,7 @@ FindRtspOut(struct libalias *la, struct in_addr src_addr, int link_type; struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); switch (proto) { case IPPROTO_UDP: link_type = LINK_UDP; @@ -1703,6 +1735,7 @@ FindOriginalAddress(struct libalias *la, struct in_addr alias_addr) { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkIn(la, la->nullAddress, alias_addr, 0, 0, LINK_ADDR, 0); if (lnk == NULL) { @@ -1735,6 +1768,7 @@ FindAliasAddress(struct libalias *la, struct in_addr original_addr) { struct alias_link *lnk; + LIBALIAS_LOCK_ASSERT(la); lnk = FindLinkOut(la, original_addr, la->nullAddress, 0, 0, LINK_ADDR, 0); if (lnk == NULL) { @@ -1891,6 +1925,8 @@ GetAliasAddress(struct alias_link *lnk) struct in_addr GetDefaultAliasAddress(struct libalias *la) { + + LIBALIAS_LOCK_ASSERT(la); return (la->aliasAddress); } @@ -1898,6 +1934,8 @@ GetDefaultAliasAddress(struct libalias *la) void SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr) { + + LIBALIAS_LOCK_ASSERT(la); la->aliasAddress = alias_addr; } @@ -2112,6 +2150,8 @@ SetExpire(struct alias_link *lnk, int expire) void ClearCheckNewLink(struct libalias *la) { + + LIBALIAS_LOCK_ASSERT(la); la->newDefaultLink = 0; } @@ -2134,6 +2174,7 @@ SetDestCallId(struct alias_link *lnk, u_int16_t cid) { struct libalias *la = lnk->la; + LIBALIAS_LOCK_ASSERT(la); la->deleteAllLinks = 1; lnk = ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr, lnk->src_port, cid, lnk->alias_port, lnk->link_type); @@ -2166,6 +2207,7 @@ HouseKeeping(struct libalias *la) struct timezone tz; #endif + LIBALIAS_LOCK_ASSERT(la); /* * Save system time (seconds) in global variable timeStamp for use * by other functions. This is done so as not to unnecessarily @@ -2213,6 +2255,8 @@ HouseKeeping(struct libalias *la) static int InitPacketAliasLog(struct libalias *la) { + + LIBALIAS_LOCK_ASSERT(la); if (~la->packetAliasMode & PKT_ALIAS_LOG) { #ifdef _KERNEL if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE))) @@ -2233,14 +2277,16 @@ InitPacketAliasLog(struct libalias *la) static void UninitPacketAliasLog(struct libalias *la) { - if (la->logDesc) { + + LIBALIAS_LOCK_ASSERT(la); + if (la->logDesc) { #ifdef _KERNEL - free(la->logDesc); + free(la->logDesc); #else - fclose(la->logDesc); + fclose(la->logDesc); #endif - la->logDesc = NULL; - } + la->logDesc = NULL; + } la->packetAliasMode &= ~PKT_ALIAS_LOG; } @@ -2273,6 +2319,7 @@ LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_p int link_type; struct alias_link *lnk; + LIBALIAS_LOCK(la); switch (proto) { case IPPROTO_UDP: link_type = LINK_UDP; @@ -2285,7 +2332,8 @@ LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_p 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 +2350,8 @@ LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_p } #endif +getout: + LIBALIAS_UNLOCK(la); return (lnk); } @@ -2310,7 +2360,9 @@ int 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 +2384,12 @@ LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr ad 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 @@ -2347,6 +2402,7 @@ LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, { 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 +2417,7 @@ LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, } #endif + LIBALIAS_UNLOCK(la); return (lnk); } @@ -2371,6 +2428,7 @@ LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, { struct alias_link *lnk; + LIBALIAS_LOCK(la); lnk = AddLink(la, src_addr, la->nullAddress, alias_addr, 0, 0, 0, LINK_ADDR); @@ -2385,6 +2443,7 @@ LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, } #endif + LIBALIAS_UNLOCK(la); return (lnk); } @@ -2393,15 +2452,19 @@ LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, 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 +2474,35 @@ LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk) /* 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 @@ -2476,8 +2547,10 @@ LibAliasInit(struct libalias *la) LIST_INIT(&la->linkTableOut[i]); for (i = 0; i < LINK_TABLE_IN_SIZE; i++) LIST_INIT(&la->linkTableIn[i]); - + LIBALIAS_LOCK_INIT(la); + LIBALIAS_LOCK(la); } else { + LIBALIAS_LOCK(la); la->deleteAllLinks = 1; CleanupAliasData(la); la->deleteAllLinks = 0; @@ -2508,12 +2581,15 @@ LibAliasInit(struct libalias *la) #ifndef _KERNEL LibAliasRefreshModules(); #endif + LIBALIAS_UNLOCK(la); return (la); } void LibAliasUninit(struct libalias *la) { + + LIBALIAS_LOCK(la); la->deleteAllLinks = 1; CleanupAliasData(la); la->deleteAllLinks = 0; @@ -2522,6 +2598,8 @@ LibAliasUninit(struct libalias *la) UninitPunchFW(la); #endif LIST_REMOVE(la, instancelist); + LIBALIAS_UNLOCK(la); + LIBALIAS_LOCK_DESTROY(la); free(la); } @@ -2534,11 +2612,14 @@ LibAliasSetMode( * do a probe for flag values) */ ) { + int res = -1; + + LIBALIAS_LOCK(la); /* Enable logging? */ if (flags & mask & PKT_ALIAS_LOG) { /* Do the enable */ if (InitPacketAliasLog(la) == ENOMEM) - return (-1); + goto getout; } else /* _Disable_ logging? */ if (~flags & mask & PKT_ALIAS_LOG) { @@ -2557,14 +2638,22 @@ LibAliasSetMode( /* Other flags can be set/cleared without special action */ la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask); - return (la->packetAliasMode); + res = la->packetAliasMode; +getout: + LIBALIAS_UNLOCK(la); + return (res); } int LibAliasCheckNewLink(struct libalias *la) { - return (la->newDefaultLink); + int res; + + LIBALIAS_LOCK(la); + res = la->newDefaultLink; + LIBALIAS_UNLOCK(la); + return (res); } @@ -2670,6 +2759,7 @@ static void InitPunchFW(struct libalias *la) { + LIBALIAS_LOCK_ASSERT(la); la->fireWallField = malloc(la->fireWallNumNums); if (la->fireWallField) { memset(la->fireWallField, 0, la->fireWallNumNums); @@ -2684,6 +2774,8 @@ InitPunchFW(struct libalias *la) static void UninitPunchFW(struct libalias *la) { + + LIBALIAS_LOCK_ASSERT(la); ClearAllFWHoles(la); if (la->fireWallFD >= 0) close(la->fireWallFD); @@ -2703,6 +2795,7 @@ PunchFWHole(struct alias_link *lnk) struct ip_fw rule; /* On-the-fly built rule */ int fwhole; /* Where to punch hole */ + LIBALIAS_LOCK_ASSERT(la); la = lnk->la; /* Don't do anything unless we are asked to */ @@ -2774,9 +2867,9 @@ PunchFWHole(struct alias_link *lnk) static void ClearFWHole(struct alias_link *lnk) { - struct libalias *la; + LIBALIAS_LOCK_ASSERT(la); la = lnk->la; if (lnk->link_type == LINK_TCP) { int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall @@ -2801,6 +2894,7 @@ ClearAllFWHoles(struct libalias *la) struct ip_fw rule; /* On-the-fly built rule */ int i; + LIBALIAS_LOCK_ASSERT(la); if (la->fireWallFD < 0) return; @@ -2819,14 +2913,20 @@ ClearAllFWHoles(struct libalias *la) 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); } diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h index 1dc50c8..2abcb69 100644 --- a/sys/netinet/libalias/alias_local.h +++ b/sys/netinet/libalias/alias_local.h @@ -51,7 +51,10 @@ #ifdef _KERNEL #include +#include #include +#include + /* XXX: LibAliasSetTarget() uses this constant. */ #define INADDR_NONE 0xffffffff #endif @@ -146,11 +149,31 @@ struct libalias { struct in_addr true_addr; /* in network byte order. */ u_short true_port; /* in host byte order. */ - +#ifdef _KERNEL + /* + * avoid races in libalias: every public 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) +#define LIBALIAS_LOCK_ASSERT(l) mtx_assert(&l->mutex, MA_OWNED) +#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_ASSERT(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 diff --git a/sys/netinet/libalias/alias_mod.c b/sys/netinet/libalias/alias_mod.c index 03daa1e..643fe5f 100644 --- a/sys/netinet/libalias/alias_mod.c +++ b/sys/netinet/libalias/alias_mod.c @@ -60,9 +60,9 @@ SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(foo); #ifdef _KERNEL -#define LIBALIAS_LOCK_INIT() \ +#define LIBALIAS_RWLOCK_INIT() \ rw_init(&handler_rw, "Libalias_modules_rwlock") -#define LIBALIAS_LOCK_DESTROY() rw_destroy(&handler_rw) +#define LIBALIAS_RWLOCK_DESTROY() rw_destroy(&handler_rw) #define LIBALIAS_WLOCK_ASSERT() \ rw_assert(&handler_rw, RA_WLOCKED) @@ -95,7 +95,7 @@ _handler_chain_init(void) { if (!rw_initialized(&handler_rw)) - LIBALIAS_LOCK_INIT(); + LIBALIAS_RWLOCK_INIT(); } static void @@ -103,12 +103,12 @@ _handler_chain_destroy(void) { if (rw_initialized(&handler_rw)) - LIBALIAS_LOCK_DESTROY(); + LIBALIAS_RWLOCK_DESTROY(); } #else -#define LIBALIAS_LOCK_INIT() ; -#define LIBALIAS_LOCK_DESTROY() ; +#define LIBALIAS_RWLOCK_INIT() ; +#define LIBALIAS_RWLOCK_DESTROY() ; #define LIBALIAS_WLOCK_ASSERT() ; #define LIBALIAS_RLOCK() ; #define LIBALIAS_RUNLOCK() ; diff --git a/sys/netinet/libalias/alias_proxy.c b/sys/netinet/libalias/alias_proxy.c index 699e421..f435771 100644 --- a/sys/netinet/libalias/alias_proxy.c +++ b/sys/netinet/libalias/alias_proxy.c @@ -312,6 +312,8 @@ RuleAdd(struct libalias *la, struct proxy_entry *entry) struct proxy_entry *ptr; struct proxy_entry *ptr_last; + LIBALIAS_LOCK_ASSERT(la); + if (la->proxyList == NULL) { la->proxyList = entry; entry->last = NULL; @@ -353,6 +355,7 @@ RuleDelete(struct proxy_entry *entry) struct libalias *la; la = entry->la; + LIBALIAS_LOCK_ASSERT(la); if (entry->last != NULL) entry->last->next = entry->next; else @@ -370,6 +373,7 @@ RuleNumberDelete(struct libalias *la, int rule_index) int err; struct proxy_entry *ptr; + LIBALIAS_LOCK_ASSERT(la); err = -1; ptr = la->proxyList; while (ptr != NULL) { @@ -566,6 +570,7 @@ ProxyCheck(struct libalias *la, struct ip *pip, struct in_addr dst_addr; struct proxy_entry *ptr; + LIBALIAS_LOCK_ASSERT(la); src_addr = pip->ip_src; dst_addr = pip->ip_dst; dst_port = ((struct tcphdr *)ip_next(pip)) @@ -606,6 +611,7 @@ ProxyModify(struct libalias *la, struct alias_link *lnk, int proxy_type) { + LIBALIAS_LOCK_ASSERT(la); (void)la; switch (proxy_type) { @@ -648,7 +654,7 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) * 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 +674,15 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +740,10 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +753,10 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +777,24 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +802,10 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +814,21 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +836,10 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +858,32 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +898,8 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) break; default: - return (-1); + ret = -1; + goto getout; break; } @@ -887,8 +925,10 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +937,26 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) 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 +971,7 @@ LibAliasProxyRule(struct libalias *la, const char *cmd) RuleAdd(la, proxy_entry); - return (0); +getout: + LIBALIAS_UNLOCK(la); + return (ret); } diff --git a/sys/netinet/libalias/alias_util.c b/sys/netinet/libalias/alias_util.c index 4cdbaf8..805b51a 100644 --- a/sys/netinet/libalias/alias_util.c +++ b/sys/netinet/libalias/alias_util.c @@ -76,6 +76,7 @@ LibAliasInternetChecksum(struct libalias *la __unused, u_short * ptr, { int sum, oddbyte; + LIBALIAS_LOCK(la); sum = 0; while (nbytes > 1) { sum += *ptr++; @@ -89,6 +90,7 @@ LibAliasInternetChecksum(struct libalias *la __unused, u_short * ptr, } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); + LIBALIAS_UNLOCK(la); return (~sum); } -- cgit v1.1