1 /*	$FreeBSD$	*/
2 
3 /*
4  * (C)Copyright (C) 2012 by Darren Reed.
5  */
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/mman.h>
9 #include <sys/socket.h>
10 #include <sys/time.h>
11 #include <sys/ioctl.h>
12 
13 #include <netinet/in.h>
14 #include <netinet/in_systm.h>
15 #include <netinet/ip.h>
16 
17 #include <net/if.h>
18 
19 #include <stdio.h>
20 #include <netdb.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 
27 #include "ip_compat.h"
28 #include "ip_fil.h"
29 #include "ip_nat.h"
30 
31 #include "ipf.h"
32 
33 extern	char	*optarg;
34 
35 
36 typedef	struct	l4cfg	{
37 	struct	l4cfg		*l4_next;
38 	struct	ipnat		l4_nat;		/* NAT rule */
39 	struct	sockaddr_in	l4_sin;		/* remote socket to connect */
40 	time_t			l4_last;	/* when we last connected */
41 	int			l4_alive;	/* 1 = remote alive */
42 	int			l4_fd;
43 	int			l4_rw;		/* 0 = reading, 1 = writing */
44 	char			*l4_rbuf;	/* read buffer */
45 	int			l4_rsize;	/* size of buffer */
46 	int			l4_rlen;	/* how much used */
47 	char			*l4_wptr;	/* next byte to write */
48 	int			l4_wlen;	/* length yet to be written */
49 } l4cfg_t;
50 
51 
52 l4cfg_t *l4list = NULL;
53 char *response = NULL;
54 char *probe = NULL;
55 l4cfg_t template;
56 int frequency = 20;
57 int ctimeout = 1;
58 int rtimeout = 1;
59 size_t plen = 0;
60 size_t rlen = 0;
61 int natfd = -1;
62 int opts = 0;
63 
64 #if defined(sun) && !defined(__svr4__) && !defined(__SVR4)
65 # define	strerror(x)	sys_errlist[x]
66 #endif
67 
68 
69 char *
70 copystr(char *dst, char *src)
71 {
72 	register char *s, *t, c;
73 	register int esc = 0;
74 
75 	for (s = src, t = dst; s && t && (c = *s++); )
76 		if (esc) {
77 			esc = 0;
78 			switch (c)
79 			{
80 			case 'n' :
81 				*t++ = '\n';
82 				break;
83 			case 'r' :
84 				*t++ = '\r';
85 				break;
86 			case 't' :
87 				*t++ = '\t';
88 				break;
89 			}
90 		} else if (c != '\\')
91 			*t++ = c;
92 		else
93 			esc = 1;
94 	*t = '\0';
95 	return(dst);
96 }
97 
98 void
99 addnat(l4cfg_t *l4)
100 {
101 	ipnat_t *ipn = &l4->l4_nat;
102 
103 	printf("Add NAT rule for %s/%#x,%u -> ", inet_ntoa(ipn->in_out[0]),
104 		ipn->in_outmsk, ntohs(ipn->in_pmin));
105 	printf("%s,%u\n", inet_ntoa(ipn->in_in[0]), ntohs(ipn->in_pnext));
106 	if (!(opts & OPT_DONOTHING)) {
107 		if (ioctl(natfd, SIOCADNAT, &ipn) == -1)
108 			perror("ioctl(SIOCADNAT)");
109 	}
110 }
111 
112 
113 void
114 delnat(l4cfg_t *l4)
115 {
116 	ipnat_t *ipn = &l4->l4_nat;
117 
118 	printf("Remove NAT rule for %s/%#x,%u -> ",
119 		inet_ntoa(ipn->in_out[0]), ipn->in_outmsk, ipn->in_pmin);
120 	printf("%s,%u\n", inet_ntoa(ipn->in_in[0]), ipn->in_pnext);
121 	if (!(opts & OPT_DONOTHING)) {
122 		if (ioctl(natfd, SIOCRMNAT, &ipn) == -1)
123 			perror("ioctl(SIOCRMNAT)");
124 	}
125 }
126 
127 
128 void
129 connectl4(l4cfg_t *l4)
130 {
131 	l4->l4_rw = 1;
132 	l4->l4_rlen = 0;
133 	l4->l4_wlen = plen;
134 	if (!l4->l4_wlen) {
135 		l4->l4_alive = 1;
136 		addnat(l4);
137 	} else
138 		l4->l4_wptr = probe;
139 }
140 
141 
142 void
143 closel4(l4cfg_t *l4, int dead)
144 {
145 	close(l4->l4_fd);
146 	l4->l4_fd = -1;
147 	l4->l4_rw = -1;
148 	if (dead && l4->l4_alive) {
149 		l4->l4_alive = 0;
150 		delnat(l4);
151 	}
152 }
153 
154 
155 void
156 connectfd(l4cfg_t *l4)
157 {
158 	if (connect(l4->l4_fd, (struct sockaddr *)&l4->l4_sin,
159 		    sizeof(l4->l4_sin)) == -1) {
160 		if (errno == EISCONN) {
161 			if (opts & OPT_VERBOSE)
162 				fprintf(stderr, "Connected fd %d\n",
163 					l4->l4_fd);
164 			connectl4(l4);
165 			return;
166 		}
167 		if (opts & OPT_VERBOSE)
168 			fprintf(stderr, "Connect failed fd %d: %s\n",
169 				l4->l4_fd, strerror(errno));
170 		closel4(l4, 1);
171 		return;
172 	}
173 	l4->l4_rw = 1;
174 }
175 
176 
177 void
178 writefd(l4cfg_t *l4)
179 {
180 	char buf[80], *ptr;
181 	int n, i, fd;
182 
183 	fd = l4->l4_fd;
184 
185 	if (l4->l4_rw == -2) {
186 		connectfd(l4);
187 		return;
188 	}
189 
190 	n = l4->l4_wlen;
191 
192 	i = send(fd, l4->l4_wptr, n, 0);
193 	if (i == 0 || i == -1) {
194 		if (opts & OPT_VERBOSE)
195 			fprintf(stderr, "Send on fd %d failed: %s\n",
196 				fd, strerror(errno));
197 		closel4(l4, 1);
198 	} else {
199 		l4->l4_wptr += i;
200 		l4->l4_wlen -= i;
201 		if (l4->l4_wlen == 0)
202 			l4->l4_rw = 0;
203 		if (opts & OPT_VERBOSE)
204 			fprintf(stderr, "Sent %d bytes to fd %d\n", i, fd);
205 	}
206 }
207 
208 
209 void readfd(l4cfg_t *l4)
210 {
211 	char buf[80], *ptr;
212 	int n, i, fd;
213 
214 	fd = l4->l4_fd;
215 
216 	if (l4->l4_rw == -2) {
217 		connectfd(l4);
218 		return;
219 	}
220 
221 	if (l4->l4_rsize) {
222 		n = l4->l4_rsize - l4->l4_rlen;
223 		ptr = l4->l4_rbuf + l4->l4_rlen;
224 	} else {
225 		n = sizeof(buf) - 1;
226 		ptr = buf;
227 	}
228 
229 	if (opts & OPT_VERBOSE)
230 		fprintf(stderr, "Read %d bytes on fd %d to %p\n",
231 			n, fd, ptr);
232 	i = recv(fd, ptr, n, 0);
233 	if (i == 0 || i == -1) {
234 		if (opts & OPT_VERBOSE)
235 			fprintf(stderr, "Read error on fd %d: %s\n",
236 				fd, (i == 0) ? "EOF" : strerror(errno));
237 		closel4(l4, 1);
238 	} else {
239 		if (ptr == buf)
240 			ptr[i] = '\0';
241 		if (opts & OPT_VERBOSE)
242 			fprintf(stderr, "%d: Read %d bytes [%*.*s]\n",
243 				fd, i, i, i, ptr);
244 		if (ptr != buf) {
245 			l4->l4_rlen += i;
246 			if (l4->l4_rlen >= l4->l4_rsize) {
247 				if (!strncmp(response, l4->l4_rbuf,
248 					     l4->l4_rsize)) {
249 					printf("%d: Good response\n",
250 						fd);
251 					if (!l4->l4_alive) {
252 						l4->l4_alive = 1;
253 						addnat(l4);
254 					}
255 					closel4(l4, 0);
256 				} else {
257 					if (opts & OPT_VERBOSE)
258 						printf("%d: Bad response\n",
259 							fd);
260 					closel4(l4, 1);
261 				}
262 			}
263 		} else if (!l4->l4_alive) {
264 			l4->l4_alive = 1;
265 			addnat(l4);
266 			closel4(l4, 0);
267 		}
268 	}
269 }
270 
271 
272 int
273 runconfig(void)
274 {
275 	int fd, opt, res, mfd, i;
276 	struct timeval tv;
277 	time_t now, now1;
278 	fd_set rfd, wfd;
279 	l4cfg_t *l4;
280 
281 	mfd = 0;
282 	opt = 1;
283 	now = time(NULL);
284 
285 	/*
286 	 * First, initiate connections that are closed, as required.
287 	 */
288 	for (l4 = l4list; l4; l4 = l4->l4_next) {
289 		if ((l4->l4_last + frequency < now) && (l4->l4_fd == -1)) {
290 			l4->l4_last = now;
291 			fd = socket(AF_INET, SOCK_STREAM, 0);
292 			if (fd == -1)
293 				continue;
294 			setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt,
295 				   sizeof(opt));
296 #ifdef	O_NONBLOCK
297 			if ((res = fcntl(fd, F_GETFL, 0)) != -1)
298 				fcntl(fd, F_SETFL, res | O_NONBLOCK);
299 #endif
300 			if (opts & OPT_VERBOSE)
301 				fprintf(stderr,
302 					"Connecting to %s,%d (fd %d)...",
303 					inet_ntoa(l4->l4_sin.sin_addr),
304 					ntohs(l4->l4_sin.sin_port), fd);
305 			if (connect(fd, (struct sockaddr *)&l4->l4_sin,
306 				    sizeof(l4->l4_sin)) == -1) {
307 				if (errno != EINPROGRESS) {
308 					if (opts & OPT_VERBOSE)
309 						fprintf(stderr, "failed\n");
310 					perror("connect");
311 					close(fd);
312 					fd = -1;
313 				} else {
314 					if (opts & OPT_VERBOSE)
315 						fprintf(stderr, "waiting\n");
316 					l4->l4_rw = -2;
317 				}
318 			} else {
319 				if (opts & OPT_VERBOSE)
320 					fprintf(stderr, "connected\n");
321 				connectl4(l4);
322 			}
323 			l4->l4_fd = fd;
324 		}
325 	}
326 
327 	/*
328 	 * Now look for fd's which we're expecting to read/write from.
329 	 */
330 	FD_ZERO(&rfd);
331 	FD_ZERO(&wfd);
332 	tv.tv_sec = MIN(rtimeout, ctimeout);
333 	tv.tv_usec = 0;
334 
335 	for (l4 = l4list; l4; l4 = l4->l4_next)
336 		if (l4->l4_rw == 0) {
337 			if (now - l4->l4_last > rtimeout) {
338 				if (opts & OPT_VERBOSE)
339 					fprintf(stderr, "%d: Read timeout\n",
340 						l4->l4_fd);
341 				closel4(l4, 1);
342 				continue;
343 			}
344 			if (opts & OPT_VERBOSE)
345 				fprintf(stderr, "Wait for read on fd %d\n",
346 					l4->l4_fd);
347 			FD_SET(l4->l4_fd, &rfd);
348 			if (l4->l4_fd > mfd)
349 				mfd = l4->l4_fd;
350 		} else if ((l4->l4_rw == 1 && l4->l4_wlen) ||
351 			   l4->l4_rw == -2) {
352 			if ((l4->l4_rw == -2) &&
353 			    (now - l4->l4_last > ctimeout)) {
354 				if (opts & OPT_VERBOSE)
355 					fprintf(stderr,
356 						"%d: connect timeout\n",
357 						l4->l4_fd);
358 				closel4(l4);
359 				continue;
360 			}
361 			if (opts & OPT_VERBOSE)
362 				fprintf(stderr, "Wait for write on fd %d\n",
363 					l4->l4_fd);
364 			FD_SET(l4->l4_fd, &wfd);
365 			if (l4->l4_fd > mfd)
366 				mfd = l4->l4_fd;
367 		}
368 
369 	if (opts & OPT_VERBOSE)
370 		fprintf(stderr, "Select: max fd %d wait %d\n", mfd + 1,
371 			tv.tv_sec);
372 	i = select(mfd + 1, &rfd, &wfd, NULL, &tv);
373 	if (i == -1) {
374 		perror("select");
375 		return(-1);
376 	}
377 
378 	now1 = time(NULL);
379 
380 	for (l4 = l4list; (i > 0) && l4; l4 = l4->l4_next) {
381 		if (l4->l4_fd < 0)
382 			continue;
383 		if (FD_ISSET(l4->l4_fd, &rfd)) {
384 			if (opts & OPT_VERBOSE)
385 				fprintf(stderr, "Ready to read on fd %d\n",
386 					l4->l4_fd);
387 			readfd(l4);
388 			i--;
389 		}
390 
391 		if ((l4->l4_fd >= 0) && FD_ISSET(l4->l4_fd, &wfd)) {
392 			if (opts & OPT_VERBOSE)
393 				fprintf(stderr, "Ready to write on fd %d\n",
394 					l4->l4_fd);
395 			writefd(l4);
396 			i--;
397 		}
398 	}
399 	return(0);
400 }
401 
402 
403 int
404 gethostport(char *str, int lnum, u_32_t *ipp, u_short *portp)
405 {
406 	struct servent *sp;
407 	struct hostent *hp;
408 	char *host, *port;
409 	struct in_addr ip;
410 
411 	host = str;
412 	port = strchr(host, ',');
413 	if (port)
414 		*port++ = '\0';
415 
416 #ifdef	HAVE_INET_ATON
417 	if (ISDIGIT(*host) && inet_aton(host, &ip))
418 		*ipp = ip.s_addr;
419 #else
420 	if (ISDIGIT(*host))
421 		*ipp = inet_addr(host);
422 #endif
423 	else {
424 		if (!(hp = gethostbyname(host))) {
425 			fprintf(stderr, "%d: can't resolve hostname: %s\n",
426 				lnum, host);
427 			return(0);
428 		}
429 		*ipp = *(u_32_t *)hp->h_addr;
430 	}
431 
432 	if (port) {
433 		if (ISDIGIT(*port))
434 			*portp = htons(atoi(port));
435 		else {
436 			sp = getservbyname(port, "tcp");
437 			if (sp)
438 				*portp = sp->s_port;
439 			else {
440 				fprintf(stderr, "%d: unknown service %s\n",
441 					lnum, port);
442 				return(0);
443 			}
444 		}
445 	} else
446 		*portp = 0;
447 	return(1);
448 }
449 
450 
451 char *
452 mapfile(char *file, size_t *sizep)
453 {
454 	struct stat sb;
455 	caddr_t addr;
456 	int fd;
457 
458 	fd = open(file, O_RDONLY);
459 	if (fd == -1) {
460 		perror("open(mapfile)");
461 		return(NULL);
462 	}
463 
464 	if (fstat(fd, &sb) == -1) {
465 		perror("fstat(mapfile)");
466 		close(fd);
467 		return(NULL);
468 	}
469 
470 	addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
471 	if (addr == (caddr_t)-1) {
472 		perror("mmap(mapfile)");
473 		close(fd);
474 		return(NULL);
475 	}
476 	close(fd);
477 	*sizep = sb.st_size;
478 	return(char *)addr;
479 }
480 
481 
482 int
483 readconfig(char *filename)
484 {
485 	char c, buf[512], *s, *t, *errtxt = NULL, *line;
486 	int num, err = 0;
487 	ipnat_t *ipn;
488 	l4cfg_t *l4;
489 	FILE *fp;
490 
491 	fp = fopen(filename, "r");
492 	if (!fp) {
493 		perror("open(configfile)");
494 		return(-1);
495 	}
496 
497 	bzero((char *)&template, sizeof(template));
498 	template.l4_fd = -1;
499 	template.l4_rw = -1;
500 	template.l4_sin.sin_family = AF_INET;
501 	ipn = &template.l4_nat;
502 	ipn->in_flags = IPN_TCP|IPN_ROUNDR;
503 	ipn->in_redir = NAT_REDIRECT;
504 
505 	for (num = 1; fgets(buf, sizeof(buf), fp); num++) {
506 		s = strchr(buf, '\n');
507 		if  (!s) {
508 			fprintf(stderr, "%d: line too long\n", num);
509 			fclose(fp);
510 			return(-1);
511 		}
512 
513 		*s = '\0';
514 
515 		/*
516 		 * lines which are comments
517 		 */
518 		s = strchr(buf, '#');
519 		if (s)
520 			*s = '\0';
521 
522 		/*
523 		 * Skip leading whitespace
524 		 */
525 		for (line = buf; (c = *line) && ISSPACE(c); line++)
526 			;
527 		if (!*line)
528 			continue;
529 
530 		if (opts & OPT_VERBOSE)
531 			fprintf(stderr, "Parsing: [%s]\n", line);
532 		t = strtok(line, " \t");
533 		if (!t)
534 			continue;
535 		if (!strcasecmp(t, "interface")) {
536 			s = strtok(NULL, " \t");
537 			if (s)
538 				t = strtok(NULL, "\t");
539 			if (!s || !t) {
540 				errtxt = line;
541 				err = -1;
542 				break;
543 			}
544 
545 			if (!strchr(t, ',')) {
546 				fprintf(stderr,
547 					"%d: local address,port missing\n",
548 					num);
549 				err = -1;
550 				break;
551 			}
552 
553 			strncpy(ipn->in_ifname, s, sizeof(ipn->in_ifname));
554 			if (!gethostport(t, num, &ipn->in_outip,
555 					 &ipn->in_pmin)) {
556 				errtxt = line;
557 				err = -1;
558 				break;
559 			}
560 			ipn->in_outmsk = 0xffffffff;
561 			ipn->in_pmax = ipn->in_pmin;
562 			if (opts & OPT_VERBOSE)
563 				fprintf(stderr,
564 					"Interface %s %s/%#x port %u\n",
565 					ipn->in_ifname,
566 					inet_ntoa(ipn->in_out[0]),
567 					ipn->in_outmsk, ipn->in_pmin);
568 		} else if (!strcasecmp(t, "remote")) {
569 			if (!*ipn->in_ifname) {
570 				fprintf(stderr,
571 					"%d: ifname not set prior to remote\n",
572 					num);
573 				err = -1;
574 				break;
575 			}
576 			s = strtok(NULL, " \t");
577 			if (s)
578 				t = strtok(NULL, "");
579 			if (!s || !t || strcasecmp(s, "server")) {
580 				errtxt = line;
581 				err = -1;
582 				break;
583 			}
584 
585 			ipn->in_pnext = 0;
586 			if (!gethostport(t, num, &ipn->in_inip,
587 					 &ipn->in_pnext)) {
588 				errtxt = line;
589 				err = -1;
590 				break;
591 			}
592 			ipn->in_inmsk = 0xffffffff;
593 			if (ipn->in_pnext == 0)
594 				ipn->in_pnext = ipn->in_pmin;
595 
596 			l4 = (l4cfg_t *)malloc(sizeof(*l4));
597 			if (!l4) {
598 				fprintf(stderr, "%d: out of memory (%d)\n",
599 					num, sizeof(*l4));
600 				err = -1;
601 				break;
602 			}
603 			bcopy((char *)&template, (char *)l4, sizeof(*l4));
604 			l4->l4_sin.sin_addr = ipn->in_in[0];
605 			l4->l4_sin.sin_port = ipn->in_pnext;
606 			l4->l4_next = l4list;
607 			l4list = l4;
608 		} else if (!strcasecmp(t, "connect")) {
609 			s = strtok(NULL, " \t");
610 			if (s)
611 				t = strtok(NULL, "\t");
612 			if (!s || !t) {
613 				errtxt = line;
614 				err = -1;
615 				break;
616 			} else if (!strcasecmp(s, "timeout")) {
617 				ctimeout = atoi(t);
618 				if (opts & OPT_VERBOSE)
619 					fprintf(stderr, "connect timeout %d\n",
620 						ctimeout);
621 			} else if (!strcasecmp(s, "frequency")) {
622 				frequency = atoi(t);
623 				if (opts & OPT_VERBOSE)
624 					fprintf(stderr,
625 						"connect frequency %d\n",
626 						frequency);
627 			} else {
628 				errtxt = line;
629 				err = -1;
630 				break;
631 			}
632 		} else if (!strcasecmp(t, "probe")) {
633 			s = strtok(NULL, " \t");
634 			if (!s) {
635 				errtxt = line;
636 				err = -1;
637 				break;
638 			} else if (!strcasecmp(s, "string")) {
639 				if (probe) {
640 					fprintf(stderr,
641 						"%d: probe already set\n",
642 						num);
643 					err = -1;
644 					break;
645 				}
646 				t = strtok(NULL, "");
647 				if (!t) {
648 					fprintf(stderr,
649 						"%d: No probe string\n", num);
650 					err = -1;
651 					break;
652 				}
653 
654 				probe = malloc(strlen(t));
655 				copystr(probe, t);
656 				plen = strlen(probe);
657 				if (opts & OPT_VERBOSE)
658 					fprintf(stderr, "Probe string [%s]\n",
659 						probe);
660 			} else if (!strcasecmp(s, "file")) {
661 				t = strtok(NULL, " \t");
662 				if (!t) {
663 					errtxt = line;
664 					err = -1;
665 					break;
666 				}
667 				if (probe) {
668 					fprintf(stderr,
669 						"%d: probe already set\n",
670 						num);
671 					err = -1;
672 					break;
673 				}
674 				probe = mapfile(t, &plen);
675 				if (opts & OPT_VERBOSE)
676 					fprintf(stderr,
677 						"Probe file %s len %u@%p\n",
678 						t, plen, probe);
679 			}
680 		} else if (!strcasecmp(t, "response")) {
681 			s = strtok(NULL, " \t");
682 			if (!s) {
683 				errtxt = line;
684 				err = -1;
685 				break;
686 			} else if (!strcasecmp(s, "timeout")) {
687 				t = strtok(NULL, " \t");
688 				if (!t) {
689 					errtxt = line;
690 					err = -1;
691 					break;
692 				}
693 				rtimeout = atoi(t);
694 				if (opts & OPT_VERBOSE)
695 					fprintf(stderr,
696 						"response timeout %d\n",
697 						rtimeout);
698 			} else if (!strcasecmp(s, "string")) {
699 				if (response) {
700 					fprintf(stderr,
701 						"%d: response already set\n",
702 						num);
703 					err = -1;
704 					break;
705 				}
706 				response = strdup(strtok(NULL, ""));
707 				rlen = strlen(response);
708 				template.l4_rsize = rlen;
709 				template.l4_rbuf = malloc(rlen);
710 				if (opts & OPT_VERBOSE)
711 					fprintf(stderr,
712 						"Response string [%s]\n",
713 						response);
714 			} else if (!strcasecmp(s, "file")) {
715 				t = strtok(NULL, " \t");
716 				if (!t) {
717 					errtxt = line;
718 					err = -1;
719 					break;
720 				}
721 				if (response) {
722 					fprintf(stderr,
723 						"%d: response already set\n",
724 						num);
725 					err = -1;
726 					break;
727 				}
728 				response = mapfile(t, &rlen);
729 				template.l4_rsize = rlen;
730 				template.l4_rbuf = malloc(rlen);
731 				if (opts & OPT_VERBOSE)
732 					fprintf(stderr,
733 						"Response file %s len %u@%p\n",
734 						t, rlen, response);
735 			}
736 		} else {
737 			errtxt = line;
738 			err = -1;
739 			break;
740 		}
741 	}
742 
743 	if (errtxt)
744 		fprintf(stderr, "%d: syntax error at \"%s\"\n", num, errtxt);
745 	fclose(fp);
746 	return(err);
747 }
748 
749 
750 void
751 usage(char *prog)
752 {
753 	fprintf(stderr, "Usage: %s -f <configfile>\n", prog);
754 	exit(1);
755 }
756 
757 
758 int
759 main(int argc, char *argv[])
760 {
761 	char *config = NULL;
762 	int c;
763 
764 	while ((c = getopt(argc, argv, "f:nv")) != -1)
765 		switch (c)
766 		{
767 		case 'f' :
768 			config = optarg;
769 			break;
770 		case 'n' :
771 			opts |= OPT_DONOTHING;
772 			break;
773 		case 'v' :
774 			opts |= OPT_VERBOSE;
775 			break;
776 		}
777 
778 	if (config == NULL)
779 		usage(argv[0]);
780 
781 	if (readconfig(config))
782 		exit(1);
783 
784 	if (!l4list) {
785 		fprintf(stderr, "No remote servers, exiting.");
786 		exit(1);
787 	}
788 
789 	if (!(opts & OPT_DONOTHING)) {
790 		natfd = open(IPL_NAT, O_RDWR);
791 		if (natfd == -1) {
792 			perror("open(IPL_NAT)");
793 			exit(1);
794 		}
795 	}
796 
797 	if (opts & OPT_VERBOSE)
798 		fprintf(stderr, "Starting...\n");
799 	while (runconfig() == 0)
800 		;
801 }
802