dissector: if no printing, then don't alloc
[netsniff-ng.git] / src / curvetun.c
blob56e63fe8ea275d7e71e54a8b0ee9ee92495e66cb
1 /*
2 * curvetun - the cipherspace wormhole creator
3 * Part of the netsniff-ng project
4 * By Daniel Borkmann <daniel@netsniff-ng.org>
5 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
6 * Copyright 2011 Emmanuel Roullit.
7 * Subject to the GPL, version 2.
9 * This is curvetun, a lightweight, high-speed ECDH multiuser IP tunnel for
10 * Linux that is based on epoll(2). curvetun uses the Linux TUN/TAP interface
11 * and supports {IPv4,IPv6} over {IPv4,IPv6} with UDP or TCP as carrier
12 * protocols. It has an integrated packet forwarding trie, thus multiple
13 * users with different IPs can be handled via a single tunnel device on the
14 * server side and flows are scheduled for processing in a CPU-local manner.
15 * For transmission, packets are being compressed and encrypted by both, the
16 * client and the server side. As an appropriate key management, public-key
17 * cryptography based on elliptic curves are being used and packets are
18 * encrypted by a symmetric stream cipher (Salsa20) and authenticated by a MAC
19 * (Poly1305), where keys have previously been computed with the ECDH key
20 * agreement protocol (Curve25519). Cryptography is based on Daniel J.
21 * Bernsteins Networking and Cryptography library (NaCl).
23 * He used often to say there was only one Road; that it was like a great
24 * river: it's springs were at every doorstep and every path was it's
25 * tributary. "It's a dangerous business, Frodo, going out of your door,"
26 * he used to say. "You step into the Road, and if you don't keep your
27 * feet, there is no telling where you might be swept off to."
29 * -- The Lord of the Rings, Frodo about his uncle Bilbo Baggins,
30 * Chapter 'Three is Company'.
35 =head1 NAME
37 curvetun - lightweight curve25519-based multiuser IP tunnel
39 =head1 SYNOPSIS
41 curvetun [-d|--dev <tun>][-x|--export][-C|--dumpc][-S|--dumps]
42 [-k|--keygen][-c|--client [<alias>]][-s|--server][-N|--no-logging]
43 [-p|--port <num>][-t|--stun <server>][-4|--ipv4][-6|--ipv6]
44 [-v|--version][-h|--help]
46 =head1 DESCRIPTION
48 curvetun embeds a client and a server to build and manage multiuser
49 IP tunnels using Elliptic Curve Cryptography (ECC)
51 =head1 EXAMPLES
53 =over
55 =item curvetun --keygen
57 Generate public/private keypair. This needs to be done before
58 to get things started.
60 =item curvetun --export
62 Export public data to remote servers
64 =item curvetun --server -4 -u -N --port 6666 --stun stunserver.org
66 Start a UDP IPv4 curvetun server on port 6666.
67 Use stunserver.org as STUN server.
69 =item curvetun --client=ethz
71 Start curvetun client using the profile called 'ethz'
73 =back
75 =head1 OPTIONS
77 =over
79 =item -k|--keygen
81 Generate public/private keypair.
83 =item -x|--export
85 Export your public data for remote servers.
87 =item -C|--dumpc
89 Dump parsed clients.
91 =item -S|--dumps
93 Dump parsed servers.
95 =item -D|--nofork
97 Do not daemonize.
99 =item -d|--dev <tun>
101 Networking tunnel device, e.g. tun0.
103 =item -c|--client [<alias>]
105 Client mode, server alias optional.
107 =item -s|--server
109 Server mode.
111 =item -N|--no-logging
113 Disable server logging (for better anonymity).
115 =item -p|--port <num>
117 Port number (mandatory).
119 =item -t|--stun <server>
121 Show public IP/Port mapping via STUN.
123 =item -u|--udp
125 Use UDP as carrier instead of TCP.
127 =item -4|--ipv4
129 Tunnel devices are IPv4.
131 =item -6|--ipv6
133 Tunnel devices are IPv6.
135 =item -v|--version
137 Print version.
139 =item -h|--help
141 Print help text and lists all options.
143 =back
145 =head1 AUTHOR
147 Written by Daniel Borkmann <daniel@netsniff-ng.org> and Emmanuel Roullit <emmanuel@netsniff-ng.org>
149 =head1 DOCUMENTATION
151 Documentation by Emmanuel Roullit <emmanuel@netsniff-ng.org>
153 =head1 BUGS
155 Please report bugs to <bugs@netsniff-ng.org>
157 =cut
161 #define _GNU_SOURCE
162 #include <stdio.h>
163 #include <stdlib.h>
164 #include <fcntl.h>
165 #include <string.h>
166 #include <ctype.h>
167 #include <getopt.h>
168 #include <errno.h>
169 #include <stdbool.h>
170 #include <limits.h>
171 #include <sys/types.h>
172 #include <sys/stat.h>
173 #include <sys/socket.h>
174 #include <sys/ptrace.h>
175 #include <netinet/in.h>
176 #include <unistd.h>
177 #include <signal.h>
179 #include "xsys.h"
180 #include "die.h"
181 #include "xmalloc.h"
182 #include "xstring.h"
183 #include "curvetun.h"
184 #include "curve.h"
185 #include "ct_usermgmt.h"
186 #include "ct_servmgmt.h"
187 #include "xio.h"
188 #include "tprintf.h"
189 #include "crypto_verify_32.h"
190 #include "crypto_box_curve25519xsalsa20poly1305.h"
191 #include "crypto_scalarmult_curve25519.h"
192 #include "crypto_auth_hmacsha512256.h"
194 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
196 extern void print_stun_probe(char *server, uint16_t sport, uint16_t tunport);
198 enum working_mode {
199 MODE_UNKNOW,
200 MODE_KEYGEN,
201 MODE_EXPORT,
202 MODE_DUMPC,
203 MODE_DUMPS,
204 MODE_CLIENT,
205 MODE_SERVER,
208 volatile sig_atomic_t sigint = 0;
210 static const char *short_options = "kxc::svhp:t:d:uCS46DN";
212 static struct option long_options[] = {
213 {"client", optional_argument, 0, 'c'},
214 {"dev", required_argument, 0, 'd'},
215 {"port", required_argument, 0, 'p'},
216 {"stun", required_argument, 0, 't'},
217 {"keygen", no_argument, 0, 'k'},
218 {"export", no_argument, 0, 'x'},
219 {"dumpc", no_argument, 0, 'C'},
220 {"dumps", no_argument, 0, 'S'},
221 {"no-logging", no_argument, 0, 'N'},
222 {"server", no_argument, 0, 's'},
223 {"udp", no_argument, 0, 'u'},
224 {"ipv4", no_argument, 0, '4'},
225 {"ipv6", no_argument, 0, '6'},
226 {"nofork", no_argument, 0, 'D'},
227 {"version", no_argument, 0, 'v'},
228 {"help", no_argument, 0, 'h'},
229 {0, 0, 0, 0}
232 static void signal_handler(int number)
234 switch (number) {
235 case SIGINT:
236 sigint = 1;
237 break;
238 default:
239 break;
243 static void header(void)
245 printf("%s%s%s\n", colorize_start(bold), "curvetun "
246 VERSION_STRING, colorize_end());
249 static void help(void)
251 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
252 VERSION_STRING);
253 printf("http://www.netsniff-ng.org\n\n");
254 printf("Usage: curvetun [options]\n");
255 printf("Options, general:\n");
256 printf(" -k|--keygen Generate public/private keypair\n");
257 printf(" -x|--export Export your public data for remote servers\n");
258 printf(" -C|--dumpc Dump parsed clients\n");
259 printf(" -S|--dumps Dump parsed servers\n");
260 printf(" -D|--nofork Do not daemonize\n");
261 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
262 printf(" -v|--version Print version\n");
263 printf(" -h|--help Print this help\n");
264 printf("Options for client:\n");
265 printf(" -c|--client[=alias] Client mode, server alias optional\n");
266 printf("Options for servers:\n");
267 printf(" -s|--server Server mode\n");
268 printf(" -N|--no-logging Disable server logging (for better anonymity)\n");
269 printf(" -p|--port <num> Port number (mandatory)\n");
270 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
271 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
272 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
273 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
274 printf(" (default: same as carrier protocol)\n");
275 printf("\n");
276 printf("Example:\n");
277 printf(" See Documentation/Curvetun for a configuration example.\n");
278 printf(" curvetun --keygen\n");
279 printf(" curvetun --export\n");
280 printf(" curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n");
281 printf(" curvetun --client=ethz\n");
282 printf("\n");
283 printf("Note:\n");
284 printf(" There is no default port specified, so that you are forced\n");
285 printf(" to select your own! For client/server status messages see syslog!\n");
286 printf(" This software is an experimental prototype intended for researchers.\n");
287 printf("\n");
288 printf("Secret ingredient: 7647-14-5\n");
289 printf("\n");
290 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
291 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
292 printf("License: GNU GPL version 2\n");
293 printf("This is free software: you are free to change and redistribute it.\n");
294 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
295 die();
298 static void version(void)
300 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
301 VERSION_STRING);
302 printf("Build: %s\n", BUILD_STRING);
303 printf("http://www.netsniff-ng.org\n\n");
304 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
305 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
306 printf("License: GNU GPL version 2\n");
307 printf("This is free software: you are free to change and redistribute it.\n");
308 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
309 die();
312 static void check_file_or_die(char *home, char *file, int maybeempty)
314 char path[PATH_MAX];
315 struct stat st;
317 memset(path, 0, sizeof(path));
318 slprintf(path, sizeof(path), "%s/%s", home, file);
320 if (stat(path, &st))
321 panic("No such file %s! Type --help for further information\n",
322 path);
324 if (!S_ISREG(st.st_mode))
325 panic("%s is not a regular file!\n", path);
327 if ((st.st_mode & ~S_IFREG) != (S_IRUSR | S_IWUSR))
328 panic("You have set too many permissions on %s (%o)!\n",
329 path, st.st_mode);
331 if (maybeempty == 0 && st.st_size == 0)
332 panic("%s is empty!\n", path);
335 static void check_config_exists_or_die(char *home)
337 if (!home)
338 panic("No home dir specified!\n");
340 check_file_or_die(home, FILE_CLIENTS, 1);
341 check_file_or_die(home, FILE_SERVERS, 1);
342 check_file_or_die(home, FILE_PRIVKEY, 0);
343 check_file_or_die(home, FILE_PUBKEY, 0);
344 check_file_or_die(home, FILE_USERNAM, 0);
347 static char *fetch_home_dir(void)
349 char *home = getenv("HOME");
350 if (!home)
351 panic("No HOME defined!\n");
352 return home;
355 static void write_username(char *home)
357 int fd, ret;
358 char path[PATH_MAX], *eof;
359 char user[512];
361 memset(path, 0, sizeof(path));
362 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
364 printf("Username: [%s] ", getenv("USER"));
365 fflush(stdout);
367 memset(user, 0, sizeof(user));
368 eof = fgets(user, sizeof(user), stdin);
369 user[sizeof(user) - 1] = 0;
370 user[strlen(user) - 1] = 0; /* omit last \n */
371 if (strlen(user) == 0)
372 strlcpy(user, getenv("USER"), sizeof(user));
374 fd = open_or_die_m(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
376 ret = write(fd, user, strlen(user));
377 if (ret != strlen(user))
378 panic("Could not write username!\n");
380 close(fd);
382 printf("Username written to %s!\n", path);
385 static void create_curvedir(char *home)
387 int ret;
388 char path[PATH_MAX];
390 memset(path, 0, sizeof(path));
391 slprintf(path, sizeof(path), "%s/%s", home, ".curvetun/");
393 errno = 0;
395 ret = mkdir(path, S_IRWXU);
396 if (ret < 0 && errno != EEXIST)
397 panic("Cannot create curvetun dir!\n");
399 printf("curvetun directory %s created!\n", path);
400 /* We also create empty files for clients and servers! */
402 memset(path, 0, sizeof(path));
403 slprintf(path, sizeof(path), "%s/%s", home, FILE_CLIENTS);
405 create_or_die(path, S_IRUSR | S_IWUSR);
407 printf("Empty client file written to %s!\n", path);
409 memset(path, 0, sizeof(path));
410 slprintf(path, sizeof(path), "%s/%s", home, FILE_SERVERS);
412 create_or_die(path, S_IRUSR | S_IWUSR);
414 printf("Empty server file written to %s!\n", path);
417 static void create_keypair(char *home)
419 int fd, err = 0;
420 ssize_t ret;
421 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
422 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
423 char path[PATH_MAX];
424 const char * errstr = NULL;
426 printf("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE);
428 fd = open_or_die(CURVETUN_ENTROPY_SOURCE, O_RDONLY);
430 ret = read_exact(fd, secretkey, sizeof(secretkey), 0);
431 if (ret != sizeof(secretkey)) {
432 err = EIO;
433 errstr = "Cannot read from "CURVETUN_ENTROPY_SOURCE"!\n";
434 goto out;
437 close(fd);
439 crypto_scalarmult_curve25519_base(publickey, secretkey);
441 memset(path, 0, sizeof(path));
442 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
444 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
445 if (fd < 0) {
446 err = EIO;
447 errstr = "Cannot open pubkey file!\n";
448 goto out;
451 ret = write(fd, publickey, sizeof(publickey));
452 if (ret != sizeof(publickey)) {
453 err = EIO;
454 errstr = "Cannot write public key!\n";
455 goto out;
458 close(fd);
460 printf("Public key written to %s!\n", path);
462 memset(path, 0, sizeof(path));
463 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
465 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
466 if (fd < 0) {
467 err = EIO;
468 errstr = "Cannot open privkey file!\n";
469 goto out;
472 ret = write(fd, secretkey, sizeof(secretkey));
473 if (ret != sizeof(secretkey)) {
474 err = EIO;
475 errstr = "Cannot write private key!\n";
476 goto out;
478 out:
479 close(fd);
481 xmemset(publickey, 0, sizeof(publickey));
482 xmemset(secretkey, 0, sizeof(secretkey));
484 if (err)
485 panic("%s: %s", errstr, strerror(errno));
486 else
487 printf("Private key written to %s!\n", path);
490 static void check_config_keypair_or_die(char *home)
492 int fd, err;
493 ssize_t ret;
494 const char * errstr = NULL;
495 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
496 unsigned char publicres[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
497 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
498 char path[PATH_MAX];
500 memset(path, 0, sizeof(path));
501 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
503 fd = open(path, O_RDONLY);
504 if (fd < 0) {
505 err = EIO;
506 errstr = "Cannot open privkey file!\n";
507 goto out;
510 ret = read(fd, secretkey, sizeof(secretkey));
511 if (ret != sizeof(secretkey)) {
512 err = EIO;
513 errstr = "Cannot read private key!\n";
514 goto out;
517 close(fd);
519 memset(path, 0, sizeof(path));
520 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
522 fd = open(path, O_RDONLY);
523 if (fd < 0) {
524 err = EIO;
525 errstr = "Cannot open pubkey file!\n";
526 goto out;
529 ret = read(fd, publickey, sizeof(publickey));
530 if (ret != sizeof(publickey)) {
531 err = EIO;
532 errstr = "Cannot read public key!\n";
533 goto out;
536 crypto_scalarmult_curve25519_base(publicres, secretkey);
538 err = crypto_verify_32(publicres, publickey);
539 if (err) {
540 err = EINVAL;
541 errstr = "WARNING: your keypair is corrupted!!! You need to "
542 "generate new keys!!!\n";
543 goto out;
545 out:
546 close(fd);
548 xmemset(publickey, 0, sizeof(publickey));
549 xmemset(publicres, 0, sizeof(publicres));
550 xmemset(secretkey, 0, sizeof(secretkey));
552 if (err)
553 panic("%s: %s\n", errstr, strerror(errno));
556 static int main_keygen(char *home)
558 create_curvedir(home);
559 write_username(home);
560 create_keypair(home);
561 check_config_keypair_or_die(home);
563 return 0;
566 static int main_export(char *home)
568 int fd, i;
569 ssize_t ret;
570 char path[PATH_MAX], tmp[64];
572 check_config_exists_or_die(home);
573 check_config_keypair_or_die(home);
575 printf("Your exported public information:\n\n");
577 memset(path, 0, sizeof(path));
578 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
580 fd = open_or_die(path, O_RDONLY);
582 while ((ret = read(fd, tmp, sizeof(tmp))) > 0) {
583 ret = write(STDOUT_FILENO, tmp, ret);
586 close(fd);
588 printf(";");
590 memset(path, 0, sizeof(path));
591 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
593 fd = open_or_die(path, O_RDONLY);
595 ret = read(fd, tmp, sizeof(tmp));
596 if (ret != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
597 panic("Cannot read public key!\n");
599 for (i = 0; i < ret; ++i)
600 if (i == ret - 1)
601 printf("%02x\n\n", (unsigned char) tmp[i]);
602 else
603 printf("%02x:", (unsigned char) tmp[i]);
605 close(fd);
606 fflush(stdout);
608 return 0;
611 static int main_dumpc(char *home)
613 check_config_exists_or_die(home);
614 check_config_keypair_or_die(home);
616 printf("Your clients:\n\n");
618 parse_userfile_and_generate_user_store_or_die(home);
620 dump_user_store();
622 destroy_user_store();
624 printf("\n");
625 die();
626 return 0;
629 static int main_dumps(char *home)
631 check_config_exists_or_die(home);
632 check_config_keypair_or_die(home);
634 printf("Your servers:\n\n");
636 parse_userfile_and_generate_serv_store_or_die(home);
638 dump_serv_store();
640 destroy_serv_store();
642 printf("\n");
643 die();
644 return 0;
647 static void daemonize(const char *lockfile)
649 char pidstr[8];
650 mode_t lperm = S_IRWXU | S_IRGRP | S_IXGRP; /* 0750 */
651 int lfp;
653 if (getppid() == 1)
654 return;
656 if (daemon(0, 0))
657 panic("Cannot daemonize: %s", strerror(errno));
659 umask(lperm);
660 if (lockfile) {
661 lfp = open(lockfile, O_RDWR | O_CREAT | O_EXCL,
662 S_IRUSR | S_IWUSR | S_IRGRP);
663 if (lfp < 0)
664 syslog_panic("Cannot create lockfile at %s! "
665 "curvetun server already running?\n",
666 lockfile);
668 slprintf(pidstr, sizeof(pidstr), "%u", getpid());
669 if (write(lfp, pidstr, strlen(pidstr)) <= 0)
670 syslog_panic("Could not write pid to pidfile %s",
671 lockfile);
673 close(lfp);
677 static int main_client(char *home, char *dev, char *alias, int daemon)
679 int ret, udp;
680 char *host, *port;
682 check_config_exists_or_die(home);
683 check_config_keypair_or_die(home);
685 parse_userfile_and_generate_serv_store_or_die(home);
687 get_serv_store_entry_by_alias(alias, alias ? strlen(alias) + 1 : 0,
688 &host, &port, &udp);
689 if (!host || !port || udp < 0)
690 panic("Did not find alias/entry in configuration!\n");
692 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
693 alias ? : "default", host, port, udp ? "udp" : "tcp");
694 if (daemon)
695 daemonize(NULL);
697 ret = client_main(home, dev, host, port, udp);
699 destroy_serv_store();
701 return ret;
704 static int main_server(char *home, char *dev, char *port, int udp,
705 int ipv4, int daemon, int log)
707 int ret;
709 check_config_exists_or_die(home);
710 check_config_keypair_or_die(home);
712 if (daemon)
713 daemonize(LOCKFILE);
715 ret = server_main(home, dev, port, udp, ipv4, log);
717 unlink(LOCKFILE);
719 return ret;
722 int main(int argc, char **argv)
724 int ret = 0, c, opt_index, udp = 0, ipv4 = -1, daemon = 1, log = 1;
725 char *port = NULL, *stun = NULL, *dev = NULL, *home = NULL, *alias = NULL;
726 enum working_mode wmode = MODE_UNKNOW;
728 if (getuid() != geteuid())
729 seteuid(getuid());
731 home = fetch_home_dir();
733 while ((c = getopt_long(argc, argv, short_options, long_options,
734 &opt_index)) != EOF) {
735 switch (c) {
736 case 'h':
737 help();
738 break;
739 case 'v':
740 version();
741 break;
742 case 'D':
743 daemon = 0;
744 break;
745 case 'N':
746 log = 0;
747 break;
748 case 'C':
749 wmode = MODE_DUMPC;
750 break;
751 case 'S':
752 wmode = MODE_DUMPS;
753 break;
754 case 'c':
755 wmode = MODE_CLIENT;
756 if (optarg) {
757 if (*optarg == '=')
758 optarg++;
759 alias = xstrdup(optarg);
761 break;
762 case 'd':
763 dev = xstrdup(optarg);
764 break;
765 case 'k':
766 wmode = MODE_KEYGEN;
767 break;
768 case '4':
769 ipv4 = 1;
770 break;
771 case '6':
772 ipv4 = 0;
773 break;
774 case 'x':
775 wmode = MODE_EXPORT;
776 break;
777 case 's':
778 wmode = MODE_SERVER;
779 break;
780 case 'u':
781 udp = 1;
782 break;
783 case 't':
784 stun = xstrdup(optarg);
785 break;
786 case 'p':
787 port = xstrdup(optarg);
788 break;
789 case '?':
790 switch (optopt) {
791 case 't':
792 case 'd':
793 case 'u':
794 case 'p':
795 panic("Option -%c requires an argument!\n",
796 optopt);
797 default:
798 if (isprint(optopt))
799 whine("Unknown option character "
800 "`0x%X\'!\n", optopt);
801 die();
803 default:
804 break;
808 if (argc < 2)
809 help();
811 register_signal(SIGINT, signal_handler);
812 register_signal(SIGHUP, signal_handler);
813 register_signal(SIGTERM, signal_handler);
814 register_signal(SIGPIPE, signal_handler);
816 header();
818 curve25519_selftest();
820 switch (wmode) {
821 case MODE_KEYGEN:
822 ret = main_keygen(home);
823 break;
824 case MODE_EXPORT:
825 ret = main_export(home);
826 break;
827 case MODE_DUMPC:
828 ret = main_dumpc(home);
829 break;
830 case MODE_DUMPS:
831 ret = main_dumps(home);
832 break;
833 case MODE_CLIENT:
834 ret = main_client(home, dev, alias, daemon);
835 break;
836 case MODE_SERVER:
837 if (!port)
838 panic("No port specified!\n");
839 if (stun)
840 print_stun_probe(stun, 3478, strtoul(port, NULL, 10));
841 ret = main_server(home, dev, port, udp, ipv4, daemon, log);
842 break;
843 default:
844 die();
847 if (dev)
848 xfree(dev);
849 if (stun)
850 xfree(stun);
851 if (port)
852 xfree(port);
853 if (alias)
854 xfree(alias);
856 return ret;