xref: /freebsd/sbin/natd/natd.c (revision f9ce010afdd3136fc73e2b500f2ed916bf9cfa59)
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  * $FreeBSD$
13  */
14 
15 #define SYSLOG_NAMES
16 
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 
21 #include <netinet/in.h>
22 #include <netinet/in_systm.h>
23 #include <netinet/ip.h>
24 #include <machine/in_cksum.h>
25 #include <netinet/tcp.h>
26 #include <netinet/udp.h>
27 #include <netinet/ip_icmp.h>
28 #include <sys/ioctl.h>
29 #include <net/if.h>
30 #include <net/route.h>
31 #include <arpa/inet.h>
32 
33 #include <alias.h>
34 #include <ctype.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <netdb.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <unistd.h>
44 
45 #include "natd.h"
46 
47 /*
48  * Default values for input and output
49  * divert socket ports.
50  */
51 
52 #define	DEFAULT_SERVICE	"natd"
53 
54 /*
55  * Definition of a port range, and macros to deal with values.
56  * FORMAT:  HI 16-bits == first port in range, 0 == all ports.
57  *          LO 16-bits == number of ports in range
58  * NOTES:   - Port values are not stored in network byte order.
59  */
60 
61 typedef u_long port_range;
62 
63 #define GETLOPORT(x)     ((x) >> 0x10)
64 #define GETNUMPORTS(x)   ((x) & 0x0000ffff)
65 #define GETHIPORT(x)     (GETLOPORT((x)) + GETNUMPORTS((x)))
66 
67 /* Set y to be the low-port value in port_range variable x. */
68 #define SETLOPORT(x,y)   ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
69 
70 /* Set y to be the number of ports in port_range variable x. */
71 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
72 
73 /*
74  * Function prototypes.
75  */
76 
77 static void	DoAliasing (int fd, int direction);
78 static void	DaemonMode (void);
79 static void	HandleRoutingInfo (int fd);
80 static void	Usage (void);
81 static char*	FormatPacket (struct ip*);
82 static void	PrintPacket (struct ip*);
83 static void	SyslogPacket (struct ip*, int priority, const char *label);
84 static void	SetAliasAddressFromIfName (char* ifName);
85 static void	InitiateShutdown (int);
86 static void	Shutdown (int);
87 static void	RefreshAddr (int);
88 static void	ParseOption (const char* option, const char* parms, int cmdLine);
89 static void	ReadConfigFile (const char* fileName);
90 static void	SetupPortRedirect (const char* parms);
91 static void	SetupAddressRedirect (const char* parms);
92 static void	SetupPptpAlias (const char* parms);
93 static void	StrToAddr (const char* str, struct in_addr* addr);
94 static u_short  StrToPort (const char* str, const char* proto);
95 static int      StrToPortRange (const char* str, const char* proto, port_range *portRange);
96 static int 	StrToProto (const char* str);
97 static int      StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange);
98 static void	ParseArgs (int argc, char** argv);
99 static void	FlushPacketBuffer (int fd);
100 
101 /*
102  * Globals.
103  */
104 
105 static	int			verbose;
106 static 	int			background;
107 static	int			running;
108 static	int			assignAliasAddr;
109 static	char*			ifName;
110 static  int			ifIndex;
111 static	u_short			inPort;
112 static	u_short			outPort;
113 static	u_short			inOutPort;
114 static	struct in_addr		aliasAddr;
115 static 	int			dynamicMode;
116 static  int			ifMTU;
117 static	int			aliasOverhead;
118 static 	int			icmpSock;
119 static	char			packetBuf[IP_MAXPACKET];
120 static 	int			packetLen;
121 static	struct sockaddr_in	packetAddr;
122 static 	int			packetSock;
123 static 	int			packetDirection;
124 static  int			dropIgnoredIncoming;
125 static  int			logDropped;
126 static	int			logFacility;
127 
128 int main (int argc, char** argv)
129 {
130 	int			divertIn;
131 	int			divertOut;
132 	int			divertInOut;
133 	int			routeSock;
134 	struct sockaddr_in	addr;
135 	fd_set			readMask;
136 	fd_set			writeMask;
137 	int			fdMax;
138 /*
139  * Initialize packet aliasing software.
140  * Done already here to be able to alter option bits
141  * during command line and configuration file processing.
142  */
143 	PacketAliasInit ();
144 /*
145  * Parse options.
146  */
147 	inPort			= 0;
148 	outPort			= 0;
149 	verbose 		= 0;
150 	inOutPort		= 0;
151 	ifName			= NULL;
152 	ifMTU			= -1;
153 	background		= 0;
154 	running			= 1;
155 	assignAliasAddr		= 0;
156 	aliasAddr.s_addr	= INADDR_NONE;
157 	aliasOverhead		= 12;
158 	dynamicMode		= 0;
159  	logDropped		= 0;
160  	logFacility		= LOG_DAEMON;
161 /*
162  * Mark packet buffer empty.
163  */
164 	packetSock		= -1;
165 	packetDirection		= DONT_KNOW;
166 
167 	ParseArgs (argc, argv);
168 /*
169  * Open syslog channel.
170  */
171 	openlog ("natd", LOG_CONS | LOG_PID, logFacility);
172 /*
173  * Check that valid aliasing address has been given.
174  */
175 	if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL)
176 		errx (1, "aliasing address not given");
177 
178 	if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL)
179 		errx (1, "both alias address and interface "
180 			 "name are not allowed");
181 /*
182  * Check that valid port number is known.
183  */
184 	if (inPort != 0 || outPort != 0)
185 		if (inPort == 0 || outPort == 0)
186 			errx (1, "both input and output ports are required");
187 
188 	if (inPort == 0 && outPort == 0 && inOutPort == 0)
189 		ParseOption ("port", DEFAULT_SERVICE, 0);
190 
191 /*
192  * Check if ignored packets should be dropped.
193  */
194 	dropIgnoredIncoming = PacketAliasSetMode (0, 0);
195 	dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING;
196 /*
197  * Create divert sockets. Use only one socket if -p was specified
198  * on command line. Otherwise, create separate sockets for
199  * outgoing and incoming connnections.
200  */
201 	if (inOutPort) {
202 
203 		divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
204 		if (divertInOut == -1)
205 			Quit ("Unable to create divert socket.");
206 
207 		divertIn  = -1;
208 		divertOut = -1;
209 /*
210  * Bind socket.
211  */
212 
213 		addr.sin_family		= AF_INET;
214 		addr.sin_addr.s_addr	= INADDR_ANY;
215 		addr.sin_port		= inOutPort;
216 
217 		if (bind (divertInOut,
218 			  (struct sockaddr*) &addr,
219 			  sizeof addr) == -1)
220 			Quit ("Unable to bind divert socket.");
221 	}
222 	else {
223 
224 		divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
225 		if (divertIn == -1)
226 			Quit ("Unable to create incoming divert socket.");
227 
228 		divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
229 		if (divertOut == -1)
230 			Quit ("Unable to create outgoing divert socket.");
231 
232 		divertInOut = -1;
233 
234 /*
235  * Bind divert sockets.
236  */
237 
238 		addr.sin_family		= AF_INET;
239 		addr.sin_addr.s_addr	= INADDR_ANY;
240 		addr.sin_port		= inPort;
241 
242 		if (bind (divertIn,
243 			  (struct sockaddr*) &addr,
244 			  sizeof addr) == -1)
245 			Quit ("Unable to bind incoming divert socket.");
246 
247 		addr.sin_family		= AF_INET;
248 		addr.sin_addr.s_addr	= INADDR_ANY;
249 		addr.sin_port		= outPort;
250 
251 		if (bind (divertOut,
252 			  (struct sockaddr*) &addr,
253 			  sizeof addr) == -1)
254 			Quit ("Unable to bind outgoing divert socket.");
255 	}
256 /*
257  * Create routing socket if interface name specified.
258  */
259 	if (ifName && dynamicMode) {
260 
261 		routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
262 		if (routeSock == -1)
263 			Quit ("Unable to create routing info socket.");
264 	}
265 	else
266 		routeSock = -1;
267 /*
268  * Create socket for sending ICMP messages.
269  */
270 	icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
271 	if (icmpSock == -1)
272 		Quit ("Unable to create ICMP socket.");
273 
274 /*
275  * And disable reads for the socket, otherwise it slowly fills
276  * up with received icmps which we do not use.
277  */
278 	shutdown(icmpSock, SHUT_RD);
279 
280 /*
281  * Become a daemon unless verbose mode was requested.
282  */
283 	if (!verbose)
284 		DaemonMode ();
285 /*
286  * Catch signals to manage shutdown and
287  * refresh of interface address.
288  */
289 	siginterrupt(SIGTERM, 1);
290 	siginterrupt(SIGHUP, 1);
291 	signal (SIGTERM, InitiateShutdown);
292 	signal (SIGHUP, RefreshAddr);
293 /*
294  * Set alias address if it has been given.
295  */
296 	if (aliasAddr.s_addr != INADDR_NONE)
297 		PacketAliasSetAddress (aliasAddr);
298 /*
299  * We need largest descriptor number for select.
300  */
301 
302 	fdMax = -1;
303 
304 	if (divertIn > fdMax)
305 		fdMax = divertIn;
306 
307 	if (divertOut > fdMax)
308 		fdMax = divertOut;
309 
310 	if (divertInOut > fdMax)
311 		fdMax = divertInOut;
312 
313 	if (routeSock > fdMax)
314 		fdMax = routeSock;
315 
316 	while (running) {
317 
318 		if (divertInOut != -1 && !ifName && packetSock == -1) {
319 /*
320  * When using only one socket, just call
321  * DoAliasing repeatedly to process packets.
322  */
323 			DoAliasing (divertInOut, DONT_KNOW);
324 			continue;
325 		}
326 /*
327  * Build read mask from socket descriptors to select.
328  */
329 		FD_ZERO (&readMask);
330 		FD_ZERO (&writeMask);
331 
332 /*
333  * If there is unsent packet in buffer, use select
334  * to check when socket comes writable again.
335  */
336 		if (packetSock != -1) {
337 
338 			FD_SET (packetSock, &writeMask);
339 		}
340 		else {
341 /*
342  * No unsent packet exists - safe to check if
343  * new ones are available.
344  */
345 			if (divertIn != -1)
346 				FD_SET (divertIn, &readMask);
347 
348 			if (divertOut != -1)
349 				FD_SET (divertOut, &readMask);
350 
351 			if (divertInOut != -1)
352 				FD_SET (divertInOut, &readMask);
353 		}
354 /*
355  * Routing info is processed always.
356  */
357 		if (routeSock != -1)
358 			FD_SET (routeSock, &readMask);
359 
360 		if (select (fdMax + 1,
361 			    &readMask,
362 			    &writeMask,
363 			    NULL,
364 			    NULL) == -1) {
365 
366 			if (errno == EINTR)
367 				continue;
368 
369 			Quit ("Select failed.");
370 		}
371 
372 		if (packetSock != -1)
373 			if (FD_ISSET (packetSock, &writeMask))
374 				FlushPacketBuffer (packetSock);
375 
376 		if (divertIn != -1)
377 			if (FD_ISSET (divertIn, &readMask))
378 				DoAliasing (divertIn, INPUT);
379 
380 		if (divertOut != -1)
381 			if (FD_ISSET (divertOut, &readMask))
382 				DoAliasing (divertOut, OUTPUT);
383 
384 		if (divertInOut != -1)
385 			if (FD_ISSET (divertInOut, &readMask))
386 				DoAliasing (divertInOut, DONT_KNOW);
387 
388 		if (routeSock != -1)
389 			if (FD_ISSET (routeSock, &readMask))
390 				HandleRoutingInfo (routeSock);
391 	}
392 
393 	if (background)
394 		unlink (PIDFILE);
395 
396 	return 0;
397 }
398 
399 static void DaemonMode ()
400 {
401 	FILE*	pidFile;
402 
403 	daemon (0, 0);
404 	background = 1;
405 
406 	pidFile = fopen (PIDFILE, "w");
407 	if (pidFile) {
408 
409 		fprintf (pidFile, "%d\n", getpid ());
410 		fclose (pidFile);
411 	}
412 }
413 
414 static void ParseArgs (int argc, char** argv)
415 {
416 	int		arg;
417 	char*		parm;
418 	char*		opt;
419 	char		parmBuf[256];
420 
421 	for (arg = 1; arg < argc; arg++) {
422 
423 		opt  = argv[arg];
424 		if (*opt != '-') {
425 
426 			warnx ("invalid option %s", opt);
427 			Usage ();
428 		}
429 
430 		parm = NULL;
431 		parmBuf[0] = '\0';
432 
433 		while (arg < argc - 1) {
434 
435 			if (argv[arg + 1][0] == '-')
436 				break;
437 
438 			if (parm)
439 				strcat (parmBuf, " ");
440 
441 			++arg;
442 			parm = parmBuf;
443 			strcat (parmBuf, argv[arg]);
444 		}
445 
446 		ParseOption (opt + 1, parm, 1);
447 	}
448 }
449 
450 static void DoAliasing (int fd, int direction)
451 {
452 	int			bytes;
453 	int			origBytes;
454 	int			status;
455 	int			addrSize;
456 	struct ip*		ip;
457 
458 	if (assignAliasAddr) {
459 
460 		SetAliasAddressFromIfName (ifName);
461 		assignAliasAddr = 0;
462 	}
463 /*
464  * Get packet from socket.
465  */
466 	addrSize  = sizeof packetAddr;
467 	origBytes = recvfrom (fd,
468 			      packetBuf,
469 			      sizeof packetBuf,
470 			      0,
471 			      (struct sockaddr*) &packetAddr,
472 			      &addrSize);
473 
474 	if (origBytes == -1) {
475 
476 		if (errno != EINTR)
477 			Warn ("read from divert socket failed");
478 
479 		return;
480 	}
481 /*
482  * This is a IP packet.
483  */
484 	ip = (struct ip*) packetBuf;
485 	if (direction == DONT_KNOW) {
486 		if (packetAddr.sin_addr.s_addr == INADDR_ANY)
487 			direction = OUTPUT;
488 		else
489 			direction = INPUT;
490 	}
491 
492 	if (verbose) {
493 /*
494  * Print packet direction and protocol type.
495  */
496 		printf (direction == OUTPUT ? "Out " : "In  ");
497 
498 		switch (ip->ip_p) {
499 		case IPPROTO_TCP:
500 			printf ("[TCP]  ");
501 			break;
502 
503 		case IPPROTO_UDP:
504 			printf ("[UDP]  ");
505 			break;
506 
507 		case IPPROTO_ICMP:
508 			printf ("[ICMP] ");
509 			break;
510 
511 		default:
512 			printf ("[%d]    ", ip->ip_p);
513 			break;
514 		}
515 /*
516  * Print addresses.
517  */
518 		PrintPacket (ip);
519 	}
520 
521 	if (direction == OUTPUT) {
522 /*
523  * Outgoing packets. Do aliasing.
524  */
525 		PacketAliasOut (packetBuf, IP_MAXPACKET);
526 	}
527 	else {
528 
529 /*
530  * Do aliasing.
531  */
532 		status = PacketAliasIn (packetBuf, IP_MAXPACKET);
533 		if (status == PKT_ALIAS_IGNORED &&
534 		    dropIgnoredIncoming) {
535 
536 			if (verbose)
537 				printf (" dropped.\n");
538 
539 			if (logDropped)
540 				SyslogPacket (ip, LOG_WARNING, "denied");
541 
542 			return;
543 		}
544 	}
545 /*
546  * Length might have changed during aliasing.
547  */
548 	bytes = ntohs (ip->ip_len);
549 /*
550  * Update alias overhead size for outgoing packets.
551  */
552 	if (direction == OUTPUT &&
553 	    bytes - origBytes > aliasOverhead)
554 		aliasOverhead = bytes - origBytes;
555 
556 	if (verbose) {
557 
558 /*
559  * Print addresses after aliasing.
560  */
561 		printf (" aliased to\n");
562 		printf ("           ");
563 		PrintPacket (ip);
564 		printf ("\n");
565 	}
566 
567 	packetLen  	= bytes;
568 	packetSock 	= fd;
569 	packetDirection = direction;
570 
571 	FlushPacketBuffer (fd);
572 }
573 
574 static void FlushPacketBuffer (int fd)
575 {
576 	int			wrote;
577 	char			msgBuf[80];
578 /*
579  * Put packet back for processing.
580  */
581 	wrote = sendto (fd,
582 		        packetBuf,
583 	    		packetLen,
584 	    		0,
585 	    		(struct sockaddr*) &packetAddr,
586 	    		sizeof packetAddr);
587 
588 	if (wrote != packetLen) {
589 /*
590  * If buffer space is not available,
591  * just return. Main loop will take care of
592  * retrying send when space becomes available.
593  */
594 		if (errno == ENOBUFS)
595 			return;
596 
597 		if (errno == EMSGSIZE) {
598 
599 			if (packetDirection == OUTPUT &&
600 			    ifMTU != -1)
601 				SendNeedFragIcmp (icmpSock,
602 						  (struct ip*) packetBuf,
603 						  ifMTU - aliasOverhead);
604 		}
605 		else {
606 
607 			sprintf (msgBuf, "failed to write packet back");
608 			Warn (msgBuf);
609 		}
610 	}
611 
612 	packetSock = -1;
613 }
614 
615 static void HandleRoutingInfo (int fd)
616 {
617 	int			bytes;
618 	struct if_msghdr	ifMsg;
619 /*
620  * Get packet from socket.
621  */
622 	bytes = read (fd, &ifMsg, sizeof ifMsg);
623 	if (bytes == -1) {
624 
625 		Warn ("read from routing socket failed");
626 		return;
627 	}
628 
629 	if (ifMsg.ifm_version != RTM_VERSION) {
630 
631 		Warn ("unexpected packet read from routing socket");
632 		return;
633 	}
634 
635 	if (verbose)
636 		printf ("Routing message %X received.\n", ifMsg.ifm_type);
637 
638 	if (ifMsg.ifm_type != RTM_NEWADDR)
639 		return;
640 
641 	if (verbose && ifMsg.ifm_index == ifIndex)
642 		printf ("Interface address has changed.\n");
643 
644 	if (ifMsg.ifm_index == ifIndex)
645 		assignAliasAddr = 1;
646 }
647 
648 static void PrintPacket (struct ip* ip)
649 {
650 	printf ("%s", FormatPacket (ip));
651 }
652 
653 static void SyslogPacket (struct ip* ip, int priority, const char *label)
654 {
655 	syslog (priority, "%s %s", label, FormatPacket (ip));
656 }
657 
658 static char* FormatPacket (struct ip* ip)
659 {
660 	static char	buf[256];
661 	struct tcphdr*	tcphdr;
662 	struct udphdr*	udphdr;
663 	struct icmp*	icmphdr;
664 	char		src[20];
665 	char		dst[20];
666 
667 	strcpy (src, inet_ntoa (ip->ip_src));
668 	strcpy (dst, inet_ntoa (ip->ip_dst));
669 
670 	switch (ip->ip_p) {
671 	case IPPROTO_TCP:
672 		tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
673 		sprintf (buf, "[TCP] %s:%d -> %s:%d",
674 			      src,
675 			      ntohs (tcphdr->th_sport),
676 			      dst,
677 			      ntohs (tcphdr->th_dport));
678 		break;
679 
680 	case IPPROTO_UDP:
681 		udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
682 		sprintf (buf, "[UDP] %s:%d -> %s:%d",
683 			      src,
684 			      ntohs (udphdr->uh_sport),
685 			      dst,
686 			      ntohs (udphdr->uh_dport));
687 		break;
688 
689 	case IPPROTO_ICMP:
690 		icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
691 		sprintf (buf, "[ICMP] %s -> %s %u(%u)",
692 			      src,
693 			      dst,
694 			      icmphdr->icmp_type,
695 			      icmphdr->icmp_code);
696 		break;
697 
698 	default:
699 		sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
700 		break;
701 	}
702 
703 	return buf;
704 }
705 
706 static void SetAliasAddressFromIfName (char* ifn)
707 {
708 	struct ifconf		cf;
709 	struct ifreq		buf[32];
710 	char			msg[80];
711 	struct ifreq*		ifPtr;
712 	int			extra;
713 	int			helperSock;
714 	int			bytes;
715 	struct sockaddr_in*	addr;
716 	int			found;
717 	struct ifreq		req;
718 	char			last[10];
719 /*
720  * Create a dummy socket to access interface information.
721  */
722 	helperSock = socket (AF_INET, SOCK_DGRAM, 0);
723 	if (helperSock == -1) {
724 
725 		Quit ("Failed to create helper socket.");
726 		exit (1);
727 	}
728 
729 	cf.ifc_len = sizeof (buf);
730 	cf.ifc_req = buf;
731 /*
732  * Get interface data.
733  */
734 	if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) {
735 
736 		Quit ("Ioctl SIOCGIFCONF failed.");
737 		exit (1);
738 	}
739 
740 	ifIndex	= 0;
741 	ifPtr	= buf;
742 	bytes	= cf.ifc_len;
743 	found   = 0;
744 	last[0] = '\0';
745 /*
746  * Loop through interfaces until one with
747  * given name is found. This is done to
748  * find correct interface index for routing
749  * message processing.
750  */
751 	while (bytes) {
752 
753 		if (ifPtr->ifr_addr.sa_family == AF_INET &&
754                     !strcmp (ifPtr->ifr_name, ifn)) {
755 
756 			found = 1;
757 			break;
758 		}
759 
760 		if (strcmp (last, ifPtr->ifr_name)) {
761 
762 			strcpy (last, ifPtr->ifr_name);
763 			++ifIndex;
764 		}
765 
766 		extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr);
767 		if (extra < 0)
768 			extra = 0;
769 
770 		ifPtr++;
771 		ifPtr = (struct ifreq*) ((char*) ifPtr + extra);
772 		bytes -= sizeof (struct ifreq) + extra;
773 	}
774 
775 	if (!found) {
776 
777 		close (helperSock);
778 		sprintf (msg, "Unknown interface name %s.\n", ifn);
779 		Quit (msg);
780 	}
781 /*
782  * Get MTU size.
783  */
784 	strcpy (req.ifr_name, ifn);
785 
786 	if (ioctl (helperSock, SIOCGIFMTU, &req) == -1)
787 		Quit ("Cannot get interface mtu size.");
788 
789 	ifMTU = req.ifr_mtu;
790 /*
791  * Get interface address.
792  */
793 	if (ioctl (helperSock, SIOCGIFADDR, &req) == -1)
794 		Quit ("Cannot get interface address.");
795 
796 	addr = (struct sockaddr_in*) &req.ifr_addr;
797 	PacketAliasSetAddress (addr->sin_addr);
798 	syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes",
799 			  inet_ntoa (addr->sin_addr),
800 			  ifMTU);
801 
802 	close (helperSock);
803 }
804 
805 void Quit (const char* msg)
806 {
807 	Warn (msg);
808 	exit (1);
809 }
810 
811 void Warn (const char* msg)
812 {
813 	if (background)
814 		syslog (LOG_ALERT, "%s (%m)", msg);
815 	else
816 		warn (msg);
817 }
818 
819 static void RefreshAddr (int sig)
820 {
821 	if (ifName)
822 		assignAliasAddr = 1;
823 }
824 
825 static void InitiateShutdown (int sig)
826 {
827 /*
828  * Start timer to allow kernel gracefully
829  * shutdown existing connections when system
830  * is shut down.
831  */
832 	siginterrupt(SIGALRM, 1);
833 	signal (SIGALRM, Shutdown);
834 	alarm (10);
835 }
836 
837 static void Shutdown (int sig)
838 {
839 	running = 0;
840 }
841 
842 /*
843  * Different options recognized by this program.
844  */
845 
846 enum Option {
847 
848 	PacketAliasOption,
849 	Verbose,
850 	InPort,
851 	OutPort,
852 	Port,
853 	AliasAddress,
854 	InterfaceName,
855 	RedirectPort,
856 	RedirectAddress,
857 	ConfigFile,
858 	DynamicMode,
859 	PptpAlias,
860 	ProxyRule,
861  	LogDenied,
862  	LogFacility
863 };
864 
865 enum Param {
866 
867 	YesNo,
868 	Numeric,
869 	String,
870 	None,
871 	Address,
872 	Service
873 };
874 
875 /*
876  * Option information structure (used by ParseOption).
877  */
878 
879 struct OptionInfo {
880 
881 	enum Option		type;
882 	int			packetAliasOpt;
883 	enum Param		parm;
884 	const char*		parmDescription;
885 	const char*		description;
886 	const char*		name;
887 	const char*		shortName;
888 };
889 
890 /*
891  * Table of known options.
892  */
893 
894 static struct OptionInfo optionTable[] = {
895 
896 	{ PacketAliasOption,
897 		PKT_ALIAS_UNREGISTERED_ONLY,
898 		YesNo,
899 		"[yes|no]",
900 		"alias only unregistered addresses",
901 		"unregistered_only",
902 		"u" },
903 
904 	{ PacketAliasOption,
905 		PKT_ALIAS_LOG,
906 		YesNo,
907 		"[yes|no]",
908 		"enable logging",
909 		"log",
910 		"l" },
911 
912 	{ PacketAliasOption,
913 		PKT_ALIAS_PROXY_ONLY,
914 		YesNo,
915 		"[yes|no]",
916 		"proxy only",
917 		"proxy_only",
918 		NULL },
919 
920 	{ PacketAliasOption,
921 		PKT_ALIAS_REVERSE,
922 		YesNo,
923 		"[yes|no]",
924 		"operate in reverse mode",
925 		"reverse",
926 		NULL },
927 
928 	{ PacketAliasOption,
929 		PKT_ALIAS_DENY_INCOMING,
930 		YesNo,
931 		"[yes|no]",
932 		"allow incoming connections",
933 		"deny_incoming",
934 		"d" },
935 
936 	{ PacketAliasOption,
937 		PKT_ALIAS_USE_SOCKETS,
938 		YesNo,
939 		"[yes|no]",
940 		"use sockets to inhibit port conflict",
941 		"use_sockets",
942 		"s" },
943 
944 	{ PacketAliasOption,
945 		PKT_ALIAS_SAME_PORTS,
946 		YesNo,
947 		"[yes|no]",
948 		"try to keep original port numbers for connections",
949 		"same_ports",
950 		"m" },
951 
952 	{ Verbose,
953 		0,
954 		YesNo,
955 		"[yes|no]",
956 		"verbose mode, dump packet information",
957 		"verbose",
958 		"v" },
959 
960 	{ DynamicMode,
961 		0,
962 		YesNo,
963 		"[yes|no]",
964 		"dynamic mode, automatically detect interface address changes",
965 		"dynamic",
966 		NULL },
967 
968 	{ InPort,
969 		0,
970 		Service,
971 		"number|service_name",
972 		"set port for incoming packets",
973 		"in_port",
974 		"i" },
975 
976 	{ OutPort,
977 		0,
978 		Service,
979 		"number|service_name",
980 		"set port for outgoing packets",
981 		"out_port",
982 		"o" },
983 
984 	{ Port,
985 		0,
986 		Service,
987 		"number|service_name",
988 		"set port (defaults to natd/divert)",
989 		"port",
990 		"p" },
991 
992 	{ AliasAddress,
993 		0,
994 		Address,
995 		"x.x.x.x",
996 		"address to use for aliasing",
997 		"alias_address",
998 		"a" },
999 
1000 	{ InterfaceName,
1001 		0,
1002 		String,
1003 	        "network_if_name",
1004 		"take aliasing address from interface",
1005 		"interface",
1006 		"n" },
1007 
1008 	{ ProxyRule,
1009 		0,
1010 		String,
1011 	        "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1012 		"a.b.c.d:yyyy",
1013 		"add transparent proxying / destination NAT",
1014 		"proxy_rule",
1015 		NULL },
1016 
1017 	{ RedirectPort,
1018 		0,
1019 		String,
1020 	        "tcp|udp local_addr:local_port_range [public_addr:]public_port_range"
1021 	 	" [remote_addr[:remote_port_range]]",
1022 		"redirect a port (or ports) for incoming traffic",
1023 		"redirect_port",
1024 		NULL },
1025 
1026 	{ RedirectAddress,
1027 		0,
1028 		String,
1029 	        "local_addr public_addr",
1030 		"define mapping between local and public addresses",
1031 		"redirect_address",
1032 		NULL },
1033 
1034        { PptpAlias,
1035 		0,
1036 		String,
1037 		"src",
1038 		"define inside machine for PPTP traffic",
1039 		"pptpalias",
1040 		NULL },
1041 
1042 	{ ConfigFile,
1043 		0,
1044 		String,
1045 		"file_name",
1046 		"read options from configuration file",
1047 		"config",
1048 		"f" },
1049 
1050 	{ LogDenied,
1051 		0,
1052 		YesNo,
1053 	        "[yes|no]",
1054 		"enable logging of denied incoming packets",
1055 		"log_denied",
1056 		NULL },
1057 
1058 	{ LogFacility,
1059 		0,
1060 		String,
1061 	        "facility",
1062 		"name of syslog facility to use for logging",
1063 		"log_facility",
1064 		NULL }
1065 
1066 };
1067 
1068 static void ParseOption (const char* option, const char* parms, int cmdLine)
1069 {
1070 	int			i;
1071 	struct OptionInfo*	info;
1072 	int			yesNoValue;
1073 	int			aliasValue;
1074 	int			numValue;
1075 	u_short			uNumValue;
1076 	const char*		strValue;
1077 	struct in_addr		addrValue;
1078 	int			max;
1079 	char*			end;
1080 	CODE* 			fac_record = NULL;
1081 /*
1082  * Find option from table.
1083  */
1084 	max = sizeof (optionTable) / sizeof (struct OptionInfo);
1085 	for (i = 0, info = optionTable; i < max; i++, info++) {
1086 
1087 		if (!strcmp (info->name, option))
1088 			break;
1089 
1090 		if (info->shortName)
1091 			if (!strcmp (info->shortName, option))
1092 				break;
1093 	}
1094 
1095 	if (i >= max) {
1096 
1097 		warnx ("unknown option %s", option);
1098 		Usage ();
1099 	}
1100 
1101 	uNumValue	= 0;
1102 	yesNoValue	= 0;
1103 	numValue	= 0;
1104 	strValue	= NULL;
1105 /*
1106  * Check parameters.
1107  */
1108 	switch (info->parm) {
1109 	case YesNo:
1110 		if (!parms)
1111 			parms = "yes";
1112 
1113 		if (!strcmp (parms, "yes"))
1114 			yesNoValue = 1;
1115 		else
1116 			if (!strcmp (parms, "no"))
1117 				yesNoValue = 0;
1118 			else
1119 				errx (1, "%s needs yes/no parameter", option);
1120 		break;
1121 
1122 	case Service:
1123 		if (!parms)
1124 			errx (1, "%s needs service name or "
1125 				 "port number parameter",
1126 				 option);
1127 
1128 		uNumValue = StrToPort (parms, "divert");
1129 		break;
1130 
1131 	case Numeric:
1132 		if (parms)
1133 			numValue = strtol (parms, &end, 10);
1134 		else
1135 			end = NULL;
1136 
1137 		if (end == parms)
1138 			errx (1, "%s needs numeric parameter", option);
1139 		break;
1140 
1141 	case String:
1142 		strValue = parms;
1143 		if (!strValue)
1144 			errx (1, "%s needs parameter", option);
1145 		break;
1146 
1147 	case None:
1148 		if (parms)
1149 			errx (1, "%s does not take parameters", option);
1150 		break;
1151 
1152 	case Address:
1153 		if (!parms)
1154 			errx (1, "%s needs address/host parameter", option);
1155 
1156 		StrToAddr (parms, &addrValue);
1157 		break;
1158 	}
1159 
1160 	switch (info->type) {
1161 	case PacketAliasOption:
1162 
1163 		aliasValue = yesNoValue ? info->packetAliasOpt : 0;
1164 		PacketAliasSetMode (aliasValue, info->packetAliasOpt);
1165 		break;
1166 
1167 	case Verbose:
1168 		verbose = yesNoValue;
1169 		break;
1170 
1171 	case DynamicMode:
1172 		dynamicMode = yesNoValue;
1173 		break;
1174 
1175 	case InPort:
1176 		inPort = uNumValue;
1177 		break;
1178 
1179 	case OutPort:
1180 		outPort = uNumValue;
1181 		break;
1182 
1183 	case Port:
1184 		inOutPort = uNumValue;
1185 		break;
1186 
1187 	case AliasAddress:
1188 		memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
1189 		break;
1190 
1191 	case RedirectPort:
1192 		SetupPortRedirect (strValue);
1193 		break;
1194 
1195 	case RedirectAddress:
1196 		SetupAddressRedirect (strValue);
1197 		break;
1198 
1199 	case PptpAlias:
1200 		SetupPptpAlias (strValue);
1201 		break;
1202 
1203 	case ProxyRule:
1204 		PacketAliasProxyRule (strValue);
1205 		break;
1206 
1207 	case InterfaceName:
1208 		if (ifName)
1209 			free (ifName);
1210 
1211 		ifName = strdup (strValue);
1212 		assignAliasAddr = 1;
1213 		break;
1214 
1215 	case ConfigFile:
1216 		ReadConfigFile (strValue);
1217 		break;
1218 
1219 	case LogDenied:
1220 		logDropped = 1;
1221 		break;
1222 
1223 	case LogFacility:
1224 
1225 		fac_record = facilitynames;
1226 		while (fac_record->c_name != NULL) {
1227 
1228 			if (!strcmp (fac_record->c_name, strValue)) {
1229 
1230 				logFacility = fac_record->c_val;
1231 				break;
1232 
1233 			}
1234 			else
1235 				fac_record++;
1236 		}
1237 
1238 		if(fac_record->c_name == NULL)
1239 			errx(1, "Unknown log facility name: %s", strValue);
1240 
1241 		break;
1242 	}
1243 }
1244 
1245 void ReadConfigFile (const char* fileName)
1246 {
1247 	FILE*	file;
1248 	char	buf[128];
1249 	char*	ptr;
1250 	char*	option;
1251 
1252 	file = fopen (fileName, "r");
1253 	if (!file) {
1254 
1255 		sprintf (buf, "Cannot open config file %s.\n", fileName);
1256 		Quit (buf);
1257 	}
1258 
1259 	while (fgets (buf, sizeof (buf), file)) {
1260 
1261 		ptr = strchr (buf, '\n');
1262 		if (!ptr)
1263 			errx (1, "config line too long: %s", buf);
1264 
1265 		*ptr = '\0';
1266 		if (buf[0] == '#')
1267 			continue;
1268 
1269 		ptr = buf;
1270 /*
1271  * Skip white space at beginning of line.
1272  */
1273 		while (*ptr && isspace (*ptr))
1274 			++ptr;
1275 
1276 		if (*ptr == '\0')
1277 			continue;
1278 /*
1279  * Extract option name.
1280  */
1281 		option = ptr;
1282 		while (*ptr && !isspace (*ptr))
1283 			++ptr;
1284 
1285 		if (*ptr != '\0') {
1286 
1287 			*ptr = '\0';
1288 			++ptr;
1289 		}
1290 /*
1291  * Skip white space between name and parms.
1292  */
1293 		while (*ptr && isspace (*ptr))
1294 			++ptr;
1295 
1296 		ParseOption (option, *ptr ? ptr : NULL, 0);
1297 	}
1298 
1299 	fclose (file);
1300 }
1301 
1302 static void Usage ()
1303 {
1304 	int			i;
1305 	int			max;
1306 	struct OptionInfo*	info;
1307 
1308 	fprintf (stderr, "Recognized options:\n\n");
1309 
1310 	max = sizeof (optionTable) / sizeof (struct OptionInfo);
1311 	for (i = 0, info = optionTable; i < max; i++, info++) {
1312 
1313 		fprintf (stderr, "-%-20s %s\n", info->name,
1314 						info->parmDescription);
1315 
1316 		if (info->shortName)
1317 			fprintf (stderr, "-%-20s %s\n", info->shortName,
1318 							info->parmDescription);
1319 
1320 		fprintf (stderr, "      %s\n\n", info->description);
1321 	}
1322 
1323 	exit (1);
1324 }
1325 
1326 void SetupPptpAlias (const char* parms)
1327 {
1328 	char		buf[128];
1329 	char*		ptr;
1330 	struct in_addr	srcAddr;
1331 
1332 	strcpy (buf, parms);
1333 
1334 /*
1335  * Extract source address.
1336  */
1337 	ptr = strtok (buf, " \t");
1338 	if (!ptr)
1339 		errx(1, "pptpalias: missing src address");
1340 
1341 	StrToAddr (ptr, &srcAddr);
1342 	PacketAliasPptp (srcAddr);
1343 }
1344 
1345 void SetupPortRedirect (const char* parms)
1346 {
1347 	char		buf[128];
1348 	char*		ptr;
1349 	struct in_addr	localAddr;
1350 	struct in_addr	publicAddr;
1351 	struct in_addr	remoteAddr;
1352 	port_range      portRange;
1353 	u_short         localPort      = 0;
1354 	u_short         publicPort     = 0;
1355 	u_short         remotePort     = 0;
1356 	u_short         numLocalPorts  = 0;
1357 	u_short         numPublicPorts = 0;
1358 	u_short         numRemotePorts = 0;
1359 	int		proto;
1360 	char*		protoName;
1361 	char*		separator;
1362 	int             i;
1363 
1364 	strcpy (buf, parms);
1365 /*
1366  * Extract protocol.
1367  */
1368 	protoName = strtok (buf, " \t");
1369 	if (!protoName)
1370 		errx (1, "redirect_port: missing protocol");
1371 
1372 	proto = StrToProto (protoName);
1373 /*
1374  * Extract local address.
1375  */
1376 	ptr = strtok (NULL, " \t");
1377 	if (!ptr)
1378 		errx (1, "redirect_port: missing local address");
1379 
1380 	if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 )
1381 	        errx (1, "redirect_port: invalid local port range");
1382 
1383 	localPort     = GETLOPORT(portRange);
1384 	numLocalPorts = GETNUMPORTS(portRange);
1385 
1386 /*
1387  * Extract public port and optionally address.
1388  */
1389 	ptr = strtok (NULL, " \t");
1390 	if (!ptr)
1391 		errx (1, "redirect_port: missing public port");
1392 
1393 	separator = strchr (ptr, ':');
1394 	if (separator) {
1395 	        if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 )
1396 		        errx (1, "redirect_port: invalid public port range");
1397 	}
1398 	else {
1399 		publicAddr.s_addr = INADDR_ANY;
1400 		if (StrToPortRange (ptr, protoName, &portRange) != 0)
1401 		        errx (1, "redirect_port: invalid public port range");
1402 	}
1403 
1404 	publicPort     = GETLOPORT(portRange);
1405 	numPublicPorts = GETNUMPORTS(portRange);
1406 
1407 /*
1408  * Extract remote address and optionally port.
1409  */
1410 	ptr = strtok (NULL, " \t");
1411 	if (ptr) {
1412 		separator = strchr (ptr, ':');
1413 		if (separator) {
1414 		        if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0)
1415 			        errx (1, "redirect_port: invalid remote port range");
1416 		} else {
1417 		        SETLOPORT(portRange, 0);
1418 			SETNUMPORTS(portRange, 1);
1419 			StrToAddr (ptr, &remoteAddr);
1420 		}
1421 	}
1422 	else {
1423 	        SETLOPORT(portRange, 0);
1424 		SETNUMPORTS(portRange, 1);
1425 		remoteAddr.s_addr = INADDR_ANY;
1426 	}
1427 
1428 	remotePort     = GETLOPORT(portRange);
1429 	numRemotePorts = GETNUMPORTS(portRange);
1430 
1431 /*
1432  * Make sure port ranges match up, then add the redirect ports.
1433  */
1434 	if (numLocalPorts != numPublicPorts)
1435 	        errx (1, "redirect_port: port ranges must be equal in size");
1436 
1437 	/* Remote port range is allowed to be '0' which means all ports. */
1438 	if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0))
1439 	        errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
1440 
1441 	for (i = 0 ; i < numPublicPorts ; ++i) {
1442 	        /* If remotePort is all ports, set it to 0. */
1443 	        u_short remotePortCopy = remotePort + i;
1444 	        if (numRemotePorts == 1 && remotePort == 0)
1445 		        remotePortCopy = 0;
1446 
1447 	        PacketAliasRedirectPort (localAddr,
1448 					 htons(localPort + i),
1449 					 remoteAddr,
1450 					 htons(remotePortCopy),
1451 					 publicAddr,
1452 					 htons(publicPort + i),
1453 					 proto);
1454 	}
1455 }
1456 
1457 void SetupAddressRedirect (const char* parms)
1458 {
1459 	char		buf[128];
1460 	char*		ptr;
1461 	struct in_addr	localAddr;
1462 	struct in_addr	publicAddr;
1463 
1464 	strcpy (buf, parms);
1465 /*
1466  * Extract local address.
1467  */
1468 	ptr = strtok (buf, " \t");
1469 	if (!ptr)
1470 		errx (1, "redirect_address: missing local address");
1471 
1472 	StrToAddr (ptr, &localAddr);
1473 /*
1474  * Extract public address.
1475  */
1476 	ptr = strtok (NULL, " \t");
1477 	if (!ptr)
1478 		errx (1, "redirect_address: missing public address");
1479 
1480 	StrToAddr (ptr, &publicAddr);
1481 	PacketAliasRedirectAddr (localAddr, publicAddr);
1482 }
1483 
1484 void StrToAddr (const char* str, struct in_addr* addr)
1485 {
1486 	struct hostent* hp;
1487 
1488 	if (inet_aton (str, addr))
1489 		return;
1490 
1491 	hp = gethostbyname (str);
1492 	if (!hp)
1493 		errx (1, "unknown host %s", str);
1494 
1495 	memcpy (addr, hp->h_addr, sizeof (struct in_addr));
1496 }
1497 
1498 u_short StrToPort (const char* str, const char* proto)
1499 {
1500 	u_short		port;
1501 	struct servent*	sp;
1502 	char*		end;
1503 
1504 	port = strtol (str, &end, 10);
1505 	if (end != str)
1506 		return htons (port);
1507 
1508 	sp = getservbyname (str, proto);
1509 	if (!sp)
1510 		errx (1, "unknown service %s/%s", str, proto);
1511 
1512 	return sp->s_port;
1513 }
1514 
1515 int StrToPortRange (const char* str, const char* proto, port_range *portRange)
1516 {
1517 	char*           sep;
1518 	struct servent*	sp;
1519 	char*		end;
1520 	u_short         loPort;
1521 	u_short         hiPort;
1522 
1523 	/* First see if this is a service, return corresponding port if so. */
1524 	sp = getservbyname (str,proto);
1525 	if (sp) {
1526 	        SETLOPORT(*portRange, ntohs(sp->s_port));
1527 		SETNUMPORTS(*portRange, 1);
1528 		return 0;
1529 	}
1530 
1531 	/* Not a service, see if it's a single port or port range. */
1532 	sep = strchr (str, '-');
1533 	if (sep == NULL) {
1534 	        SETLOPORT(*portRange, strtol(str, &end, 10));
1535 		if (end != str) {
1536 		        /* Single port. */
1537 		        SETNUMPORTS(*portRange, 1);
1538 			return 0;
1539 		}
1540 
1541 		/* Error in port range field. */
1542 		errx (1, "unknown service %s/%s", str, proto);
1543 	}
1544 
1545 	/* Port range, get the values and sanity check. */
1546 	sscanf (str, "%hu-%hu", &loPort, &hiPort);
1547 	SETLOPORT(*portRange, loPort);
1548 	SETNUMPORTS(*portRange, 0);	/* Error by default */
1549 	if (loPort <= hiPort)
1550 	        SETNUMPORTS(*portRange, hiPort - loPort + 1);
1551 
1552 	if (GETNUMPORTS(*portRange) == 0)
1553 	        errx (1, "invalid port range %s", str);
1554 
1555 	return 0;
1556 }
1557 
1558 
1559 int StrToProto (const char* str)
1560 {
1561 	if (!strcmp (str, "tcp"))
1562 		return IPPROTO_TCP;
1563 
1564 	if (!strcmp (str, "udp"))
1565 		return IPPROTO_UDP;
1566 
1567 	errx (1, "unknown protocol %s. Expected tcp or udp", str);
1568 }
1569 
1570 int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
1571 {
1572 	char*	ptr;
1573 
1574 	ptr = strchr (str, ':');
1575 	if (!ptr)
1576 		errx (1, "%s is missing port number", str);
1577 
1578 	*ptr = '\0';
1579 	++ptr;
1580 
1581 	StrToAddr (str, addr);
1582 	return StrToPortRange (ptr, proto, portRange);
1583 }
1584