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