Ejemplo n.º 1
0
void	netstart (void)
{
	char	buffer[20];		/* input buffer			*/
	int32	nchars;			/* number Of characters read	*/
	int32	i;			/* counter from 0 to nchars	*/
	bool8	found;			/* was a valid answer found?	*/
	char	ch;			/* one character from the buff.	*/
	struct	ifentry	*ifptr;		/* ptr to interface		*/
	uint32	ipaddr;			/* IP address on interface 0	*/
	uint32	suffix;			/* host suffix to use on both	*/
					/*   othernet interfaces	*/
	static	uint32	rarindex = 1;	/* next RAR index to use	*/
	struct	ether	*ethptr;	/* ptr to Ethernet control blk.	*/
	char	*ifnames[] = {"Lab Ethernet","Othernet 1","Othernet 2"};

	/* Initialize network interfaces */

	kprintf("...initializing network stack\n");
	net_init();

	/* Initialize NAT tables */

	nat_init();

	/* Delay because Ethernet driver doesn't work without it */

	sleepms(800);
	
	/* Force system to use DHCP to obtain an address */

	kprintf("...using dhcp to obtain an IP address\n");
	ipaddr = getlocalip();
	if (ipaddr == SYSERR) {
		panic("Error: could not obtain an IP address\n\r");
	}
	kprintf("\nIP address is %d.%d.%d.%d   (0x%08x)\n\r",
		(ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff,
		ipaddr&0xff,ipaddr);
	ifptr = &if_tab[0];

	kprintf("Subnet mask is %d.%d.%d.%d and router is %d.%d.%d.%d\n\r",
		(ifptr->if_ipmask>>24)&0xff, (ifptr->if_ipmask>>16)&0xff,
		(ifptr->if_ipmask>> 8)&0xff,  ifptr->if_ipmask&0xff,
		(ifptr->if_iprouter>>24)&0xff, (ifptr->if_iprouter>>16)&0xff,
		(ifptr->if_iprouter>> 8)&0xff, ifptr->if_iprouter&0xff);

	/* Ask the user for a Bing ID */

	found = FALSE;
	while (!found) {
		printf("\n\rEnter a bing ID between 0 and 255: ");
		nchars = read(CONSOLE, buffer, 20);
		if ((nchars == SYSERR) || (nchars == EOF) ||
						(nchars < 2)) {
			continue;
		}
		nchars--;	/* Eliminate NEWLINE */
		bingid = 0;
		for (i=0; i<nchars; i++) {
			ch = buffer[i];
			if ( (ch<'0') || (ch>'9')) {
				break;
			}
			bingid = 10*bingid + (ch-'0');
		}
		if ((i<nchars) || (bingid > 254)) {
			continue;
		}
		found = TRUE;
	}
	printf("Bing ID is set to %d.\n", bingid);

	/* Generate Othernet emulation addresses */

	suffix = ipaddr & 0x0000ffff;	/* suffix is last two bytes of	*/
					/*   the IP address		*/

	ethptr = &ethertab[0];

	/* Othernet 1 */

	ifptr = &if_tab[1];
	ifptr->if_ipmask  = 0xffff0000;	/* 255.255.0.0. */
	ifptr->if_ipprefix= 0x0a010000;	/* 10.1.0.0/16	*/
	ifptr->if_ipucast = ifptr->if_ipprefix | suffix;
	ifptr->if_ipbcast = ifptr->if_ipprefix | ~ifptr->if_ipmask;

	ifptr->if_macucast[0] = 0x11;
	ifptr->if_macucast[1] = 0xff & (ipaddr >> 24);
	ifptr->if_macucast[2] = 0xff & (ipaddr >> 16);
	ifptr->if_macucast[3] = 0xff & (ipaddr >>  8);
	ifptr->if_macucast[4] = 0xff & (ipaddr >>  0);
	ifptr->if_macucast[5] = 0xff & bingid;
	e1000e_rar_set(ethptr, ifptr->if_macucast, rarindex++);

	ifptr->if_macbcast[0] = 0x11;
	ifptr->if_macbcast[1] = 0xff;
	ifptr->if_macbcast[2] = 0xff;
	ifptr->if_macbcast[3] = 0xff;
	ifptr->if_macbcast[4] = 0xff;
	ifptr->if_macbcast[5] = 0xff & bingid;
	e1000e_rar_set(ethptr, ifptr->if_macbcast, rarindex++);
	ifptr->if_ipvalid = TRUE;


	/* Othernet 2 */

	ifptr = &if_tab[2];
	ifptr->if_ipmask  = 0xffff0000;	/* 255.255.0.0. */
	ifptr->if_ipprefix= 0x0a020000;	/* 10.2.0.0/16	*/
	ifptr->if_ipucast = ifptr->if_ipprefix | suffix;
	ifptr->if_ipbcast = ifptr->if_ipprefix | ~ifptr->if_ipmask;

	ifptr->if_macucast[0] = 0x21;
	ifptr->if_macucast[1] = 0xff & (ipaddr >> 24);
	ifptr->if_macucast[2] = 0xff & (ipaddr >> 16);
	ifptr->if_macucast[3] = 0xff & (ipaddr >>  8);
	ifptr->if_macucast[4] = 0xff & (ipaddr >>  0);
	ifptr->if_macucast[5] = 0xff & bingid;
	e1000e_rar_set(ethptr, ifptr->if_macucast, rarindex++);

	ifptr->if_macbcast[0] = 0x21;
	ifptr->if_macbcast[1] = 0xff;
	ifptr->if_macbcast[2] = 0xff;
	ifptr->if_macbcast[3] = 0xff;
	ifptr->if_macbcast[4] = 0xff;
	ifptr->if_macbcast[5] = 0xff & bingid;
	e1000e_rar_set(ethptr, ifptr->if_macbcast, rarindex++);
	ifptr->if_ipvalid = TRUE;

	/* Ask the user what to run */

	found = FALSE;
	while (!found) {
		printf("\nEnter r for router or hX for host on interface X: ");
		nchars = read(CONSOLE, buffer, 20);
		switch (nchars) {
		    case 2:
			ch = buffer[0];
			if ( (ch!='r') && (ch!='R')) {
				continue;
			}
			host = FALSE;
			ifprime = 0;
			found = TRUE;
			break;

		    case 3:
			ch = buffer[0];
			if ((ch!='h') && (ch!='H')) {
				continue;
			}
			ch = buffer[1];
			if ( (ch<'0') || (ch>'2')) {
				continue;
			}
			ifprime = ch - '0';
			host = TRUE;
			found = TRUE;
			break;

		    default:
			continue;
		}

	}
	if (host) {
		printf("\nRunning host on %s\n\r", ifnames[ifprime]);
		if (ifprime != 0) {
			/* Shut off Ethernet and bring up other net */
			if_tab[0].if_state = IF_DOWN;
			ifptr = &if_tab[ifprime];
			ifptr->if_state = IF_UP;
			/* Set default route to router address */
			if (ifptr->if_iprouter == 0) {
				ifptr->if_iprouter = ifptr->if_ipprefix |
							ROUTER_SUFFIX;
			}
		}
	} else {
		kprintf("Running a router\n\r");
		for (i=0; i<NIFACES; i++) {
			ifptr = &if_tab[i];
			ifptr->if_state = IF_UP;
			if (i != 0) {
				/* Set router address */
				ifptr->if_ipucast = ifptr->if_ipprefix |
							ROUTER_SUFFIX;
			}
		}
	}
	return;
}
Ejemplo n.º 2
0
/*
 * Main entry point.
 */
int
main(int argc, char *argv[])
{
	const char *argv0;
	int ch;
	opts_t *opts;
	char *natengine;
	int pidfd = -1;
	int rv = EXIT_FAILURE;

	argv0 = argv[0];
	opts = opts_new();
	natengine = strdup(nat_getdefaultname());

	while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z
	                    "k:c:C:K:t:OPs:e:Eu:j:p:l:L:S:dDVh")) != -1) {
		switch (ch) {
			case 'c':
				if (opts->cacrt)
					X509_free(opts->cacrt);
				opts->cacrt = ssl_x509_load(optarg);
				if (!opts->cacrt) {
					fprintf(stderr, "%s: error loading CA "
					                "cert from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				ssl_x509_refcount_inc(opts->cacrt);
				sk_X509_insert(opts->chain, opts->cacrt, 0);
				if (!opts->cakey) {
					opts->cakey = ssl_key_load(optarg);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'k':
				if (opts->cakey)
					EVP_PKEY_free(opts->cakey);
				opts->cakey = ssl_key_load(optarg);
				if (!opts->cakey) {
					fprintf(stderr, "%s: error loading CA "
					                "key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				if (!opts->cacrt) {
					opts->cacrt = ssl_x509_load(optarg);
					if (opts->cacrt) {
						ssl_x509_refcount_inc(
						               opts->cacrt);
						sk_X509_insert(opts->chain,
						               opts->cacrt, 0);
					}
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'C':
				if (ssl_x509chain_load(NULL, &opts->chain,
				                       optarg) == -1) {
					fprintf(stderr, "%s: error loading "
					                "chain from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
			case 'K':
				if (opts->key)
					EVP_PKEY_free(opts->key);
				opts->key = ssl_key_load(optarg);
				if (!opts->key) {
					fprintf(stderr, "%s: error loading lea"
					                "f key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 't':
				if (!sys_isdir(optarg)) {
					fprintf(stderr, "%s: '%s' is not a "
					                "directory\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				if (opts->tgcrtdir)
					free(opts->tgcrtdir);
				opts->tgcrtdir = strdup(optarg);
				break;
			case 'O':
				opts->deny_ocsp = 1;
				break;
			case 'P':
				opts->passthrough = 1;
				break;
#ifndef OPENSSL_NO_DH
			case 'g':
				if (opts->dh)
					DH_free(opts->dh);
				opts->dh = ssl_dh_load(optarg);
				if (!opts->dh) {
					fprintf(stderr, "%s: error loading DH "
					                "params from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH
			case 'G':
			{
				EC_KEY *ec;
				if (opts->ecdhcurve)
					free(opts->ecdhcurve);
				if (!(ec = ssl_ec_by_name(optarg))) {
					fprintf(stderr, "%s: unknown curve "
					                "'%s'\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				EC_KEY_free(ec);
				opts->ecdhcurve = strdup(optarg);
				break;
			}
#endif /* !OPENSSL_NO_ECDH */
#ifdef SSL_OP_NO_COMPRESSION
			case 'Z':
				opts->sslcomp = 0;
				break;
#endif /* SSL_OP_NO_COMPRESSION */
			case 's':
				if (opts->ciphers)
					free(opts->ciphers);
				opts->ciphers = strdup(optarg);
				break;
			case 'e':
				free(natengine);
				natengine = strdup(optarg);
				break;
			case 'E':
				nat_list_engines();
				exit(EXIT_SUCCESS);
				break;
			case 'u':
				if (opts->dropuser)
					free(opts->dropuser);
				opts->dropuser = strdup(optarg);
				break;
			case 'p':
				if (opts->pidfile)
					free(opts->pidfile);
				opts->pidfile = strdup(optarg);
				break;
			case 'j':
				if (opts->jaildir)
					free(opts->jaildir);
				opts->jaildir = strdup(optarg);
				break;
			case 'l':
				if (opts->connectlog)
					free(opts->connectlog);
				opts->connectlog = strdup(optarg);
				break;
			case 'L':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 0;
				break;
			case 'S':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 1;
				break;
			case 'd':
				opts->detach = 1;
				break;
			case 'D':
				log_dbg_mode(LOG_DBG_MODE_ERRLOG);
				opts->debug = 1;
				break;
			case 'V':
				main_version();
				exit(EXIT_SUCCESS);
			case 'h':
				main_usage();
				exit(EXIT_SUCCESS);
			case '?':
				exit(EXIT_FAILURE);
			default:
				main_usage();
				exit(EXIT_FAILURE);
		}
	}
	argc -= optind;
	argv += optind;
	opts->spec = proxyspec_parse(&argc, &argv, natengine);

	/* usage checks */
	if (opts->detach && OPTS_DEBUG(opts)) {
		fprintf(stderr, "%s: -d and -D are mutually exclusive.\n",
		                argv0);
		exit(EXIT_FAILURE);
	}
	if (!opts->spec) {
		fprintf(stderr, "%s: no proxyspec specified.\n", argv0);
		exit(EXIT_FAILURE);
	}
	for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
		if (spec->connect_addrlen || spec->sni_port)
			continue;
		if (!spec->natengine) {
			fprintf(stderr, "%s: no supported NAT engines "
			                "on this platform.\n"
			                "Only static addr and SNI proxyspecs "
			                "supported.\n", argv0);
			exit(EXIT_FAILURE);
		}
		if (spec->listen_addr.ss_family == AF_INET6 &&
		    !nat_ipv6ready(spec->natengine)) {
			fprintf(stderr, "%s: IPv6 not supported by '%s'\n",
			                argv0, spec->natengine);
			exit(EXIT_FAILURE);
		}
		spec->natlookup = nat_getlookupcb(spec->natengine);
		spec->natsocket = nat_getsocketcb(spec->natengine);
	}
	if (opts_has_ssl_spec(opts)) {
		if ((opts->cacrt || !opts->tgcrtdir) && !opts->cakey) {
			fprintf(stderr, "%s: no CA key specified (-k).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && !opts->cacrt) {
			fprintf(stderr, "%s: no CA cert specified (-c).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && opts->cacrt &&
		    (X509_check_private_key(opts->cacrt, opts->cakey) != 1)) {
			fprintf(stderr, "%s: CA cert does not match key.\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
	}

	/* prevent multiple instances running */
	if (opts->pidfile) {
		pidfd = sys_pidf_open(opts->pidfile);
		if (pidfd == -1) {
			fprintf(stderr, "%s: cannot open PID file '%s' "
			                "- process already running?\n",
			                argv0, opts->pidfile);
			exit(EXIT_FAILURE);
		}
	}

	/* dynamic defaults */
	if (!opts->ciphers) {
		opts->ciphers = strdup("ALL:-aNULL");
		if (!opts->ciphers) {
			fprintf(stderr, "%s: out of memory.\n", argv0);
			exit(EXIT_FAILURE);
		}
	}
	if (!opts->jaildir && (geteuid() == 0) && !opts->contentlogdir) {
		opts->jaildir = strdup("/var/empty");
	}
	if (!opts->dropuser && !geteuid() && !getuid() &&
	    !opts->contentlogdir) {
		opts->dropuser = strdup("nobody");
	}
	if (opts_has_ssl_spec(opts) && !opts->key) {
		opts->key = ssl_key_genrsa(1024);
		if (!opts->key) {
			fprintf(stderr, "%s: error generating RSA key:\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Generated RSA key for leaf certs.\n");
		}
	}

	/* debugging */
	if (OPTS_DEBUG(opts)) {
		main_version();
		log_dbg_printf("proxyspecs:\n");
		for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
			char *lbuf, *cbuf = NULL;
			lbuf = sys_sockaddr_str((struct sockaddr *)
			                        &spec->listen_addr,
			                        spec->listen_addrlen);
			if (spec->connect_addrlen) {
				cbuf = sys_sockaddr_str((struct sockaddr *)
				                        &spec->connect_addr,
				                        spec->connect_addrlen);
			}
			if (spec->sni_port) {
				asprintf(&cbuf, "sni %i", spec->sni_port);
			}
			log_dbg_printf("- %s %s %s %s\n", lbuf,
			               (spec->ssl ? "ssl" : "tcp"),
			               (spec->http ? "http" : "plain"),
			               (spec->natengine ? spec->natengine
			                                : cbuf));
			if (lbuf)
				free(lbuf);
			if (cbuf)
				free(cbuf);
		}
		if (opts->cacrt) {
			char *subj = ssl_x509_subject(opts->cacrt);
			log_dbg_printf("Loaded CA: '%s'\n", subj);
			free(subj);
#ifdef DEBUG_CERTIFICATE
			log_dbg_print_free(ssl_x509_to_str(opts->cacrt));
			log_dbg_print_free(ssl_x509_to_pem(opts->cacrt));
#endif /* DEBUG_CERTIFICATE */
		} else {
			log_dbg_printf("No CA loaded.\n");
		}
	}

	/*
	 * Initialize as much as possible before daemon() in order to be
	 * able to provide direct feedback to the user when failing.
	 */
	if (cachemgr_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit cachemgr.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (log_preinit(opts) == -1) {
		fprintf(stderr, "%s: failed to preinit logging.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (nat_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit NAT lookup.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Bind listeners before dropping privileges */
	proxy_ctx_t *proxy = proxy_new(opts);
	if (!proxy) {
		fprintf(stderr, "%s: failed to initialize proxy.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Drop privs, chroot, detach from TTY */
	if (sys_privdrop(opts->dropuser, opts->jaildir) == -1) {
		fprintf(stderr, "%s: failed to drop privileges: %s\n",
		                argv0, strerror(errno));
		exit(EXIT_FAILURE);
	}
	if (opts->detach) {
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Detaching from TTY, see syslog for "
			               "errors after this point\n");
		}
		if (daemon(1, 0) == -1) {
			fprintf(stderr, "%s: failed to detach from TTY: %s\n",
			                argv0, strerror(errno));
			exit(EXIT_FAILURE);
		}
		log_err_mode(LOG_ERR_MODE_SYSLOG);
		ssl_reinit();
	}

	/* Post-privdrop/chroot/detach initialization, thread spawning */
	if (log_init(opts) == -1) {
		fprintf(stderr, "%s: failed to init log facility.\n", argv0);
		goto out_log_failed;
	}
	if (opts->pidfile && (sys_pidf_write(pidfd) == -1)) {
		log_err_printf("Failed to write PID to PID file '%s': %s\n",
		               opts->pidfile, strerror(errno));
		goto out_pidwrite_failed;
	}
	if (cachemgr_init() == -1) {
		log_err_printf("Failed to init cache manager.\n");
		goto out_cachemgr_failed;
	}
	if (nat_init() == -1) {
		log_err_printf("Failed to init NAT state table lookup.\n");
		goto out_nat_failed;
	}

	if (opts->tgcrtdir) {
		sys_dir_eachfile(opts->tgcrtdir, main_loadtgcrt, opts);
	}

	rv = EXIT_SUCCESS;

	proxy_run(proxy);
	proxy_free(proxy);
	nat_fini();
out_nat_failed:
	cachemgr_fini();
out_cachemgr_failed:
	if (opts->pidfile) {
		sys_pidf_close(pidfd, opts->pidfile);
	}
out_pidwrite_failed:
	log_fini();
out_log_failed:
	opts_free(opts);
	ssl_fini();
	return rv;
}
Ejemplo n.º 3
0
int main(int argc, char **argv)
{
	struct packet_mreq	pmr;
	struct ethtool_value	ethtool;

	int	sniff_sock;
	int	length;
	char	buffer[PACKET_BUFFER];

	int	i;
	time_t	prevtime, curtime;

	log_info(PACKAGE_STRING " is starting");

	/* initialize the socket for sniffing */
	if ((sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==
	    -1) {
		log_error("Unable to create listening socket");
		return 1;
	}

	/* get the interface */
	strncpy(interface.ifr_name, INTERFACE, IFNAMSIZ);
	if (ioctl(sniff_sock, SIOCGIFINDEX, &interface) == -1) {
		log_error("Unable to get the interface");
		return 1;
	}

	/* get interface's HW address (i.e. MAC) */
	if (ioctl(sniff_sock, SIOCGIFHWADDR, &interface) == 0) {
		memcpy(&mac, &interface.ifr_hwaddr.sa_data,
		       sizeof(struct s_mac_addr));

		/* disable generic segmentation offload */
		ethtool.cmd = ETHTOOL_SGSO;
		ethtool.data = 0;
		interface.ifr_data = (caddr_t) &ethtool;
		if (ioctl(sniff_sock, SIOCETHTOOL, &interface) == -1) {
			log_error("Unable to disable generic segmentation "
				  "offload on the interface");
			return 1;
		}

		/* reinitialize the interface */
		interface.ifr_data = NULL;
		if (ioctl(sniff_sock, SIOCGIFINDEX, &interface) == -1) {
			log_error("Unable to reinitialize the interface");
			return 1;
		}
	} else {
		log_error("Unable to get the interface's HW address");
		return 1;
	}

	/* set the promiscuous mode */
	memset(&pmr, 0x0, sizeof(pmr));
	pmr.mr_ifindex = interface.ifr_ifindex;
	pmr.mr_type = PACKET_MR_PROMISC;
	if (setsockopt(sniff_sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
	    (char *) &pmr, sizeof(pmr)) == -1) {
		log_error("Unable to set the promiscuous mode on the "
			  "interface");
		return 1;
	}

	/* some preparations */
	/* compute binary IPv6 address of NDP multicast */
	inet_pton(AF_INET6, "ff02::1:ff00:0", &ndp_multicast_addr);

	/* compute binary IPv6 address of WrapSix prefix */
	inet_pton(AF_INET6, PREFIX, &wrapsix_ipv6_prefix);

	/* compute binary IPv4 address of WrapSix */
	inet_pton(AF_INET, IPV4_ADDR, &wrapsix_ipv4_addr);

	/* compute binary IPv6 address of WrapSix host */
	inet_pton(AF_INET6, HOST_IPV6_ADDR, &host_ipv6_addr);

	/* compute binary IPv4 address of WrapSix host */
	inet_pton(AF_INET, HOST_IPV4_ADDR, &host_ipv4_addr);

	/* initiate sending socket */
	if (transmission_init()) {
		log_error("Unable to initiate sending socket");
		return 1;
	}

	/* initiate NAT tables */
	nat_init();

	/* initiate random numbers generator */
	srand((unsigned int) time(NULL));

	/* initialize time */
	prevtime = time(NULL);

	/* sniff! :c) */
	for (i = 1;; i++) {
		if ((length = recv(sniff_sock, buffer, PACKET_BUFFER, 0)) ==
		    -1) {
			log_error("Unable to retrieve data from socket");
			return 1;
		}

		process((char *) &buffer);

		if (i % 250000) {
			curtime = time(NULL);
			/* 2 seconds is minimum normal timeout */
			if ((curtime - prevtime) >= 2) {
				nat_cleaning();
				prevtime = curtime;
			}
			i = 0;
		}
	}

	/* clean-up */
	/* close sending socket */
	transmission_quit();

	/* empty NAT tables */
	nat_quit();

	/* unset the promiscuous mode */
	if (setsockopt(sniff_sock, SOL_PACKET, PACKET_DROP_MEMBERSHIP,
	    (char *) &pmr, sizeof(pmr)) == -1) {
		log_error("Unable to unset the promiscuous mode on the "
			  "interface");
		/* do not call return here as we want to close the socket too */
	}

	/* close the socket */
	close(sniff_sock);

	return 0;
}