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