xref: /freebsd/sbin/natd/natd.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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)
646 		return;
647 
648 	if (verbose && ifMsg.ifm_index == ifIndex)
649 		printf ("Interface address has changed.\n");
650 
651 	if (ifMsg.ifm_index == ifIndex)
652 		assignAliasAddr = 1;
653 }
654 
655 static void PrintPacket (struct ip* ip)
656 {
657 	printf ("%s", FormatPacket (ip));
658 }
659 
660 static void SyslogPacket (struct ip* ip, int priority, const char *label)
661 {
662 	syslog (priority, "%s %s", label, FormatPacket (ip));
663 }
664 
665 static char* FormatPacket (struct ip* ip)
666 {
667 	static char	buf[256];
668 	struct tcphdr*	tcphdr;
669 	struct udphdr*	udphdr;
670 	struct icmp*	icmphdr;
671 	char		src[20];
672 	char		dst[20];
673 
674 	strcpy (src, inet_ntoa (ip->ip_src));
675 	strcpy (dst, inet_ntoa (ip->ip_dst));
676 
677 	switch (ip->ip_p) {
678 	case IPPROTO_TCP:
679 		tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
680 		sprintf (buf, "[TCP] %s:%d -> %s:%d",
681 			      src,
682 			      ntohs (tcphdr->th_sport),
683 			      dst,
684 			      ntohs (tcphdr->th_dport));
685 		break;
686 
687 	case IPPROTO_UDP:
688 		udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
689 		sprintf (buf, "[UDP] %s:%d -> %s:%d",
690 			      src,
691 			      ntohs (udphdr->uh_sport),
692 			      dst,
693 			      ntohs (udphdr->uh_dport));
694 		break;
695 
696 	case IPPROTO_ICMP:
697 		icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
698 		sprintf (buf, "[ICMP] %s -> %s %u(%u)",
699 			      src,
700 			      dst,
701 			      icmphdr->icmp_type,
702 			      icmphdr->icmp_code);
703 		break;
704 
705 	default:
706 		sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
707 		break;
708 	}
709 
710 	return buf;
711 }
712 
713 static void
714 SetAliasAddressFromIfName(const char *ifn)
715 {
716 	size_t needed;
717 	int mib[6];
718 	char *buf, *lim, *next;
719 	struct if_msghdr *ifm;
720 	struct ifa_msghdr *ifam;
721 	struct sockaddr_dl *sdl;
722 	struct sockaddr_in *sin;
723 
724 	mib[0] = CTL_NET;
725 	mib[1] = PF_ROUTE;
726 	mib[2] = 0;
727 	mib[3] = AF_INET;	/* Only IP addresses please */
728 	mib[4] = NET_RT_IFLIST;
729 	mib[5] = 0;		/* ifIndex??? */
730 /*
731  * Get interface data.
732  */
733 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
734 		err(1, "iflist-sysctl-estimate");
735 	if ((buf = malloc(needed)) == NULL)
736 		errx(1, "malloc failed");
737 	if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
738 		err(1, "iflist-sysctl-get");
739 	lim = buf + needed;
740 /*
741  * Loop through interfaces until one with
742  * given name is found. This is done to
743  * find correct interface index for routing
744  * message processing.
745  */
746 	ifIndex	= 0;
747 	next = buf;
748 	while (next < lim) {
749 		ifm = (struct if_msghdr *)next;
750 		next += ifm->ifm_msglen;
751 		if (ifm->ifm_version != RTM_VERSION) {
752 			if (verbose)
753 				warnx("routing message version %d "
754 				      "not understood", ifm->ifm_version);
755 			continue;
756 		}
757 		if (ifm->ifm_type == RTM_IFINFO) {
758 			sdl = (struct sockaddr_dl *)(ifm + 1);
759 			if (strlen(ifn) == sdl->sdl_nlen &&
760 			    strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
761 				ifIndex = ifm->ifm_index;
762 				ifMTU = ifm->ifm_data.ifi_mtu;
763 				break;
764 			}
765 		}
766 	}
767 	if (!ifIndex)
768 		errx(1, "unknown interface name %s", ifn);
769 /*
770  * Get interface address.
771  */
772 	sin = NULL;
773 	while (next < lim) {
774 		ifam = (struct ifa_msghdr *)next;
775 		next += ifam->ifam_msglen;
776 		if (ifam->ifam_version != RTM_VERSION) {
777 			if (verbose)
778 				warnx("routing message version %d "
779 				      "not understood", ifam->ifam_version);
780 			continue;
781 		}
782 		if (ifam->ifam_type != RTM_NEWADDR)
783 			break;
784 		if (ifam->ifam_addrs & RTA_IFA) {
785 			int i;
786 			char *cp = (char *)(ifam + 1);
787 
788 #define ROUNDUP(a) \
789 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
790 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
791 
792 			for (i = 1; i < RTA_IFA; i <<= 1)
793 				if (ifam->ifam_addrs & i)
794 					ADVANCE(cp, (struct sockaddr *)cp);
795 			if (((struct sockaddr *)cp)->sa_family == AF_INET) {
796 				sin = (struct sockaddr_in *)cp;
797 				break;
798 			}
799 		}
800 	}
801 	if (sin == NULL)
802 		errx(1, "%s: cannot get interface address", ifn);
803 
804 	PacketAliasSetAddress(sin->sin_addr);
805 	syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes",
806 	       inet_ntoa(sin->sin_addr), ifMTU);
807 
808 	free(buf);
809 }
810 
811 void Quit (const char* msg)
812 {
813 	Warn (msg);
814 	exit (1);
815 }
816 
817 void Warn (const char* msg)
818 {
819 	if (background)
820 		syslog (LOG_ALERT, "%s (%m)", msg);
821 	else
822 		warn (msg);
823 }
824 
825 static void RefreshAddr (int sig)
826 {
827 	if (ifName)
828 		assignAliasAddr = 1;
829 }
830 
831 static void InitiateShutdown (int sig)
832 {
833 /*
834  * Start timer to allow kernel gracefully
835  * shutdown existing connections when system
836  * is shut down.
837  */
838 	siginterrupt(SIGALRM, 1);
839 	signal (SIGALRM, Shutdown);
840 	alarm (10);
841 }
842 
843 static void Shutdown (int sig)
844 {
845 	running = 0;
846 }
847 
848 /*
849  * Different options recognized by this program.
850  */
851 
852 enum Option {
853 
854 	PacketAliasOption,
855 	Verbose,
856 	InPort,
857 	OutPort,
858 	Port,
859 	AliasAddress,
860 	InterfaceName,
861 	RedirectPort,
862 	RedirectAddress,
863 	ConfigFile,
864 	DynamicMode,
865 	PptpAlias,
866 	ProxyRule,
867  	LogDenied,
868  	LogFacility
869 };
870 
871 enum Param {
872 
873 	YesNo,
874 	Numeric,
875 	String,
876 	None,
877 	Address,
878 	Service
879 };
880 
881 /*
882  * Option information structure (used by ParseOption).
883  */
884 
885 struct OptionInfo {
886 
887 	enum Option		type;
888 	int			packetAliasOpt;
889 	enum Param		parm;
890 	const char*		parmDescription;
891 	const char*		description;
892 	const char*		name;
893 	const char*		shortName;
894 };
895 
896 /*
897  * Table of known options.
898  */
899 
900 static struct OptionInfo optionTable[] = {
901 
902 	{ PacketAliasOption,
903 		PKT_ALIAS_UNREGISTERED_ONLY,
904 		YesNo,
905 		"[yes|no]",
906 		"alias only unregistered addresses",
907 		"unregistered_only",
908 		"u" },
909 
910 	{ PacketAliasOption,
911 		PKT_ALIAS_LOG,
912 		YesNo,
913 		"[yes|no]",
914 		"enable logging",
915 		"log",
916 		"l" },
917 
918 	{ PacketAliasOption,
919 		PKT_ALIAS_PROXY_ONLY,
920 		YesNo,
921 		"[yes|no]",
922 		"proxy only",
923 		"proxy_only",
924 		NULL },
925 
926 	{ PacketAliasOption,
927 		PKT_ALIAS_REVERSE,
928 		YesNo,
929 		"[yes|no]",
930 		"operate in reverse mode",
931 		"reverse",
932 		NULL },
933 
934 	{ PacketAliasOption,
935 		PKT_ALIAS_DENY_INCOMING,
936 		YesNo,
937 		"[yes|no]",
938 		"allow incoming connections",
939 		"deny_incoming",
940 		"d" },
941 
942 	{ PacketAliasOption,
943 		PKT_ALIAS_USE_SOCKETS,
944 		YesNo,
945 		"[yes|no]",
946 		"use sockets to inhibit port conflict",
947 		"use_sockets",
948 		"s" },
949 
950 	{ PacketAliasOption,
951 		PKT_ALIAS_SAME_PORTS,
952 		YesNo,
953 		"[yes|no]",
954 		"try to keep original port numbers for connections",
955 		"same_ports",
956 		"m" },
957 
958 	{ Verbose,
959 		0,
960 		YesNo,
961 		"[yes|no]",
962 		"verbose mode, dump packet information",
963 		"verbose",
964 		"v" },
965 
966 	{ DynamicMode,
967 		0,
968 		YesNo,
969 		"[yes|no]",
970 		"dynamic mode, automatically detect interface address changes",
971 		"dynamic",
972 		NULL },
973 
974 	{ InPort,
975 		0,
976 		Service,
977 		"number|service_name",
978 		"set port for incoming packets",
979 		"in_port",
980 		"i" },
981 
982 	{ OutPort,
983 		0,
984 		Service,
985 		"number|service_name",
986 		"set port for outgoing packets",
987 		"out_port",
988 		"o" },
989 
990 	{ Port,
991 		0,
992 		Service,
993 		"number|service_name",
994 		"set port (defaults to natd/divert)",
995 		"port",
996 		"p" },
997 
998 	{ AliasAddress,
999 		0,
1000 		Address,
1001 		"x.x.x.x",
1002 		"address to use for aliasing",
1003 		"alias_address",
1004 		"a" },
1005 
1006 	{ InterfaceName,
1007 		0,
1008 		String,
1009 	        "network_if_name",
1010 		"take aliasing address from interface",
1011 		"interface",
1012 		"n" },
1013 
1014 	{ ProxyRule,
1015 		0,
1016 		String,
1017 	        "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
1018 		"a.b.c.d:yyyy",
1019 		"add transparent proxying / destination NAT",
1020 		"proxy_rule",
1021 		NULL },
1022 
1023 	{ RedirectPort,
1024 		0,
1025 		String,
1026 	        "tcp|udp local_addr:local_port_range [public_addr:]public_port_range"
1027 	 	" [remote_addr[:remote_port_range]]",
1028 		"redirect a port (or ports) for incoming traffic",
1029 		"redirect_port",
1030 		NULL },
1031 
1032 	{ RedirectAddress,
1033 		0,
1034 		String,
1035 	        "local_addr public_addr",
1036 		"define mapping between local and public addresses",
1037 		"redirect_address",
1038 		NULL },
1039 
1040        { PptpAlias,
1041 		0,
1042 		String,
1043 		"src",
1044 		"define inside machine for PPTP traffic",
1045 		"pptpalias",
1046 		NULL },
1047 
1048 	{ ConfigFile,
1049 		0,
1050 		String,
1051 		"file_name",
1052 		"read options from configuration file",
1053 		"config",
1054 		"f" },
1055 
1056 	{ LogDenied,
1057 		0,
1058 		YesNo,
1059 	        "[yes|no]",
1060 		"enable logging of denied incoming packets",
1061 		"log_denied",
1062 		NULL },
1063 
1064 	{ LogFacility,
1065 		0,
1066 		String,
1067 	        "facility",
1068 		"name of syslog facility to use for logging",
1069 		"log_facility",
1070 		NULL }
1071 
1072 };
1073 
1074 static void ParseOption (const char* option, const char* parms, int cmdLine)
1075 {
1076 	int			i;
1077 	struct OptionInfo*	info;
1078 	int			yesNoValue;
1079 	int			aliasValue;
1080 	int			numValue;
1081 	u_short			uNumValue;
1082 	const char*		strValue;
1083 	struct in_addr		addrValue;
1084 	int			max;
1085 	char*			end;
1086 	CODE* 			fac_record = NULL;
1087 /*
1088  * Find option from table.
1089  */
1090 	max = sizeof (optionTable) / sizeof (struct OptionInfo);
1091 	for (i = 0, info = optionTable; i < max; i++, info++) {
1092 
1093 		if (!strcmp (info->name, option))
1094 			break;
1095 
1096 		if (info->shortName)
1097 			if (!strcmp (info->shortName, option))
1098 				break;
1099 	}
1100 
1101 	if (i >= max) {
1102 
1103 		warnx ("unknown option %s", option);
1104 		Usage ();
1105 	}
1106 
1107 	uNumValue	= 0;
1108 	yesNoValue	= 0;
1109 	numValue	= 0;
1110 	strValue	= NULL;
1111 /*
1112  * Check parameters.
1113  */
1114 	switch (info->parm) {
1115 	case YesNo:
1116 		if (!parms)
1117 			parms = "yes";
1118 
1119 		if (!strcmp (parms, "yes"))
1120 			yesNoValue = 1;
1121 		else
1122 			if (!strcmp (parms, "no"))
1123 				yesNoValue = 0;
1124 			else
1125 				errx (1, "%s needs yes/no parameter", option);
1126 		break;
1127 
1128 	case Service:
1129 		if (!parms)
1130 			errx (1, "%s needs service name or "
1131 				 "port number parameter",
1132 				 option);
1133 
1134 		uNumValue = StrToPort (parms, "divert");
1135 		break;
1136 
1137 	case Numeric:
1138 		if (parms)
1139 			numValue = strtol (parms, &end, 10);
1140 		else
1141 			end = NULL;
1142 
1143 		if (end == parms)
1144 			errx (1, "%s needs numeric parameter", option);
1145 		break;
1146 
1147 	case String:
1148 		strValue = parms;
1149 		if (!strValue)
1150 			errx (1, "%s needs parameter", option);
1151 		break;
1152 
1153 	case None:
1154 		if (parms)
1155 			errx (1, "%s does not take parameters", option);
1156 		break;
1157 
1158 	case Address:
1159 		if (!parms)
1160 			errx (1, "%s needs address/host parameter", option);
1161 
1162 		StrToAddr (parms, &addrValue);
1163 		break;
1164 	}
1165 
1166 	switch (info->type) {
1167 	case PacketAliasOption:
1168 
1169 		aliasValue = yesNoValue ? info->packetAliasOpt : 0;
1170 		PacketAliasSetMode (aliasValue, info->packetAliasOpt);
1171 		break;
1172 
1173 	case Verbose:
1174 		verbose = yesNoValue;
1175 		break;
1176 
1177 	case DynamicMode:
1178 		dynamicMode = yesNoValue;
1179 		break;
1180 
1181 	case InPort:
1182 		inPort = uNumValue;
1183 		break;
1184 
1185 	case OutPort:
1186 		outPort = uNumValue;
1187 		break;
1188 
1189 	case Port:
1190 		inOutPort = uNumValue;
1191 		break;
1192 
1193 	case AliasAddress:
1194 		memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
1195 		break;
1196 
1197 	case RedirectPort:
1198 		SetupPortRedirect (strValue);
1199 		break;
1200 
1201 	case RedirectAddress:
1202 		SetupAddressRedirect (strValue);
1203 		break;
1204 
1205 	case PptpAlias:
1206 		SetupPptpAlias (strValue);
1207 		break;
1208 
1209 	case ProxyRule:
1210 		PacketAliasProxyRule (strValue);
1211 		break;
1212 
1213 	case InterfaceName:
1214 		if (ifName)
1215 			free (ifName);
1216 
1217 		ifName = strdup (strValue);
1218 		break;
1219 
1220 	case ConfigFile:
1221 		ReadConfigFile (strValue);
1222 		break;
1223 
1224 	case LogDenied:
1225 		logDropped = 1;
1226 		break;
1227 
1228 	case LogFacility:
1229 
1230 		fac_record = facilitynames;
1231 		while (fac_record->c_name != NULL) {
1232 
1233 			if (!strcmp (fac_record->c_name, strValue)) {
1234 
1235 				logFacility = fac_record->c_val;
1236 				break;
1237 
1238 			}
1239 			else
1240 				fac_record++;
1241 		}
1242 
1243 		if(fac_record->c_name == NULL)
1244 			errx(1, "Unknown log facility name: %s", strValue);
1245 
1246 		break;
1247 	}
1248 }
1249 
1250 void ReadConfigFile (const char* fileName)
1251 {
1252 	FILE*	file;
1253 	char	buf[128];
1254 	char	*ptr, *p;
1255 	char*	option;
1256 
1257 	file = fopen (fileName, "r");
1258 	if (!file) {
1259 
1260 		sprintf (buf, "Cannot open config file %s.\n", fileName);
1261 		Quit (buf);
1262 	}
1263 
1264 	while (fgets (buf, sizeof (buf), file)) {
1265 
1266 		ptr = strchr (buf, '\n');
1267 		if (!ptr)
1268 			errx (1, "config line too long: %s", buf);
1269 
1270 		*ptr = '\0';
1271 
1272 /*
1273  * Check for comments, strip off trailing spaces.
1274  */
1275 		if ((ptr = strchr(buf, '#')))
1276 			*ptr = '\0';
1277 		for (ptr = buf; isspace(*ptr); ++ptr)
1278 			continue;
1279 		if (*ptr == '\0')
1280 			continue;
1281 		for (p = strchr(buf, '\0'); isspace(*--p);)
1282 			continue;
1283 		*++p = '\0';
1284 
1285 /*
1286  * Extract option name.
1287  */
1288 		option = ptr;
1289 		while (*ptr && !isspace (*ptr))
1290 			++ptr;
1291 
1292 		if (*ptr != '\0') {
1293 
1294 			*ptr = '\0';
1295 			++ptr;
1296 		}
1297 /*
1298  * Skip white space between name and parms.
1299  */
1300 		while (*ptr && isspace (*ptr))
1301 			++ptr;
1302 
1303 		ParseOption (option, *ptr ? ptr : NULL, 0);
1304 	}
1305 
1306 	fclose (file);
1307 }
1308 
1309 static void Usage ()
1310 {
1311 	int			i;
1312 	int			max;
1313 	struct OptionInfo*	info;
1314 
1315 	fprintf (stderr, "Recognized options:\n\n");
1316 
1317 	max = sizeof (optionTable) / sizeof (struct OptionInfo);
1318 	for (i = 0, info = optionTable; i < max; i++, info++) {
1319 
1320 		fprintf (stderr, "-%-20s %s\n", info->name,
1321 						info->parmDescription);
1322 
1323 		if (info->shortName)
1324 			fprintf (stderr, "-%-20s %s\n", info->shortName,
1325 							info->parmDescription);
1326 
1327 		fprintf (stderr, "      %s\n\n", info->description);
1328 	}
1329 
1330 	exit (1);
1331 }
1332 
1333 void SetupPptpAlias (const char* parms)
1334 {
1335 	char		buf[128];
1336 	char*		ptr;
1337 	struct in_addr	srcAddr;
1338 
1339 	strcpy (buf, parms);
1340 
1341 /*
1342  * Extract source address.
1343  */
1344 	ptr = strtok (buf, " \t");
1345 	if (!ptr)
1346 		errx(1, "pptpalias: missing src address");
1347 
1348 	StrToAddr (ptr, &srcAddr);
1349 	PacketAliasPptp (srcAddr);
1350 }
1351 
1352 void SetupPortRedirect (const char* parms)
1353 {
1354 	char		buf[128];
1355 	char*		ptr;
1356 	struct in_addr	localAddr;
1357 	struct in_addr	publicAddr;
1358 	struct in_addr	remoteAddr;
1359 	port_range      portRange;
1360 	u_short         localPort      = 0;
1361 	u_short         publicPort     = 0;
1362 	u_short         remotePort     = 0;
1363 	u_short         numLocalPorts  = 0;
1364 	u_short         numPublicPorts = 0;
1365 	u_short         numRemotePorts = 0;
1366 	int		proto;
1367 	char*		protoName;
1368 	char*		separator;
1369 	int             i;
1370 
1371 	strcpy (buf, parms);
1372 /*
1373  * Extract protocol.
1374  */
1375 	protoName = strtok (buf, " \t");
1376 	if (!protoName)
1377 		errx (1, "redirect_port: missing protocol");
1378 
1379 	proto = StrToProto (protoName);
1380 /*
1381  * Extract local address.
1382  */
1383 	ptr = strtok (NULL, " \t");
1384 	if (!ptr)
1385 		errx (1, "redirect_port: missing local address");
1386 
1387 	if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 )
1388 	        errx (1, "redirect_port: invalid local port range");
1389 
1390 	localPort     = GETLOPORT(portRange);
1391 	numLocalPorts = GETNUMPORTS(portRange);
1392 
1393 /*
1394  * Extract public port and optionally address.
1395  */
1396 	ptr = strtok (NULL, " \t");
1397 	if (!ptr)
1398 		errx (1, "redirect_port: missing public port");
1399 
1400 	separator = strchr (ptr, ':');
1401 	if (separator) {
1402 	        if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 )
1403 		        errx (1, "redirect_port: invalid public port range");
1404 	}
1405 	else {
1406 		publicAddr.s_addr = INADDR_ANY;
1407 		if (StrToPortRange (ptr, protoName, &portRange) != 0)
1408 		        errx (1, "redirect_port: invalid public port range");
1409 	}
1410 
1411 	publicPort     = GETLOPORT(portRange);
1412 	numPublicPorts = GETNUMPORTS(portRange);
1413 
1414 /*
1415  * Extract remote address and optionally port.
1416  */
1417 	ptr = strtok (NULL, " \t");
1418 	if (ptr) {
1419 		separator = strchr (ptr, ':');
1420 		if (separator) {
1421 		        if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0)
1422 			        errx (1, "redirect_port: invalid remote port range");
1423 		} else {
1424 		        SETLOPORT(portRange, 0);
1425 			SETNUMPORTS(portRange, 1);
1426 			StrToAddr (ptr, &remoteAddr);
1427 		}
1428 	}
1429 	else {
1430 	        SETLOPORT(portRange, 0);
1431 		SETNUMPORTS(portRange, 1);
1432 		remoteAddr.s_addr = INADDR_ANY;
1433 	}
1434 
1435 	remotePort     = GETLOPORT(portRange);
1436 	numRemotePorts = GETNUMPORTS(portRange);
1437 
1438 /*
1439  * Make sure port ranges match up, then add the redirect ports.
1440  */
1441 	if (numLocalPorts != numPublicPorts)
1442 	        errx (1, "redirect_port: port ranges must be equal in size");
1443 
1444 	/* Remote port range is allowed to be '0' which means all ports. */
1445 	if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0))
1446 	        errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
1447 
1448 	for (i = 0 ; i < numPublicPorts ; ++i) {
1449 	        /* If remotePort is all ports, set it to 0. */
1450 	        u_short remotePortCopy = remotePort + i;
1451 	        if (numRemotePorts == 1 && remotePort == 0)
1452 		        remotePortCopy = 0;
1453 
1454 	        PacketAliasRedirectPort (localAddr,
1455 					 htons(localPort + i),
1456 					 remoteAddr,
1457 					 htons(remotePortCopy),
1458 					 publicAddr,
1459 					 htons(publicPort + i),
1460 					 proto);
1461 	}
1462 }
1463 
1464 void SetupAddressRedirect (const char* parms)
1465 {
1466 	char		buf[128];
1467 	char*		ptr;
1468 	struct in_addr	localAddr;
1469 	struct in_addr	publicAddr;
1470 
1471 	strcpy (buf, parms);
1472 /*
1473  * Extract local address.
1474  */
1475 	ptr = strtok (buf, " \t");
1476 	if (!ptr)
1477 		errx (1, "redirect_address: missing local address");
1478 
1479 	StrToAddr (ptr, &localAddr);
1480 /*
1481  * Extract public address.
1482  */
1483 	ptr = strtok (NULL, " \t");
1484 	if (!ptr)
1485 		errx (1, "redirect_address: missing public address");
1486 
1487 	StrToAddr (ptr, &publicAddr);
1488 	PacketAliasRedirectAddr (localAddr, publicAddr);
1489 }
1490 
1491 void StrToAddr (const char* str, struct in_addr* addr)
1492 {
1493 	struct hostent* hp;
1494 
1495 	if (inet_aton (str, addr))
1496 		return;
1497 
1498 	hp = gethostbyname (str);
1499 	if (!hp)
1500 		errx (1, "unknown host %s", str);
1501 
1502 	memcpy (addr, hp->h_addr, sizeof (struct in_addr));
1503 }
1504 
1505 u_short StrToPort (const char* str, const char* proto)
1506 {
1507 	u_short		port;
1508 	struct servent*	sp;
1509 	char*		end;
1510 
1511 	port = strtol (str, &end, 10);
1512 	if (end != str)
1513 		return htons (port);
1514 
1515 	sp = getservbyname (str, proto);
1516 	if (!sp)
1517 		errx (1, "unknown service %s/%s", str, proto);
1518 
1519 	return sp->s_port;
1520 }
1521 
1522 int StrToPortRange (const char* str, const char* proto, port_range *portRange)
1523 {
1524 	char*           sep;
1525 	struct servent*	sp;
1526 	char*		end;
1527 	u_short         loPort;
1528 	u_short         hiPort;
1529 
1530 	/* First see if this is a service, return corresponding port if so. */
1531 	sp = getservbyname (str,proto);
1532 	if (sp) {
1533 	        SETLOPORT(*portRange, ntohs(sp->s_port));
1534 		SETNUMPORTS(*portRange, 1);
1535 		return 0;
1536 	}
1537 
1538 	/* Not a service, see if it's a single port or port range. */
1539 	sep = strchr (str, '-');
1540 	if (sep == NULL) {
1541 	        SETLOPORT(*portRange, strtol(str, &end, 10));
1542 		if (end != str) {
1543 		        /* Single port. */
1544 		        SETNUMPORTS(*portRange, 1);
1545 			return 0;
1546 		}
1547 
1548 		/* Error in port range field. */
1549 		errx (1, "unknown service %s/%s", str, proto);
1550 	}
1551 
1552 	/* Port range, get the values and sanity check. */
1553 	sscanf (str, "%hu-%hu", &loPort, &hiPort);
1554 	SETLOPORT(*portRange, loPort);
1555 	SETNUMPORTS(*portRange, 0);	/* Error by default */
1556 	if (loPort <= hiPort)
1557 	        SETNUMPORTS(*portRange, hiPort - loPort + 1);
1558 
1559 	if (GETNUMPORTS(*portRange) == 0)
1560 	        errx (1, "invalid port range %s", str);
1561 
1562 	return 0;
1563 }
1564 
1565 
1566 int StrToProto (const char* str)
1567 {
1568 	if (!strcmp (str, "tcp"))
1569 		return IPPROTO_TCP;
1570 
1571 	if (!strcmp (str, "udp"))
1572 		return IPPROTO_UDP;
1573 
1574 	errx (1, "unknown protocol %s. Expected tcp or udp", str);
1575 }
1576 
1577 int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
1578 {
1579 	char*	ptr;
1580 
1581 	ptr = strchr (str, ':');
1582 	if (!ptr)
1583 		errx (1, "%s is missing port number", str);
1584 
1585 	*ptr = '\0';
1586 	++ptr;
1587 
1588 	StrToAddr (str, addr);
1589 	return StrToPortRange (ptr, proto, portRange);
1590 }
1591