]> git.saurik.com Git - apple/network_cmds.git/blame - natd.tproj/natd.c
network_cmds-245.15.tar.gz
[apple/network_cmds.git] / natd.tproj / natd.c
CommitLineData
7ba0088d
A
1/*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
a2c93a76
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
7ba0088d 11 *
a2c93a76
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
7ba0088d
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
a2c93a76
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
7ba0088d
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
b7080c8e
A
22/*
23 * natd - Network Address Translation Daemon for FreeBSD.
24 *
25 * This software is provided free of charge, with no
26 * warranty of any kind, either expressed or implied.
27 * Use at your own risk.
28 *
29 * You may copy, modify and distribute this software (natd.c) freely.
30 *
31 * Ari Suutari <suutari@iki.fi>
32 *
7ba0088d
A
33 * Based upon:
34 * $FreeBSD: src/sbin/natd/natd.c,v 1.25.2.3 2000/07/11 20:00:57 ru Exp $
b7080c8e
A
35 */
36
37#define SYSLOG_NAMES
38
39#include <sys/types.h>
40#include <sys/socket.h>
2b484d24
A
41#include <net/if.h>
42#include <ifaddrs.h>
7ba0088d 43#include <sys/sysctl.h>
b7080c8e
A
44#include <sys/time.h>
45
46#include <netinet/in.h>
47#include <netinet/in_systm.h>
48#include <netinet/ip.h>
49#include <netinet/tcp.h>
50#include <netinet/udp.h>
51#include <netinet/ip_icmp.h>
b7080c8e 52#include <net/if.h>
7ba0088d 53#include <net/if_dl.h>
b7080c8e
A
54#include <net/route.h>
55#include <arpa/inet.h>
56
57#include <alias.h>
58#include <ctype.h>
59#include <err.h>
60#include <errno.h>
61#include <netdb.h>
62#include <signal.h>
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>
66#include <syslog.h>
67#include <unistd.h>
2b484d24
A
68#include <mach/mach_time.h>
69#include <mach/clock_types.h>
b7080c8e
A
70
71#include "natd.h"
72
73/*
74 * Default values for input and output
75 * divert socket ports.
76 */
77
78#define DEFAULT_SERVICE "natd"
79
80/*
81 * Definition of a port range, and macros to deal with values.
82 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
83 * LO 16-bits == number of ports in range
84 * NOTES: - Port values are not stored in network byte order.
85 */
86
87typedef u_long port_range;
88
89#define GETLOPORT(x) ((x) >> 0x10)
90#define GETNUMPORTS(x) ((x) & 0x0000ffff)
91#define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
92
93/* Set y to be the low-port value in port_range variable x. */
94#define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
95
96/* Set y to be the number of ports in port_range variable x. */
97#define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
98
99/*
100 * Function prototypes.
101 */
102
103static void DoAliasing (int fd, int direction);
104static void DaemonMode (void);
105static void HandleRoutingInfo (int fd);
106static void Usage (void);
107static char* FormatPacket (struct ip*);
108static void PrintPacket (struct ip*);
109static void SyslogPacket (struct ip*, int priority, const char *label);
7ba0088d 110static void SetAliasAddressFromIfName (const char *ifName);
b7080c8e
A
111static void InitiateShutdown (int);
112static void Shutdown (int);
113static void RefreshAddr (int);
7ba0088d 114static void ParseOption (const char* option, const char* parms);
b7080c8e
A
115static void ReadConfigFile (const char* fileName);
116static void SetupPortRedirect (const char* parms);
7ba0088d 117static void SetupProtoRedirect(const char* parms);
b7080c8e 118static void SetupAddressRedirect (const char* parms);
b7080c8e
A
119static void StrToAddr (const char* str, struct in_addr* addr);
120static u_short StrToPort (const char* str, const char* proto);
121static int StrToPortRange (const char* str, const char* proto, port_range *portRange);
122static int StrToProto (const char* str);
123static int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange);
124static void ParseArgs (int argc, char** argv);
125static void FlushPacketBuffer (int fd);
7ba0088d 126static void SetupPunchFW(const char *strValue);
b7080c8e
A
127
128/*
129 * Globals.
130 */
131
132static int verbose;
133static int background;
134static int running;
135static int assignAliasAddr;
136static char* ifName;
137static int ifIndex;
138static u_short inPort;
139static u_short outPort;
140static u_short inOutPort;
141static struct in_addr aliasAddr;
142static int dynamicMode;
285dd90c 143static int clampMSS;
b7080c8e
A
144static int ifMTU;
145static int aliasOverhead;
146static int icmpSock;
147static char packetBuf[IP_MAXPACKET];
148static int packetLen;
149static struct sockaddr_in packetAddr;
150static int packetSock;
151static int packetDirection;
152static int dropIgnoredIncoming;
153static int logDropped;
154static int logFacility;
155
2b484d24
A
156#define NATPORTMAP 1
157
158#ifdef NATPORTMAP
159#define NATPMPORT 5351
160
161#define NATPMVERSION 0
162#define PUBLICADDRREQ 0
163#define MAPUDPREQ 1
164#define MAPTCPREQ 2
165#define MAPUDPTCPREQ 3
166#define SERVERREPLYOP 128
167#define PUBLICADDRRLY SERVERREPLYOP+PUBLICADDRREQ
168
169#define SUCCESS 0
170#define NOTSUPPORTEDVERSION 1
171#define NOTAUTHORIZED 2
172#define NETWORKFAILURE 3
173#define OUTOFRESOURCES 4
174#define UNSUPPORTEDOPCODE 5
175#define MAXRETRY 10
176#define TIMER_RATE 250
177
178#define FAILED -1
179
180typedef struct stdportmaprequest{
181 char version;
182 unsigned char opcode;
183 unsigned short result;
184 unsigned int epoch;
185 char data[4];
186 }stdportmaprequest;
187
188typedef struct publicaddrreply{
189 char version;
190 unsigned char opcode;
191 unsigned short result;
192 unsigned int epoch;
193 struct in_addr addr;
194 }publicaddrreply;
195typedef struct publicportreq{
196 char version;
197 unsigned char opcode;
198 unsigned short result;
199 unsigned int epoch;
200 unsigned short privateport;
201 unsigned short publicport;
202 int lifetime; /* in second */
203 }publicportreq;
204typedef struct stderrreply{
205 char version;
206 unsigned char opcode;
207 unsigned short result;
208 unsigned int epoch;
209 }stderrreply;
210
211
212static int enable_natportmap = 0;
213static struct in_addr lastassignaliasAddr;
214static int portmapSock = -1;
215static struct in_addr *forwardedinterfaceaddr;
216static char **forwardedinterfacename;
217static int numofinterfaces = 0; /* has to be at least one */
218static u_short natPMPport;
219static int numoftries=MAXRETRY;
220static struct itimerval itval;
221static int Natdtimerset = 0;
222static double secdivisor;
223
224
225static void HandlePortMap( int fd );
226static void SendPortMapResponse( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, unsigned char origopcode, unsigned short result);
227static void SendPublicAddress( int fd, struct sockaddr_in *clientaddr, int clientaddrlen );
228static void SendPublicPortResponse( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, publicportreq *reply, int publicport);
229static void Doubletime( struct timeval *tvp);
230static void Stoptimer();
231static void Natdtimer();
232static void SendPortMapMulti( );
233static void NotifyPublicAddress();
234static void DoPortMapping( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, publicportreq *req);
235static void NatPortMapPInit();
236static u_short get_natportmap_port(void);
237
238extern int FindAliasPortOut(struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short pub_port, u_char proto, int lifetime, char addmapping);
239
240#endif
241
b7080c8e
A
242int main (int argc, char** argv)
243{
244 int divertIn;
245 int divertOut;
246 int divertInOut;
247 int routeSock;
248 struct sockaddr_in addr;
249 fd_set readMask;
250 fd_set writeMask;
251 int fdMax;
252/*
253 * Initialize packet aliasing software.
254 * Done already here to be able to alter option bits
255 * during command line and configuration file processing.
256 */
257 PacketAliasInit ();
258/*
259 * Parse options.
260 */
261 inPort = 0;
262 outPort = 0;
263 verbose = 0;
264 inOutPort = 0;
265 ifName = NULL;
266 ifMTU = -1;
267 background = 0;
268 running = 1;
269 assignAliasAddr = 0;
270 aliasAddr.s_addr = INADDR_NONE;
2b484d24
A
271#ifdef NATPORTMAP
272 lastassignaliasAddr.s_addr = INADDR_NONE;
273#endif
b7080c8e
A
274 aliasOverhead = 12;
275 dynamicMode = 0;
276 logDropped = 0;
277 logFacility = LOG_DAEMON;
278/*
279 * Mark packet buffer empty.
280 */
281 packetSock = -1;
282 packetDirection = DONT_KNOW;
283
284 ParseArgs (argc, argv);
285/*
286 * Open syslog channel.
287 */
7ba0088d
A
288 openlog ("natd", LOG_CONS | LOG_PID | (verbose ? LOG_PERROR : 0),
289 logFacility);
b7080c8e
A
290/*
291 * Check that valid aliasing address has been given.
292 */
293 if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL)
294 errx (1, "aliasing address not given");
295
b7080c8e
A
296/*
297 * Check that valid port number is known.
298 */
299 if (inPort != 0 || outPort != 0)
300 if (inPort == 0 || outPort == 0)
301 errx (1, "both input and output ports are required");
302
303 if (inPort == 0 && outPort == 0 && inOutPort == 0)
7ba0088d 304 ParseOption ("port", DEFAULT_SERVICE);
b7080c8e
A
305
306/*
307 * Check if ignored packets should be dropped.
308 */
309 dropIgnoredIncoming = PacketAliasSetMode (0, 0);
310 dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING;
311/*
312 * Create divert sockets. Use only one socket if -p was specified
313 * on command line. Otherwise, create separate sockets for
314 * outgoing and incoming connnections.
315 */
316 if (inOutPort) {
317
318 divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
319 if (divertInOut == -1)
320 Quit ("Unable to create divert socket.");
321
322 divertIn = -1;
323 divertOut = -1;
324/*
325 * Bind socket.
326 */
327
328 addr.sin_family = AF_INET;
329 addr.sin_addr.s_addr = INADDR_ANY;
330 addr.sin_port = inOutPort;
331
332 if (bind (divertInOut,
333 (struct sockaddr*) &addr,
334 sizeof addr) == -1)
335 Quit ("Unable to bind divert socket.");
336 }
337 else {
338
339 divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
340 if (divertIn == -1)
341 Quit ("Unable to create incoming divert socket.");
342
343 divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
344 if (divertOut == -1)
345 Quit ("Unable to create outgoing divert socket.");
346
347 divertInOut = -1;
348
349/*
350 * Bind divert sockets.
351 */
352
353 addr.sin_family = AF_INET;
354 addr.sin_addr.s_addr = INADDR_ANY;
355 addr.sin_port = inPort;
356
357 if (bind (divertIn,
358 (struct sockaddr*) &addr,
359 sizeof addr) == -1)
360 Quit ("Unable to bind incoming divert socket.");
361
362 addr.sin_family = AF_INET;
363 addr.sin_addr.s_addr = INADDR_ANY;
364 addr.sin_port = outPort;
365
366 if (bind (divertOut,
367 (struct sockaddr*) &addr,
368 sizeof addr) == -1)
369 Quit ("Unable to bind outgoing divert socket.");
370 }
371/*
7ba0088d 372 * Create routing socket if interface name specified and in dynamic mode.
b7080c8e 373 */
7ba0088d
A
374 routeSock = -1;
375 if (ifName) {
376 if (dynamicMode) {
b7080c8e 377
7ba0088d
A
378 routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
379 if (routeSock == -1)
380 Quit ("Unable to create routing info socket.");
381
382 assignAliasAddr = 1;
383 }
2b484d24 384 else{
7ba0088d 385 SetAliasAddressFromIfName (ifName);
2b484d24 386 }
b7080c8e 387 }
b7080c8e
A
388/*
389 * Create socket for sending ICMP messages.
390 */
391 icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
392 if (icmpSock == -1)
393 Quit ("Unable to create ICMP socket.");
394
395/*
396 * And disable reads for the socket, otherwise it slowly fills
397 * up with received icmps which we do not use.
398 */
399 shutdown(icmpSock, SHUT_RD);
400
2b484d24
A
401
402#if NATPORTMAP
403 if ( enable_natportmap )
404 {
405 /* create socket to listen for port mapping */
406 portmapSock = socket( AF_INET, SOCK_DGRAM, 0);
407 if ( portmapSock != -1 )
408 {
409 natPMPport = get_natportmap_port();
410 addr.sin_family = AF_INET;
411 addr.sin_addr.s_addr = INADDR_ANY;
412 addr.sin_port = NATPMPORT;
413
414 if (bind ( portmapSock,
415 (struct sockaddr*) &addr,
416 sizeof addr) == -1)
417 printf("Binding to NATPM port failed!\n");
418
419 /* NATPORTMAPP initial set up */
420 NatPortMapPInit();
421 }
422 if ( !Natdtimerset ){
423 Natdtimerset = 1;
424 signal(SIGALRM, Natdtimer);
425 }
426 }
427#endif
b7080c8e
A
428/*
429 * Become a daemon unless verbose mode was requested.
430 */
431 if (!verbose)
432 DaemonMode ();
433/*
434 * Catch signals to manage shutdown and
435 * refresh of interface address.
436 */
7ba0088d
A
437 siginterrupt(SIGTERM, 1);
438 siginterrupt(SIGHUP, 1);
b7080c8e
A
439 signal (SIGTERM, InitiateShutdown);
440 signal (SIGHUP, RefreshAddr);
441/*
442 * Set alias address if it has been given.
443 */
444 if (aliasAddr.s_addr != INADDR_NONE)
2b484d24 445 {
b7080c8e 446 PacketAliasSetAddress (aliasAddr);
2b484d24
A
447#ifdef NATPORTMAP
448 if ( (enable_natportmap) && (aliasAddr.s_addr != lastassignaliasAddr.s_addr) ){
449 lastassignaliasAddr.s_addr = aliasAddr.s_addr;
450 NotifyPublicAddress();
451 }
452#endif
453 }
b7080c8e
A
454/*
455 * We need largest descriptor number for select.
456 */
457
458 fdMax = -1;
459
460 if (divertIn > fdMax)
461 fdMax = divertIn;
462
463 if (divertOut > fdMax)
464 fdMax = divertOut;
465
466 if (divertInOut > fdMax)
467 fdMax = divertInOut;
468
469 if (routeSock > fdMax)
470 fdMax = routeSock;
471
2b484d24
A
472#ifdef NATPORTMAP
473 if ( portmapSock > fdMax )
474 fdMax = portmapSock;
475
476#endif
477
b7080c8e
A
478 while (running) {
479
480 if (divertInOut != -1 && !ifName && packetSock == -1) {
481/*
482 * When using only one socket, just call
483 * DoAliasing repeatedly to process packets.
484 */
485 DoAliasing (divertInOut, DONT_KNOW);
486 continue;
487 }
488/*
489 * Build read mask from socket descriptors to select.
490 */
491 FD_ZERO (&readMask);
492 FD_ZERO (&writeMask);
493
494/*
495 * If there is unsent packet in buffer, use select
496 * to check when socket comes writable again.
497 */
498 if (packetSock != -1) {
499
500 FD_SET (packetSock, &writeMask);
501 }
502 else {
503/*
504 * No unsent packet exists - safe to check if
505 * new ones are available.
506 */
507 if (divertIn != -1)
508 FD_SET (divertIn, &readMask);
509
510 if (divertOut != -1)
511 FD_SET (divertOut, &readMask);
512
513 if (divertInOut != -1)
514 FD_SET (divertInOut, &readMask);
515 }
516/*
517 * Routing info is processed always.
518 */
519 if (routeSock != -1)
520 FD_SET (routeSock, &readMask);
2b484d24
A
521#ifdef NATPORTMAP
522 if ( portmapSock != -1 )
523 FD_SET (portmapSock, &readMask);
524#endif
b7080c8e
A
525 if (select (fdMax + 1,
526 &readMask,
527 &writeMask,
528 NULL,
529 NULL) == -1) {
530
531 if (errno == EINTR)
532 continue;
533
534 Quit ("Select failed.");
535 }
536
537 if (packetSock != -1)
538 if (FD_ISSET (packetSock, &writeMask))
539 FlushPacketBuffer (packetSock);
540
541 if (divertIn != -1)
542 if (FD_ISSET (divertIn, &readMask))
543 DoAliasing (divertIn, INPUT);
544
545 if (divertOut != -1)
546 if (FD_ISSET (divertOut, &readMask))
547 DoAliasing (divertOut, OUTPUT);
548
549 if (divertInOut != -1)
550 if (FD_ISSET (divertInOut, &readMask))
551 DoAliasing (divertInOut, DONT_KNOW);
552
553 if (routeSock != -1)
554 if (FD_ISSET (routeSock, &readMask))
555 HandleRoutingInfo (routeSock);
2b484d24
A
556#ifdef NATPORTMAP
557 if ( portmapSock != -1)
558 if (FD_ISSET (portmapSock, &readMask))
559 HandlePortMap( portmapSock );
560#endif
b7080c8e
A
561 }
562
563 if (background)
564 unlink (PIDFILE);
565
566 return 0;
567}
568
569static void DaemonMode ()
570{
571 FILE* pidFile;
572
573 daemon (0, 0);
574 background = 1;
575
576 pidFile = fopen (PIDFILE, "w");
577 if (pidFile) {
578
579 fprintf (pidFile, "%d\n", getpid ());
580 fclose (pidFile);
581 }
582}
583
584static void ParseArgs (int argc, char** argv)
585{
586 int arg;
b7080c8e
A
587 char* opt;
588 char parmBuf[256];
7ba0088d 589 int len; /* bounds checking */
b7080c8e
A
590
591 for (arg = 1; arg < argc; arg++) {
592
593 opt = argv[arg];
594 if (*opt != '-') {
595
596 warnx ("invalid option %s", opt);
597 Usage ();
598 }
599
b7080c8e 600 parmBuf[0] = '\0';
7ba0088d 601 len = 0;
b7080c8e
A
602
603 while (arg < argc - 1) {
604
605 if (argv[arg + 1][0] == '-')
606 break;
607
7ba0088d
A
608 if (len) {
609 strncat (parmBuf, " ", sizeof(parmBuf) - (len + 1));
610 len += strlen(parmBuf + len);
611 }
b7080c8e
A
612
613 ++arg;
7ba0088d
A
614 strncat (parmBuf, argv[arg], sizeof(parmBuf) - (len + 1));
615 len += strlen(parmBuf + len);
616
b7080c8e
A
617 }
618
7ba0088d
A
619 ParseOption (opt + 1, (len ? parmBuf : NULL));
620
b7080c8e
A
621 }
622}
623
624static void DoAliasing (int fd, int direction)
625{
626 int bytes;
627 int origBytes;
628 int status;
629 int addrSize;
630 struct ip* ip;
631
632 if (assignAliasAddr) {
633
634 SetAliasAddressFromIfName (ifName);
635 assignAliasAddr = 0;
636 }
637/*
638 * Get packet from socket.
639 */
640 addrSize = sizeof packetAddr;
641 origBytes = recvfrom (fd,
642 packetBuf,
643 sizeof packetBuf,
644 0,
645 (struct sockaddr*) &packetAddr,
646 &addrSize);
647
648 if (origBytes == -1) {
649
650 if (errno != EINTR)
651 Warn ("read from divert socket failed");
652
653 return;
654 }
655/*
656 * This is a IP packet.
657 */
658 ip = (struct ip*) packetBuf;
7ba0088d 659 if (direction == DONT_KNOW) {
b7080c8e
A
660 if (packetAddr.sin_addr.s_addr == INADDR_ANY)
661 direction = OUTPUT;
662 else
663 direction = INPUT;
7ba0088d 664 }
b7080c8e
A
665
666 if (verbose) {
b7080c8e
A
667/*
668 * Print packet direction and protocol type.
669 */
670 printf (direction == OUTPUT ? "Out " : "In ");
671
672 switch (ip->ip_p) {
673 case IPPROTO_TCP:
674 printf ("[TCP] ");
675 break;
676
677 case IPPROTO_UDP:
678 printf ("[UDP] ");
679 break;
680
681 case IPPROTO_ICMP:
682 printf ("[ICMP] ");
683 break;
684
685 default:
686 printf ("[%d] ", ip->ip_p);
687 break;
688 }
689/*
690 * Print addresses.
691 */
692 PrintPacket (ip);
693 }
694
695 if (direction == OUTPUT) {
696/*
697 * Outgoing packets. Do aliasing.
698 */
699 PacketAliasOut (packetBuf, IP_MAXPACKET);
700 }
701 else {
702
703/*
704 * Do aliasing.
705 */
706 status = PacketAliasIn (packetBuf, IP_MAXPACKET);
707 if (status == PKT_ALIAS_IGNORED &&
708 dropIgnoredIncoming) {
709
710 if (verbose)
711 printf (" dropped.\n");
712
713 if (logDropped)
714 SyslogPacket (ip, LOG_WARNING, "denied");
715
716 return;
717 }
718 }
719/*
720 * Length might have changed during aliasing.
721 */
722 bytes = ntohs (ip->ip_len);
723/*
724 * Update alias overhead size for outgoing packets.
725 */
726 if (direction == OUTPUT &&
727 bytes - origBytes > aliasOverhead)
728 aliasOverhead = bytes - origBytes;
729
730 if (verbose) {
731
732/*
733 * Print addresses after aliasing.
734 */
735 printf (" aliased to\n");
736 printf (" ");
737 PrintPacket (ip);
738 printf ("\n");
739 }
740
741 packetLen = bytes;
742 packetSock = fd;
743 packetDirection = direction;
744
745 FlushPacketBuffer (fd);
746}
747
748static void FlushPacketBuffer (int fd)
749{
750 int wrote;
751 char msgBuf[80];
752/*
753 * Put packet back for processing.
754 */
755 wrote = sendto (fd,
756 packetBuf,
757 packetLen,
758 0,
759 (struct sockaddr*) &packetAddr,
760 sizeof packetAddr);
761
762 if (wrote != packetLen) {
763/*
764 * If buffer space is not available,
765 * just return. Main loop will take care of
766 * retrying send when space becomes available.
767 */
768 if (errno == ENOBUFS)
769 return;
770
771 if (errno == EMSGSIZE) {
772
773 if (packetDirection == OUTPUT &&
774 ifMTU != -1)
775 SendNeedFragIcmp (icmpSock,
776 (struct ip*) packetBuf,
777 ifMTU - aliasOverhead);
778 }
779 else {
780
781 sprintf (msgBuf, "failed to write packet back");
782 Warn (msgBuf);
783 }
784 }
785
786 packetSock = -1;
787}
788
789static void HandleRoutingInfo (int fd)
790{
791 int bytes;
792 struct if_msghdr ifMsg;
793/*
794 * Get packet from socket.
795 */
796 bytes = read (fd, &ifMsg, sizeof ifMsg);
797 if (bytes == -1) {
798
799 Warn ("read from routing socket failed");
800 return;
801 }
802
803 if (ifMsg.ifm_version != RTM_VERSION) {
804
805 Warn ("unexpected packet read from routing socket");
806 return;
807 }
808
809 if (verbose)
7ba0088d 810 printf ("Routing message %#x received.\n", ifMsg.ifm_type);
b7080c8e 811
7ba0088d
A
812 if ((ifMsg.ifm_type == RTM_NEWADDR || ifMsg.ifm_type == RTM_IFINFO) &&
813 ifMsg.ifm_index == ifIndex) {
814 if (verbose)
815 printf("Interface address/MTU has probably changed.\n");
b7080c8e 816 assignAliasAddr = 1;
7ba0088d 817 }
b7080c8e
A
818}
819
2b484d24
A
820#ifdef NATPORTMAP
821
822void getdivisor()
823{
824 struct mach_timebase_info info;
825
826 (void) mach_timebase_info (&info);
827
828 secdivisor = ( (double)info.denom / (double)info.numer) * 1000;
829
830}
831
832unsigned int getuptime()
833{
834 uint64_t now;
835 unsigned long epochtime;
836
837 now = mach_absolute_time();
838 epochtime = (now / secdivisor) /USEC_PER_SEC;
839 return( epochtime );
840
841}
842
843/* return NATPORTMAP port defined in /etc/servcies if there's one, else use NATPMPORT */
844static u_short get_natportmap_port(void)
845{
846 struct servent *ent;
847
848 ent = getservbyname( "natportmap", "udp" );
849 if (ent != NULL){
850 return( ent->s_port );
851 }
852 return( NATPMPORT );
853}
854
855/* set up neccessary info for doing NatPortMapP */
856static void NatPortMapPInit()
857{
858 int i;
859 struct ifaddrs *ifap, *ifa;
860
861 forwardedinterfaceaddr = (struct in_addr *)
862 malloc(numofinterfaces * sizeof(*forwardedinterfaceaddr));
863 bzero(forwardedinterfaceaddr,
864 numofinterfaces * sizeof(*forwardedinterfaceaddr));
865 /* interface address hasn't been set up, get interface address */
866 getifaddrs(&ifap);
867 for ( ifa= ifap; ifa; ifa=ifa->ifa_next)
868 {
869 struct sockaddr_in * a;
870 if (ifa->ifa_addr->sa_family != AF_INET)
871 {
872 continue;
873 }
874 a = (struct sockaddr_in *)ifa->ifa_addr;
875 for ( i = 0; i < numofinterfaces; i++ )
876 {
877 if (strcmp(ifa->ifa_name, forwardedinterfacename[i]))
878 {
879 continue;
880 }
881 if (forwardedinterfaceaddr[i].s_addr == 0)
882 {
883 /* copy the first IP address */
884 forwardedinterfaceaddr[i] = a->sin_addr;
885 }
886 break;
887 }
888 }
889 freeifaddrs( ifap );
890 getdivisor();
891}
892
893/* SendPortMapResponse */
894/* send generic reponses to NATPORTMAP requests */
895static void SendPortMapResponse( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, unsigned char origopcode, unsigned short result)
896{
897 stderrreply reply;
898 int bytes;
899
900 reply.version = NATPMVERSION;
901 reply.opcode = origopcode + SERVERREPLYOP;
902 reply.result = result;
903 reply.epoch = getuptime();
904 bytes = sendto( fd, (void*)&reply, sizeof(reply), 0, (struct sockaddr*)clientaddr, clientaddrlen );
905 if ( bytes != sizeof(reply) )
906 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply.opcode );
907}
908
909/* SendPublicAddress */
910/* return public address to requestor */
911static void SendPublicAddress( int fd, struct sockaddr_in *clientaddr, int clientaddrlen )
912{
913
914 publicaddrreply reply;
915 int bytes;
916
917 reply.version = NATPMVERSION;
918 reply.opcode = SERVERREPLYOP + PUBLICADDRREQ;
919 reply.result = SUCCESS;
920 reply.addr = lastassignaliasAddr;
921 reply.epoch = getuptime();
922
923 bytes = sendto (fd, (void*)&reply, sizeof(reply), 0, (struct sockaddr*)clientaddr, clientaddrlen);
924 if ( bytes != sizeof(reply) )
925 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply.opcode );
926}
927
928/* SendPublicPortResponse */
929/* response for portmap request and portmap removal request */
930/* publicport <= 0 means error */
931static void SendPublicPortResponse( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, publicportreq *reply, int publicport)
932{
933
934 int bytes;
935
936 reply->version = NATPMVERSION;
937 reply->opcode = SERVERREPLYOP + reply->opcode;
938 if ( publicport <= 0)
939 /* error in port mapping */
940 reply->result = OUTOFRESOURCES;
941 else
942 reply->result = SUCCESS;
943 reply->epoch = getuptime();
944
945 if ( reply->lifetime ) /* not delete mapping */
946 reply->publicport = publicport;
947 bytes = sendto (fd, (void*)reply, sizeof(publicportreq), 0, (struct sockaddr*)clientaddr, clientaddrlen);
948 if ( bytes != sizeof(publicportreq) )
949 printf( "PORTMAP::problem sending portmap reply - opcode %d\n", reply->opcode );
950}
951
952/* SendPortMapMulti */
953/* send multicast to local network for new alias address */
954static void SendPortMapMulti()
955{
956
957 publicaddrreply reply;
958 int bytes;
959 struct sockaddr_in multiaddr;
960 int multisock;
961 int i;
962
963#define LOCALGROUP "224.0.0.1"
964 numoftries++;
965 memset(&multiaddr,0,sizeof(struct sockaddr_in));
966 multiaddr.sin_family=AF_INET;
967 multiaddr.sin_addr.s_addr=inet_addr(LOCALGROUP);
968 multiaddr.sin_port=htons(NATPMPORT);
969 reply.version = NATPMVERSION;
970 reply.opcode = SERVERREPLYOP + PUBLICADDRREQ;
971 reply.result = SUCCESS;
972 reply.addr = lastassignaliasAddr;
973 reply.epoch = 0;
974
975 /* send multicast to all forwarded interfaces */
976 for ( i = 0; i < numofinterfaces; i++)
977 {
978 if (forwardedinterfaceaddr[i].s_addr == 0)
979 {
980 continue;
981 }
982 multisock = socket( AF_INET, SOCK_DGRAM, 0);
983
984 if ( multisock == -1 )
985 {
986 printf("cannot get socket for sending multicast\n");
987 return;
988 }
989 if (setsockopt(multisock, IPPROTO_IP, IP_MULTICAST_IF, &forwardedinterfaceaddr[i], sizeof(struct in_addr)) < 0)
990 {
991 printf("setsockopt failed\n");
992 close(multisock);
993 continue;
994 }
995 bytes = sendto (multisock, (void*)&reply, sizeof(reply), 0, (struct sockaddr*)&multiaddr, sizeof(multiaddr));
996 if ( bytes != sizeof(reply) )
997 printf( "PORTMAP::problem sending multicast alias address - opcode %d\n", reply.opcode );
998 close(multisock);
999 }
1000
1001}
1002
1003/* double the time value */
1004static void Doubletime( struct timeval *tvp)
1005{
1006
1007 if ( tvp->tv_sec )
1008 tvp->tv_sec *= 2;
1009 if ( tvp->tv_usec )
1010 tvp->tv_usec *= 2;
1011 if (tvp->tv_usec >= 1000000) {
1012 tvp->tv_sec += tvp->tv_usec / 1000000;
1013 tvp->tv_usec = tvp->tv_usec % 1000000;
1014 }
1015}
1016
1017/* stop running natd timer */
1018static void Stoptimer()
1019{
1020 itval.it_value.tv_usec = 0;
1021 if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
1022 printf( "setitimer err: %d\n", errno);
1023}
1024
1025/* natdtimer */
1026/* timer routine to send new public IP address */
1027static void Natdtimer()
1028{
1029 if ( !enable_natportmap )
1030 return;
1031
1032 SendPortMapMulti();
1033
1034 if ( numoftries < MAXRETRY ){
1035 Doubletime( &itval.it_value);
1036 itval.it_interval = itval.it_value;
1037 if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
1038 printf( "setitimer err: %d\n", errno);
1039 }
1040 else
1041 {
1042 Stoptimer();
1043 return;
1044 }
1045
1046}
1047
1048/* NotifyPublicAddress */
1049/* Advertise new public address */
1050static void NotifyPublicAddress()
1051{
1052 if ( numoftries < MAXRETRY)
1053 {
1054 /* there is an old timer running, cancel it */
1055 Stoptimer();
1056 }
1057 /* send up new timer */
1058 numoftries = 0;
1059 SendPortMapMulti();
1060 itval.it_value.tv_sec = 0;
1061 itval.it_value.tv_usec = TIMER_RATE;
1062 itval.it_interval.tv_sec = 0;
1063 itval.it_interval.tv_usec = TIMER_RATE;
1064 if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
1065 printf( "setitimer err: %d\n", errno);
1066
1067}
1068
1069/* DoPortMapping */
1070/* find/add/remove port mapping from alias manager */
1071void DoPortMapping( int fd, struct sockaddr_in *clientaddr, int clientaddrlen, publicportreq *req)
1072{
1073 u_char proto = IPPROTO_TCP;
1074 int aliasport;
1075
1076 if ( req->opcode == MAPUDPREQ)
1077 proto = IPPROTO_UDP;
1078 if ( req->lifetime == 0)
1079 {
1080 /* remove port mapping */
1081 if ( !FindAliasPortOut( clientaddr->sin_addr, lastassignaliasAddr, req->privateport, req->publicport, proto, req->lifetime, 0))
1082 /* FindAliasPortOut returns no error, port successfully removed, return no error response to client */
1083 SendPublicPortResponse( fd, clientaddr, clientaddrlen, req, 1 );
1084 else
1085 /* deleting port fails, return error */
1086 SendPublicPortResponse( fd, clientaddr, clientaddrlen, req, -1 );
1087 }
1088 else
1089 {
1090 /* look for port mapping - public port is ignored in this case */
1091 /* create port mapping - map provided public port to private port if public port is not 0 */
1092 aliasport = FindAliasPortOut( clientaddr->sin_addr, lastassignaliasAddr, req->privateport, req->publicport, proto, req->lifetime, 1);
1093 /* aliasport should be non zero if mapping is successfully, else -1 is returned, alias port shouldn't be zero???? */
1094 SendPublicPortResponse( fd, clientaddr, clientaddrlen, req, aliasport );
1095
1096 }
1097}
1098
1099/* HandlePortMap */
1100/* handle all packets sent to NATPORTMAP port */
1101static void HandlePortMap( int fd )
1102{
1103#define MAXBUFFERSIZE 100
1104
1105 struct sockaddr_in clientaddr;
1106 int clientaddrlen;
1107 unsigned char buffer[MAXBUFFERSIZE];
1108 int bytes;
1109 unsigned short result = SUCCESS;
1110 struct stdportmaprequest *req;
1111
1112 clientaddrlen = sizeof( clientaddr );
1113 bytes = recvfrom( fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientaddr, &clientaddrlen);
1114 if ( bytes == -1 )
1115 {
1116 printf( "Read NATPM port error\n");
1117 return;
1118 }
1119 req = (struct stdportmaprequest*)buffer;
1120
1121#ifdef DEBUG
1122 {
1123 int i;
1124
1125 for ( i = 0; i<bytes; i++)
1126 {
1127 printf("%d", buffer[i]);
1128 }
1129 printf("\n");
1130 }
1131#endif
1132 /* check client version */
1133 if ( req->version > NATPMVERSION )
1134 result = NOTSUPPORTEDVERSION;
1135 else if ( !enable_natportmap )
1136 /* natd wasn't launched with portmapping enabled */
1137 result = NOTAUTHORIZED;
1138
1139 if ( result )
1140 {
1141 SendPortMapResponse( fd, &clientaddr, clientaddrlen, req->opcode, result );
1142 return;
1143 }
1144
1145 switch ( req->opcode )
1146 {
1147 case PUBLICADDRREQ:
1148 {
1149 SendPublicAddress(fd, &clientaddr, clientaddrlen);
1150 break;
1151 }
1152
1153 case MAPUDPREQ:
1154 case MAPTCPREQ:
1155 case MAPUDPTCPREQ:
1156 {
1157 DoPortMapping( fd, &clientaddr, clientaddrlen, (publicportreq*)req);
1158 break;
1159 }
1160
1161
1162 default:
1163 SendPortMapResponse( fd, &clientaddr, clientaddrlen, req->opcode, UNSUPPORTEDOPCODE );
1164 }
1165
1166}
1167
1168
1169#endif
1170
b7080c8e
A
1171static void PrintPacket (struct ip* ip)
1172{
1173 printf ("%s", FormatPacket (ip));
1174}
1175
1176static void SyslogPacket (struct ip* ip, int priority, const char *label)
1177{
1178 syslog (priority, "%s %s", label, FormatPacket (ip));
1179}
1180
1181static char* FormatPacket (struct ip* ip)
1182{
1183 static char buf[256];
1184 struct tcphdr* tcphdr;
1185 struct udphdr* udphdr;
1186 struct icmp* icmphdr;
1187 char src[20];
1188 char dst[20];
1189
1190 strcpy (src, inet_ntoa (ip->ip_src));
1191 strcpy (dst, inet_ntoa (ip->ip_dst));
1192
1193 switch (ip->ip_p) {
1194 case IPPROTO_TCP:
1195 tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
1196 sprintf (buf, "[TCP] %s:%d -> %s:%d",
1197 src,
1198 ntohs (tcphdr->th_sport),
1199 dst,
1200 ntohs (tcphdr->th_dport));
1201 break;
1202
1203 case IPPROTO_UDP:
1204 udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
1205 sprintf (buf, "[UDP] %s:%d -> %s:%d",
1206 src,
1207 ntohs (udphdr->uh_sport),
1208 dst,
1209 ntohs (udphdr->uh_dport));
1210 break;
1211
1212 case IPPROTO_ICMP:
1213 icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
1214 sprintf (buf, "[ICMP] %s -> %s %u(%u)",
1215 src,
1216 dst,
1217 icmphdr->icmp_type,
1218 icmphdr->icmp_code);
1219 break;
1220
1221 default:
1222 sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
1223 break;
1224 }
1225
1226 return buf;
1227}
1228
7ba0088d
A
1229static void
1230SetAliasAddressFromIfName(const char *ifn)
b7080c8e 1231{
7ba0088d
A
1232 size_t needed;
1233 int mib[6];
1234 char *buf, *lim, *next;
1235 struct if_msghdr *ifm;
1236 struct ifa_msghdr *ifam;
1237 struct sockaddr_dl *sdl;
1238 struct sockaddr_in *sin;
1239
1240 mib[0] = CTL_NET;
1241 mib[1] = PF_ROUTE;
1242 mib[2] = 0;
1243 mib[3] = AF_INET; /* Only IP addresses please */
1244 mib[4] = NET_RT_IFLIST;
1245 mib[5] = 0; /* ifIndex??? */
b7080c8e
A
1246/*
1247 * Get interface data.
1248 */
7ba0088d
A
1249 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
1250 err(1, "iflist-sysctl-estimate");
1251 if ((buf = malloc(needed)) == NULL)
1252 errx(1, "malloc failed");
1253 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
1254 err(1, "iflist-sysctl-get");
1255 lim = buf + needed;
b7080c8e
A
1256/*
1257 * Loop through interfaces until one with
1258 * given name is found. This is done to
1259 * find correct interface index for routing
1260 * message processing.
1261 */
7ba0088d
A
1262 ifIndex = 0;
1263 next = buf;
1264 while (next < lim) {
1265 ifm = (struct if_msghdr *)next;
1266 next += ifm->ifm_msglen;
1267 if (ifm->ifm_version != RTM_VERSION) {
1268 if (verbose)
1269 warnx("routing message version %d "
1270 "not understood", ifm->ifm_version);
1271 continue;
b7080c8e 1272 }
7ba0088d
A
1273 if (ifm->ifm_type == RTM_IFINFO) {
1274 sdl = (struct sockaddr_dl *)(ifm + 1);
1275 if (strlen(ifn) == sdl->sdl_nlen &&
1276 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
1277 ifIndex = ifm->ifm_index;
1278 ifMTU = ifm->ifm_data.ifi_mtu;
285dd90c
A
1279 if (clampMSS)
1280 PacketAliasClampMSS(ifMTU - sizeof(struct tcphdr) - sizeof(struct ip));
7ba0088d
A
1281 break;
1282 }
b7080c8e 1283 }
b7080c8e 1284 }
7ba0088d
A
1285 if (!ifIndex)
1286 errx(1, "unknown interface name %s", ifn);
b7080c8e
A
1287/*
1288 * Get interface address.
1289 */
285dd90c 1290 if (aliasAddr.s_addr == INADDR_NONE) {
7ba0088d
A
1291 sin = NULL;
1292 while (next < lim) {
1293 ifam = (struct ifa_msghdr *)next;
1294 next += ifam->ifam_msglen;
1295 if (ifam->ifam_version != RTM_VERSION) {
1296 if (verbose)
1297 warnx("routing message version %d "
1298 "not understood", ifam->ifam_version);
1299 continue;
1300 }
1301 if (ifam->ifam_type != RTM_NEWADDR)
1302 break;
1303 if (ifam->ifam_addrs & RTA_IFA) {
1304 int i;
1305 char *cp = (char *)(ifam + 1);
1306
1307#define ROUNDUP(a) \
1308 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1309#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
1310
1311 for (i = 1; i < RTA_IFA; i <<= 1)
1312 if (ifam->ifam_addrs & i)
1313 ADVANCE(cp, (struct sockaddr *)cp);
1314 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
1315 sin = (struct sockaddr_in *)cp;
1316 break;
1317 }
1318 }
1319 }
1320 if (sin == NULL)
1321 errx(1, "%s: cannot get interface address", ifn);
b7080c8e 1322
7ba0088d 1323 PacketAliasSetAddress(sin->sin_addr);
2b484d24
A
1324#ifdef NATPORTMAP
1325 if ( (enable_natportmap) && (sin->sin_addr.s_addr != lastassignaliasAddr.s_addr) )
1326 {
1327 lastassignaliasAddr.s_addr = sin->sin_addr.s_addr;
1328 /* make sure the timer handler was set before setting timer */
1329 if ( !Natdtimerset ){
1330 Natdtimerset = 1;
1331 signal(SIGALRM, Natdtimer);
1332 }
1333 NotifyPublicAddress();
1334 }
1335#endif
7ba0088d
A
1336 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes",
1337 inet_ntoa(sin->sin_addr), ifMTU);
285dd90c 1338 }
b7080c8e 1339
7ba0088d 1340 free(buf);
b7080c8e
A
1341}
1342
1343void Quit (const char* msg)
1344{
1345 Warn (msg);
1346 exit (1);
1347}
1348
1349void Warn (const char* msg)
1350{
1351 if (background)
1352 syslog (LOG_ALERT, "%s (%m)", msg);
1353 else
7ba0088d 1354 warn ("%s", msg);
b7080c8e
A
1355}
1356
1357static void RefreshAddr (int sig)
1358{
b7080c8e
A
1359 if (ifName)
1360 assignAliasAddr = 1;
1361}
1362
1363static void InitiateShutdown (int sig)
1364{
1365/*
1366 * Start timer to allow kernel gracefully
1367 * shutdown existing connections when system
1368 * is shut down.
1369 */
7ba0088d 1370 siginterrupt(SIGALRM, 1);
b7080c8e
A
1371 signal (SIGALRM, Shutdown);
1372 alarm (10);
1373}
1374
1375static void Shutdown (int sig)
1376{
1377 running = 0;
1378}
1379
1380/*
1381 * Different options recognized by this program.
1382 */
1383
1384enum Option {
1385
1386 PacketAliasOption,
1387 Verbose,
1388 InPort,
1389 OutPort,
1390 Port,
1391 AliasAddress,
7ba0088d 1392 TargetAddress,
b7080c8e
A
1393 InterfaceName,
1394 RedirectPort,
7ba0088d 1395 RedirectProto,
b7080c8e
A
1396 RedirectAddress,
1397 ConfigFile,
1398 DynamicMode,
285dd90c 1399 ClampMSS,
b7080c8e
A
1400 ProxyRule,
1401 LogDenied,
7ba0088d 1402 LogFacility,
2b484d24
A
1403 PunchFW,
1404#ifdef NATPORTMAP
1405 NATPortMap,
1406 ToInterfaceName
1407#endif
b7080c8e
A
1408};
1409
1410enum Param {
1411
1412 YesNo,
1413 Numeric,
1414 String,
1415 None,
1416 Address,
1417 Service
1418};
1419
1420/*
1421 * Option information structure (used by ParseOption).
1422 */
1423
1424struct OptionInfo {
1425
1426 enum Option type;
1427 int packetAliasOpt;
1428 enum Param parm;
1429 const char* parmDescription;
1430 const char* description;
1431 const char* name;
1432 const char* shortName;
1433};
1434
1435/*
1436 * Table of known options.
1437 */
1438
1439static struct OptionInfo optionTable[] = {
1440
1441 { PacketAliasOption,
1442 PKT_ALIAS_UNREGISTERED_ONLY,
1443 YesNo,
1444 "[yes|no]",
1445 "alias only unregistered addresses",
1446 "unregistered_only",
1447 "u" },
1448
1449 { PacketAliasOption,
1450 PKT_ALIAS_LOG,
1451 YesNo,
1452 "[yes|no]",
1453 "enable logging",
1454 "log",
1455 "l" },
1456
1457 { PacketAliasOption,
1458 PKT_ALIAS_PROXY_ONLY,
1459 YesNo,
1460 "[yes|no]",
1461 "proxy only",
1462 "proxy_only",
1463 NULL },
1464
1465 { PacketAliasOption,
1466 PKT_ALIAS_REVERSE,
1467 YesNo,
1468 "[yes|no]",
1469 "operate in reverse mode",
1470 "reverse",
1471 NULL },
1472
1473 { PacketAliasOption,
1474 PKT_ALIAS_DENY_INCOMING,
1475 YesNo,
1476 "[yes|no]",
1477 "allow incoming connections",
1478 "deny_incoming",
1479 "d" },
1480
1481 { PacketAliasOption,
1482 PKT_ALIAS_USE_SOCKETS,
1483 YesNo,
1484 "[yes|no]",
1485 "use sockets to inhibit port conflict",
1486 "use_sockets",
1487 "s" },
1488
1489 { PacketAliasOption,
1490 PKT_ALIAS_SAME_PORTS,
1491 YesNo,
1492 "[yes|no]",
1493 "try to keep original port numbers for connections",
1494 "same_ports",
1495 "m" },
1496
1497 { Verbose,
1498 0,
1499 YesNo,
1500 "[yes|no]",
1501 "verbose mode, dump packet information",
1502 "verbose",
1503 "v" },
1504
1505 { DynamicMode,
1506 0,
1507 YesNo,
1508 "[yes|no]",
1509 "dynamic mode, automatically detect interface address changes",
1510 "dynamic",
1511 NULL },
1512
285dd90c
A
1513 { ClampMSS,
1514 0,
1515 YesNo,
1516 "[yes|no]",
1517 "enable TCP MSS clamping",
1518 "clamp_mss",
1519 NULL },
1520
b7080c8e
A
1521 { InPort,
1522 0,
1523 Service,
1524 "number|service_name",
1525 "set port for incoming packets",
1526 "in_port",
1527 "i" },
1528
1529 { OutPort,
1530 0,
1531 Service,
1532 "number|service_name",
1533 "set port for outgoing packets",
1534 "out_port",
1535 "o" },
1536
1537 { Port,
1538 0,
1539 Service,
1540 "number|service_name",
1541 "set port (defaults to natd/divert)",
1542 "port",
1543 "p" },
1544
1545 { AliasAddress,
1546 0,
1547 Address,
1548 "x.x.x.x",
1549 "address to use for aliasing",
1550 "alias_address",
1551 "a" },
1552
7ba0088d
A
1553 { TargetAddress,
1554 0,
1555 Address,
1556 "x.x.x.x",
1557 "address to use for incoming sessions",
1558 "target_address",
1559 "t" },
1560
b7080c8e
A
1561 { InterfaceName,
1562 0,
1563 String,
1564 "network_if_name",
1565 "take aliasing address from interface",
1566 "interface",
1567 "n" },
1568
1569 { ProxyRule,
1570 0,
1571 String,
1572 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1573 "a.b.c.d:yyyy",
1574 "add transparent proxying / destination NAT",
1575 "proxy_rule",
1576 NULL },
1577
1578 { RedirectPort,
1579 0,
1580 String,
7ba0088d 1581 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
b7080c8e
A
1582 " [remote_addr[:remote_port_range]]",
1583 "redirect a port (or ports) for incoming traffic",
1584 "redirect_port",
1585 NULL },
1586
7ba0088d 1587 { RedirectProto,
b7080c8e
A
1588 0,
1589 String,
7ba0088d
A
1590 "proto local_addr [public_addr] [remote_addr]",
1591 "redirect packets of a given proto",
1592 "redirect_proto",
b7080c8e
A
1593 NULL },
1594
7ba0088d 1595 { RedirectAddress,
b7080c8e
A
1596 0,
1597 String,
7ba0088d
A
1598 "local_addr[,...] public_addr",
1599 "define mapping between local and public addresses",
1600 "redirect_address",
b7080c8e
A
1601 NULL },
1602
1603 { ConfigFile,
1604 0,
1605 String,
1606 "file_name",
1607 "read options from configuration file",
1608 "config",
1609 "f" },
1610
1611 { LogDenied,
1612 0,
1613 YesNo,
1614 "[yes|no]",
1615 "enable logging of denied incoming packets",
1616 "log_denied",
1617 NULL },
1618
1619 { LogFacility,
1620 0,
1621 String,
1622 "facility",
1623 "name of syslog facility to use for logging",
1624 "log_facility",
7ba0088d 1625 NULL },
b7080c8e 1626
7ba0088d
A
1627 { PunchFW,
1628 0,
1629 String,
1630 "basenumber:count",
1631 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1632 "punch_fw",
2b484d24
A
1633 NULL },
1634
1635#ifdef NATPORTMAP
1636 { NATPortMap,
1637 0,
1638 YesNo,
1639 "[yes|no]",
1640 "enable NATPortMap protocol",
1641 "enable_natportmap",
1642 NULL },
1643
1644 { ToInterfaceName,
1645 0,
1646 String,
1647 "network_if_name",
1648 "take aliasing address to interface",
1649 "natportmap_interface",
1650 NULL },
1651
1652#endif
b7080c8e
A
1653};
1654
7ba0088d 1655static void ParseOption (const char* option, const char* parms)
b7080c8e
A
1656{
1657 int i;
1658 struct OptionInfo* info;
1659 int yesNoValue;
1660 int aliasValue;
1661 int numValue;
1662 u_short uNumValue;
1663 const char* strValue;
1664 struct in_addr addrValue;
1665 int max;
1666 char* end;
1667 CODE* fac_record = NULL;
1668/*
1669 * Find option from table.
1670 */
1671 max = sizeof (optionTable) / sizeof (struct OptionInfo);
1672 for (i = 0, info = optionTable; i < max; i++, info++) {
1673
1674 if (!strcmp (info->name, option))
1675 break;
1676
1677 if (info->shortName)
1678 if (!strcmp (info->shortName, option))
1679 break;
1680 }
1681
1682 if (i >= max) {
1683
1684 warnx ("unknown option %s", option);
1685 Usage ();
1686 }
1687
1688 uNumValue = 0;
1689 yesNoValue = 0;
1690 numValue = 0;
1691 strValue = NULL;
1692/*
1693 * Check parameters.
1694 */
1695 switch (info->parm) {
1696 case YesNo:
1697 if (!parms)
1698 parms = "yes";
1699
1700 if (!strcmp (parms, "yes"))
1701 yesNoValue = 1;
1702 else
1703 if (!strcmp (parms, "no"))
1704 yesNoValue = 0;
1705 else
1706 errx (1, "%s needs yes/no parameter", option);
1707 break;
1708
1709 case Service:
1710 if (!parms)
1711 errx (1, "%s needs service name or "
1712 "port number parameter",
1713 option);
1714
1715 uNumValue = StrToPort (parms, "divert");
1716 break;
1717
1718 case Numeric:
1719 if (parms)
1720 numValue = strtol (parms, &end, 10);
1721 else
1722 end = NULL;
1723
1724 if (end == parms)
1725 errx (1, "%s needs numeric parameter", option);
1726 break;
1727
1728 case String:
1729 strValue = parms;
1730 if (!strValue)
1731 errx (1, "%s needs parameter", option);
1732 break;
1733
1734 case None:
1735 if (parms)
1736 errx (1, "%s does not take parameters", option);
1737 break;
1738
1739 case Address:
1740 if (!parms)
1741 errx (1, "%s needs address/host parameter", option);
1742
1743 StrToAddr (parms, &addrValue);
1744 break;
1745 }
1746
1747 switch (info->type) {
1748 case PacketAliasOption:
1749
1750 aliasValue = yesNoValue ? info->packetAliasOpt : 0;
1751 PacketAliasSetMode (aliasValue, info->packetAliasOpt);
1752 break;
1753
1754 case Verbose:
1755 verbose = yesNoValue;
1756 break;
1757
1758 case DynamicMode:
1759 dynamicMode = yesNoValue;
1760 break;
1761
285dd90c
A
1762 case ClampMSS:
1763 clampMSS = yesNoValue;
1764 break;
1765
b7080c8e
A
1766 case InPort:
1767 inPort = uNumValue;
1768 break;
1769
1770 case OutPort:
1771 outPort = uNumValue;
1772 break;
1773
1774 case Port:
1775 inOutPort = uNumValue;
1776 break;
1777
1778 case AliasAddress:
1779 memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
1780 break;
1781
7ba0088d
A
1782 case TargetAddress:
1783 PacketAliasSetTarget(addrValue);
1784 break;
1785
b7080c8e
A
1786 case RedirectPort:
1787 SetupPortRedirect (strValue);
1788 break;
1789
7ba0088d
A
1790 case RedirectProto:
1791 SetupProtoRedirect(strValue);
b7080c8e
A
1792 break;
1793
7ba0088d
A
1794 case RedirectAddress:
1795 SetupAddressRedirect (strValue);
b7080c8e
A
1796 break;
1797
1798 case ProxyRule:
1799 PacketAliasProxyRule (strValue);
1800 break;
1801
1802 case InterfaceName:
1803 if (ifName)
1804 free (ifName);
1805
1806 ifName = strdup (strValue);
b7080c8e
A
1807 break;
1808
1809 case ConfigFile:
1810 ReadConfigFile (strValue);
1811 break;
1812
1813 case LogDenied:
1814 logDropped = 1;
1815 break;
1816
1817 case LogFacility:
1818
1819 fac_record = facilitynames;
1820 while (fac_record->c_name != NULL) {
1821
1822 if (!strcmp (fac_record->c_name, strValue)) {
1823
1824 logFacility = fac_record->c_val;
1825 break;
1826
1827 }
1828 else
1829 fac_record++;
1830 }
1831
1832 if(fac_record->c_name == NULL)
1833 errx(1, "Unknown log facility name: %s", strValue);
1834
1835 break;
7ba0088d
A
1836
1837 case PunchFW:
1838 SetupPunchFW(strValue);
1839 break;
2b484d24
A
1840
1841#ifdef NATPORTMAP
1842 case NATPortMap:
1843 enable_natportmap = yesNoValue;
1844 break;
1845
1846
1847 case ToInterfaceName:
1848 {
1849 if (forwardedinterfacename != NULL)
1850 {
1851 if ( realloc(forwardedinterfacename, (numofinterfaces+1) * sizeof(*forwardedinterfacename)) == NULL){
1852 printf("realloc error, cannot allocate memory for fowarded interface name.\n");
1853 return;
1854 }
1855 }
1856 else {
1857 if ( (forwardedinterfacename = malloc( sizeof(*forwardedinterfacename) )) == NULL ){
1858 printf("malloc error, cannot allocate memory for fowarded interface name.\n");
1859 return;
1860 }
1861 }
1862
1863 forwardedinterfacename[numofinterfaces] = strdup(strValue);
1864 numofinterfaces++;
1865
1866 break;
1867 }
1868
1869#endif
1870
b7080c8e
A
1871 }
1872}
1873
1874void ReadConfigFile (const char* fileName)
1875{
1876 FILE* file;
7ba0088d
A
1877 char *buf;
1878 size_t len;
1879 char *ptr, *p;
b7080c8e
A
1880 char* option;
1881
1882 file = fopen (fileName, "r");
7ba0088d
A
1883 if (!file)
1884 err(1, "cannot open config file %s", fileName);
b7080c8e 1885
7ba0088d
A
1886 while ((buf = fgetln(file, &len)) != NULL) {
1887 if (buf[len - 1] == '\n')
1888 buf[len - 1] = '\0';
1889 else
1890 errx(1, "config file format error: "
1891 "last line should end with newline");
b7080c8e 1892
b7080c8e 1893/*
7ba0088d 1894 * Check for comments, strip off trailing spaces.
b7080c8e 1895 */
7ba0088d
A
1896 if ((ptr = strchr(buf, '#')))
1897 *ptr = '\0';
1898 for (ptr = buf; isspace(*ptr); ++ptr)
1899 continue;
b7080c8e
A
1900 if (*ptr == '\0')
1901 continue;
7ba0088d
A
1902 for (p = strchr(buf, '\0'); isspace(*--p);)
1903 continue;
1904 *++p = '\0';
1905
b7080c8e
A
1906/*
1907 * Extract option name.
1908 */
1909 option = ptr;
1910 while (*ptr && !isspace (*ptr))
1911 ++ptr;
1912
1913 if (*ptr != '\0') {
1914
1915 *ptr = '\0';
1916 ++ptr;
1917 }
1918/*
1919 * Skip white space between name and parms.
1920 */
1921 while (*ptr && isspace (*ptr))
1922 ++ptr;
1923
7ba0088d 1924 ParseOption (option, *ptr ? ptr : NULL);
b7080c8e
A
1925 }
1926
1927 fclose (file);
1928}
1929
1930static void Usage ()
1931{
1932 int i;
1933 int max;
1934 struct OptionInfo* info;
1935
1936 fprintf (stderr, "Recognized options:\n\n");
1937
1938 max = sizeof (optionTable) / sizeof (struct OptionInfo);
1939 for (i = 0, info = optionTable; i < max; i++, info++) {
1940
1941 fprintf (stderr, "-%-20s %s\n", info->name,
1942 info->parmDescription);
1943
1944 if (info->shortName)
1945 fprintf (stderr, "-%-20s %s\n", info->shortName,
1946 info->parmDescription);
1947
1948 fprintf (stderr, " %s\n\n", info->description);
1949 }
1950
1951 exit (1);
1952}
1953
b7080c8e
A
1954void SetupPortRedirect (const char* parms)
1955{
1956 char buf[128];
1957 char* ptr;
7ba0088d 1958 char* serverPool;
b7080c8e
A
1959 struct in_addr localAddr;
1960 struct in_addr publicAddr;
1961 struct in_addr remoteAddr;
1962 port_range portRange;
1963 u_short localPort = 0;
1964 u_short publicPort = 0;
1965 u_short remotePort = 0;
1966 u_short numLocalPorts = 0;
1967 u_short numPublicPorts = 0;
1968 u_short numRemotePorts = 0;
1969 int proto;
1970 char* protoName;
1971 char* separator;
1972 int i;
7ba0088d 1973 struct alias_link *link = NULL;
b7080c8e
A
1974
1975 strcpy (buf, parms);
1976/*
1977 * Extract protocol.
1978 */
1979 protoName = strtok (buf, " \t");
1980 if (!protoName)
1981 errx (1, "redirect_port: missing protocol");
1982
1983 proto = StrToProto (protoName);
1984/*
1985 * Extract local address.
1986 */
1987 ptr = strtok (NULL, " \t");
1988 if (!ptr)
1989 errx (1, "redirect_port: missing local address");
1990
7ba0088d
A
1991 separator = strchr(ptr, ',');
1992 if (separator) { /* LSNAT redirection syntax. */
1993 localAddr.s_addr = INADDR_NONE;
1994 localPort = ~0;
1995 numLocalPorts = 1;
1996 serverPool = ptr;
1997 } else {
1998 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 )
1999 errx (1, "redirect_port: invalid local port range");
2000
2001 localPort = GETLOPORT(portRange);
2002 numLocalPorts = GETNUMPORTS(portRange);
2003 serverPool = NULL;
2004 }
b7080c8e
A
2005
2006/*
7ba0088d 2007 * Extract public port and optionally address.
b7080c8e
A
2008 */
2009 ptr = strtok (NULL, " \t");
2010 if (!ptr)
2011 errx (1, "redirect_port: missing public port");
2012
2013 separator = strchr (ptr, ':');
2014 if (separator) {
2015 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 )
2016 errx (1, "redirect_port: invalid public port range");
2017 }
2018 else {
2019 publicAddr.s_addr = INADDR_ANY;
2020 if (StrToPortRange (ptr, protoName, &portRange) != 0)
2021 errx (1, "redirect_port: invalid public port range");
2022 }
2023
2024 publicPort = GETLOPORT(portRange);
2025 numPublicPorts = GETNUMPORTS(portRange);
2026
2027/*
2028 * Extract remote address and optionally port.
2029 */
2030 ptr = strtok (NULL, " \t");
2031 if (ptr) {
2032 separator = strchr (ptr, ':');
7ba0088d 2033 if (separator) {
b7080c8e
A
2034 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0)
2035 errx (1, "redirect_port: invalid remote port range");
7ba0088d 2036 } else {
b7080c8e
A
2037 SETLOPORT(portRange, 0);
2038 SETNUMPORTS(portRange, 1);
2039 StrToAddr (ptr, &remoteAddr);
2040 }
2041 }
2042 else {
2043 SETLOPORT(portRange, 0);
2044 SETNUMPORTS(portRange, 1);
2045 remoteAddr.s_addr = INADDR_ANY;
2046 }
2047
2048 remotePort = GETLOPORT(portRange);
2049 numRemotePorts = GETNUMPORTS(portRange);
2050
2051/*
2052 * Make sure port ranges match up, then add the redirect ports.
2053 */
2054 if (numLocalPorts != numPublicPorts)
2055 errx (1, "redirect_port: port ranges must be equal in size");
2056
2057 /* Remote port range is allowed to be '0' which means all ports. */
7ba0088d 2058 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0))
b7080c8e
A
2059 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
2060
2061 for (i = 0 ; i < numPublicPorts ; ++i) {
2062 /* If remotePort is all ports, set it to 0. */
2063 u_short remotePortCopy = remotePort + i;
2064 if (numRemotePorts == 1 && remotePort == 0)
2065 remotePortCopy = 0;
2066
7ba0088d
A
2067 link = PacketAliasRedirectPort (localAddr,
2068 htons(localPort + i),
2069 remoteAddr,
2070 htons(remotePortCopy),
2071 publicAddr,
2072 htons(publicPort + i),
2073 proto);
b7080c8e 2074 }
7ba0088d
A
2075
2076/*
2077 * Setup LSNAT server pool.
2078 */
2079 if (serverPool != NULL && link != NULL) {
2080 ptr = strtok(serverPool, ",");
2081 while (ptr != NULL) {
2082 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0)
2083 errx(1, "redirect_port: invalid local port range");
2084
2085 localPort = GETLOPORT(portRange);
2086 if (GETNUMPORTS(portRange) != 1)
2087 errx(1, "redirect_port: local port must be single in this context");
2088 PacketAliasAddServer(link, localAddr, htons(localPort));
2089 ptr = strtok(NULL, ",");
2090 }
2091 }
2092}
2093
2094void
2095SetupProtoRedirect(const char* parms)
2096{
2097 char buf[128];
2098 char* ptr;
2099 struct in_addr localAddr;
2100 struct in_addr publicAddr;
2101 struct in_addr remoteAddr;
2102 int proto;
2103 char* protoName;
2104 struct protoent *protoent;
2105
2106 strcpy (buf, parms);
2107/*
2108 * Extract protocol.
2109 */
2110 protoName = strtok(buf, " \t");
2111 if (!protoName)
2112 errx(1, "redirect_proto: missing protocol");
2113
2114 protoent = getprotobyname(protoName);
2115 if (protoent == NULL)
2116 errx(1, "redirect_proto: unknown protocol %s", protoName);
2117 else
2118 proto = protoent->p_proto;
2119/*
2120 * Extract local address.
2121 */
2122 ptr = strtok(NULL, " \t");
2123 if (!ptr)
2124 errx(1, "redirect_proto: missing local address");
2125 else
2126 StrToAddr(ptr, &localAddr);
2127/*
2128 * Extract optional public address.
2129 */
2130 ptr = strtok(NULL, " \t");
2131 if (ptr)
2132 StrToAddr(ptr, &publicAddr);
2133 else
2134 publicAddr.s_addr = INADDR_ANY;
2135/*
2136 * Extract optional remote address.
2137 */
2138 ptr = strtok(NULL, " \t");
2139 if (ptr)
2140 StrToAddr(ptr, &remoteAddr);
2141 else
2142 remoteAddr.s_addr = INADDR_ANY;
2143/*
2144 * Create aliasing link.
2145 */
2146 (void)PacketAliasRedirectProto(localAddr, remoteAddr, publicAddr,
2147 proto);
b7080c8e
A
2148}
2149
2150void SetupAddressRedirect (const char* parms)
2151{
2152 char buf[128];
2153 char* ptr;
7ba0088d 2154 char* separator;
b7080c8e
A
2155 struct in_addr localAddr;
2156 struct in_addr publicAddr;
7ba0088d
A
2157 char* serverPool;
2158 struct alias_link *link;
b7080c8e
A
2159
2160 strcpy (buf, parms);
2161/*
2162 * Extract local address.
2163 */
2164 ptr = strtok (buf, " \t");
2165 if (!ptr)
2166 errx (1, "redirect_address: missing local address");
2167
7ba0088d
A
2168 separator = strchr(ptr, ',');
2169 if (separator) { /* LSNAT redirection syntax. */
2170 localAddr.s_addr = INADDR_NONE;
2171 serverPool = ptr;
2172 } else {
2173 StrToAddr (ptr, &localAddr);
2174 serverPool = NULL;
2175 }
b7080c8e
A
2176/*
2177 * Extract public address.
2178 */
2179 ptr = strtok (NULL, " \t");
2180 if (!ptr)
2181 errx (1, "redirect_address: missing public address");
2182
2183 StrToAddr (ptr, &publicAddr);
7ba0088d
A
2184 link = PacketAliasRedirectAddr(localAddr, publicAddr);
2185
2186/*
2187 * Setup LSNAT server pool.
2188 */
2189 if (serverPool != NULL && link != NULL) {
2190 ptr = strtok(serverPool, ",");
2191 while (ptr != NULL) {
2192 StrToAddr(ptr, &localAddr);
2193 PacketAliasAddServer(link, localAddr, htons(~0));
2194 ptr = strtok(NULL, ",");
2195 }
2196 }
b7080c8e
A
2197}
2198
2199void StrToAddr (const char* str, struct in_addr* addr)
2200{
2201 struct hostent* hp;
2202
2203 if (inet_aton (str, addr))
2204 return;
2205
2206 hp = gethostbyname (str);
2207 if (!hp)
2208 errx (1, "unknown host %s", str);
2209
2210 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
2211}
2212
2213u_short StrToPort (const char* str, const char* proto)
2214{
2215 u_short port;
2216 struct servent* sp;
2217 char* end;
2218
2219 port = strtol (str, &end, 10);
2220 if (end != str)
2221 return htons (port);
2222
2223 sp = getservbyname (str, proto);
2224 if (!sp)
2225 errx (1, "unknown service %s/%s", str, proto);
2226
2227 return sp->s_port;
2228}
2229
2230int StrToPortRange (const char* str, const char* proto, port_range *portRange)
2231{
2232 char* sep;
2233 struct servent* sp;
2234 char* end;
2235 u_short loPort;
2236 u_short hiPort;
2237
2238 /* First see if this is a service, return corresponding port if so. */
2239 sp = getservbyname (str,proto);
2240 if (sp) {
2241 SETLOPORT(*portRange, ntohs(sp->s_port));
2242 SETNUMPORTS(*portRange, 1);
2243 return 0;
2244 }
2245
2246 /* Not a service, see if it's a single port or port range. */
2247 sep = strchr (str, '-');
2248 if (sep == NULL) {
2249 SETLOPORT(*portRange, strtol(str, &end, 10));
2250 if (end != str) {
2251 /* Single port. */
2252 SETNUMPORTS(*portRange, 1);
2253 return 0;
2254 }
2255
2256 /* Error in port range field. */
2257 errx (1, "unknown service %s/%s", str, proto);
2258 }
2259
2260 /* Port range, get the values and sanity check. */
2261 sscanf (str, "%hu-%hu", &loPort, &hiPort);
2262 SETLOPORT(*portRange, loPort);
2263 SETNUMPORTS(*portRange, 0); /* Error by default */
2264 if (loPort <= hiPort)
2265 SETNUMPORTS(*portRange, hiPort - loPort + 1);
2266
2267 if (GETNUMPORTS(*portRange) == 0)
2268 errx (1, "invalid port range %s", str);
2269
2270 return 0;
2271}
2272
2273
2274int StrToProto (const char* str)
2275{
2276 if (!strcmp (str, "tcp"))
2277 return IPPROTO_TCP;
2278
2279 if (!strcmp (str, "udp"))
2280 return IPPROTO_UDP;
2281
2282 errx (1, "unknown protocol %s. Expected tcp or udp", str);
2283}
2284
2285int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
2286{
2287 char* ptr;
2288
2289 ptr = strchr (str, ':');
2290 if (!ptr)
2291 errx (1, "%s is missing port number", str);
2292
2293 *ptr = '\0';
2294 ++ptr;
2295
2296 StrToAddr (str, addr);
2297 return StrToPortRange (ptr, proto, portRange);
2298}
7ba0088d
A
2299
2300static void
2301SetupPunchFW(const char *strValue)
2302{
2303 unsigned int base, num;
2304
2305 if (sscanf(strValue, "%u:%u", &base, &num) != 2)
2306 errx(1, "punch_fw: basenumber:count parameter required");
2307
2308 PacketAliasSetFWBase(base, num);
2309 (void)PacketAliasSetMode(PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW);
2310}