1 /*
2  *  6tunnel v0.13
3  *  (C) Copyright 2000-2005,2013,2016,2019 by Wojtek Kaniewski <wojtekka@toxygen.net>
4  *
5  *  Contributions by:
6  *  - Dariusz Jackowski <ascent@linux.pl>
7  *  - Ramunas Lukosevicius <lukoramu@parok.lt>
8  *  - Roland Stigge <stigge@antcom.de>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License Version 2 as
12  *  published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <netdb.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <sys/select.h>
32 #include <sys/socket.h>
33 #include <arpa/inet.h>
34 #include <sys/wait.h>
35 #include <fcntl.h>
36 #include <signal.h>
37 #include <errno.h>
38 #include <ctype.h>
39 #include <pwd.h>
40 #include <time.h>
41 
42 #define debug(x...) do { \
43 	if (verbose) \
44 		printf(x); \
45 } while(0)
46 
47 int verbose = 0, conn_count = 0;
48 int remote_port, verbose, hexdump = 0;
49 int remote_hint[2] = { AF_INET6, AF_INET };
50 int local_hint = AF_INET;
51 char *remote_host, *irc_pass = NULL;
52 char *irc_send_pass = NULL;
53 char *pid_file = NULL;
54 const char *source_host;
55 
56 typedef struct source_map {
57 	char *ipv4;
58 	char *ipv6;
59 	struct source_map *next;
60 } source_map_t;
61 
62 source_map_t *source_map = NULL;
63 char *source_map_file = NULL;
64 
xmalloc(int size)65 char *xmalloc(int size)
66 {
67 	char *tmp;
68 
69 	tmp = malloc(size);
70 
71 	if (tmp == NULL) {
72 		perror("malloc");
73 		exit(1);
74 	}
75 
76 	return tmp;
77 }
78 
xrealloc(char * ptr,int size)79 char *xrealloc(char *ptr, int size)
80 {
81 	char *tmp;
82 
83 	tmp = realloc(ptr, size);
84 
85 	if (tmp == NULL) {
86 		perror("realloc");
87 		exit(1);
88 	}
89 
90 	return tmp;
91 }
92 
xstrdup(const char * str)93 char *xstrdup(const char *str)
94 {
95 	char *tmp;
96 
97 	tmp = strdup(str);
98 
99 	if (tmp == NULL) {
100 		perror("strdup");
101 		exit(1);
102 	}
103 
104 	return tmp;
105 }
106 
xntop(const struct sockaddr * sa)107 char *xntop(const struct sockaddr *sa)
108 {
109 	char *tmp = NULL;
110 
111 	if (sa->sa_family == AF_INET)
112 	{
113 		struct sockaddr_in *sin = (struct sockaddr_in*) sa;
114 
115 		tmp = xmalloc(INET_ADDRSTRLEN);
116 
117 		if (inet_ntop(sa->sa_family, &sin->sin_addr, tmp, INET_ADDRSTRLEN) == NULL)
118 		{
119 			free(tmp);
120 			tmp = NULL;
121 		}
122 	}
123 	else if (sa->sa_family == AF_INET6)
124 	{
125 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6*) sa;
126 		tmp = xmalloc(INET6_ADDRSTRLEN);
127 
128 		if (inet_ntop(sa->sa_family, &sin6->sin6_addr, tmp, INET6_ADDRSTRLEN) == NULL)
129 		{
130 			free(tmp);
131 			tmp = NULL;
132 		}
133 	}
134 
135 	return tmp;
136 }
137 
resolve_host(const char * name,int port,int hint)138 struct addrinfo *resolve_host(const char *name, int port, int hint)
139 {
140 	struct addrinfo *result = NULL;
141 	struct addrinfo hints;
142 	char port_str[16];
143 	int rc;
144 
145 	snprintf(port_str, sizeof(port_str), "%u", port);
146 
147 	memset(&hints, 0, sizeof(hints));
148 	hints.ai_family = hint;
149 	hints.ai_socktype = SOCK_STREAM;
150 	hints.ai_flags = (name == NULL && port != 0) ? AI_PASSIVE : 0;
151 
152 	rc = getaddrinfo(name, (port != 0) ? port_str : NULL, &hints, &result);
153 
154 	if (rc == 0)
155 		return result;
156 
157 	debug("resolver %s port %d hint %d failed: %s\n", name, port, hint, gai_strerror(rc));
158 
159 	return NULL;
160 }
161 
print_hexdump(const char * buf,int len)162 void print_hexdump(const char *buf, int len)
163 {
164 	int i, j;
165 
166 	for (i = 0; i < ((len / 16) + ((len % 16) ? 1 : 0)); i++) {
167 		printf("%.4x: ", i * 16);
168 
169 		for (j = 0; j < 16; j++) {
170 			if (i * 16 + j < len)
171 				printf("%.2x ", buf[i*16+j]);
172 			else
173 				printf("   ");
174 			if (j == 7)
175 				printf(" ");
176 		}
177 
178 		printf(" ");
179 
180 		for (j = 0; j < 16; j++) {
181 			if (i * 16 + j < len) {
182 				char ch = buf[i * 16 + j];
183 
184 				printf("%c", (isprint(ch)) ? ch : '.');
185 			}
186 		}
187 
188 		printf("\n");
189 	}
190 }
191 
source_map_find(const char * ipv4)192 const char *source_map_find(const char *ipv4)
193 {
194 	source_map_t *m;
195 
196 	for (m = source_map; m != NULL; m = m->next) {
197 		if (strcmp(m->ipv4, ipv4) == 0)
198 			return m->ipv6;
199 	}
200 
201 	for (m = source_map; m != NULL; m = m->next) {
202 		if ((strcmp(m->ipv4, "0.0.0.0") == 0) || (strcmp(m->ipv4, "default") == 0))
203 			return m->ipv6;
204 	}
205 
206 	return source_host;
207 }
208 
make_tunnel(int rsock,const char * client_addr)209 void make_tunnel(int rsock, const char *client_addr)
210 {
211 	char buf[4096], *outbuf = NULL, *inbuf = NULL;
212 	int sock = -1, outlen = 0, inlen = 0;
213 	struct sockaddr *sa = NULL;
214 	const char *source;
215 	struct addrinfo *connect_ai = NULL;
216 	struct addrinfo *bind_ai = NULL;
217 	struct addrinfo *ai_ptr;
218 	int source_hint;
219 
220 	if (source_map != NULL) {
221 		source = source_map_find(client_addr);
222 
223 		if (source == NULL) {
224 			debug("<%d> connection from unmapped address (%s), disconnecting\n", rsock, client_addr);
225 			goto cleanup;
226 		}
227 
228 		debug("<%d> mapped to %s\n", rsock, source);
229 	} else
230 		source = source_host;
231 
232 	if (irc_pass != NULL) {
233 		int i, ret;
234 
235 		for (i = 0; i < sizeof(buf) - 1; i++) {
236 			if ((ret = read(rsock, buf + i, 1)) < 1)
237 				goto cleanup;
238 			if (buf[i] == '\n')
239 				break;
240 		}
241 
242 		buf[i] = 0;
243 
244 		if (i > 0 && buf[i - 1] == '\r')
245 			buf[i - 1] = 0;
246 
247 		if (i == 4095 || strncasecmp(buf, "PASS ", 5) != 0) {
248 			char *tmp;
249 
250 			debug("<%d> irc proxy auth failed - junk\n", rsock);
251 
252 			tmp = "ERROR :Closing link: Make your client send password first\r\n";
253 			if (write(rsock, tmp, strlen(tmp)) != strlen(tmp)) {
254 				// Do nothing. We're failing anyway.
255 			}
256 
257 			goto cleanup;
258 		}
259 
260 		if (strcmp(buf + 5, irc_pass) != 0) {
261 			char *tmp;
262 
263 			debug("<%d> irc proxy auth failed - password incorrect\n", rsock);
264 			tmp = ":6tunnel 464 * :Password incorrect\r\nERROR :Closing link: Password incorrect\r\n";
265 			if (write(rsock, tmp, strlen(tmp)) != strlen(tmp)) {
266 				// Do nothing. We're failing anyway.
267 			}
268 
269 			goto cleanup;
270 		}
271 
272 		debug("<%d> irc proxy auth succeeded\n", rsock);
273 	}
274 
275 	connect_ai = resolve_host(remote_host, remote_port, remote_hint[0]);
276 
277 	if (connect_ai == NULL) {
278 		connect_ai = resolve_host(remote_host, remote_port, remote_hint[1]);
279 
280 		if (connect_ai == NULL) {
281 			debug("<%d> unable to resolve %s,%d\n", rsock, remote_host, remote_port);
282 			goto cleanup;
283 		}
284 
285 		source_hint = remote_hint[1];
286 	} else {
287 		source_hint = remote_hint[0];
288 	}
289 
290 	for (ai_ptr = connect_ai; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
291 		sock = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, 0);
292 
293 		if (sock == -1) {
294 			if (ai_ptr->ai_next != NULL)
295 				continue;
296 			debug("<%d> unable to create socket (%s)\n", rsock, strerror(errno));
297 			goto cleanup;
298 		}
299 
300 		if (source != NULL)
301 		{
302 			bind_ai = resolve_host(source, 0, source_hint);
303 
304 			if (bind_ai == NULL) {
305 				debug("<%d> unable to resolve source host (%s)\n", rsock, (source != NULL) ? source : "default");
306 				goto cleanup;
307 			}
308 
309 			if (bind(sock, bind_ai->ai_addr, bind_ai->ai_addrlen) == -1) {
310 				if (ai_ptr->ai_next != NULL) {
311 					close(sock);
312 					sock = -1;
313 					continue;
314 				}
315 				debug("<%d> unable to bind to source host (%s)\n", rsock, (source != NULL) ? source : "default");
316 				goto cleanup;
317 			}
318 
319 			freeaddrinfo(bind_ai);
320 			bind_ai = NULL;
321 		}
322 
323 		if (connect(sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen) != -1)
324 			break;
325 
326 		if (ai_ptr->ai_next == NULL) {
327 			debug("<%d> connection failed (%s,%d)\n", rsock, remote_host, remote_port);
328 			goto cleanup;
329 		}
330 
331 		close(sock);
332 		sock = -1;
333 	}
334 
335 	freeaddrinfo(connect_ai);
336 	connect_ai = NULL;
337 
338 	debug("<%d> connected to %s,%d\n", rsock, remote_host, remote_port);
339 
340 	if (irc_send_pass != NULL) {
341 		snprintf(buf, sizeof(buf), "PASS %s\r\n", irc_send_pass);
342 		if (write(sock, buf, strlen(buf)) != strlen(buf))
343 			goto cleanup;
344 	}
345 
346 	for (;;) {
347 		fd_set rds, wds;
348 		int ret, sent;
349 
350 		FD_ZERO(&rds);
351 		FD_SET(sock, &rds);
352 		FD_SET(rsock, &rds);
353 
354 		FD_ZERO(&wds);
355 		if (outbuf && outlen)
356 			FD_SET(rsock, &wds);
357 		if (inbuf && inlen)
358 			FD_SET(sock, &wds);
359 
360 		ret = select((sock > rsock) ? (sock + 1) : (rsock + 1), &rds, &wds, NULL, NULL);
361 
362 		if (FD_ISSET(rsock, &wds)) {
363 			sent = write(rsock, outbuf, outlen);
364 
365 			if (sent < 1)
366 				goto cleanup;
367 
368 			if (sent == outlen) {
369 				free(outbuf);
370 				outbuf = NULL;
371 				outlen = 0;
372 			} else {
373 				memmove(outbuf, outbuf + sent, outlen - sent);
374 				outlen -= sent;
375 			}
376 		}
377 
378 		if (FD_ISSET(sock, &wds)) {
379 			sent = write(sock, inbuf, inlen);
380 
381 			if (sent < 1)
382 				goto cleanup;
383 
384 			if (sent == inlen) {
385 				free(inbuf);
386 				inbuf = NULL;
387 				inlen = 0;
388 			} else {
389 				memmove(inbuf, inbuf + sent, inlen - sent);
390 				inlen -= sent;
391 			}
392 		}
393 
394 		if (FD_ISSET(sock, &rds)) {
395 			if ((ret = read(sock, buf, sizeof(buf))) < 1)
396 				goto cleanup;
397 
398 			if (hexdump) {
399 				printf("<%d> recvfrom %s,%d\n", rsock, remote_host, remote_port);
400 				print_hexdump(buf, ret);
401 			}
402 
403 			sent = write(rsock, buf, ret);
404 
405 			if (sent < 1)
406 				goto cleanup;
407 
408 			if (sent < ret) {
409 				outbuf = xrealloc(outbuf, outlen + ret - sent);
410 				memcpy(outbuf + outlen, buf + sent, ret - sent);
411 				outlen = ret - sent;
412 			}
413 		}
414 
415 		if (FD_ISSET(rsock, &rds)) {
416 			if ((ret = read(rsock, buf, sizeof(buf))) < 1)
417 				goto cleanup;
418 
419 			if (hexdump) {
420 				printf("<%d> sendto %s,%d\n", rsock, remote_host, remote_port);
421 				print_hexdump(buf, ret);
422 			}
423 
424 			sent = write(sock, buf, ret);
425 
426 			if (sent < 1)
427 				goto cleanup;
428 
429 			if (sent < ret) {
430 				inbuf = xrealloc(inbuf, inlen + ret - sent);
431 				memcpy(inbuf + inlen, buf + sent, ret - sent);
432 				inlen = ret - sent;
433 			}
434 		}
435 	}
436 
437 cleanup:
438 	if (connect_ai != NULL)
439 		freeaddrinfo(connect_ai);
440 
441 	if (bind_ai != NULL)
442 		freeaddrinfo(bind_ai);
443 
444 	close(rsock);
445 
446 	if (sock != -1)
447 		close(sock);
448 }
449 
usage(const char * arg0)450 void usage(const char *arg0)
451 {
452 	fprintf(stderr,
453 
454 "usage: %s [-146dvh] [-s sourcehost] [-l localhost] [-i pass]\n"
455 "           [-I pass] [-L limit] [-A filename] [-p pidfile]\n"
456 "           [-m mapfile] localport remotehost [remoteport]\n"
457 "\n"
458 "  -1  allow only single connection and quit\n"
459 "  -4  connect to IPv4 endpoints (default: connect to IPv6)\n"
460 "  -6  bind to IPv6 address (default: bind to IPv4)\n"
461 "  -d  don't detach\n"
462 "  -f  force tunneling (even if remotehost isn't resolvable)\n"
463 "  -h  print hex dump of packets\n"
464 "  -u  change UID and GID after bind()\n"
465 "  -i  act like irc proxy and ask for password\n"
466 "  -I  send specified password to the irc server\n"
467 "  -l  bind to specified address\n"
468 "  -L  limit simultaneous connections\n"
469 "  -p  write down pid to specified file\n"
470 "  -s  connect using specified address\n"
471 "  -m  read specified IPv4-to-IPv6 map file\n"
472 "  -v  be verbose\n"
473 "\n", arg0);
474 }
475 
clear_argv(char * argv)476 void clear_argv(char *argv)
477 {
478 	int x;
479 
480 	for (x = 0; x < strlen(argv); x++)
481 		argv[x] = 'x';
482 
483 	return;
484 }
485 
source_map_destroy(void)486 void source_map_destroy(void)
487 {
488 	source_map_t *m;
489 
490 	debug("source_map_destroy()\n");
491 
492 	for (m = source_map; m != NULL; ) {
493 		source_map_t *n;
494 
495 		free(m->ipv4);
496 		free(m->ipv6);
497 		n = m;
498 		m = m->next;
499 		free(n);
500 	}
501 
502 	source_map = NULL;
503 }
504 
map_read(void)505 void map_read(void)
506 {
507 	char buf[256];
508 	FILE *f;
509 
510 	debug("reading map from %s\n", source_map_file);
511 
512 	f = fopen(source_map_file, "r");
513 
514 	if (f == NULL) {
515 		debug("unable to read map file, ignoring\n");
516 		return;
517 	}
518 
519 	while (fgets(buf, sizeof(buf), f) != NULL) {
520 		char *p, *ipv4, *ipv6;
521 		source_map_t *m;
522 
523 		for (p = buf; *p == ' ' || *p == '\t'; p++);
524 
525 		if (!*p)
526 			continue;
527 
528 		ipv4 = p;
529 
530 		for (; *p && *p != ' ' && *p != '\t'; p++);
531 
532 		if (!*p)
533 			continue;
534 
535 		*p = 0;
536 		p++;
537 
538 		for (; *p == ' ' || *p == '\t'; p++);
539 
540 		if (!*p)
541 			continue;
542 
543 		ipv6 = p;
544 
545 		for (; *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n'; p++);
546 
547 		*p = 0;
548 
549 		debug("[%s] mapped to [%s]\n", ipv4, ipv6);
550 
551 		m = (source_map_t*) xmalloc(sizeof(source_map_t));
552 		m->ipv4 = xstrdup(ipv4);
553 		m->ipv6 = xstrdup(ipv6);
554 		m->next = source_map;
555 		source_map = m;
556 	}
557 
558 	fclose(f);
559 }
560 
sighup()561 void sighup()
562 {
563 	source_map_destroy();
564 	map_read();
565 
566 	signal(SIGHUP, sighup);
567 }
568 
sigchld()569 void sigchld()
570 {
571 	while (waitpid(-1, NULL, WNOHANG) > 0) {
572 		debug("child process exited\n");
573 		conn_count--;
574 	}
575 
576 	signal(SIGCHLD, sigchld);
577 }
578 
sigterm()579 void sigterm()
580 {
581 	if (pid_file != NULL)
582 		unlink(pid_file);
583 
584 	exit(0);
585 }
586 
main(int argc,char ** argv)587 int main(int argc, char **argv)
588 {
589 	int force = 0, listen_fd, single_connection = 0, jeden = 1, local_port;
590 	int detach = 1, sa_len, conn_limit = 0, optc;
591 	const char *username = NULL;
592 	char *local_host = NULL;
593 	struct addrinfo *ai;
594 	struct addrinfo *ai_ptr;
595 	struct sockaddr *sa;
596 	struct sockaddr_in laddr;
597 	struct sockaddr_in6 laddr6;
598 	struct passwd *pw = NULL;
599 	char *tmp;
600 	int source_hint;
601 
602 	while ((optc = getopt(argc, argv, "1dv46fHs:l:I:i:hu:m:L:A:p:")) != -1) {
603 		switch (optc) {
604 			case '1':
605 				single_connection = 1;
606 				break;
607 			case 'd':
608 				detach = 0;
609 				break;
610 			case 'v':
611 				verbose = 1;
612 				break;
613 			case '4':
614 				remote_hint[0] = AF_INET;
615 				remote_hint[1] = AF_INET6;
616 				break;
617 			case '6':
618 				local_hint = AF_INET6;
619 				break;
620 			case 's':
621 				source_host = optarg;
622 				break;
623 			case 'l':
624 				local_host = optarg;
625 				break;
626 			case 'f':
627 				force = 1;
628 				break;
629 			case 'i':
630 				irc_pass = xstrdup(optarg);
631 				clear_argv(argv[optind - 1]);
632 				break;
633 			case 'I':
634 				irc_send_pass = xstrdup(optarg);
635 				clear_argv(argv[optind - 1]);
636 				break;
637 			case 'h':
638 				hexdump = 1;
639 				break;
640 			case 'u':
641 				username = optarg;
642 				break;
643 			case 'm':
644 				source_map_file = optarg;
645 				break;
646 			case 'L':
647 				conn_limit = atoi(optarg);
648 				break;
649 			case 'p':
650 				pid_file = optarg;
651 				break;
652 			case 'H':
653 				fprintf(stderr, "%s: warning: -H is deprecated, please use proper combination of -4 and -6.\n", argv[0]);
654 				break;
655 			default:
656 				return 1;
657 		}
658 	}
659 
660 	if (hexdump)
661 		verbose = 1;
662 
663 	if (verbose)
664 		detach = 0;
665 
666 	if (detach)
667 		verbose = 0;
668 
669 	if (argc - optind < 2) {
670 		usage(argv[0]);
671 		exit(1);
672 	}
673 
674 	if (username != NULL) {
675 		pw = getpwnam(username);
676 
677 		if (pw == NULL) {
678 			fprintf(stderr, "%s: unknown user %s\n", argv[0], username);
679 			exit(1);
680 		}
681 	}
682 
683 	if (source_map_file != NULL)
684 		map_read();
685 
686 	local_port = atoi(argv[optind++]);
687 	remote_host = argv[optind++];
688 	remote_port = (argc == optind) ? local_port : atoi(argv[optind]);
689 
690 	/* Check if destination and source hosts are resolvable. If it's expected to be
691 	 * available later, -f can be used. */
692 
693 	debug("resolving %s\n", remote_host);
694 
695 	ai = resolve_host(remote_host, remote_port, remote_hint[0]);
696 
697 	if (ai == NULL) {
698 		ai = resolve_host(remote_host, remote_port, remote_hint[1]);
699 
700 		if (ai == NULL && !force) {
701 			fprintf(stderr, "%s: unable to resolve host %s\n", argv[0], remote_host);
702 			exit(1);
703 		}
704 
705 		source_hint = remote_hint[1];
706 	} else {
707 		source_hint = remote_hint[0];
708 	}
709 
710 	if (ai != NULL) {
711 
712 		if (source_hint == AF_INET && local_hint == AF_INET)
713 			fprintf(stderr, "%s: warning: both local and remote addresses are IPv4\n", argv[0]);
714 
715 		if (source_hint == AF_INET6 && local_hint == AF_INET6)
716 			fprintf(stderr, "%s: warning: both local and remote addresses are IPv6\n", argv[0]);
717 
718 		tmp = xntop(ai->ai_addr);
719 		debug("resolved to %s\n", tmp);
720 		free(tmp);
721 
722 		freeaddrinfo(ai);
723 	}
724 
725 	if (source_host != NULL) {
726 		debug("resolving %s\n", source_host);
727 
728 		ai = resolve_host(source_host, 0, source_hint);
729 
730 		if (ai == NULL && !force) {
731 			fprintf(stderr, "%s: unable to resolve host %s\n", argv[0], source_host);
732 			exit(1);
733 		}
734 
735 		tmp = xntop(ai->ai_addr);
736 		debug("resolved to %s\n", tmp);
737 		free(tmp);
738 
739 		freeaddrinfo(ai);
740 	}
741 
742 	/* Resolve local address for bind(). In case of NULL address resolve_host() will
743 	 * return INADDR_ANY or in6addr_any, so we can bind either way. */
744 
745 	debug("resolving local address %s\n", (local_host != NULL) ? local_host : "default");
746 
747 	ai = resolve_host(local_host, local_port, local_hint);
748 
749 	if (ai == NULL) {
750 		fprintf(stderr, "%s: unable to resolve host %s\n", argv[0], local_host);
751 		exit(1);
752 	}
753 
754 	tmp = xntop(ai->ai_addr);
755 	debug("resolved to %s\n", tmp);
756 	free(tmp);
757 
758 	/* Now that we know that hosts are resolvable, dump some debugging information. */
759 
760 	debug("local: %s,%d; ", (local_host != NULL) ? local_host : "default", local_port);
761 	debug("remote: %s,%d; ", remote_host, remote_port);
762 
763 	if (source_map != NULL)
764 		debug("source: mapped\n");
765 	else
766 		debug("source: %s\n", (source_host != NULL) ? source_host : "default");
767 
768 	/* Now bind. */
769 
770 	listen_fd = socket(ai->ai_family, ai->ai_socktype, 0);
771 
772 	if (listen_fd == -1) {
773 		perror("socket");
774 		exit(1);
775 	}
776 
777 	if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &jeden, sizeof(jeden)) == -1) {
778 		perror("setsockopt");
779 		exit(1);
780 	}
781 
782 	for (ai_ptr = ai; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
783 		if (bind(listen_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen) == -1 && ai_ptr->ai_next == NULL) {
784 			perror("bind");
785 			exit(1);
786 		}
787 	}
788 
789 	if (listen(listen_fd, 100) == -1) {
790 		perror("listen");
791 		exit(1);
792 	}
793 
794 	freeaddrinfo(ai);
795 	ai = NULL;
796 
797 	/* Daemonize. */
798 
799 	if (detach) {
800 		int i, ret;
801 
802 		signal(SIGHUP, sighup);
803 
804 		for (i = 0; i < 3; i++)
805 			close(i);
806 
807 		ret = fork();
808 
809 		if (ret == -1) {
810 			perror("fork");
811 			exit(1);
812 		}
813 
814 		if (ret)
815 			exit(0);
816 	}
817 
818 	/* Store process id if requested. */
819 
820 	if (pid_file != NULL) {
821 		FILE *f = fopen(pid_file, "w");
822 
823 		if (!f)
824 			debug("warning: cannot write to pidfile (%s)\n", strerror(errno));
825 		else {
826 			fprintf(f, "%d", getpid());
827 			fclose(f);
828 		}
829 	}
830 
831 	/* Change user and group id if requested. */
832 
833 	if (pw != NULL) {
834 		if ((setgid(pw->pw_gid) == -1) || (setuid(pw->pw_uid) == -1)) {
835 			perror("setuid/setgid");
836 			exit(1);
837 		}
838 	}
839 
840 	setsid();
841 	signal(SIGCHLD, sigchld);
842 	signal(SIGTERM, sigterm);
843 	signal(SIGINT, sigterm);
844 	signal(SIGHUP, sighup);
845 
846 	for (;;) {
847 		int ret;
848 		fd_set rds;
849 		int client_fd;
850 		char *client_addr;
851 		int client_port;
852 		struct sockaddr sa;
853 		unsigned int sa_len = sizeof(sa);
854 
855 		FD_ZERO(&rds);
856 		FD_SET(listen_fd, &rds);
857 
858 		if (select(listen_fd + 1, &rds, NULL, NULL, NULL) == -1) {
859 			if (errno == EINTR)
860 				continue;
861 
862 			perror("select");
863 			break;
864 		}
865 
866 		client_fd = accept(listen_fd, &sa, &sa_len);
867 
868 		if (client_fd == -1) {
869 			perror("accept");
870 			break;
871 		}
872 
873 		client_addr = xntop(&sa);
874 
875 		client_port = (sa.sa_family == AF_INET) ? ((struct sockaddr_in*) &sa)->sin_port :
876 			((struct sockaddr_in6*) &sa)->sin6_port;
877 
878 		debug("<%d> connection from %s,%d", client_fd, client_addr, ntohs(client_port));
879 
880 		if (conn_limit && (conn_count >= conn_limit)) {
881 			debug(" -- rejected due to limit.\n");
882 			shutdown(client_fd, 2);
883 			close(client_fd);
884 			continue;
885 		}
886 
887 		if (conn_limit) {
888 			conn_count++;
889 			debug(" (no. %d)", conn_count);
890 		}
891 
892 		fflush(stdout);
893 
894 		if ((ret = fork()) == -1) {
895 			debug(" -- fork() failed.\n");
896 			shutdown(client_fd, 2);
897 			close(client_fd);
898 			free(client_addr);
899 			continue;
900 		}
901 
902 		if (!ret) {
903 			signal(SIGHUP, SIG_IGN);
904 			close(listen_fd);
905 			debug("\n");
906 			make_tunnel(client_fd, client_addr);
907 			free(client_addr);
908 			debug("<%d> connection closed\n", client_fd);
909 			exit(0);
910 		}
911 
912 		close(client_fd);
913 		free(client_addr);
914 
915 		if (single_connection) {
916 			shutdown(listen_fd, 2);
917 			close(listen_fd);
918 			exit(0);
919 		}
920 
921 	}
922 
923 	close(listen_fd);
924 
925 	exit(1);
926 }
927