Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4337251218 | ||
|
|
baca343fdf | ||
|
|
c20a2a5a13 | ||
|
|
7fc368cf3c | ||
|
|
25b62bf4c6 | ||
|
|
47432ecafa | ||
|
|
e4f2a92c5b | ||
|
|
89d2edb61b | ||
|
|
310e499234 | ||
|
|
9ff87109f9 | ||
|
|
bfcf38f380 |
@@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ([2.65])
|
AC_PREREQ([2.65])
|
||||||
AC_INIT([glorytun], [0.0.2], [https://github.com/angt/glorytun/issues],
|
AC_INIT([glorytun], [0.0.3], [https://github.com/angt/glorytun/issues],
|
||||||
[glorytun], [https://github.com/angt/glorytun])
|
[glorytun], [https://github.com/angt/glorytun])
|
||||||
AC_CONFIG_SRCDIR([src/common.h])
|
AC_CONFIG_SRCDIR([src/common.h])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
|||||||
13
src/common.c
13
src/common.c
@@ -3,6 +3,19 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int gt_print (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int ret = vfprintf(stdout, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ret<0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void gt_log (const char *fmt, ...)
|
void gt_log (const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ struct buffer {
|
|||||||
uint8_t *end;
|
uint8_t *end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int gt_print (const char *, ...) _printf_(1,2);
|
||||||
void gt_log (const char *, ...) _printf_(1,2);
|
void gt_log (const char *, ...) _printf_(1,2);
|
||||||
void gt_fatal (const char *, ...) _printf_(1,2) _noreturn_;
|
void gt_fatal (const char *, ...) _printf_(1,2) _noreturn_;
|
||||||
void gt_na (const char *);
|
void gt_na (const char *);
|
||||||
|
|||||||
193
src/main.c
193
src/main.c
@@ -1,8 +1,8 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -67,51 +67,54 @@ static void fd_set_nonblock (int fd)
|
|||||||
perror("fcntl O_NONBLOCK");
|
perror("fcntl O_NONBLOCK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sk_set_nodelay (int fd)
|
static void sk_set (int fd, const char *name, const void *val, socklen_t len)
|
||||||
{
|
{
|
||||||
int val = 1;
|
if (!name || !val || len<=0)
|
||||||
|
|
||||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY , &val, sizeof(val))==-1)
|
|
||||||
perror("setsockopt TCP_NODELAY");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sk_set_reuseaddr (int fd)
|
|
||||||
{
|
|
||||||
int val = 1;
|
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))==-1)
|
|
||||||
perror("setsockopt SO_REUSEADDR");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sk_set_keepalive (int fd)
|
|
||||||
{
|
|
||||||
int val = 1;
|
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val))==-1)
|
|
||||||
perror("setsockopt SO_KEEPALIVE");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TCP_CONGESTION
|
|
||||||
static void sk_set_congestion (int fd, const char *name)
|
|
||||||
{
|
|
||||||
size_t len = str_len(name);
|
|
||||||
|
|
||||||
if (!len)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, name, len+1)==-1)
|
struct {
|
||||||
perror("setsockopt TCP_CONGESTION");
|
const char *name;
|
||||||
}
|
const int level;
|
||||||
#else
|
const int option;
|
||||||
static void sk_set_congestion (_unused_ int fd, _unused_ const char *name)
|
} ops[] = {
|
||||||
{
|
{ "TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY },
|
||||||
gt_na("TCP_CONGESTION");
|
{ "SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR },
|
||||||
}
|
{ "SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE },
|
||||||
|
#ifdef TCP_KEEPCNT
|
||||||
|
{ "TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TCP_KEEPIDLE
|
||||||
|
{ "TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE },
|
||||||
|
#endif
|
||||||
|
#ifdef TCP_KEEPINTVL
|
||||||
|
{ "TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL },
|
||||||
|
#endif
|
||||||
|
#ifdef TCP_CONGESTION
|
||||||
|
{ "TCP_CONGESTION", IPPROTO_TCP, TCP_CONGESTION },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int k=0; k<COUNT(ops); k++) {
|
||||||
|
if (str_cmp(ops[k].name, name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (setsockopt(fd, ops[k].level, ops[k].option, val, len)==-1)
|
||||||
|
gt_log("couldn't set socket option `%s'\n", name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gt_na(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sk_set_int (int fd, const char *name, int val)
|
||||||
|
{
|
||||||
|
return sk_set(fd, name, &val, sizeof(val));
|
||||||
|
}
|
||||||
|
|
||||||
static int sk_listen (int fd, struct addrinfo *ai)
|
static int sk_listen (int fd, struct addrinfo *ai)
|
||||||
{
|
{
|
||||||
sk_set_reuseaddr(fd);
|
sk_set_int(fd, "SO_REUSEADDR", 1);
|
||||||
|
|
||||||
int ret = bind(fd, ai->ai_addr, ai->ai_addrlen);
|
int ret = bind(fd, ai->ai_addr, ai->ai_addrlen);
|
||||||
|
|
||||||
@@ -471,9 +474,13 @@ static int gt_setup_secretkey (struct crypto_ctx *ctx, char *keyfile)
|
|||||||
if (!keyfile)
|
if (!keyfile)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int fd = open(keyfile, O_RDONLY|O_CLOEXEC);
|
int fd;
|
||||||
|
|
||||||
if (fd<0) {
|
do {
|
||||||
|
fd = open(keyfile, O_RDONLY|O_CLOEXEC);
|
||||||
|
} while (fd==-1 && errno==EINTR);
|
||||||
|
|
||||||
|
if (fd==-1) {
|
||||||
perror("open keyfile");
|
perror("open keyfile");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -580,9 +587,12 @@ int main (int argc, char **argv)
|
|||||||
char *dev = PACKAGE_NAME;
|
char *dev = PACKAGE_NAME;
|
||||||
char *keyfile = NULL;
|
char *keyfile = NULL;
|
||||||
char *congestion = NULL;
|
char *congestion = NULL;
|
||||||
|
long buffer_size = GT_BUFFER_SIZE;
|
||||||
int delay = 0;
|
int delay = 0;
|
||||||
int multiqueue = 0;
|
int multiqueue = 0;
|
||||||
int keepalive = 0;
|
long ka_count = -1;
|
||||||
|
long ka_idle = -1;
|
||||||
|
long ka_interval = -1;
|
||||||
int version = 0;
|
int version = 0;
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
|
|
||||||
@@ -593,18 +603,26 @@ int main (int argc, char **argv)
|
|||||||
} tcpinfo = {0};
|
} tcpinfo = {0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct option ka_opts[] = {
|
||||||
|
{ "count", &ka_count, option_long },
|
||||||
|
{ "idle", &ka_idle, option_long },
|
||||||
|
{ "interval", &ka_interval, option_long },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
struct option opts[] = {
|
struct option opts[] = {
|
||||||
{ "listener", &listener, option_flag },
|
{ "listener", &listener, option_flag },
|
||||||
{ "host", &host, option_str },
|
{ "host", &host, option_str },
|
||||||
{ "port", &port, option_str },
|
{ "port", &port, option_str },
|
||||||
{ "dev", &dev, option_str },
|
{ "dev", &dev, option_str },
|
||||||
{ "keyfile", &keyfile, option_str },
|
{ "keyfile", &keyfile, option_str },
|
||||||
{ "congestion", &congestion, option_str },
|
{ "congestion", &congestion, option_str },
|
||||||
{ "delay", &delay, option_flag },
|
{ "delay", &delay, option_flag },
|
||||||
{ "multiqueue", &multiqueue, option_flag },
|
{ "multiqueue", &multiqueue, option_flag },
|
||||||
{ "keepalive", &keepalive, option_flag },
|
{ "keepalive", ka_opts, option_option },
|
||||||
{ "debug", &debug, option_flag },
|
{ "buffer-size", &buffer_size, option_long },
|
||||||
{ "version", &version, option_flag },
|
{ "debug", &debug, option_flag },
|
||||||
|
{ "version", &version, option_flag },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -612,10 +630,17 @@ int main (int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (version) {
|
if (version) {
|
||||||
printf(PACKAGE_STRING"\n");
|
gt_print(PACKAGE_STRING"\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int keepalive = option_is_set(opts, "keepalive");
|
||||||
|
|
||||||
|
if (buffer_size < 2048) {
|
||||||
|
buffer_size = 2048;
|
||||||
|
gt_log("buffer size must be greater than 2048!\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (sodium_init()==-1) {
|
if (sodium_init()==-1) {
|
||||||
gt_log("libsodium initialization has failed!\n");
|
gt_log("libsodium initialization has failed!\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -646,8 +671,8 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
fd_set_nonblock(tun.fd);
|
fd_set_nonblock(tun.fd);
|
||||||
|
|
||||||
buffer_setup(&sock.write.buf, NULL, GT_BUFFER_SIZE);
|
buffer_setup(&sock.write.buf, NULL, buffer_size);
|
||||||
buffer_setup(&sock.read.buf, NULL, GT_BUFFER_SIZE);
|
buffer_setup(&sock.read.buf, NULL, buffer_size);
|
||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
@@ -658,7 +683,7 @@ int main (int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (!gt_close) {
|
||||||
sock.fd = listener?sk_accept(fd):sk_create(ai, sk_connect);
|
sock.fd = listener?sk_accept(fd):sk_create(ai, sk_connect);
|
||||||
|
|
||||||
if (sock.fd==-1) {
|
if (sock.fd==-1) {
|
||||||
@@ -673,15 +698,23 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
gt_log("%s: connected\n", sockname);
|
gt_log("%s: connected\n", sockname);
|
||||||
|
|
||||||
if (!delay)
|
|
||||||
sk_set_nodelay(sock.fd);
|
|
||||||
|
|
||||||
fd_set_nonblock(sock.fd);
|
fd_set_nonblock(sock.fd);
|
||||||
|
|
||||||
if (keepalive)
|
sk_set_int(sock.fd, "TCP_NODELAY", !delay);
|
||||||
sk_set_keepalive(sock.fd);
|
sk_set_int(sock.fd, "SO_KEEPALIVE", keepalive);
|
||||||
|
|
||||||
sk_set_congestion(sock.fd, congestion);
|
if (keepalive) {
|
||||||
|
if (ka_count>=0 && ka_count<=INT_MAX)
|
||||||
|
sk_set_int(sock.fd, "TCP_KEEPCNT", ka_count);
|
||||||
|
|
||||||
|
if (ka_idle>=0 && ka_idle<=INT_MAX)
|
||||||
|
sk_set_int(sock.fd, "TCP_KEEPIDLE", ka_idle);
|
||||||
|
|
||||||
|
if (ka_interval>=0 && ka_interval<=INT_MAX)
|
||||||
|
sk_set_int(sock.fd, "TCP_KEEPINTVL", ka_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_set(sock.fd, "TCP_CONGESTION", congestion, str_len(congestion));
|
||||||
|
|
||||||
switch (gt_setup_crypto(&ctx, sock.fd, listener)) {
|
switch (gt_setup_crypto(&ctx, sock.fd, listener)) {
|
||||||
case -2: gt_log("%s: key exchange could not be verified!\n", sockname);
|
case -2: gt_log("%s: key exchange could not be verified!\n", sockname);
|
||||||
@@ -703,14 +736,16 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
int stop_loop = 0;
|
int stop_loop = 0;
|
||||||
|
|
||||||
|
buffer_format(&sock.write.buf);
|
||||||
|
buffer_format(&sock.read.buf);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (gt_close)
|
if (gt_close)
|
||||||
stop_loop = 1;
|
stop_loop = 1;
|
||||||
|
|
||||||
if (stop_loop) {
|
if (stop_loop) {
|
||||||
if (((stop_loop>>1)==3) &&
|
if (((stop_loop&(1<<2)) || !buffer_read_size(&sock.write.buf)) &&
|
||||||
(buffer_read_size(&sock.write.buf)==0) &&
|
((stop_loop&(1<<1)) || !buffer_read_size(&sock.read.buf)))
|
||||||
(buffer_read_size(&sock.read.buf)==0))
|
|
||||||
goto restart;
|
goto restart;
|
||||||
FD_CLR(tun.fd, &rfds);
|
FD_CLR(tun.fd, &rfds);
|
||||||
} else {
|
} else {
|
||||||
@@ -719,7 +754,9 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
FD_SET(sock.fd, &rfds);
|
FD_SET(sock.fd, &rfds);
|
||||||
|
|
||||||
if (select(sock.fd+1, &rfds, &wfds, NULL, NULL)==-1 && errno!=EINTR) {
|
if (select(sock.fd+1, &rfds, &wfds, NULL, NULL)==-1) {
|
||||||
|
if (errno==EINTR)
|
||||||
|
continue;
|
||||||
perror("select");
|
perror("select");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -773,29 +810,27 @@ int main (int argc, char **argv)
|
|||||||
FD_CLR(sock.fd, &wfds);
|
FD_CLR(sock.fd, &wfds);
|
||||||
|
|
||||||
if (buffer_read_size(&sock.write.buf)) {
|
if (buffer_read_size(&sock.write.buf)) {
|
||||||
ssize_t r = fd_write(sock.fd, sock.write.buf.read, buffer_read_size(&sock.write.buf));
|
ssize_t r = fd_write(sock.fd, sock.write.buf.read,
|
||||||
|
buffer_read_size(&sock.write.buf));
|
||||||
|
|
||||||
if (r==-1)
|
if (r==-1)
|
||||||
FD_SET(sock.fd, &wfds);
|
FD_SET(sock.fd, &wfds);
|
||||||
|
|
||||||
if (!r) {
|
if (!r)
|
||||||
stop_loop |= (1<<2);
|
stop_loop |= (1<<2);
|
||||||
buffer_format(&sock.write.buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r>0)
|
if (r>0)
|
||||||
sock.write.buf.read += r;
|
sock.write.buf.read += r;
|
||||||
} else {
|
} else {
|
||||||
if (stop_loop) {
|
if (stop_loop)
|
||||||
stop_loop |= (1<<2);
|
|
||||||
shutdown(sock.fd, SHUT_WR);
|
shutdown(sock.fd, SHUT_WR);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_shift(&sock.read.buf);
|
buffer_shift(&sock.read.buf);
|
||||||
|
|
||||||
if (FD_ISSET(sock.fd, &rfds)) {
|
if (FD_ISSET(sock.fd, &rfds)) {
|
||||||
ssize_t r = fd_read(sock.fd, sock.read.buf.write, buffer_write_size(&sock.read.buf));
|
ssize_t r = fd_read(sock.fd, sock.read.buf.write,
|
||||||
|
buffer_write_size(&sock.read.buf));
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
stop_loop |= (1<<1);
|
stop_loop |= (1<<1);
|
||||||
@@ -815,11 +850,8 @@ int main (int argc, char **argv)
|
|||||||
if (!ip_size)
|
if (!ip_size)
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
if (ip_size<0 || (size_t)ip_size+16>size) {
|
if (ip_size<0 || (size_t)ip_size+16>size)
|
||||||
if (stop_loop&(1<<1))
|
|
||||||
buffer_format(&sock.read.buf);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (decrypt_packet(&ctx, tunw.buf, ip_size, &sock.read.buf)) {
|
if (decrypt_packet(&ctx, tunw.buf, ip_size, &sock.read.buf)) {
|
||||||
gt_log("%s: message could not be verified!\n", sockname);
|
gt_log("%s: message could not be verified!\n", sockname);
|
||||||
@@ -855,9 +887,6 @@ int main (int argc, char **argv)
|
|||||||
close(sock.fd);
|
close(sock.fd);
|
||||||
sock.fd = -1;
|
sock.fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gt_close)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
|
|||||||
63
src/option.c
63
src/option.c
@@ -16,7 +16,7 @@ int option_flag (void *data, _unused_ int argc, _unused_ char **argv)
|
|||||||
int option_str (void *data, int argc, char **argv)
|
int option_str (void *data, int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc<2 || !argv[1]) {
|
if (argc<2 || !argv[1]) {
|
||||||
printf("option `%s' need a string argument\n", argv[0]);
|
gt_print("option `%s' need a string argument\n", argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ int option_str (void *data, int argc, char **argv)
|
|||||||
int option_long (void *data, int argc, char **argv)
|
int option_long (void *data, int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc<2 || !argv[1]) {
|
if (argc<2 || !argv[1]) {
|
||||||
printf("option `%s' need an integer argument\n", argv[0]);
|
gt_print("option `%s' need an integer argument\n", argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ int option_long (void *data, int argc, char **argv)
|
|||||||
long val = strtol(argv[1], &end, 0);
|
long val = strtol(argv[1], &end, 0);
|
||||||
|
|
||||||
if (errno || argv[1]==end) {
|
if (errno || argv[1]==end) {
|
||||||
printf("argument `%s' is not a valid integer\n", argv[1]);
|
gt_print("argument `%s' is not a valid integer\n", argv[1]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +46,16 @@ int option_long (void *data, int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int option_is_set (struct option *opts, const char *name)
|
||||||
|
{
|
||||||
|
for (int k=0; opts[k].name; k++) {
|
||||||
|
if (!str_cmp(opts[k].name, name))
|
||||||
|
return opts[k].set;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int option_option (void *data, int argc, char **argv)
|
int option_option (void *data, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct option *opts = (struct option *)data;
|
struct option *opts = (struct option *)data;
|
||||||
@@ -61,7 +71,7 @@ int option_option (void *data, int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (opts[k].set) {
|
if (opts[k].set) {
|
||||||
printf("option `%s' is already set\n", opts[k].name);
|
gt_print("option `%s' is already set\n", opts[k].name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,31 +94,30 @@ int option_option (void *data, int argc, char **argv)
|
|||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void option_usage (struct option *opts, char *name)
|
static int option_usage (struct option *opts, int slen)
|
||||||
{
|
{
|
||||||
char *usage = "usage: ";
|
int len = slen;
|
||||||
size_t slen = str_len(usage)+str_len(name);
|
|
||||||
size_t len = slen;
|
|
||||||
|
|
||||||
printf("%s%s", usage, name);
|
|
||||||
|
|
||||||
if (slen>40)
|
|
||||||
slen = 12;
|
|
||||||
|
|
||||||
for (int k=0; opts[k].name; k++) {
|
for (int k=0; opts[k].name; k++) {
|
||||||
char *arg = (opts[k].call==option_flag)?"":" ARG";
|
if (len>60) {
|
||||||
size_t inc = str_len(opts[k].name)+str_len(arg)+3;
|
gt_print("\n%*s", (int)slen, "");
|
||||||
|
|
||||||
if (len+inc>72) {
|
|
||||||
printf("\n%*s", (int)slen, "");
|
|
||||||
len = slen;
|
len = slen;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" [%s%s]", opts[k].name, arg);
|
len += gt_print(" [%s", opts[k].name);
|
||||||
len += inc;
|
|
||||||
|
if (opts[k].call!=option_flag) {
|
||||||
|
if (opts[k].call==option_option) {
|
||||||
|
len += option_usage((struct option *)opts[k].data, len);
|
||||||
|
} else {
|
||||||
|
len += gt_print(" ARG");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len += gt_print("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int option (struct option *opts, int argc, char **argv)
|
int option (struct option *opts, int argc, char **argv)
|
||||||
@@ -121,8 +130,16 @@ int option (struct option *opts, int argc, char **argv)
|
|||||||
if (ret<0 || ret+1>=argc)
|
if (ret<0 || ret+1>=argc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
printf("option `%s' is unknown\n", argv[ret+1]);
|
gt_print("option `%s' is unknown\n", argv[ret+1]);
|
||||||
option_usage(opts, argv[0]);
|
|
||||||
|
int slen = gt_print("usage: %s", argv[0]);
|
||||||
|
|
||||||
|
if (slen>40)
|
||||||
|
slen = 12;
|
||||||
|
|
||||||
|
option_usage(opts, slen);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ int option_str (void *, int, char **);
|
|||||||
int option_long (void *, int, char **);
|
int option_long (void *, int, char **);
|
||||||
int option_option (void *, int, char **);
|
int option_option (void *, int, char **);
|
||||||
|
|
||||||
int option (struct option *, int, char **);
|
int option_is_set (struct option *, const char *);
|
||||||
|
int option (struct option *, int, char **);
|
||||||
|
|||||||
36
src/tun.c
36
src/tun.c
@@ -56,42 +56,42 @@ int tun_create (char *name, int multiqueue)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("tun name: %s\n", ifr.ifr_name);
|
gt_print("tun name: %s\n", ifr.ifr_name);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
int tun_create (_unused_ char *name, _unused_ int mq)
|
int tun_create (_unused_ char *name, _unused_ int mq)
|
||||||
{
|
{
|
||||||
struct ctl_info ctlInfo;
|
|
||||||
struct sockaddr_ctl sc;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
for (unsigned dev_id = 0U; dev_id<32U; dev_id++) {
|
for (unsigned dev_id = 0U; dev_id<32U; dev_id++) {
|
||||||
byte_set(&ctlInfo, 0, sizeof(ctlInfo));
|
struct ctl_info ci;
|
||||||
str_cpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name));
|
byte_set(&ci, 0, sizeof(ci));
|
||||||
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
str_cpy(ci.ctl_name, UTUN_CONTROL_NAME, sizeof(ci.ctl_name)-1);
|
||||||
|
|
||||||
|
int fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||||
|
|
||||||
if (fd==-1)
|
if (fd==-1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (ioctl(fd, CTLIOCGINFO, &ctlInfo)==-1) {
|
if (ioctl(fd, CTLIOCGINFO, &ci)==-1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.sc_id = ctlInfo.ctl_id;
|
struct sockaddr_ctl sc = {
|
||||||
sc.sc_len = sizeof(sc);
|
.sc_id = ci.ctl_id,
|
||||||
sc.sc_family = AF_SYSTEM;
|
.sc_len = sizeof(sc),
|
||||||
sc.ss_sysaddr = AF_SYS_CONTROL;
|
.sc_family = AF_SYSTEM,
|
||||||
sc.sc_unit = dev_id+1;
|
.ss_sysaddr = AF_SYS_CONTROL,
|
||||||
|
.sc_unit = dev_id+1,
|
||||||
|
};
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *) &sc, sizeof(sc))==-1) {
|
if (connect(fd, (struct sockaddr *)&sc, sizeof(sc))==-1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("tun name: /dev/utun%u\n", dev_id);
|
gt_print("tun name: /dev/utun%u\n", dev_id);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -104,12 +104,12 @@ int tun_create (_unused_ char *name, _unused_ int mq)
|
|||||||
for (unsigned dev_id = 0U; dev_id<32U; dev_id++) {
|
for (unsigned dev_id = 0U; dev_id<32U; dev_id++) {
|
||||||
char dev_path[11U];
|
char dev_path[11U];
|
||||||
|
|
||||||
snprintf(dev_path, sizeof(dev_path), "/dev/tun%u", dev_id);
|
sngt_print(dev_path, sizeof(dev_path), "/dev/tun%u", dev_id);
|
||||||
|
|
||||||
int fd = open(dev_path, O_RDWR);
|
int fd = open(dev_path, O_RDWR);
|
||||||
|
|
||||||
if (fd!=-1) {
|
if (fd!=-1) {
|
||||||
printf("tun name: /dev/tun%u\n", dev_id);
|
gt_print("tun name: /dev/tun%u\n", dev_id);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user