summaryrefslogtreecommitdiffstats
path: root/usr.sbin/natd/natd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/natd/natd.c')
-rw-r--r--usr.sbin/natd/natd.c1477
1 files changed, 0 insertions, 1477 deletions
diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c
deleted file mode 100644
index 5dab03e..0000000
--- a/usr.sbin/natd/natd.c
+++ /dev/null
@@ -1,1477 +0,0 @@
-/*
- * natd - Network Address Translation Daemon for FreeBSD.
- *
- * This software is provided free of charge, with no
- * warranty of any kind, either expressed or implied.
- * Use at your own risk.
- *
- * You may copy, modify and distribute this software (natd.c) freely.
- *
- * Ari Suutari <suutari@iki.fi>
- *
- * $Id: natd.c,v 1.10 1999/03/07 18:23:56 brian Exp $
- */
-
-#define SYSLOG_NAMES
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <machine/in_cksum.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#include <netinet/ip_icmp.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <arpa/inet.h>
-
-#include <alias.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <netdb.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "natd.h"
-
-/*
- * Default values for input and output
- * divert socket ports.
- */
-
-#define DEFAULT_SERVICE "natd"
-
-/*
- * Function prototypes.
- */
-
-static void DoAliasing (int fd, int direction);
-static void DaemonMode ();
-static void HandleRoutingInfo (int fd);
-static void Usage ();
-static char* FormatPacket (struct ip*);
-static void PrintPacket (struct ip*);
-static void SyslogPacket (struct ip*, int priority, char *label);
-static void SetAliasAddressFromIfName (char* ifName);
-static void InitiateShutdown ();
-static void Shutdown ();
-static void RefreshAddr ();
-static void ParseOption (char* option, char* parms, int cmdLine);
-static void ReadConfigFile (char* fileName);
-static void SetupPortRedirect (char* parms);
-static void SetupAddressRedirect (char* parms);
-static void SetupPptpAlias (char* parms);
-static void StrToAddr (char* str, struct in_addr* addr);
-static u_short StrToPort (char* str, char* proto);
-static int StrToProto (char* str);
-static u_short 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 u_short inPort;
-static u_short outPort;
-static u_short 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;
-static int packetDirection;
-static int dropIgnoredIncoming;
-static int logDropped;
-static int logFacility;
-
-int main (int argc, char** argv)
-{
- int divertIn;
- int divertOut;
- int divertInOut;
- 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.
- */
- PacketAliasInit ();
-/*
- * Parse options.
- */
- inPort = 0;
- outPort = 0;
- verbose = 0;
- inOutPort = 0;
- ifName = NULL;
- ifMTU = -1;
- background = 0;
- running = 1;
- assignAliasAddr = 0;
- aliasAddr.s_addr = INADDR_NONE;
- aliasOverhead = 12;
- dynamicMode = 0;
- logDropped = 0;
- logFacility = LOG_DAEMON;
-/*
- * Mark packet buffer empty.
- */
- packetSock = -1;
- packetDirection = DONT_KNOW;
-
- ParseArgs (argc, argv);
-/*
- * Open syslog channel.
- */
- openlog ("natd", LOG_CONS | LOG_PID, logFacility);
-/*
- * Check that valid aliasing address has been given.
- */
- if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL)
- errx (1, "aliasing address not given");
-
- if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL)
- errx (1, "both alias address and interface "
- "name are not allowed");
-/*
- * Check that valid port number is known.
- */
- if (inPort != 0 || outPort != 0)
- if (inPort == 0 || outPort == 0)
- errx (1, "both input and output ports are required");
-
- if (inPort == 0 && outPort == 0 && inOutPort == 0)
- ParseOption ("port", DEFAULT_SERVICE, 0);
-
-/*
- * Check if ignored packets should be dropped.
- */
- dropIgnoredIncoming = PacketAliasSetMode (0, 0);
- dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING;
-/*
- * Create divert sockets. Use only one socket if -p was specified
- * on command line. Otherwise, create separate sockets for
- * outgoing and incoming connnections.
- */
- if (inOutPort) {
-
- divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
- if (divertInOut == -1)
- Quit ("Unable to create divert socket.");
-
- divertIn = -1;
- divertOut = -1;
-/*
- * Bind socket.
- */
-
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = inOutPort;
-
- if (bind (divertInOut,
- (struct sockaddr*) &addr,
- sizeof addr) == -1)
- Quit ("Unable to bind divert socket.");
- }
- else {
-
- divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
- if (divertIn == -1)
- Quit ("Unable to create incoming divert socket.");
-
- divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
- if (divertOut == -1)
- Quit ("Unable to create outgoing divert socket.");
-
- divertInOut = -1;
-
-/*
- * Bind divert sockets.
- */
-
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = inPort;
-
- if (bind (divertIn,
- (struct sockaddr*) &addr,
- sizeof addr) == -1)
- Quit ("Unable to bind incoming divert socket.");
-
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = outPort;
-
- if (bind (divertOut,
- (struct sockaddr*) &addr,
- sizeof addr) == -1)
- Quit ("Unable to bind outgoing divert socket.");
- }
-/*
- * Create routing socket if interface name specified.
- */
- if (ifName && dynamicMode) {
-
- routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
- if (routeSock == -1)
- Quit ("Unable to create routing info socket.");
- }
- else
- routeSock = -1;
-/*
- * Create socket for sending ICMP messages.
- */
- icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (icmpSock == -1)
- Quit ("Unable to create ICMP socket.");
-/*
- * Become a daemon unless verbose mode was requested.
- */
- if (!verbose)
- DaemonMode ();
-/*
- * Catch signals to manage shutdown and
- * refresh of interface address.
- */
- signal (SIGTERM, InitiateShutdown);
- signal (SIGHUP, RefreshAddr);
-/*
- * Set alias address if it has been given.
- */
- if (aliasAddr.s_addr != INADDR_NONE)
- PacketAliasSetAddress (aliasAddr);
-/*
- * We need largest descriptor number for select.
- */
-
- fdMax = -1;
-
- if (divertIn > fdMax)
- fdMax = divertIn;
-
- if (divertOut > fdMax)
- fdMax = divertOut;
-
- if (divertInOut > fdMax)
- fdMax = divertInOut;
-
- if (routeSock > fdMax)
- fdMax = routeSock;
-
- while (running) {
-
- if (divertInOut != -1 && !ifName && packetSock == -1) {
-/*
- * When using only one socket, just call
- * DoAliasing repeatedly to process packets.
- */
- DoAliasing (divertInOut, DONT_KNOW);
- continue;
- }
-/*
- * Build read mask from socket descriptors to select.
- */
- 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);
-
- if (divertOut != -1)
- FD_SET (divertOut, &readMask);
-
- if (divertInOut != -1)
- FD_SET (divertInOut, &readMask);
- }
-/*
- * 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, INPUT);
-
- if (divertOut != -1)
- if (FD_ISSET (divertOut, &readMask))
- DoAliasing (divertOut, OUTPUT);
-
- if (divertInOut != -1)
- if (FD_ISSET (divertInOut, &readMask))
- DoAliasing (divertInOut, DONT_KNOW);
-
- if (routeSock != -1)
- if (FD_ISSET (routeSock, &readMask))
- HandleRoutingInfo (routeSock);
- }
-
- if (background)
- unlink (PIDFILE);
-
- return 0;
-}
-
-static void DaemonMode ()
-{
- FILE* pidFile;
-
- daemon (0, 0);
- background = 1;
-
- pidFile = fopen (PIDFILE, "w");
- if (pidFile) {
-
- fprintf (pidFile, "%d\n", getpid ());
- fclose (pidFile);
- }
-}
-
-static void ParseArgs (int argc, char** argv)
-{
- int arg;
- char* parm;
- char* opt;
- char parmBuf[256];
-
- for (arg = 1; arg < argc; arg++) {
-
- opt = argv[arg];
- if (*opt != '-') {
-
- warnx ("invalid option %s", opt);
- Usage ();
- }
-
- parm = NULL;
- parmBuf[0] = '\0';
-
- while (arg < argc - 1) {
-
- if (argv[arg + 1][0] == '-')
- break;
-
- if (parm)
- strcat (parmBuf, " ");
-
- ++arg;
- parm = parmBuf;
- strcat (parmBuf, argv[arg]);
- }
-
- ParseOption (opt + 1, parm, 1);
- }
-}
-
-static void DoAliasing (int fd, int direction)
-{
- int bytes;
- int origBytes;
- int status;
- int addrSize;
- struct ip* ip;
-
- if (assignAliasAddr) {
-
- SetAliasAddressFromIfName (ifName);
- assignAliasAddr = 0;
- }
-/*
- * Get packet from socket.
- */
- addrSize = sizeof packetAddr;
- origBytes = recvfrom (fd,
- packetBuf,
- sizeof packetBuf,
- 0,
- (struct sockaddr*) &packetAddr,
- &addrSize);
-
- if (origBytes == -1) {
-
- if (errno != EINTR)
- Warn ("read from divert socket failed");
-
- return;
- }
-/*
- * This is a IP packet.
- */
- ip = (struct ip*) packetBuf;
- if (direction == DONT_KNOW)
- if (packetAddr.sin_addr.s_addr == INADDR_ANY)
- direction = OUTPUT;
- else
- direction = INPUT;
-
- if (verbose) {
-
-/*
- * Print packet direction and protocol type.
- */
- printf (direction == OUTPUT ? "Out " : "In ");
-
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- printf ("[TCP] ");
- break;
-
- case IPPROTO_UDP:
- printf ("[UDP] ");
- break;
-
- case IPPROTO_ICMP:
- printf ("[ICMP] ");
- break;
-
- default:
- printf ("[%d] ", ip->ip_p);
- break;
- }
-/*
- * Print addresses.
- */
- PrintPacket (ip);
- }
-
- if (direction == OUTPUT) {
-/*
- * Outgoing packets. Do aliasing.
- */
- PacketAliasOut (packetBuf, IP_MAXPACKET);
- }
- else {
-
-/*
- * Do aliasing.
- */
- status = PacketAliasIn (packetBuf, IP_MAXPACKET);
- if (status == PKT_ALIAS_IGNORED &&
- dropIgnoredIncoming) {
-
- if (verbose)
- printf (" dropped.\n");
-
- if (logDropped)
- SyslogPacket (ip, LOG_WARNING, "denied");
-
- return;
- }
- }
-/*
- * Length might have changed during aliasing.
- */
- bytes = ntohs (ip->ip_len);
-/*
- * Update alias overhead size for outgoing packets.
- */
- if (direction == OUTPUT &&
- bytes - origBytes > aliasOverhead)
- aliasOverhead = bytes - origBytes;
-
- if (verbose) {
-
-/*
- * Print addresses after aliasing.
- */
- printf (" aliased to\n");
- printf (" ");
- PrintPacket (ip);
- printf ("\n");
- }
-
- packetLen = bytes;
- packetSock = fd;
- packetDirection = direction;
-
- FlushPacketBuffer (fd);
-}
-
-static void FlushPacketBuffer (int fd)
-{
- int wrote;
- char msgBuf[80];
-/*
- * Put packet back for processing.
- */
- wrote = sendto (fd,
- packetBuf,
- packetLen,
- 0,
- (struct sockaddr*) &packetAddr,
- sizeof packetAddr);
-
- 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 (packetDirection == OUTPUT &&
- ifMTU != -1)
- SendNeedFragIcmp (icmpSock,
- (struct ip*) packetBuf,
- ifMTU - aliasOverhead);
- }
- else {
-
- sprintf (msgBuf, "failed to write packet back");
- Warn (msgBuf);
- }
- }
-
- packetSock = -1;
-}
-
-static void HandleRoutingInfo (int fd)
-{
- int bytes;
- struct if_msghdr ifMsg;
-/*
- * Get packet from socket.
- */
- bytes = read (fd, &ifMsg, sizeof ifMsg);
- if (bytes == -1) {
-
- Warn ("read from routing socket failed");
- return;
- }
-
- if (ifMsg.ifm_version != RTM_VERSION) {
-
- Warn ("unexpected packet read from routing socket");
- return;
- }
-
- if (verbose)
- printf ("Routing message %X received.\n", ifMsg.ifm_type);
-
- if (ifMsg.ifm_type != RTM_NEWADDR)
- return;
-
- if (verbose && ifMsg.ifm_index == ifIndex)
- printf ("Interface address has changed.\n");
-
- if (ifMsg.ifm_index == ifIndex)
- assignAliasAddr = 1;
-}
-
-static void PrintPacket (struct ip* ip)
-{
- printf ("%s", FormatPacket (ip));
-}
-
-static void SyslogPacket (struct ip* ip, int priority, char *label)
-{
- syslog (priority, "%s %s", label, FormatPacket (ip));
-}
-
-static char* FormatPacket (struct ip* ip)
-{
- static char buf[256];
- struct tcphdr* tcphdr;
- struct udphdr* udphdr;
- struct icmp* icmphdr;
- char src[20];
- char dst[20];
-
- strcpy (src, inet_ntoa (ip->ip_src));
- strcpy (dst, inet_ntoa (ip->ip_dst));
-
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[TCP] %s:%d -> %s:%d",
- src,
- ntohs (tcphdr->th_sport),
- dst,
- ntohs (tcphdr->th_dport));
- break;
-
- case IPPROTO_UDP:
- udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[UDP] %s:%d -> %s:%d",
- src,
- ntohs (udphdr->uh_sport),
- dst,
- ntohs (udphdr->uh_dport));
- break;
-
- case IPPROTO_ICMP:
- icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[ICMP] %s -> %s %u(%u)",
- src,
- dst,
- icmphdr->icmp_type,
- icmphdr->icmp_code);
- break;
-
- default:
- sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
- break;
- }
-
- return buf;
-}
-
-static void SetAliasAddressFromIfName (char* ifName)
-{
- struct ifconf cf;
- struct ifreq buf[32];
- char msg[80];
- struct ifreq* ifPtr;
- int extra;
- int helperSock;
- int bytes;
- struct sockaddr_in* addr;
- int found;
- struct ifreq req;
- char last[10];
-/*
- * Create a dummy socket to access interface information.
- */
- helperSock = socket (AF_INET, SOCK_DGRAM, 0);
- if (helperSock == -1) {
-
- Quit ("Failed to create helper socket.");
- exit (1);
- }
-
- cf.ifc_len = sizeof (buf);
- cf.ifc_req = buf;
-/*
- * Get interface data.
- */
- if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) {
-
- Quit ("Ioctl SIOCGIFCONF failed.");
- exit (1);
- }
-
- ifIndex = 0;
- ifPtr = buf;
- bytes = cf.ifc_len;
- found = 0;
- last[0] = '\0';
-/*
- * Loop through interfaces until one with
- * given name is found. This is done to
- * find correct interface index for routing
- * message processing.
- */
- while (bytes) {
-
- if (ifPtr->ifr_addr.sa_family == AF_INET &&
- !strcmp (ifPtr->ifr_name, ifName)) {
-
- found = 1;
- break;
- }
-
- if (strcmp (last, ifPtr->ifr_name)) {
-
- strcpy (last, ifPtr->ifr_name);
- ++ifIndex;
- }
-
- extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr);
-
- ifPtr++;
- ifPtr = (struct ifreq*) ((char*) ifPtr + extra);
- bytes -= sizeof (struct ifreq) + extra;
- }
-
- if (!found) {
-
- close (helperSock);
- sprintf (msg, "Unknown interface name %s.\n", ifName);
- Quit (msg);
- }
-/*
- * Get MTU size.
- */
- strcpy (req.ifr_name, ifName);
-
- if (ioctl (helperSock, SIOCGIFMTU, &req) == -1)
- Quit ("Cannot get interface mtu size.");
-
- ifMTU = req.ifr_mtu;
-/*
- * Get interface address.
- */
- if (ioctl (helperSock, SIOCGIFADDR, &req) == -1)
- Quit ("Cannot get interface address.");
-
- addr = (struct sockaddr_in*) &req.ifr_addr;
- PacketAliasSetAddress (addr->sin_addr);
- syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes",
- inet_ntoa (addr->sin_addr),
- ifMTU);
-
- close (helperSock);
-}
-
-void Quit (char* msg)
-{
- Warn (msg);
- exit (1);
-}
-
-void Warn (char* msg)
-{
- if (background)
- syslog (LOG_ALERT, "%s (%m)", msg);
- else
- warn (msg);
-}
-
-static void RefreshAddr ()
-{
- signal (SIGHUP, RefreshAddr);
- if (ifName)
- assignAliasAddr = 1;
-}
-
-static void InitiateShutdown ()
-{
-/*
- * Start timer to allow kernel gracefully
- * shutdown existing connections when system
- * is shut down.
- */
- signal (SIGALRM, Shutdown);
- alarm (10);
-}
-
-static void Shutdown ()
-{
- running = 0;
-}
-
-/*
- * Different options recognized by this program.
- */
-
-enum Option {
-
- PacketAliasOption,
- Verbose,
- InPort,
- OutPort,
- Port,
- AliasAddress,
- InterfaceName,
- RedirectPort,
- RedirectAddress,
- ConfigFile,
- DynamicMode,
- PptpAlias,
- ProxyRule,
- LogDenied,
- LogFacility
-};
-
-enum Param {
-
- YesNo,
- Numeric,
- String,
- None,
- Address,
- Service
-};
-
-/*
- * Option information structure (used by ParseOption).
- */
-
-struct OptionInfo {
-
- enum Option type;
- int packetAliasOpt;
- enum Param parm;
- char* parmDescription;
- char* description;
- char* name;
- char* shortName;
-};
-
-/*
- * Table of known options.
- */
-
-static struct OptionInfo optionTable[] = {
-
- { PacketAliasOption,
- PKT_ALIAS_UNREGISTERED_ONLY,
- YesNo,
- "[yes|no]",
- "alias only unregistered addresses",
- "unregistered_only",
- "u" },
-
- { PacketAliasOption,
- PKT_ALIAS_LOG,
- YesNo,
- "[yes|no]",
- "enable logging",
- "log",
- "l" },
-
- { PacketAliasOption,
- PKT_ALIAS_PROXY_ONLY,
- YesNo,
- "[yes|no]",
- "proxy only",
- "proxy_only",
- NULL },
-
- { PacketAliasOption,
- PKT_ALIAS_REVERSE,
- YesNo,
- "[yes|no]",
- "operate in reverse mode",
- "reverse",
- NULL },
-
- { PacketAliasOption,
- PKT_ALIAS_DENY_INCOMING,
- YesNo,
- "[yes|no]",
- "allow incoming connections",
- "deny_incoming",
- "d" },
-
- { PacketAliasOption,
- PKT_ALIAS_USE_SOCKETS,
- YesNo,
- "[yes|no]",
- "use sockets to inhibit port conflict",
- "use_sockets",
- "s" },
-
- { PacketAliasOption,
- PKT_ALIAS_SAME_PORTS,
- YesNo,
- "[yes|no]",
- "try to keep original port numbers for connections",
- "same_ports",
- "m" },
-
- { Verbose,
- 0,
- YesNo,
- "[yes|no]",
- "verbose mode, dump packet information",
- "verbose",
- "v" },
-
- { DynamicMode,
- 0,
- YesNo,
- "[yes|no]",
- "dynamic mode, automatically detect interface address changes",
- "dynamic",
- NULL },
-
- { InPort,
- 0,
- Service,
- "number|service_name",
- "set port for incoming packets",
- "in_port",
- "i" },
-
- { OutPort,
- 0,
- Service,
- "number|service_name",
- "set port for outgoing packets",
- "out_port",
- "o" },
-
- { Port,
- 0,
- Service,
- "number|service_name",
- "set port (defaults to natd/divert)",
- "port",
- "p" },
-
- { AliasAddress,
- 0,
- Address,
- "x.x.x.x",
- "address to use for aliasing",
- "alias_address",
- "a" },
-
- { InterfaceName,
- 0,
- String,
- "network_if_name",
- "take aliasing address from interface",
- "interface",
- "n" },
-
- { ProxyRule,
- 0,
- String,
- "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
- "a.b.c.d:yyyy",
- "add transparent proxying / destination NAT",
- "proxy_rule",
- NULL },
-
- { RedirectPort,
- 0,
- String,
- "tcp|udp local_addr:local_port [public_addr:]public_port"
- " [remote_addr[:remote_port]]",
- "redirect a port for incoming traffic",
- "redirect_port",
- NULL },
-
- { RedirectAddress,
- 0,
- String,
- "local_addr public_addr",
- "define mapping between local and public addresses",
- "redirect_address",
- NULL },
-
- { PptpAlias,
- 0,
- String,
- "src",
- "define inside machine for PPTP traffic",
- "pptpalias",
- NULL },
-
- { ConfigFile,
- 0,
- String,
- "file_name",
- "read options from configuration file",
- "config",
- "f" },
-
- { LogDenied,
- 0,
- YesNo,
- "[yes|no]",
- "enable logging of denied incoming packets",
- "log_denied",
- NULL },
-
- { LogFacility,
- 0,
- String,
- "facility",
- "name of syslog facility to use for logging",
- "log_facility",
- NULL }
-
-};
-
-static void ParseOption (char* option, char* parms, int cmdLine)
-{
- int i;
- struct OptionInfo* info;
- int yesNoValue;
- int aliasValue;
- int numValue;
- u_short uNumValue;
- char* strValue;
- struct in_addr addrValue;
- int max;
- char* end;
- CODE* fac_record = NULL;
-/*
- * Find option from table.
- */
- max = sizeof (optionTable) / sizeof (struct OptionInfo);
- for (i = 0, info = optionTable; i < max; i++, info++) {
-
- if (!strcmp (info->name, option))
- break;
-
- if (info->shortName)
- if (!strcmp (info->shortName, option))
- break;
- }
-
- if (i >= max) {
-
- warnx ("unknown option %s", option);
- Usage ();
- }
-
- uNumValue = 0;
- yesNoValue = 0;
- numValue = 0;
- strValue = NULL;
-/*
- * Check parameters.
- */
- switch (info->parm) {
- case YesNo:
- if (!parms)
- parms = "yes";
-
- if (!strcmp (parms, "yes"))
- yesNoValue = 1;
- else
- if (!strcmp (parms, "no"))
- yesNoValue = 0;
- else
- errx (1, "%s needs yes/no parameter", option);
- break;
-
- case Service:
- if (!parms)
- errx (1, "%s needs service name or "
- "port number parameter",
- option);
-
- uNumValue = StrToPort (parms, "divert");
- break;
-
- case Numeric:
- if (parms)
- numValue = strtol (parms, &end, 10);
- else
- end = parms;
-
- if (end == parms)
- errx (1, "%s needs numeric parameter", option);
- break;
-
- case String:
- strValue = parms;
- if (!strValue)
- errx (1, "%s needs parameter", option);
- break;
-
- case None:
- if (parms)
- errx (1, "%s does not take parameters", option);
- break;
-
- case Address:
- if (!parms)
- errx (1, "%s needs address/host parameter", option);
-
- StrToAddr (parms, &addrValue);
- break;
- }
-
- switch (info->type) {
- case PacketAliasOption:
-
- aliasValue = yesNoValue ? info->packetAliasOpt : 0;
- PacketAliasSetMode (aliasValue, info->packetAliasOpt);
- break;
-
- case Verbose:
- verbose = yesNoValue;
- break;
-
- case DynamicMode:
- dynamicMode = yesNoValue;
- break;
-
- case InPort:
- inPort = uNumValue;
- break;
-
- case OutPort:
- outPort = uNumValue;
- break;
-
- case Port:
- inOutPort = uNumValue;
- break;
-
- case AliasAddress:
- memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
- break;
-
- case RedirectPort:
- SetupPortRedirect (strValue);
- break;
-
- case RedirectAddress:
- SetupAddressRedirect (strValue);
- break;
-
- case PptpAlias:
- SetupPptpAlias (strValue);
- break;
-
- case ProxyRule:
- PacketAliasProxyRule (strValue);
- break;
-
- case InterfaceName:
- if (ifName)
- free (ifName);
-
- ifName = strdup (strValue);
- assignAliasAddr = 1;
- break;
-
- case ConfigFile:
- ReadConfigFile (strValue);
- break;
-
- case LogDenied:
- logDropped = 1;
- break;
-
- case LogFacility:
-
- fac_record = facilitynames;
- while (fac_record->c_name != NULL) {
-
- if (!strcmp (fac_record->c_name, strValue)) {
-
- logFacility = fac_record->c_val;
- break;
-
- }
- else
- fac_record++;
- }
-
- if(fac_record->c_name == NULL)
- errx(1, "Unknown log facility name: %s", strValue);
-
- break;
- }
-}
-
-void ReadConfigFile (char* fileName)
-{
- FILE* file;
- char buf[128];
- char* ptr;
- char* option;
-
- file = fopen (fileName, "r");
- if (!file) {
-
- sprintf (buf, "Cannot open config file %s.\n", fileName);
- Quit (buf);
- }
-
- while (fgets (buf, sizeof (buf), file)) {
-
- ptr = strchr (buf, '\n');
- if (!ptr)
- errx (1, "config line too long: %s", buf);
-
- *ptr = '\0';
- if (buf[0] == '#')
- continue;
-
- ptr = buf;
-/*
- * Skip white space at beginning of line.
- */
- while (*ptr && isspace (*ptr))
- ++ptr;
-
- if (*ptr == '\0')
- continue;
-/*
- * Extract option name.
- */
- option = ptr;
- while (*ptr && !isspace (*ptr))
- ++ptr;
-
- if (*ptr != '\0') {
-
- *ptr = '\0';
- ++ptr;
- }
-/*
- * Skip white space between name and parms.
- */
- while (*ptr && isspace (*ptr))
- ++ptr;
-
- ParseOption (option, *ptr ? ptr : NULL, 0);
- }
-
- fclose (file);
-}
-
-static void Usage ()
-{
- int i;
- int max;
- struct OptionInfo* info;
-
- fprintf (stderr, "Recognized options:\n\n");
-
- max = sizeof (optionTable) / sizeof (struct OptionInfo);
- for (i = 0, info = optionTable; i < max; i++, info++) {
-
- fprintf (stderr, "-%-20s %s\n", info->name,
- info->parmDescription);
-
- if (info->shortName)
- fprintf (stderr, "-%-20s %s\n", info->shortName,
- info->parmDescription);
-
- fprintf (stderr, " %s\n\n", info->description);
- }
-
- exit (1);
-}
-
-void SetupPptpAlias (char* parms)
-{
- char buf[128];
- char* ptr;
- struct in_addr srcAddr;
-
- strcpy (buf, parms);
-
-/*
- * Extract source address.
- */
- ptr = strtok (buf, " \t");
- if (!ptr)
- errx(1, "pptpalias: missing src address");
-
- StrToAddr (ptr, &srcAddr);
- PacketAliasPptp (srcAddr);
-}
-
-void SetupPortRedirect (char* parms)
-{
- char buf[128];
- char* ptr;
- struct in_addr localAddr;
- struct in_addr publicAddr;
- struct in_addr remoteAddr;
- u_short localPort;
- u_short publicPort;
- u_short remotePort;
- int proto;
- char* protoName;
- char* separator;
-
- strcpy (buf, parms);
-/*
- * Extract protocol.
- */
- protoName = strtok (buf, " \t");
- if (!protoName)
- errx (1, "redirect_port: missing protocol");
-
- proto = StrToProto (protoName);
-/*
- * Extract local address.
- */
- ptr = strtok (NULL, " \t");
- if (!ptr)
- errx (1, "redirect_port: missing local address");
-
- localPort = StrToAddrAndPort (ptr, &localAddr, protoName);
-/*
- * Extract public port and optinally address.
- */
- ptr = strtok (NULL, " \t");
- if (!ptr)
- errx (1, "redirect_port: missing public port");
-
- separator = strchr (ptr, ':');
- if (separator)
- publicPort = StrToAddrAndPort (ptr, &publicAddr, protoName);
- else {
-
- publicAddr.s_addr = INADDR_ANY;
- publicPort = StrToPort (ptr, protoName);
- }
-
-/*
- * Extract remote address and optionally port.
- */
- ptr = strtok (NULL, " \t");
- if (ptr) {
-
-
- separator = strchr (ptr, ':');
- if (separator)
- remotePort = StrToAddrAndPort (ptr,
- &remoteAddr,
- protoName);
- else {
-
- remotePort = 0;
- StrToAddr (ptr, &remoteAddr);
- }
- }
- else {
-
- remotePort = 0;
- remoteAddr.s_addr = INADDR_ANY;
- }
-
- PacketAliasRedirectPort (localAddr,
- localPort,
- remoteAddr,
- remotePort,
- publicAddr,
- publicPort,
- proto);
-}
-
-void SetupAddressRedirect (char* parms)
-{
- char buf[128];
- char* ptr;
- struct in_addr localAddr;
- struct in_addr publicAddr;
-
- strcpy (buf, parms);
-/*
- * Extract local address.
- */
- ptr = strtok (buf, " \t");
- if (!ptr)
- errx (1, "redirect_address: missing local address");
-
- StrToAddr (ptr, &localAddr);
-/*
- * Extract public address.
- */
- ptr = strtok (NULL, " \t");
- if (!ptr)
- errx (1, "redirect_address: missing public address");
-
- StrToAddr (ptr, &publicAddr);
- PacketAliasRedirectAddr (localAddr, publicAddr);
-}
-
-void StrToAddr (char* str, struct in_addr* addr)
-{
- struct hostent* hp;
-
- if (inet_aton (str, addr))
- return;
-
- hp = gethostbyname (str);
- if (!hp)
- errx (1, "unknown host %s", str);
-
- memcpy (addr, hp->h_addr, sizeof (struct in_addr));
-}
-
-u_short StrToPort (char* str, char* proto)
-{
- u_short port;
- struct servent* sp;
- char* end;
-
- port = strtol (str, &end, 10);
- if (end != str)
- return htons (port);
-
- sp = getservbyname (str, proto);
- if (!sp)
- errx (1, "unknown service %s/%s", str, proto);
-
- return sp->s_port;
-}
-
-int StrToProto (char* str)
-{
- if (!strcmp (str, "tcp"))
- return IPPROTO_TCP;
-
- if (!strcmp (str, "udp"))
- return IPPROTO_UDP;
-
- errx (1, "unknown protocol %s. Expected tcp or udp", str);
-}
-
-u_short StrToAddrAndPort (char* str, struct in_addr* addr, char* proto)
-{
- char* ptr;
-
- ptr = strchr (str, ':');
- if (!ptr)
- errx (1, "%s is missing port number", str);
-
- *ptr = '\0';
- ++ptr;
-
- StrToAddr (str, addr);
- return StrToPort (ptr, proto);
-}
-
OpenPOWER on IntegriCloud