- 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>
This commit is contained in:
parent
a5e8237d2a
commit
fb994b078f
113
sbin/natd/HISTORY
Normal file
113
sbin/natd/HISTORY
Normal file
@ -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 <brian@awfulhak.org> 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 <brian@awfulhak.org> 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 <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.
|
53
sbin/natd/README
Normal file
53
sbin/natd/README
Normal file
@ -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 <archie@whistle.com> Divert sockets
|
||||
Charles Mott <cmott@srv.net> Packet aliasing engine
|
||||
Eivind Eklund <eivind@dimaga.com> Packet aliasing engine
|
||||
Ari Suutari <suutari@iki.fi> Natd
|
||||
Brian Somers <brian@awfulhak.org> 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)
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -377,5 +377,5 @@ times:
|
||||
Divert sockets: Archie Cobbs <archie@whistle.com>
|
||||
Packet aliasing: Charles Mott <cmott@srv.net>
|
||||
IRC support & misc additions: Eivind Eklund <eivind@dimaga.com>
|
||||
Natd: Ari Suutari <ari.suutari@ps.carel.fi>
|
||||
Natd: Ari Suutari <suutari@iki.fi>
|
||||
Glue: Brian Somers <brian@awfulhak.org>
|
||||
|
232
sbin/natd/natd.c
232
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);
|
||||
|
||||
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:
|
||||
|
113
usr.sbin/natd/HISTORY
Normal file
113
usr.sbin/natd/HISTORY
Normal file
@ -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 <brian@awfulhak.org> 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 <brian@awfulhak.org> 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 <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.
|
53
usr.sbin/natd/README
Normal file
53
usr.sbin/natd/README
Normal file
@ -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 <archie@whistle.com> Divert sockets
|
||||
Charles Mott <cmott@srv.net> Packet aliasing engine
|
||||
Eivind Eklund <eivind@dimaga.com> Packet aliasing engine
|
||||
Ari Suutari <suutari@iki.fi> Natd
|
||||
Brian Somers <brian@awfulhak.org> 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)
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -377,5 +377,5 @@ times:
|
||||
Divert sockets: Archie Cobbs <archie@whistle.com>
|
||||
Packet aliasing: Charles Mott <cmott@srv.net>
|
||||
IRC support & misc additions: Eivind Eklund <eivind@dimaga.com>
|
||||
Natd: Ari Suutari <ari.suutari@ps.carel.fi>
|
||||
Natd: Ari Suutari <suutari@iki.fi>
|
||||
Glue: Brian Somers <brian@awfulhak.org>
|
||||
|
@ -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);
|
||||
|
||||
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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user