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