summaryrefslogtreecommitdiffstats
path: root/sbin/natd/natd.c
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>1997-08-10 21:55:52 +0000
committerbrian <brian@FreeBSD.org>1997-08-10 21:55:52 +0000
commit69210a76930cd9f8b1cd7b25f62b62feacb73c43 (patch)
tree65326d3024b1606d6fc19b37cf6da72801dc4bb1 /sbin/natd/natd.c
parentd89f54f7a31493ef7ab830f3ea3911c80ba43f2e (diff)
downloadFreeBSD-src-69210a76930cd9f8b1cd7b25f62b62feacb73c43.zip
FreeBSD-src-69210a76930cd9f8b1cd7b25f62b62feacb73c43.tar.gz
- Buffer space problem found by Sergio Lenzi <lenzi@bsi.com.br>
fixed. Natd now waits with select(2) for buffer space to become available if write fails. - Packet aliasing library upgraded to 2.2. Submitted by: Ari Suutari <suutari@iki.fi>
Diffstat (limited to 'sbin/natd/natd.c')
-rw-r--r--sbin/natd/natd.c218
1 files changed, 128 insertions, 90 deletions
diff --git a/sbin/natd/natd.c b/sbin/natd/natd.c
index f166765..13cf6ab 100644
--- a/sbin/natd/natd.c
+++ b/sbin/natd/natd.c
@@ -7,7 +7,7 @@
*
* You may copy, modify and distribute this software (natd.c) freely.
*
- * Ari Suutari (ari@kn6-045.ktvlpr.inet.fi, ari@ps.carel.fi)
+ * Ari Suutari <suutari@iki.fi>
*
*/
@@ -70,25 +70,30 @@ static int StrToPort (char* str, char* proto);
static int StrToProto (char* str);
static int StrToAddrAndPort (char* str, struct in_addr* addr, char* proto);
static void ParseArgs (int argc, char** argv);
+static void FlushPacketBuffer (int fd);
/*
* Globals.
*/
-static int verbose;
-static int background;
-static int running;
-static int assignAliasAddr;
-static char* ifName;
-static int ifIndex;
-static int inPort;
-static int outPort;
-static int inOutPort;
-static struct in_addr aliasAddr;
-static int dynamicMode;
-static int ifMTU;
-static int aliasOverhead;
-static int icmpSock;
+static int verbose;
+static int background;
+static int running;
+static int assignAliasAddr;
+static char* ifName;
+static int ifIndex;
+static int inPort;
+static int outPort;
+static int inOutPort;
+static struct in_addr aliasAddr;
+static int dynamicMode;
+static int ifMTU;
+static int aliasOverhead;
+static int icmpSock;
+static char packetBuf[IP_MAXPACKET];
+static int packetLen;
+static struct sockaddr_in packetAddr;
+static int packetSock;
int main (int argc, char** argv)
{
@@ -98,13 +103,14 @@ int main (int argc, char** argv)
int routeSock;
struct sockaddr_in addr;
fd_set readMask;
+ fd_set writeMask;
int fdMax;
/*
* Initialize packet aliasing software.
* Done already here to be able to alter option bits
* during command line and configuration file processing.
*/
- InitPacketAlias ();
+ PacketAliasInit ();
/*
* Parse options.
*/
@@ -120,6 +126,10 @@ int main (int argc, char** argv)
aliasAddr.s_addr = INADDR_NONE;
aliasOverhead = 12;
dynamicMode = 0;
+/*
+ * Mark packet buffer empty.
+ */
+ packetSock = -1;
ParseArgs (argc, argv);
/*
@@ -243,42 +253,55 @@ int main (int argc, char** argv)
* Set alias address if it has been given.
*/
if (aliasAddr.s_addr != INADDR_NONE)
- SetPacketAliasAddress (aliasAddr);
+ PacketAliasSetAddress (aliasAddr);
- if (divertInOut != -1 && !ifName) {
-
-/*
- * When using only one socket, just call
- * DoAliasing repeatedly to process packets.
- */
- while (running)
- DoAliasing (divertInOut);
- }
- else {
/*
* We need largest descriptor number for select.
*/
- fdMax = -1;
+ fdMax = -1;
+
+ if (divertIn > fdMax)
+ fdMax = divertIn;
- if (divertIn > fdMax)
- fdMax = divertIn;
+ if (divertOut > fdMax)
+ fdMax = divertOut;
- if (divertOut > fdMax)
- fdMax = divertOut;
+ if (divertInOut > fdMax)
+ fdMax = divertInOut;
- if (divertInOut > fdMax)
- fdMax = divertInOut;
+ if (routeSock > fdMax)
+ fdMax = routeSock;
- if (routeSock > fdMax)
- fdMax = routeSock;
+ while (running) {
- while (running) {
+ if (divertInOut != -1 && !ifName && packetSock == -1) {
+/*
+ * When using only one socket, just call
+ * DoAliasing repeatedly to process packets.
+ */
+ DoAliasing (divertInOut);
+ continue;
+ }
/*
* Build read mask from socket descriptors to select.
*/
- FD_ZERO (&readMask);
+ FD_ZERO (&readMask);
+ FD_ZERO (&writeMask);
+/*
+ * If there is unsent packet in buffer, use select
+ * to check when socket comes writable again.
+ */
+ if (packetSock != -1) {
+
+ FD_SET (packetSock, &writeMask);
+ }
+ else {
+/*
+ * No unsent packet exists - safe to check if
+ * new ones are available.
+ */
if (divertIn != -1)
FD_SET (divertIn, &readMask);
@@ -287,38 +310,44 @@ int main (int argc, char** argv)
if (divertInOut != -1)
FD_SET (divertInOut, &readMask);
+ }
+/*
+ * Routing info is processed always.
+ */
+ if (routeSock != -1)
+ FD_SET (routeSock, &readMask);
- if (routeSock != -1)
- FD_SET (routeSock, &readMask);
+ if (select (fdMax + 1,
+ &readMask,
+ &writeMask,
+ NULL,
+ NULL) == -1) {
- if (select (fdMax + 1,
- &readMask,
- NULL,
- NULL,
- NULL) == -1) {
+ if (errno == EINTR)
+ continue;
- if (errno == EINTR)
- continue;
+ Quit ("Select failed.");
+ }
- Quit ("Select failed.");
- }
+ if (packetSock != -1)
+ if (FD_ISSET (packetSock, &writeMask))
+ FlushPacketBuffer (packetSock);
- if (divertIn != -1)
- if (FD_ISSET (divertIn, &readMask))
- DoAliasing (divertIn);
+ if (divertIn != -1)
+ if (FD_ISSET (divertIn, &readMask))
+ DoAliasing (divertIn);
- if (divertOut != -1)
- if (FD_ISSET (divertOut, &readMask))
- DoAliasing (divertOut);
+ if (divertOut != -1)
+ if (FD_ISSET (divertOut, &readMask))
+ DoAliasing (divertOut);
- if (divertInOut != -1)
- if (FD_ISSET (divertInOut, &readMask))
- DoAliasing (divertInOut);
+ if (divertInOut != -1)
+ if (FD_ISSET (divertInOut, &readMask))
+ DoAliasing (divertInOut);
- if (routeSock != -1)
- if (FD_ISSET (routeSock, &readMask))
- HandleRoutingInfo (routeSock);
- }
+ if (routeSock != -1)
+ if (FD_ISSET (routeSock, &readMask))
+ HandleRoutingInfo (routeSock);
}
if (background)
@@ -382,12 +411,8 @@ static void DoAliasing (int fd)
{
int bytes;
int origBytes;
- char buf[IP_MAXPACKET];
- struct sockaddr_in addr;
- int wrote;
int addrSize;
struct ip* ip;
- char msgBuf[80];
if (assignAliasAddr) {
@@ -397,12 +422,12 @@ static void DoAliasing (int fd)
/*
* Get packet from socket.
*/
- addrSize = sizeof addr;
+ addrSize = sizeof packetAddr;
origBytes = recvfrom (fd,
- buf,
- sizeof buf,
+ packetBuf,
+ sizeof packetBuf,
0,
- (struct sockaddr*) &addr,
+ (struct sockaddr*) &packetAddr,
&addrSize);
if (origBytes == -1) {
@@ -415,7 +440,7 @@ static void DoAliasing (int fd)
/*
* This is a IP packet.
*/
- ip = (struct ip*) buf;
+ ip = (struct ip*) packetBuf;
if (verbose) {
@@ -423,7 +448,7 @@ static void DoAliasing (int fd)
* Print packet direction and protocol type.
*/
- if (addr.sin_addr.s_addr == INADDR_ANY)
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY)
printf ("Out ");
else
printf ("In ");
@@ -451,23 +476,17 @@ static void DoAliasing (int fd)
PrintPacket (ip);
}
- if (addr.sin_addr.s_addr == INADDR_ANY) {
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY) {
/*
* Outgoing packets. Do aliasing.
*/
- PacketAliasOut (buf, IP_MAXPACKET);
+ PacketAliasOut (packetBuf, IP_MAXPACKET);
}
else {
/*
- * Incoming packets may have ip checksum zeroed
- * when read from divert socket. Re-calculate it.
- */
- if (ip->ip_sum == 0)
- ip->ip_sum = in_cksum_hdr (ip);
-/*
* Do aliasing.
*/
- PacketAliasIn (buf, IP_MAXPACKET);
+ PacketAliasIn (packetBuf, IP_MAXPACKET);
}
/*
* Length might have changed during aliasing.
@@ -476,7 +495,7 @@ static void DoAliasing (int fd)
/*
* Update alias overhead size for outgoing packets.
*/
- if (addr.sin_addr.s_addr == INADDR_ANY &&
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY &&
bytes - origBytes > aliasOverhead)
aliasOverhead = bytes - origBytes;
@@ -490,24 +509,41 @@ static void DoAliasing (int fd)
PrintPacket (ip);
printf ("\n");
}
+
+ packetLen = bytes;
+ packetSock = fd;
+ FlushPacketBuffer (fd);
+}
+
+static void FlushPacketBuffer (int fd)
+{
+ int wrote;
+ char msgBuf[80];
/*
* Put packet back for processing.
*/
wrote = sendto (fd,
- buf,
- bytes,
+ packetBuf,
+ packetLen,
0,
- (struct sockaddr*) &addr,
- sizeof addr);
+ (struct sockaddr*) &packetAddr,
+ sizeof packetAddr);
- if (wrote != bytes) {
+ if (wrote != packetLen) {
+/*
+ * If buffer space is not available,
+ * just return. Main loop will take care of
+ * retrying send when space becomes available.
+ */
+ if (errno == ENOBUFS)
+ return;
if (errno == EMSGSIZE) {
- if (addr.sin_addr.s_addr == INADDR_ANY &&
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY &&
ifMTU != -1)
SendNeedFragIcmp (icmpSock,
- (struct ip*) buf,
+ (struct ip*) packetBuf,
ifMTU - aliasOverhead);
}
else {
@@ -516,6 +552,8 @@ static void DoAliasing (int fd)
Warn (msgBuf);
}
}
+
+ packetSock = -1;
}
static void HandleRoutingInfo (int fd)
@@ -1001,7 +1039,7 @@ static void ParseOption (char* option, char* parms, int cmdLine)
case PacketAliasOption:
aliasValue = yesNoValue ? info->packetAliasOpt : 0;
- SetPacketAliasMode (aliasValue, info->packetAliasOpt);
+ PacketAliasSetMode (aliasValue, info->packetAliasOpt);
break;
case Verbose:
OpenPOWER on IntegriCloud