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