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