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