diff --git a/sbin/natd/HISTORY b/sbin/natd/HISTORY new file mode 100644 index 000000000000..404be4be06d0 --- /dev/null +++ b/sbin/natd/HISTORY @@ -0,0 +1,113 @@ +* Version 0.1 + + Initial version of natd. + +* Version 0.2 + + - Alias address can now be set by giving interface name with + new (-n) command-line option. + + - New Makefile based on bsd.prog.mk. + + - Error messages are written to syslog + after natd has become a daemon. + +* Version 1.0 + + - Support for using only single socket (-p option) + +* Version 1.1 + + - -a option now understands a hostname also. + - -a option no longer dumps core. + - Packet aliasing software upgraded to v. 1.9 + - added long option names (like -address) + +* Version 1.2 + + - Fixed core dump with -port option. + - Added -Wall to CFLAGS and some headers added to natd.c + to get clean compile by Brian Somers [brian@awfulhak.org]. + +* Version 1.3 + + - Aliasing address initialization is delayed until first + packet arrives. This allows natd to start up before + interface address is set. + - SIGTERM is now catched to allow kernel to close + existing connections when system is shutting down. + - SIGHUP is now catched to allow natd to refresh aliasing + address from interface, which might be useful to tun devices. + +* Version 1.4 + + - Changed command line options to be compatible with + command names used in ppp+packetAlias package (which is the + original application using aliasing routines). + + The options which map directly to packet aliasing options are: + + -unregistered_only [yes|no] + -log [yes|no] + -deny_incoming [yes|no] + -use_sockets [yes|no] + -same_ports [yes|no] + + The short option names are the same as in previous + releases. + + - Command line parser rewritten to provide more flexible + way to support new packet aliasing options. + + - Support for natd.cf configuration file has been added. + + - SIGHUP no longer causes problems when running without + interface name option. + + - When using -interface command line option, routing socket + is optionally listened for interface address changes. This + mode is activated by -dynamic option. + + - Directory tree reorganized, alias package is now a library. + + - Manual page written by Brian Somers added. + - README file updated. + +* Version 1.5 + + - Support for sending ICMP 'need fragmentation' messages + when packet size exceeds mtu size of outgoing network interface. + + - ipfw rule example in manual page fixed. + +* Version 1.6 + + - Upgrade to new packet aliasing engine (2.1) + - redirect_port and redirect_address configuration + parameters added. + - It is no longer necessary to quote complex parameter values + in command line. + - Manual page fixed (same_port -> same_ports). + +* Version 1.7 + + - A bug in command-line parsing fixed (it appeared due + to changes made in 1.6). + +* Version 1.8 + + - Fixed problems with -dynamic option. + - Added /var/run/natd.pid + +* Version 1.9 + + - Changes to manual page by + Brian Somers integrated. + - Checksum for incoming packets is always recalculated + for FreeBSD 2.2 and never recalculated for newer + versions. This should fix the problem with wrong + checksum of fragmented packets. + - Buffer space problem found by Sergio Lenzi + fixed. Natd now waits with select(2) for buffer space + to become available if write fails. + - Packet aliasing library upgraded to 2.2. diff --git a/sbin/natd/README b/sbin/natd/README new file mode 100644 index 000000000000..6c158d5e4ca1 --- /dev/null +++ b/sbin/natd/README @@ -0,0 +1,53 @@ + + A Network Address Translation Daemon for FreeBSD + + +1. WHAT IS NATD ? + + This is a simple daemon based on FreeBSD divert sockets + which performs network address translation (or masquerading) + for IP packets (see related RFCs 1631 and 1918). + It is based on packet aliasing package (see README.alias) + written by Charles Mott (cmott@srv.net). + + This package works with any network interface (doesn't have + to be ppp). I run it on a computer having two ethernet cards, + one connected to internet and the other one to local network. + +2. GETTING IT RUNNING + + 1) Get FreeBSD 2.2 - I think the divert sockets are + not available on earlier versions, + + 2) Compile this software by executing "make". + + 3) Install the software by executing "make install". + + 4) See man natd for further instructions. + +3. FTP SITES FOR NATD + + This package is available at ftp://ftp.suutari.iki.fi/pub/natd. + +4. AUTHORS + + This program is the result of the efforts of many people + at different times: + + Archie Cobbs Divert sockets + Charles Mott Packet aliasing engine + Eivind Eklund Packet aliasing engine + Ari Suutari Natd + Brian Somers Manual page, glue and + bunch of good ideas. + + The original package written by Charles Mott + is available at http://www.srv.net/~cmott. + It is described in README.alias. + + Happy Networking - comments and fixes are welcome! + + Ari S. (suutari@iki.fi) + + + diff --git a/sbin/natd/icmp.c b/sbin/natd/icmp.c index 40464ff004e3..2018f66128c9 100644 --- a/sbin/natd/icmp.c +++ b/sbin/natd/icmp.c @@ -72,7 +72,8 @@ int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu) /* * Calculate checksum. */ - icmp->icmp_cksum = InternetChecksum ((u_short*) icmp, icmpLen); + icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp, + icmpLen); /* * Add IP header using old IP header as template. */ diff --git a/sbin/natd/natd.8 b/sbin/natd/natd.8 index dbda1c5c1707..c38887c7c55c 100644 --- a/sbin/natd/natd.8 +++ b/sbin/natd/natd.8 @@ -377,5 +377,5 @@ times: Divert sockets: Archie Cobbs Packet aliasing: Charles Mott IRC support & misc additions: Eivind Eklund - Natd: Ari Suutari + Natd: Ari Suutari Glue: Brian Somers diff --git a/sbin/natd/natd.c b/sbin/natd/natd.c index f1667654eec3..13cf6ab0540c 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 * */ @@ -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); - - if (routeSock != -1) - FD_SET (routeSock, &readMask); - - if (select (fdMax + 1, - &readMask, - NULL, - NULL, - NULL) == -1) { - - if (errno == EINTR) - continue; - - Quit ("Select failed."); - } - - if (divertIn != -1) - if (FD_ISSET (divertIn, &readMask)) - DoAliasing (divertIn); - - if (divertOut != -1) - if (FD_ISSET (divertOut, &readMask)) - DoAliasing (divertOut); - - if (divertInOut != -1) - if (FD_ISSET (divertInOut, &readMask)) - DoAliasing (divertInOut); - - if (routeSock != -1) - if (FD_ISSET (routeSock, &readMask)) - HandleRoutingInfo (routeSock); } +/* + * Routing info is processed always. + */ + if (routeSock != -1) + FD_SET (routeSock, &readMask); + + if (select (fdMax + 1, + &readMask, + &writeMask, + NULL, + NULL) == -1) { + + if (errno == EINTR) + continue; + + Quit ("Select failed."); + } + + if (packetSock != -1) + if (FD_ISSET (packetSock, &writeMask)) + FlushPacketBuffer (packetSock); + + if (divertIn != -1) + if (FD_ISSET (divertIn, &readMask)) + DoAliasing (divertIn); + + if (divertOut != -1) + if (FD_ISSET (divertOut, &readMask)) + DoAliasing (divertOut); + + if (divertInOut != -1) + if (FD_ISSET (divertInOut, &readMask)) + DoAliasing (divertInOut); + + 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: diff --git a/usr.sbin/natd/HISTORY b/usr.sbin/natd/HISTORY new file mode 100644 index 000000000000..404be4be06d0 --- /dev/null +++ b/usr.sbin/natd/HISTORY @@ -0,0 +1,113 @@ +* Version 0.1 + + Initial version of natd. + +* Version 0.2 + + - Alias address can now be set by giving interface name with + new (-n) command-line option. + + - New Makefile based on bsd.prog.mk. + + - Error messages are written to syslog + after natd has become a daemon. + +* Version 1.0 + + - Support for using only single socket (-p option) + +* Version 1.1 + + - -a option now understands a hostname also. + - -a option no longer dumps core. + - Packet aliasing software upgraded to v. 1.9 + - added long option names (like -address) + +* Version 1.2 + + - Fixed core dump with -port option. + - Added -Wall to CFLAGS and some headers added to natd.c + to get clean compile by Brian Somers [brian@awfulhak.org]. + +* Version 1.3 + + - Aliasing address initialization is delayed until first + packet arrives. This allows natd to start up before + interface address is set. + - SIGTERM is now catched to allow kernel to close + existing connections when system is shutting down. + - SIGHUP is now catched to allow natd to refresh aliasing + address from interface, which might be useful to tun devices. + +* Version 1.4 + + - Changed command line options to be compatible with + command names used in ppp+packetAlias package (which is the + original application using aliasing routines). + + The options which map directly to packet aliasing options are: + + -unregistered_only [yes|no] + -log [yes|no] + -deny_incoming [yes|no] + -use_sockets [yes|no] + -same_ports [yes|no] + + The short option names are the same as in previous + releases. + + - Command line parser rewritten to provide more flexible + way to support new packet aliasing options. + + - Support for natd.cf configuration file has been added. + + - SIGHUP no longer causes problems when running without + interface name option. + + - When using -interface command line option, routing socket + is optionally listened for interface address changes. This + mode is activated by -dynamic option. + + - Directory tree reorganized, alias package is now a library. + + - Manual page written by Brian Somers added. + - README file updated. + +* Version 1.5 + + - Support for sending ICMP 'need fragmentation' messages + when packet size exceeds mtu size of outgoing network interface. + + - ipfw rule example in manual page fixed. + +* Version 1.6 + + - Upgrade to new packet aliasing engine (2.1) + - redirect_port and redirect_address configuration + parameters added. + - It is no longer necessary to quote complex parameter values + in command line. + - Manual page fixed (same_port -> same_ports). + +* Version 1.7 + + - A bug in command-line parsing fixed (it appeared due + to changes made in 1.6). + +* Version 1.8 + + - Fixed problems with -dynamic option. + - Added /var/run/natd.pid + +* Version 1.9 + + - Changes to manual page by + Brian Somers integrated. + - Checksum for incoming packets is always recalculated + for FreeBSD 2.2 and never recalculated for newer + versions. This should fix the problem with wrong + checksum of fragmented packets. + - Buffer space problem found by Sergio Lenzi + fixed. Natd now waits with select(2) for buffer space + to become available if write fails. + - Packet aliasing library upgraded to 2.2. diff --git a/usr.sbin/natd/README b/usr.sbin/natd/README new file mode 100644 index 000000000000..6c158d5e4ca1 --- /dev/null +++ b/usr.sbin/natd/README @@ -0,0 +1,53 @@ + + A Network Address Translation Daemon for FreeBSD + + +1. WHAT IS NATD ? + + This is a simple daemon based on FreeBSD divert sockets + which performs network address translation (or masquerading) + for IP packets (see related RFCs 1631 and 1918). + It is based on packet aliasing package (see README.alias) + written by Charles Mott (cmott@srv.net). + + This package works with any network interface (doesn't have + to be ppp). I run it on a computer having two ethernet cards, + one connected to internet and the other one to local network. + +2. GETTING IT RUNNING + + 1) Get FreeBSD 2.2 - I think the divert sockets are + not available on earlier versions, + + 2) Compile this software by executing "make". + + 3) Install the software by executing "make install". + + 4) See man natd for further instructions. + +3. FTP SITES FOR NATD + + This package is available at ftp://ftp.suutari.iki.fi/pub/natd. + +4. AUTHORS + + This program is the result of the efforts of many people + at different times: + + Archie Cobbs Divert sockets + Charles Mott Packet aliasing engine + Eivind Eklund Packet aliasing engine + Ari Suutari Natd + Brian Somers Manual page, glue and + bunch of good ideas. + + The original package written by Charles Mott + is available at http://www.srv.net/~cmott. + It is described in README.alias. + + Happy Networking - comments and fixes are welcome! + + Ari S. (suutari@iki.fi) + + + diff --git a/usr.sbin/natd/icmp.c b/usr.sbin/natd/icmp.c index 40464ff004e3..2018f66128c9 100644 --- a/usr.sbin/natd/icmp.c +++ b/usr.sbin/natd/icmp.c @@ -72,7 +72,8 @@ int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu) /* * Calculate checksum. */ - icmp->icmp_cksum = InternetChecksum ((u_short*) icmp, icmpLen); + icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp, + icmpLen); /* * Add IP header using old IP header as template. */ diff --git a/usr.sbin/natd/natd.8 b/usr.sbin/natd/natd.8 index dbda1c5c1707..c38887c7c55c 100644 --- a/usr.sbin/natd/natd.8 +++ b/usr.sbin/natd/natd.8 @@ -377,5 +377,5 @@ times: Divert sockets: Archie Cobbs Packet aliasing: Charles Mott IRC support & misc additions: Eivind Eklund - Natd: Ari Suutari + Natd: Ari Suutari Glue: Brian Somers diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c index f1667654eec3..13cf6ab0540c 100644 --- a/usr.sbin/natd/natd.c +++ b/usr.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 * */ @@ -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); - - if (routeSock != -1) - FD_SET (routeSock, &readMask); - - if (select (fdMax + 1, - &readMask, - NULL, - NULL, - NULL) == -1) { - - if (errno == EINTR) - continue; - - Quit ("Select failed."); - } - - if (divertIn != -1) - if (FD_ISSET (divertIn, &readMask)) - DoAliasing (divertIn); - - if (divertOut != -1) - if (FD_ISSET (divertOut, &readMask)) - DoAliasing (divertOut); - - if (divertInOut != -1) - if (FD_ISSET (divertInOut, &readMask)) - DoAliasing (divertInOut); - - if (routeSock != -1) - if (FD_ISSET (routeSock, &readMask)) - HandleRoutingInfo (routeSock); } +/* + * Routing info is processed always. + */ + if (routeSock != -1) + FD_SET (routeSock, &readMask); + + if (select (fdMax + 1, + &readMask, + &writeMask, + NULL, + NULL) == -1) { + + if (errno == EINTR) + continue; + + Quit ("Select failed."); + } + + if (packetSock != -1) + if (FD_ISSET (packetSock, &writeMask)) + FlushPacketBuffer (packetSock); + + if (divertIn != -1) + if (FD_ISSET (divertIn, &readMask)) + DoAliasing (divertIn); + + if (divertOut != -1) + if (FD_ISSET (divertOut, &readMask)) + DoAliasing (divertOut); + + if (divertInOut != -1) + if (FD_ISSET (divertInOut, &readMask)) + DoAliasing (divertInOut); + + 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: