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