1 /*
2 * natd - Network Address Translation Daemon for FreeBSD.
3 *
4 * This software is provided free of charge, with no
5 * warranty of any kind, either expressed or implied.
6 * Use at your own risk.
7 *
8 * You may copy, modify and distribute this software (natd.c) freely.
9 *
10 * Ari Suutari <suutari@iki.fi>
11 */
12
13 #include <sys/cdefs.h>
14 __FBSDID("$FreeBSD: stable/9/sbin/natd/natd.c 242544 2012-11-04 01:21:49Z eadler $");
15
16 #define SYSLOG_NAMES
17
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/sysctl.h>
21 #include <sys/time.h>
22 #include <sys/queue.h>
23
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <machine/in_cksum.h>
28 #include <netinet/tcp.h>
29 #include <netinet/udp.h>
30 #include <netinet/ip_icmp.h>
31 #include <net/if.h>
32 #include <net/if_dl.h>
33 #include <net/route.h>
34 #include <arpa/inet.h>
35
36 #include <alias.h>
37 #include <ctype.h>
38 #include <err.h>
39 #include <errno.h>
40 #include <netdb.h>
41 #include <signal.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <syslog.h>
46 #include <unistd.h>
47
48 #include "natd.h"
49
50 struct instance {
51 const char *name;
52 struct libalias *la;
53 LIST_ENTRY(instance) list;
54
55 int ifIndex;
56 int assignAliasAddr;
57 char* ifName;
58 int logDropped;
59 u_short inPort;
60 u_short outPort;
61 u_short inOutPort;
62 struct in_addr aliasAddr;
63 int ifMTU;
64 int aliasOverhead;
65 int dropIgnoredIncoming;
66 int divertIn;
67 int divertOut;
68 int divertInOut;
69 };
70
71 static LIST_HEAD(, instance) root = LIST_HEAD_INITIALIZER(root);
72
73 struct libalias *mla;
74 struct instance *mip;
75 int ninstance = 1;
76
77 /*
78 * Default values for input and output
79 * divert socket ports.
80 */
81
82 #define DEFAULT_SERVICE "natd"
83
84 /*
85 * Definition of a port range, and macros to deal with values.
86 * FORMAT: HI 16-bits == first port in range, 0 == all ports.
87 * LO 16-bits == number of ports in range
88 * NOTES: - Port values are not stored in network byte order.
89 */
90
91 typedef u_long port_range;
92
93 #define GETLOPORT(x) ((x) >> 0x10)
94 #define GETNUMPORTS(x) ((x) & 0x0000ffff)
95 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
96
97 /* Set y to be the low-port value in port_range variable x. */
98 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
99
100 /* Set y to be the number of ports in port_range variable x. */
101 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
102
103 /*
104 * Function prototypes.
105 */
106
107 static void DoAliasing (int fd, int direction);
108 static void DaemonMode (void);
109 static void HandleRoutingInfo (int fd);
110 static void Usage (void);
111 static char* FormatPacket (struct ip*);
112 static void PrintPacket (struct ip*);
113 static void SyslogPacket (struct ip*, int priority, const char *label);
114 static int SetAliasAddressFromIfName (const char *ifName);
115 static void InitiateShutdown (int);
116 static void Shutdown (int);
117 static void RefreshAddr (int);
118 static void ParseOption (const char* option, const char* parms);
119 static void ReadConfigFile (const char* fileName);
120 static void SetupPortRedirect (const char* parms);
121 static void SetupProtoRedirect(const char* parms);
122 static void SetupAddressRedirect (const char* parms);
123 static void StrToAddr (const char* str, struct in_addr* addr);
124 static u_short StrToPort (const char* str, const char* proto);
125 static int StrToPortRange (const char* str, const char* proto, port_range *portRange);
126 static int StrToProto (const char* str);
127 static int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange);
128 static void ParseArgs (int argc, char** argv);
129 static void SetupPunchFW(const char *strValue);
130 static void SetupSkinnyPort(const char *strValue);
131 static void NewInstance(const char *name);
132 static void DoGlobal (int fd);
133 static int CheckIpfwRulenum(unsigned int rnum);
134
135 /*
136 * Globals.
137 */
138
139 static int verbose;
140 static int background;
141 static int running;
142 static int logFacility;
143
144 static int dynamicMode;
145 static int icmpSock;
146 static int logIpfwDenied;
147 static const char* pidName;
148 static int routeSock;
149 static int globalPort;
150 static int divertGlobal;
151 static int exitDelay;
152
153
main(int argc,char ** argv)154 int main (int argc, char** argv)
155 {
156 struct sockaddr_in addr;
157 fd_set readMask;
158 int fdMax;
159 int rval;
160 /*
161 * Initialize packet aliasing software.
162 * Done already here to be able to alter option bits
163 * during command line and configuration file processing.
164 */
165 NewInstance("default");
166
167 /*
168 * Parse options.
169 */
170 verbose = 0;
171 background = 0;
172 running = 1;
173 dynamicMode = 0;
174 logFacility = LOG_DAEMON;
175 logIpfwDenied = -1;
176 pidName = PIDFILE;
177 routeSock = -1;
178 icmpSock = -1;
179 fdMax = -1;
180 divertGlobal = -1;
181 exitDelay = EXIT_DELAY;
182
183 ParseArgs (argc, argv);
184 /*
185 * Log ipfw(8) denied packets by default in verbose mode.
186 */
187 if (logIpfwDenied == -1)
188 logIpfwDenied = verbose;
189 /*
190 * Open syslog channel.
191 */
192 openlog ("natd", LOG_CONS | LOG_PID | (verbose ? LOG_PERROR : 0),
193 logFacility);
194
195 LIST_FOREACH(mip, &root, list) {
196 mla = mip->la;
197 /*
198 * If not doing the transparent proxying only,
199 * check that valid aliasing address has been given.
200 */
201 if (mip->aliasAddr.s_addr == INADDR_NONE && mip->ifName == NULL &&
202 !(LibAliasSetMode(mla, 0,0) & PKT_ALIAS_PROXY_ONLY))
203 errx (1, "instance %s: aliasing address not given", mip->name);
204
205 if (mip->aliasAddr.s_addr != INADDR_NONE && mip->ifName != NULL)
206 errx (1, "both alias address and interface "
207 "name are not allowed");
208 /*
209 * Check that valid port number is known.
210 */
211 if (mip->inPort != 0 || mip->outPort != 0)
212 if (mip->inPort == 0 || mip->outPort == 0)
213 errx (1, "both input and output ports are required");
214
215 if (mip->inPort == 0 && mip->outPort == 0 && mip->inOutPort == 0)
216 ParseOption ("port", DEFAULT_SERVICE);
217
218 /*
219 * Check if ignored packets should be dropped.
220 */
221 mip->dropIgnoredIncoming = LibAliasSetMode (mla, 0, 0);
222 mip->dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING;
223 /*
224 * Create divert sockets. Use only one socket if -p was specified
225 * on command line. Otherwise, create separate sockets for
226 * outgoing and incoming connnections.
227 */
228 if (mip->inOutPort) {
229
230 mip->divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
231 if (mip->divertInOut == -1)
232 Quit ("Unable to create divert socket.");
233 if (mip->divertInOut > fdMax)
234 fdMax = mip->divertInOut;
235
236 mip->divertIn = -1;
237 mip->divertOut = -1;
238 /*
239 * Bind socket.
240 */
241
242 addr.sin_family = AF_INET;
243 addr.sin_addr.s_addr = INADDR_ANY;
244 addr.sin_port = mip->inOutPort;
245
246 if (bind (mip->divertInOut,
247 (struct sockaddr*) &addr,
248 sizeof addr) == -1)
249 Quit ("Unable to bind divert socket.");
250 }
251 else {
252
253 mip->divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
254 if (mip->divertIn == -1)
255 Quit ("Unable to create incoming divert socket.");
256 if (mip->divertIn > fdMax)
257 fdMax = mip->divertIn;
258
259
260 mip->divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
261 if (mip->divertOut == -1)
262 Quit ("Unable to create outgoing divert socket.");
263 if (mip->divertOut > fdMax)
264 fdMax = mip->divertOut;
265
266 mip->divertInOut = -1;
267
268 /*
269 * Bind divert sockets.
270 */
271
272 addr.sin_family = AF_INET;
273 addr.sin_addr.s_addr = INADDR_ANY;
274 addr.sin_port = mip->inPort;
275
276 if (bind (mip->divertIn,
277 (struct sockaddr*) &addr,
278 sizeof addr) == -1)
279 Quit ("Unable to bind incoming divert socket.");
280
281 addr.sin_family = AF_INET;
282 addr.sin_addr.s_addr = INADDR_ANY;
283 addr.sin_port = mip->outPort;
284
285 if (bind (mip->divertOut,
286 (struct sockaddr*) &addr,
287 sizeof addr) == -1)
288 Quit ("Unable to bind outgoing divert socket.");
289 }
290 /*
291 * Create routing socket if interface name specified and in dynamic mode.
292 */
293 if (mip->ifName) {
294 if (dynamicMode) {
295
296 if (routeSock == -1)
297 routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
298 if (routeSock == -1)
299 Quit ("Unable to create routing info socket.");
300 if (routeSock > fdMax)
301 fdMax = routeSock;
302
303 mip->assignAliasAddr = 1;
304 }
305 else {
306 do {
307 rval = SetAliasAddressFromIfName (mip->ifName);
308 if (background == 0 || dynamicMode == 0)
309 break;
310 if (rval == EAGAIN)
311 sleep(1);
312 } while (rval == EAGAIN);
313 if (rval != 0)
314 exit(1);
315 }
316 }
317
318 }
319 if (globalPort) {
320
321 divertGlobal = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
322 if (divertGlobal == -1)
323 Quit ("Unable to create divert socket.");
324 if (divertGlobal > fdMax)
325 fdMax = divertGlobal;
326
327 /*
328 * Bind socket.
329 */
330
331 addr.sin_family = AF_INET;
332 addr.sin_addr.s_addr = INADDR_ANY;
333 addr.sin_port = globalPort;
334
335 if (bind (divertGlobal,
336 (struct sockaddr*) &addr,
337 sizeof addr) == -1)
338 Quit ("Unable to bind global divert socket.");
339 }
340 /*
341 * Create socket for sending ICMP messages.
342 */
343 icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
344 if (icmpSock == -1)
345 Quit ("Unable to create ICMP socket.");
346
347 /*
348 * And disable reads for the socket, otherwise it slowly fills
349 * up with received icmps which we do not use.
350 */
351 shutdown(icmpSock, SHUT_RD);
352
353 /*
354 * Become a daemon unless verbose mode was requested.
355 */
356 if (!verbose)
357 DaemonMode ();
358 /*
359 * Catch signals to manage shutdown and
360 * refresh of interface address.
361 */
362 siginterrupt(SIGTERM, 1);
363 siginterrupt(SIGHUP, 1);
364 if (exitDelay)
365 signal(SIGTERM, InitiateShutdown);
366 else
367 signal(SIGTERM, Shutdown);
368 signal (SIGHUP, RefreshAddr);
369 /*
370 * Set alias address if it has been given.
371 */
372 mip = LIST_FIRST(&root); /* XXX: simon */
373 LIST_FOREACH(mip, &root, list) {
374 mla = mip->la;
375 if (mip->aliasAddr.s_addr != INADDR_NONE)
376 LibAliasSetAddress (mla, mip->aliasAddr);
377 }
378
379 while (running) {
380 mip = LIST_FIRST(&root); /* XXX: simon */
381
382 if (mip->divertInOut != -1 && !mip->ifName && ninstance == 1) {
383 /*
384 * When using only one socket, just call
385 * DoAliasing repeatedly to process packets.
386 */
387 DoAliasing (mip->divertInOut, DONT_KNOW);
388 continue;
389 }
390 /*
391 * Build read mask from socket descriptors to select.
392 */
393 FD_ZERO (&readMask);
394 /*
395 * Check if new packets are available.
396 */
397 LIST_FOREACH(mip, &root, list) {
398 if (mip->divertIn != -1)
399 FD_SET (mip->divertIn, &readMask);
400
401 if (mip->divertOut != -1)
402 FD_SET (mip->divertOut, &readMask);
403
404 if (mip->divertInOut != -1)
405 FD_SET (mip->divertInOut, &readMask);
406 }
407 /*
408 * Routing info is processed always.
409 */
410 if (routeSock != -1)
411 FD_SET (routeSock, &readMask);
412
413 if (divertGlobal != -1)
414 FD_SET (divertGlobal, &readMask);
415
416 if (select (fdMax + 1,
417 &readMask,
418 NULL,
419 NULL,
420 NULL) == -1) {
421
422 if (errno == EINTR)
423 continue;
424
425 Quit ("Select failed.");
426 }
427
428 if (divertGlobal != -1)
429 if (FD_ISSET (divertGlobal, &readMask))
430 DoGlobal (divertGlobal);
431 LIST_FOREACH(mip, &root, list) {
432 mla = mip->la;
433 if (mip->divertIn != -1)
434 if (FD_ISSET (mip->divertIn, &readMask))
435 DoAliasing (mip->divertIn, INPUT);
436
437 if (mip->divertOut != -1)
438 if (FD_ISSET (mip->divertOut, &readMask))
439 DoAliasing (mip->divertOut, OUTPUT);
440
441 if (mip->divertInOut != -1)
442 if (FD_ISSET (mip->divertInOut, &readMask))
443 DoAliasing (mip->divertInOut, DONT_KNOW);
444
445 }
446 if (routeSock != -1)
447 if (FD_ISSET (routeSock, &readMask))
448 HandleRoutingInfo (routeSock);
449 }
450
451 if (background)
452 unlink (pidName);
453
454 return 0;
455 }
456
DaemonMode(void)457 static void DaemonMode(void)
458 {
459 FILE* pidFile;
460
461 daemon (0, 0);
462 background = 1;
463
464 pidFile = fopen (pidName, "w");
465 if (pidFile) {
466
467 fprintf (pidFile, "%d\n", getpid ());
468 fclose (pidFile);
469 }
470 }
471
ParseArgs(int argc,char ** argv)472 static void ParseArgs (int argc, char** argv)
473 {
474 int arg;
475 char* opt;
476 char parmBuf[256];
477 int len; /* bounds checking */
478
479 for (arg = 1; arg < argc; arg++) {
480
481 opt = argv[arg];
482 if (*opt != '-') {
483
484 warnx ("invalid option %s", opt);
485 Usage ();
486 }
487
488 parmBuf[0] = '\0';
489 len = 0;
490
491 while (arg < argc - 1) {
492
493 if (argv[arg + 1][0] == '-')
494 break;
495
496 if (len) {
497 strncat (parmBuf, " ", sizeof(parmBuf) - (len + 1));
498 len += strlen(parmBuf + len);
499 }
500
501 ++arg;
502 strncat (parmBuf, argv[arg], sizeof(parmBuf) - (len + 1));
503 len += strlen(parmBuf + len);
504
505 }
506
507 ParseOption (opt + 1, (len ? parmBuf : NULL));
508
509 }
510 }
511
DoGlobal(int fd)512 static void DoGlobal (int fd)
513 {
514 int bytes;
515 int origBytes;
516 char buf[IP_MAXPACKET];
517 struct sockaddr_in addr;
518 int wrote;
519 socklen_t addrSize;
520 struct ip* ip;
521 char msgBuf[80];
522
523 /*
524 * Get packet from socket.
525 */
526 addrSize = sizeof addr;
527 origBytes = recvfrom (fd,
528 buf,
529 sizeof buf,
530 0,
531 (struct sockaddr*) &addr,
532 &addrSize);
533
534 if (origBytes == -1) {
535
536 if (errno != EINTR)
537 Warn ("read from divert socket failed");
538
539 return;
540 }
541
542 #if 0
543 if (mip->assignAliasAddr) {
544 if (SetAliasAddressFromIfName (mip->ifName) != 0)
545 exit(1);
546 mip->assignAliasAddr = 0;
547 }
548 #endif
549 /*
550 * This is an IP packet.
551 */
552 ip = (struct ip*) buf;
553
554 if (verbose) {
555 /*
556 * Print packet direction and protocol type.
557 */
558 printf ("Glb ");
559
560 switch (ip->ip_p) {
561 case IPPROTO_TCP:
562 printf ("[TCP] ");
563 break;
564
565 case IPPROTO_UDP:
566 printf ("[UDP] ");
567 break;
568
569 case IPPROTO_ICMP:
570 printf ("[ICMP] ");
571 break;
572
573 default:
574 printf ("[%d] ", ip->ip_p);
575 break;
576 }
577 /*
578 * Print addresses.
579 */
580 PrintPacket (ip);
581 }
582
583 LIST_FOREACH(mip, &root, list) {
584 mla = mip->la;
585 if (LibAliasOutTry (mla, buf, IP_MAXPACKET, 0) != PKT_ALIAS_IGNORED)
586 break;
587 }
588 /*
589 * Length might have changed during aliasing.
590 */
591 bytes = ntohs (ip->ip_len);
592 /*
593 * Update alias overhead size for outgoing packets.
594 */
595 if (mip != NULL && bytes - origBytes > mip->aliasOverhead)
596 mip->aliasOverhead = bytes - origBytes;
597
598 if (verbose) {
599
600 /*
601 * Print addresses after aliasing.
602 */
603 printf (" aliased to\n");
604 printf (" ");
605 PrintPacket (ip);
606 printf ("\n");
607 }
608
609 /*
610 * Put packet back for processing.
611 */
612 wrote = sendto (fd,
613 buf,
614 bytes,
615 0,
616 (struct sockaddr*) &addr,
617 sizeof addr);
618
619 if (wrote != bytes) {
620
621 if (errno == EMSGSIZE) {
622
623 if (mip->ifMTU != -1)
624 SendNeedFragIcmp (icmpSock,
625 (struct ip*) buf,
626 mip->ifMTU - mip->aliasOverhead);
627 }
628 else if (errno == EACCES && logIpfwDenied) {
629
630 sprintf (msgBuf, "failed to write packet back");
631 Warn (msgBuf);
632 }
633 }
634 }
635
636
DoAliasing(int fd,int direction)637 static void DoAliasing (int fd, int direction)
638 {
639 int bytes;
640 int origBytes;
641 char buf[IP_MAXPACKET];
642 struct sockaddr_in addr;
643 int wrote;
644 int status;
645 socklen_t addrSize;
646 struct ip* ip;
647 char msgBuf[80];
648 int rval;
649
650 if (mip->assignAliasAddr) {
651 do {
652 rval = SetAliasAddressFromIfName (mip->ifName);
653 if (background == 0 || dynamicMode == 0)
654 break;
655 if (rval == EAGAIN)
656 sleep(1);
657 } while (rval == EAGAIN);
658 if (rval != 0)
659 exit(1);
660 mip->assignAliasAddr = 0;
661 }
662 /*
663 * Get packet from socket.
664 */
665 addrSize = sizeof addr;
666 origBytes = recvfrom (fd,
667 buf,
668 sizeof buf,
669 0,
670 (struct sockaddr*) &addr,
671 &addrSize);
672
673 if (origBytes == -1) {
674
675 if (errno != EINTR)
676 Warn ("read from divert socket failed");
677
678 return;
679 }
680 /*
681 * This is an IP packet.
682 */
683 ip = (struct ip*) buf;
684 if (direction == DONT_KNOW) {
685 if (addr.sin_addr.s_addr == INADDR_ANY)
686 direction = OUTPUT;
687 else
688 direction = INPUT;
689 }
690
691 if (verbose) {
692 /*
693 * Print packet direction and protocol type.
694 */
695 printf (direction == OUTPUT ? "Out " : "In ");
696 if (ninstance > 1)
697 printf ("{%s}", mip->name);
698
699 switch (ip->ip_p) {
700 case IPPROTO_TCP:
701 printf ("[TCP] ");
702 break;
703
704 case IPPROTO_UDP:
705 printf ("[UDP] ");
706 break;
707
708 case IPPROTO_ICMP:
709 printf ("[ICMP] ");
710 break;
711
712 default:
713 printf ("[%d] ", ip->ip_p);
714 break;
715 }
716 /*
717 * Print addresses.
718 */
719 PrintPacket (ip);
720 }
721
722 if (direction == OUTPUT) {
723 /*
724 * Outgoing packets. Do aliasing.
725 */
726 LibAliasOut (mla, buf, IP_MAXPACKET);
727 }
728 else {
729
730 /*
731 * Do aliasing.
732 */
733 status = LibAliasIn (mla, buf, IP_MAXPACKET);
734 if (status == PKT_ALIAS_IGNORED &&
735 mip->dropIgnoredIncoming) {
736
737 if (verbose)
738 printf (" dropped.\n");
739
740 if (mip->logDropped)
741 SyslogPacket (ip, LOG_WARNING, "denied");
742
743 return;
744 }
745 }
746 /*
747 * Length might have changed during aliasing.
748 */
749 bytes = ntohs (ip->ip_len);
750 /*
751 * Update alias overhead size for outgoing packets.
752 */
753 if (direction == OUTPUT &&
754 bytes - origBytes > mip->aliasOverhead)
755 mip->aliasOverhead = bytes - origBytes;
756
757 if (verbose) {
758
759 /*
760 * Print addresses after aliasing.
761 */
762 printf (" aliased to\n");
763 printf (" ");
764 PrintPacket (ip);
765 printf ("\n");
766 }
767
768 /*
769 * Put packet back for processing.
770 */
771 wrote = sendto (fd,
772 buf,
773 bytes,
774 0,
775 (struct sockaddr*) &addr,
776 sizeof addr);
777
778 if (wrote != bytes) {
779
780 if (errno == EMSGSIZE) {
781
782 if (direction == OUTPUT &&
783 mip->ifMTU != -1)
784 SendNeedFragIcmp (icmpSock,
785 (struct ip*) buf,
786 mip->ifMTU - mip->aliasOverhead);
787 }
788 else if (errno == EACCES && logIpfwDenied) {
789
790 sprintf (msgBuf, "failed to write packet back");
791 Warn (msgBuf);
792 }
793 }
794 }
795
HandleRoutingInfo(int fd)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 LIST_FOREACH(mip, &root, list) {
821 mla = mip->la;
822 if (ifMsg.ifm_index == mip->ifIndex) {
823 if (verbose)
824 printf("Interface address/MTU has probably changed.\n");
825 mip->assignAliasAddr = 1;
826 }
827 }
828 }
829 }
830
PrintPacket(struct ip * ip)831 static void PrintPacket (struct ip* ip)
832 {
833 printf ("%s", FormatPacket (ip));
834 }
835
SyslogPacket(struct ip * ip,int priority,const char * label)836 static void SyslogPacket (struct ip* ip, int priority, const char *label)
837 {
838 syslog (priority, "%s %s", label, FormatPacket (ip));
839 }
840
FormatPacket(struct ip * ip)841 static char* FormatPacket (struct ip* ip)
842 {
843 static char buf[256];
844 struct tcphdr* tcphdr;
845 struct udphdr* udphdr;
846 struct icmp* icmphdr;
847 char src[20];
848 char dst[20];
849
850 strcpy (src, inet_ntoa (ip->ip_src));
851 strcpy (dst, inet_ntoa (ip->ip_dst));
852
853 switch (ip->ip_p) {
854 case IPPROTO_TCP:
855 tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
856 sprintf (buf, "[TCP] %s:%d -> %s:%d",
857 src,
858 ntohs (tcphdr->th_sport),
859 dst,
860 ntohs (tcphdr->th_dport));
861 break;
862
863 case IPPROTO_UDP:
864 udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
865 sprintf (buf, "[UDP] %s:%d -> %s:%d",
866 src,
867 ntohs (udphdr->uh_sport),
868 dst,
869 ntohs (udphdr->uh_dport));
870 break;
871
872 case IPPROTO_ICMP:
873 icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
874 sprintf (buf, "[ICMP] %s -> %s %u(%u)",
875 src,
876 dst,
877 icmphdr->icmp_type,
878 icmphdr->icmp_code);
879 break;
880
881 default:
882 sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
883 break;
884 }
885
886 return buf;
887 }
888
889 static int
SetAliasAddressFromIfName(const char * ifn)890 SetAliasAddressFromIfName(const char *ifn)
891 {
892 size_t needed;
893 int mib[6];
894 char *buf, *lim, *next;
895 struct if_msghdr *ifm;
896 struct ifa_msghdr *ifam;
897 struct sockaddr_dl *sdl;
898 struct sockaddr_in *sin;
899
900 mib[0] = CTL_NET;
901 mib[1] = PF_ROUTE;
902 mib[2] = 0;
903 mib[3] = AF_INET; /* Only IP addresses please */
904 mib[4] = NET_RT_IFLIST;
905 mib[5] = 0; /* ifIndex??? */
906 /*
907 * Get interface data.
908 */
909 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
910 err(1, "iflist-sysctl-estimate");
911 if ((buf = malloc(needed)) == NULL)
912 errx(1, "malloc failed");
913 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1 && errno != ENOMEM)
914 err(1, "iflist-sysctl-get");
915 lim = buf + needed;
916 /*
917 * Loop through interfaces until one with
918 * given name is found. This is done to
919 * find correct interface index for routing
920 * message processing.
921 */
922 mip->ifIndex = 0;
923 next = buf;
924 while (next < lim) {
925 ifm = (struct if_msghdr *)next;
926 next += ifm->ifm_msglen;
927 if (ifm->ifm_version != RTM_VERSION) {
928 if (verbose)
929 warnx("routing message version %d "
930 "not understood", ifm->ifm_version);
931 continue;
932 }
933 if (ifm->ifm_type == RTM_IFINFO) {
934 sdl = (struct sockaddr_dl *)(ifm + 1);
935 if (strlen(ifn) == sdl->sdl_nlen &&
936 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
937 mip->ifIndex = ifm->ifm_index;
938 mip->ifMTU = ifm->ifm_data.ifi_mtu;
939 break;
940 }
941 }
942 }
943 if (!mip->ifIndex)
944 errx(1, "unknown interface name %s", ifn);
945 /*
946 * Get interface address.
947 */
948 sin = NULL;
949 while (next < lim) {
950 ifam = (struct ifa_msghdr *)next;
951 next += ifam->ifam_msglen;
952 if (ifam->ifam_version != RTM_VERSION) {
953 if (verbose)
954 warnx("routing message version %d "
955 "not understood", ifam->ifam_version);
956 continue;
957 }
958 if (ifam->ifam_type != RTM_NEWADDR)
959 break;
960 if (ifam->ifam_addrs & RTA_IFA) {
961 int i;
962 char *cp = (char *)(ifam + 1);
963
964 for (i = 1; i < RTA_IFA; i <<= 1)
965 if (ifam->ifam_addrs & i)
966 cp += SA_SIZE((struct sockaddr *)cp);
967 if (((struct sockaddr *)cp)->sa_family == AF_INET) {
968 sin = (struct sockaddr_in *)cp;
969 break;
970 }
971 }
972 }
973 if (sin == NULL) {
974 warnx("%s: cannot get interface address", ifn);
975 free(buf);
976 return EAGAIN;
977 }
978
979 LibAliasSetAddress(mla, sin->sin_addr);
980 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes",
981 inet_ntoa(sin->sin_addr), mip->ifMTU);
982
983 free(buf);
984
985 return 0;
986 }
987
Quit(const char * msg)988 void Quit (const char* msg)
989 {
990 Warn (msg);
991 exit (1);
992 }
993
Warn(const char * msg)994 void Warn (const char* msg)
995 {
996 if (background)
997 syslog (LOG_ALERT, "%s (%m)", msg);
998 else
999 warn ("%s", msg);
1000 }
1001
RefreshAddr(int sig __unused)1002 static void RefreshAddr (int sig __unused)
1003 {
1004 LibAliasRefreshModules();
1005 if (mip != NULL && mip->ifName != NULL)
1006 mip->assignAliasAddr = 1;
1007 }
1008
InitiateShutdown(int sig __unused)1009 static void InitiateShutdown (int sig __unused)
1010 {
1011 /*
1012 * Start timer to allow kernel gracefully
1013 * shutdown existing connections when system
1014 * is shut down.
1015 */
1016 siginterrupt(SIGALRM, 1);
1017 signal (SIGALRM, Shutdown);
1018 ualarm(exitDelay*1000, 1000);
1019 }
1020
Shutdown(int sig __unused)1021 static void Shutdown (int sig __unused)
1022 {
1023 running = 0;
1024 }
1025
1026 /*
1027 * Different options recognized by this program.
1028 */
1029
1030 enum Option {
1031
1032 LibAliasOption,
1033 Instance,
1034 Verbose,
1035 InPort,
1036 OutPort,
1037 Port,
1038 GlobalPort,
1039 AliasAddress,
1040 TargetAddress,
1041 InterfaceName,
1042 RedirectPort,
1043 RedirectProto,
1044 RedirectAddress,
1045 ConfigFile,
1046 DynamicMode,
1047 ProxyRule,
1048 LogDenied,
1049 LogFacility,
1050 PunchFW,
1051 SkinnyPort,
1052 LogIpfwDenied,
1053 PidFile,
1054 ExitDelay
1055 };
1056
1057 enum Param {
1058
1059 YesNo,
1060 Numeric,
1061 String,
1062 None,
1063 Address,
1064 Service
1065 };
1066
1067 /*
1068 * Option information structure (used by ParseOption).
1069 */
1070
1071 struct OptionInfo {
1072
1073 enum Option type;
1074 int packetAliasOpt;
1075 enum Param parm;
1076 const char* parmDescription;
1077 const char* description;
1078 const char* name;
1079 const char* shortName;
1080 };
1081
1082 /*
1083 * Table of known options.
1084 */
1085
1086 static struct OptionInfo optionTable[] = {
1087
1088 { LibAliasOption,
1089 PKT_ALIAS_UNREGISTERED_ONLY,
1090 YesNo,
1091 "[yes|no]",
1092 "alias only unregistered addresses",
1093 "unregistered_only",
1094 "u" },
1095
1096 { LibAliasOption,
1097 PKT_ALIAS_LOG,
1098 YesNo,
1099 "[yes|no]",
1100 "enable logging",
1101 "log",
1102 "l" },
1103
1104 { LibAliasOption,
1105 PKT_ALIAS_PROXY_ONLY,
1106 YesNo,
1107 "[yes|no]",
1108 "proxy only",
1109 "proxy_only",
1110 NULL },
1111
1112 { LibAliasOption,
1113 PKT_ALIAS_REVERSE,
1114 YesNo,
1115 "[yes|no]",
1116 "operate in reverse mode",
1117 "reverse",
1118 NULL },
1119
1120 { LibAliasOption,
1121 PKT_ALIAS_DENY_INCOMING,
1122 YesNo,
1123 "[yes|no]",
1124 "allow incoming connections",
1125 "deny_incoming",
1126 "d" },
1127
1128 { LibAliasOption,
1129 PKT_ALIAS_USE_SOCKETS,
1130 YesNo,
1131 "[yes|no]",
1132 "use sockets to inhibit port conflict",
1133 "use_sockets",
1134 "s" },
1135
1136 { LibAliasOption,
1137 PKT_ALIAS_SAME_PORTS,
1138 YesNo,
1139 "[yes|no]",
1140 "try to keep original port numbers for connections",
1141 "same_ports",
1142 "m" },
1143
1144 { Verbose,
1145 0,
1146 YesNo,
1147 "[yes|no]",
1148 "verbose mode, dump packet information",
1149 "verbose",
1150 "v" },
1151
1152 { DynamicMode,
1153 0,
1154 YesNo,
1155 "[yes|no]",
1156 "dynamic mode, automatically detect interface address changes",
1157 "dynamic",
1158 NULL },
1159
1160 { InPort,
1161 0,
1162 Service,
1163 "number|service_name",
1164 "set port for incoming packets",
1165 "in_port",
1166 "i" },
1167
1168 { OutPort,
1169 0,
1170 Service,
1171 "number|service_name",
1172 "set port for outgoing packets",
1173 "out_port",
1174 "o" },
1175
1176 { Port,
1177 0,
1178 Service,
1179 "number|service_name",
1180 "set port (defaults to natd/divert)",
1181 "port",
1182 "p" },
1183
1184 { GlobalPort,
1185 0,
1186 Service,
1187 "number|service_name",
1188 "set globalport",
1189 "globalport",
1190 NULL },
1191
1192 { AliasAddress,
1193 0,
1194 Address,
1195 "x.x.x.x",
1196 "address to use for aliasing",
1197 "alias_address",
1198 "a" },
1199
1200 { TargetAddress,
1201 0,
1202 Address,
1203 "x.x.x.x",
1204 "address to use for incoming sessions",
1205 "target_address",
1206 "t" },
1207
1208 { InterfaceName,
1209 0,
1210 String,
1211 "network_if_name",
1212 "take aliasing address from interface",
1213 "interface",
1214 "n" },
1215
1216 { ProxyRule,
1217 0,
1218 String,
1219 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1220 "a.b.c.d:yyyy",
1221 "add transparent proxying / destination NAT",
1222 "proxy_rule",
1223 NULL },
1224
1225 { RedirectPort,
1226 0,
1227 String,
1228 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range"
1229 " [remote_addr[:remote_port_range]]",
1230 "redirect a port (or ports) for incoming traffic",
1231 "redirect_port",
1232 NULL },
1233
1234 { RedirectProto,
1235 0,
1236 String,
1237 "proto local_addr [public_addr] [remote_addr]",
1238 "redirect packets of a given proto",
1239 "redirect_proto",
1240 NULL },
1241
1242 { RedirectAddress,
1243 0,
1244 String,
1245 "local_addr[,...] public_addr",
1246 "define mapping between local and public addresses",
1247 "redirect_address",
1248 NULL },
1249
1250 { ConfigFile,
1251 0,
1252 String,
1253 "file_name",
1254 "read options from configuration file",
1255 "config",
1256 "f" },
1257
1258 { LogDenied,
1259 0,
1260 YesNo,
1261 "[yes|no]",
1262 "enable logging of denied incoming packets",
1263 "log_denied",
1264 NULL },
1265
1266 { LogFacility,
1267 0,
1268 String,
1269 "facility",
1270 "name of syslog facility to use for logging",
1271 "log_facility",
1272 NULL },
1273
1274 { PunchFW,
1275 0,
1276 String,
1277 "basenumber:count",
1278 "punch holes in the firewall for incoming FTP/IRC DCC connections",
1279 "punch_fw",
1280 NULL },
1281
1282 { SkinnyPort,
1283 0,
1284 String,
1285 "port",
1286 "set the TCP port for use with the Skinny Station protocol",
1287 "skinny_port",
1288 NULL },
1289
1290 { LogIpfwDenied,
1291 0,
1292 YesNo,
1293 "[yes|no]",
1294 "log packets converted by natd, but denied by ipfw",
1295 "log_ipfw_denied",
1296 NULL },
1297
1298 { PidFile,
1299 0,
1300 String,
1301 "file_name",
1302 "store PID in an alternate file",
1303 "pid_file",
1304 "P" },
1305 { Instance,
1306 0,
1307 String,
1308 "instance name",
1309 "name of aliasing engine instance",
1310 "instance",
1311 NULL },
1312 { ExitDelay,
1313 0,
1314 Numeric,
1315 "ms",
1316 "delay in ms before daemon exit after signal",
1317 "exit_delay",
1318 NULL },
1319 };
1320
ParseOption(const char * option,const char * parms)1321 static void ParseOption (const char* option, const char* parms)
1322 {
1323 int i;
1324 struct OptionInfo* info;
1325 int yesNoValue;
1326 int aliasValue;
1327 int numValue;
1328 u_short uNumValue;
1329 const char* strValue;
1330 struct in_addr addrValue;
1331 int max;
1332 char* end;
1333 CODE* fac_record = NULL;
1334 /*
1335 * Find option from table.
1336 */
1337 max = sizeof (optionTable) / sizeof (struct OptionInfo);
1338 for (i = 0, info = optionTable; i < max; i++, info++) {
1339
1340 if (!strcmp (info->name, option))
1341 break;
1342
1343 if (info->shortName)
1344 if (!strcmp (info->shortName, option))
1345 break;
1346 }
1347
1348 if (i >= max) {
1349
1350 warnx ("unknown option %s", option);
1351 Usage ();
1352 }
1353
1354 uNumValue = 0;
1355 yesNoValue = 0;
1356 numValue = 0;
1357 strValue = NULL;
1358 /*
1359 * Check parameters.
1360 */
1361 switch (info->parm) {
1362 case YesNo:
1363 if (!parms)
1364 parms = "yes";
1365
1366 if (!strcmp (parms, "yes"))
1367 yesNoValue = 1;
1368 else
1369 if (!strcmp (parms, "no"))
1370 yesNoValue = 0;
1371 else
1372 errx (1, "%s needs yes/no parameter", option);
1373 break;
1374
1375 case Service:
1376 if (!parms)
1377 errx (1, "%s needs service name or "
1378 "port number parameter",
1379 option);
1380
1381 uNumValue = StrToPort (parms, "divert");
1382 break;
1383
1384 case Numeric:
1385 if (parms)
1386 numValue = strtol (parms, &end, 10);
1387 else
1388 end = NULL;
1389
1390 if (end == parms)
1391 errx (1, "%s needs numeric parameter", option);
1392 break;
1393
1394 case String:
1395 strValue = parms;
1396 if (!strValue)
1397 errx (1, "%s needs parameter", option);
1398 break;
1399
1400 case None:
1401 if (parms)
1402 errx (1, "%s does not take parameters", option);
1403 break;
1404
1405 case Address:
1406 if (!parms)
1407 errx (1, "%s needs address/host parameter", option);
1408
1409 StrToAddr (parms, &addrValue);
1410 break;
1411 }
1412
1413 switch (info->type) {
1414 case LibAliasOption:
1415
1416 aliasValue = yesNoValue ? info->packetAliasOpt : 0;
1417 LibAliasSetMode (mla, aliasValue, info->packetAliasOpt);
1418 break;
1419
1420 case Verbose:
1421 verbose = yesNoValue;
1422 break;
1423
1424 case DynamicMode:
1425 dynamicMode = yesNoValue;
1426 break;
1427
1428 case InPort:
1429 mip->inPort = uNumValue;
1430 break;
1431
1432 case OutPort:
1433 mip->outPort = uNumValue;
1434 break;
1435
1436 case Port:
1437 mip->inOutPort = uNumValue;
1438 break;
1439
1440 case GlobalPort:
1441 globalPort = uNumValue;
1442 break;
1443
1444 case AliasAddress:
1445 memcpy (&mip->aliasAddr, &addrValue, sizeof (struct in_addr));
1446 break;
1447
1448 case TargetAddress:
1449 LibAliasSetTarget(mla, addrValue);
1450 break;
1451
1452 case RedirectPort:
1453 SetupPortRedirect (strValue);
1454 break;
1455
1456 case RedirectProto:
1457 SetupProtoRedirect(strValue);
1458 break;
1459
1460 case RedirectAddress:
1461 SetupAddressRedirect (strValue);
1462 break;
1463
1464 case ProxyRule:
1465 LibAliasProxyRule (mla, strValue);
1466 break;
1467
1468 case InterfaceName:
1469 if (mip->ifName)
1470 free (mip->ifName);
1471
1472 mip->ifName = strdup (strValue);
1473 break;
1474
1475 case ConfigFile:
1476 ReadConfigFile (strValue);
1477 break;
1478
1479 case LogDenied:
1480 mip->logDropped = yesNoValue;
1481 break;
1482
1483 case LogFacility:
1484
1485 fac_record = facilitynames;
1486 while (fac_record->c_name != NULL) {
1487
1488 if (!strcmp (fac_record->c_name, strValue)) {
1489
1490 logFacility = fac_record->c_val;
1491 break;
1492
1493 }
1494 else
1495 fac_record++;
1496 }
1497
1498 if(fac_record->c_name == NULL)
1499 errx(1, "Unknown log facility name: %s", strValue);
1500
1501 break;
1502
1503 case PunchFW:
1504 SetupPunchFW(strValue);
1505 break;
1506
1507 case SkinnyPort:
1508 SetupSkinnyPort(strValue);
1509 break;
1510
1511 case LogIpfwDenied:
1512 logIpfwDenied = yesNoValue;
1513 break;
1514
1515 case PidFile:
1516 pidName = strdup (strValue);
1517 break;
1518 case Instance:
1519 NewInstance(strValue);
1520 break;
1521 case ExitDelay:
1522 if (numValue < 0 || numValue > MAX_EXIT_DELAY)
1523 errx(1, "Incorrect exit delay: %d", numValue);
1524 exitDelay = numValue;
1525 break;
1526 }
1527 }
1528
ReadConfigFile(const char * fileName)1529 void ReadConfigFile (const char* fileName)
1530 {
1531 FILE* file;
1532 char *buf;
1533 size_t len;
1534 char *ptr, *p;
1535 char* option;
1536
1537 file = fopen (fileName, "r");
1538 if (!file)
1539 err(1, "cannot open config file %s", fileName);
1540
1541 while ((buf = fgetln(file, &len)) != NULL) {
1542 if (buf[len - 1] == '\n')
1543 buf[len - 1] = '\0';
1544 else
1545 errx(1, "config file format error: "
1546 "last line should end with newline");
1547
1548 /*
1549 * Check for comments, strip off trailing spaces.
1550 */
1551 if ((ptr = strchr(buf, '#')))
1552 *ptr = '\0';
1553 for (ptr = buf; isspace(*ptr); ++ptr)
1554 continue;
1555 if (*ptr == '\0')
1556 continue;
1557 for (p = strchr(buf, '\0'); isspace(*--p);)
1558 continue;
1559 *++p = '\0';
1560
1561 /*
1562 * Extract option name.
1563 */
1564 option = ptr;
1565 while (*ptr && !isspace (*ptr))
1566 ++ptr;
1567
1568 if (*ptr != '\0') {
1569
1570 *ptr = '\0';
1571 ++ptr;
1572 }
1573 /*
1574 * Skip white space between name and parms.
1575 */
1576 while (*ptr && isspace (*ptr))
1577 ++ptr;
1578
1579 ParseOption (option, *ptr ? ptr : NULL);
1580 }
1581
1582 fclose (file);
1583 }
1584
Usage(void)1585 static void Usage(void)
1586 {
1587 int i;
1588 int max;
1589 struct OptionInfo* info;
1590
1591 fprintf (stderr, "Recognized options:\n\n");
1592
1593 max = sizeof (optionTable) / sizeof (struct OptionInfo);
1594 for (i = 0, info = optionTable; i < max; i++, info++) {
1595
1596 fprintf (stderr, "-%-20s %s\n", info->name,
1597 info->parmDescription);
1598
1599 if (info->shortName)
1600 fprintf (stderr, "-%-20s %s\n", info->shortName,
1601 info->parmDescription);
1602
1603 fprintf (stderr, " %s\n\n", info->description);
1604 }
1605
1606 exit (1);
1607 }
1608
SetupPortRedirect(const char * parms)1609 void SetupPortRedirect (const char* parms)
1610 {
1611 char *buf;
1612 char* ptr;
1613 char* serverPool;
1614 struct in_addr localAddr;
1615 struct in_addr publicAddr;
1616 struct in_addr remoteAddr;
1617 port_range portRange;
1618 u_short localPort = 0;
1619 u_short publicPort = 0;
1620 u_short remotePort = 0;
1621 u_short numLocalPorts = 0;
1622 u_short numPublicPorts = 0;
1623 u_short numRemotePorts = 0;
1624 int proto;
1625 char* protoName;
1626 char* separator;
1627 int i;
1628 struct alias_link *aliaslink = NULL;
1629
1630 buf = strdup (parms);
1631 if (!buf)
1632 errx (1, "redirect_port: strdup() failed");
1633 /*
1634 * Extract protocol.
1635 */
1636 protoName = strtok (buf, " \t");
1637 if (!protoName)
1638 errx (1, "redirect_port: missing protocol");
1639
1640 proto = StrToProto (protoName);
1641 /*
1642 * Extract local address.
1643 */
1644 ptr = strtok (NULL, " \t");
1645 if (!ptr)
1646 errx (1, "redirect_port: missing local address");
1647
1648 separator = strchr(ptr, ',');
1649 if (separator) { /* LSNAT redirection syntax. */
1650 localAddr.s_addr = INADDR_NONE;
1651 localPort = ~0;
1652 numLocalPorts = 1;
1653 serverPool = ptr;
1654 } else {
1655 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 )
1656 errx (1, "redirect_port: invalid local port range");
1657
1658 localPort = GETLOPORT(portRange);
1659 numLocalPorts = GETNUMPORTS(portRange);
1660 serverPool = NULL;
1661 }
1662
1663 /*
1664 * Extract public port and optionally address.
1665 */
1666 ptr = strtok (NULL, " \t");
1667 if (!ptr)
1668 errx (1, "redirect_port: missing public port");
1669
1670 separator = strchr (ptr, ':');
1671 if (separator) {
1672 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 )
1673 errx (1, "redirect_port: invalid public port range");
1674 }
1675 else {
1676 publicAddr.s_addr = INADDR_ANY;
1677 if (StrToPortRange (ptr, protoName, &portRange) != 0)
1678 errx (1, "redirect_port: invalid public port range");
1679 }
1680
1681 publicPort = GETLOPORT(portRange);
1682 numPublicPorts = GETNUMPORTS(portRange);
1683
1684 /*
1685 * Extract remote address and optionally port.
1686 */
1687 ptr = strtok (NULL, " \t");
1688 if (ptr) {
1689 separator = strchr (ptr, ':');
1690 if (separator) {
1691 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0)
1692 errx (1, "redirect_port: invalid remote port range");
1693 } else {
1694 SETLOPORT(portRange, 0);
1695 SETNUMPORTS(portRange, 1);
1696 StrToAddr (ptr, &remoteAddr);
1697 }
1698 }
1699 else {
1700 SETLOPORT(portRange, 0);
1701 SETNUMPORTS(portRange, 1);
1702 remoteAddr.s_addr = INADDR_ANY;
1703 }
1704
1705 remotePort = GETLOPORT(portRange);
1706 numRemotePorts = GETNUMPORTS(portRange);
1707
1708 /*
1709 * Make sure port ranges match up, then add the redirect ports.
1710 */
1711 if (numLocalPorts != numPublicPorts)
1712 errx (1, "redirect_port: port ranges must be equal in size");
1713
1714 /* Remote port range is allowed to be '0' which means all ports. */
1715 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0))
1716 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
1717
1718 for (i = 0 ; i < numPublicPorts ; ++i) {
1719 /* If remotePort is all ports, set it to 0. */
1720 u_short remotePortCopy = remotePort + i;
1721 if (numRemotePorts == 1 && remotePort == 0)
1722 remotePortCopy = 0;
1723
1724 aliaslink = LibAliasRedirectPort (mla, localAddr,
1725 htons(localPort + i),
1726 remoteAddr,
1727 htons(remotePortCopy),
1728 publicAddr,
1729 htons(publicPort + i),
1730 proto);
1731 }
1732
1733 /*
1734 * Setup LSNAT server pool.
1735 */
1736 if (serverPool != NULL && aliaslink != NULL) {
1737 ptr = strtok(serverPool, ",");
1738 while (ptr != NULL) {
1739 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0)
1740 errx(1, "redirect_port: invalid local port range");
1741
1742 localPort = GETLOPORT(portRange);
1743 if (GETNUMPORTS(portRange) != 1)
1744 errx(1, "redirect_port: local port must be single in this context");
1745 LibAliasAddServer(mla, aliaslink, localAddr, htons(localPort));
1746 ptr = strtok(NULL, ",");
1747 }
1748 }
1749
1750 free (buf);
1751 }
1752
1753 void
SetupProtoRedirect(const char * parms)1754 SetupProtoRedirect(const char* parms)
1755 {
1756 char *buf;
1757 char* ptr;
1758 struct in_addr localAddr;
1759 struct in_addr publicAddr;
1760 struct in_addr remoteAddr;
1761 int proto;
1762 char* protoName;
1763 struct protoent *protoent;
1764
1765 buf = strdup (parms);
1766 if (!buf)
1767 errx (1, "redirect_port: strdup() failed");
1768 /*
1769 * Extract protocol.
1770 */
1771 protoName = strtok(buf, " \t");
1772 if (!protoName)
1773 errx(1, "redirect_proto: missing protocol");
1774
1775 protoent = getprotobyname(protoName);
1776 if (protoent == NULL)
1777 errx(1, "redirect_proto: unknown protocol %s", protoName);
1778 else
1779 proto = protoent->p_proto;
1780 /*
1781 * Extract local address.
1782 */
1783 ptr = strtok(NULL, " \t");
1784 if (!ptr)
1785 errx(1, "redirect_proto: missing local address");
1786 else
1787 StrToAddr(ptr, &localAddr);
1788 /*
1789 * Extract optional public address.
1790 */
1791 ptr = strtok(NULL, " \t");
1792 if (ptr)
1793 StrToAddr(ptr, &publicAddr);
1794 else
1795 publicAddr.s_addr = INADDR_ANY;
1796 /*
1797 * Extract optional remote address.
1798 */
1799 ptr = strtok(NULL, " \t");
1800 if (ptr)
1801 StrToAddr(ptr, &remoteAddr);
1802 else
1803 remoteAddr.s_addr = INADDR_ANY;
1804 /*
1805 * Create aliasing link.
1806 */
1807 (void)LibAliasRedirectProto(mla, localAddr, remoteAddr, publicAddr,
1808 proto);
1809
1810 free (buf);
1811 }
1812
SetupAddressRedirect(const char * parms)1813 void SetupAddressRedirect (const char* parms)
1814 {
1815 char *buf;
1816 char* ptr;
1817 char* separator;
1818 struct in_addr localAddr;
1819 struct in_addr publicAddr;
1820 char* serverPool;
1821 struct alias_link *aliaslink;
1822
1823 buf = strdup (parms);
1824 if (!buf)
1825 errx (1, "redirect_port: strdup() failed");
1826 /*
1827 * Extract local address.
1828 */
1829 ptr = strtok (buf, " \t");
1830 if (!ptr)
1831 errx (1, "redirect_address: missing local address");
1832
1833 separator = strchr(ptr, ',');
1834 if (separator) { /* LSNAT redirection syntax. */
1835 localAddr.s_addr = INADDR_NONE;
1836 serverPool = ptr;
1837 } else {
1838 StrToAddr (ptr, &localAddr);
1839 serverPool = NULL;
1840 }
1841 /*
1842 * Extract public address.
1843 */
1844 ptr = strtok (NULL, " \t");
1845 if (!ptr)
1846 errx (1, "redirect_address: missing public address");
1847
1848 StrToAddr (ptr, &publicAddr);
1849 aliaslink = LibAliasRedirectAddr(mla, localAddr, publicAddr);
1850
1851 /*
1852 * Setup LSNAT server pool.
1853 */
1854 if (serverPool != NULL && aliaslink != NULL) {
1855 ptr = strtok(serverPool, ",");
1856 while (ptr != NULL) {
1857 StrToAddr(ptr, &localAddr);
1858 LibAliasAddServer(mla, aliaslink, localAddr, htons(~0));
1859 ptr = strtok(NULL, ",");
1860 }
1861 }
1862
1863 free (buf);
1864 }
1865
StrToAddr(const char * str,struct in_addr * addr)1866 void StrToAddr (const char* str, struct in_addr* addr)
1867 {
1868 struct hostent* hp;
1869
1870 if (inet_aton (str, addr))
1871 return;
1872
1873 hp = gethostbyname (str);
1874 if (!hp)
1875 errx (1, "unknown host %s", str);
1876
1877 memcpy (addr, hp->h_addr, sizeof (struct in_addr));
1878 }
1879
StrToPort(const char * str,const char * proto)1880 u_short StrToPort (const char* str, const char* proto)
1881 {
1882 u_short port;
1883 struct servent* sp;
1884 char* end;
1885
1886 port = strtol (str, &end, 10);
1887 if (end != str)
1888 return htons (port);
1889
1890 sp = getservbyname (str, proto);
1891 if (!sp)
1892 errx (1, "%s/%s: unknown service", str, proto);
1893
1894 return sp->s_port;
1895 }
1896
StrToPortRange(const char * str,const char * proto,port_range * portRange)1897 int StrToPortRange (const char* str, const char* proto, port_range *portRange)
1898 {
1899 char* sep;
1900 struct servent* sp;
1901 char* end;
1902 u_short loPort;
1903 u_short hiPort;
1904
1905 /* First see if this is a service, return corresponding port if so. */
1906 sp = getservbyname (str,proto);
1907 if (sp) {
1908 SETLOPORT(*portRange, ntohs(sp->s_port));
1909 SETNUMPORTS(*portRange, 1);
1910 return 0;
1911 }
1912
1913 /* Not a service, see if it's a single port or port range. */
1914 sep = strchr (str, '-');
1915 if (sep == NULL) {
1916 SETLOPORT(*portRange, strtol(str, &end, 10));
1917 if (end != str) {
1918 /* Single port. */
1919 SETNUMPORTS(*portRange, 1);
1920 return 0;
1921 }
1922
1923 /* Error in port range field. */
1924 errx (1, "%s/%s: unknown service", str, proto);
1925 }
1926
1927 /* Port range, get the values and sanity check. */
1928 sscanf (str, "%hu-%hu", &loPort, &hiPort);
1929 SETLOPORT(*portRange, loPort);
1930 SETNUMPORTS(*portRange, 0); /* Error by default */
1931 if (loPort <= hiPort)
1932 SETNUMPORTS(*portRange, hiPort - loPort + 1);
1933
1934 if (GETNUMPORTS(*portRange) == 0)
1935 errx (1, "invalid port range %s", str);
1936
1937 return 0;
1938 }
1939
1940
StrToProto(const char * str)1941 int StrToProto (const char* str)
1942 {
1943 if (!strcmp (str, "tcp"))
1944 return IPPROTO_TCP;
1945
1946 if (!strcmp (str, "udp"))
1947 return IPPROTO_UDP;
1948
1949 errx (1, "unknown protocol %s. Expected tcp or udp", str);
1950 }
1951
StrToAddrAndPortRange(const char * str,struct in_addr * addr,char * proto,port_range * portRange)1952 int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
1953 {
1954 char* ptr;
1955
1956 ptr = strchr (str, ':');
1957 if (!ptr)
1958 errx (1, "%s is missing port number", str);
1959
1960 *ptr = '\0';
1961 ++ptr;
1962
1963 StrToAddr (str, addr);
1964 return StrToPortRange (ptr, proto, portRange);
1965 }
1966
1967 static void
SetupPunchFW(const char * strValue)1968 SetupPunchFW(const char *strValue)
1969 {
1970 unsigned int base, num;
1971
1972 if (sscanf(strValue, "%u:%u", &base, &num) != 2)
1973 errx(1, "punch_fw: basenumber:count parameter required");
1974
1975 if (CheckIpfwRulenum(base + num - 1) == -1)
1976 errx(1, "punch_fw: basenumber:count parameter should fit "
1977 "the maximum allowed rule numbers");
1978
1979 LibAliasSetFWBase(mla, base, num);
1980 (void)LibAliasSetMode(mla, PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW);
1981 }
1982
1983 static void
SetupSkinnyPort(const char * strValue)1984 SetupSkinnyPort(const char *strValue)
1985 {
1986 unsigned int port;
1987
1988 if (sscanf(strValue, "%u", &port) != 1)
1989 errx(1, "skinny_port: port parameter required");
1990
1991 LibAliasSetSkinnyPort(mla, port);
1992 }
1993
1994 static void
NewInstance(const char * name)1995 NewInstance(const char *name)
1996 {
1997 struct instance *ip;
1998
1999 LIST_FOREACH(ip, &root, list) {
2000 if (!strcmp(ip->name, name)) {
2001 mla = ip->la;
2002 mip = ip;
2003 return;
2004 }
2005 }
2006 ninstance++;
2007 ip = calloc(sizeof *ip, 1);
2008 ip->name = strdup(name);
2009 ip->la = LibAliasInit (ip->la);
2010 ip->assignAliasAddr = 0;
2011 ip->ifName = NULL;
2012 ip->logDropped = 0;
2013 ip->inPort = 0;
2014 ip->outPort = 0;
2015 ip->inOutPort = 0;
2016 ip->aliasAddr.s_addr = INADDR_NONE;
2017 ip->ifMTU = -1;
2018 ip->aliasOverhead = 12;
2019 LIST_INSERT_HEAD(&root, ip, list);
2020 mla = ip->la;
2021 mip = ip;
2022 }
2023
2024 static int
CheckIpfwRulenum(unsigned int rnum)2025 CheckIpfwRulenum(unsigned int rnum)
2026 {
2027 unsigned int default_rule;
2028 size_t len = sizeof(default_rule);
2029
2030 if (sysctlbyname("net.inet.ip.fw.default_rule", &default_rule, &len,
2031 NULL, 0) == -1) {
2032 warn("Failed to get the default ipfw rule number, using "
2033 "default historical value 65535. The reason was");
2034 default_rule = 65535;
2035 }
2036 if (rnum >= default_rule) {
2037 return -1;
2038 }
2039
2040 return 0;
2041 }
2042