Compare commits

..

22 Commits

Author SHA1 Message Date
Adrien Gallouët
fd7ddf7814 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-24 09:57:21 +00:00
Adrien Gallouët
7e7b52f9fd Try to limit pkt drops
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-19 14:00:00 +00:00
Adrien Gallouët
97784c43ac Revert "Try to use submodules"
This reverts commit bccc9945f4.
2019-09-17 17:07:45 +00:00
Adrien Gallouët
4b4c080cc4 Use aegis256
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-17 16:48:42 +00:00
Adrien Gallouët
43e1dfe86f Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-16 15:20:58 +00:00
Adrien Gallouët
ed1cf51af2 Don't use -j alone for portability
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-16 15:20:41 +00:00
Adrien Gallouët
264f26286d Move static build files in .static
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-11 21:08:59 +00:00
Adrien Gallouët
7c17e16fea Block on sendmsg and revert 4a68866
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-09 16:25:35 +00:00
Adrien Gallouët
38d31c0637 Upload artifact
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-04 10:33:01 +00:00
Adrien Gallouët
bccc9945f4 Try to use submodules
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-04 09:59:59 +00:00
Adrien Gallouët
9c9f679497 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:56:50 +00:00
Adrien Gallouët
9177778d0f Add .github/workflows/ccpp.yml
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:27:57 +00:00
Adrien Gallouët
6853b59dc3 Add sodium.sh
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:27:57 +00:00
Adrien Gallouët
d451bc75b0 Doll up
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-23 13:17:59 +00:00
Adrien Gallouët
1f82b15373 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-22 13:08:17 +00:00
Adrien Gallouët
56b5a41633 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
004380827f A more friendly command path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
a7f57de42a Remove useless tests in ctl
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
2f3f9e7e86 Update desc of show
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-20 08:53:47 +00:00
Adrien Gallouët
0528adcfe2 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-20 08:19:55 +00:00
Adrien Gallouët
67ea65b1a8 Don't show all tunnels
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-19 22:40:31 +00:00
Adrien Gallouët
ed82531fc0 Always unlink ctl socket
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-19 21:51:28 +00:00
17 changed files with 258 additions and 164 deletions

24
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Build
on: [push]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- name: Build glorytun
run: |
git submodule update --init --recursive
./sodium.sh
make prefix=. install
- uses: actions/upload-artifact@v1
with:
name: bin
path: ./bin

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ configure
build-aux
.deps
.dirstamp
.static
glorytun
build*
VERSION

View File

@@ -11,7 +11,10 @@ CFLAGS ?= -std=c11 -O2 -Wall -fstack-protector-strong
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
FLAGS += -DPACKAGE_NAME=\"$(NAME)\" -DPACKAGE_VERSION=\"$(VERSION)\"
SRC := argz/argz.c mud/mud.c $(wildcard src/*.c)
FLAGS += -I.static/$(CROSS)/libsodium-stable/src/libsodium/include
FLAGS += -L.static/$(CROSS)/libsodium-stable/src/libsodium/.libs
SRC := argz/argz.c mud/mud.c mud/aegis256/aegis256.c $(wildcard src/*.c)
.PHONY: $(NAME)
$(NAME):

View File

@@ -9,6 +9,8 @@ glorytun_SOURCES = \
argz/argz.h \
mud/mud.c \
mud/mud.h \
mud/aegis256/aegis256.c \
mud/aegis256/aegis256.h \
src/bench.c \
src/bind.c \
src/common.c \

View File

@@ -20,8 +20,8 @@ The key features of Glorytun come directly from mud:
The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure
your communications without impacting performance.
Glorytun uses AES only if AES-NI is available otherwise ChaCha20 is used.
If you are not cpu bounded, you can force the use of ChaCha20 for higher security.
Glorytun uses AEGIS-256 only if AES-NI is available otherwise ChaCha20Poly1305 is used.
If you are not cpu bounded, you can force the use of ChaCha20Poly1305 for higher security.
All messages are encrypted, authenticated and marked with a timestamp.
Perfect forward secrecy is also implemented with ECDH over Curve25519.
@@ -75,7 +75,7 @@ Just run `glorytun` with no arguments to view the list of available commands:
$ glorytun
available commands:
show show all running tunnels
show show tunnel info
bench start a crypto bench
bind start a new tunnel
set change tunnel properties

2
argz

Submodule argz updated: 31f3c44d9b...47ad9daf43

View File

@@ -23,6 +23,7 @@ executable('glorytun', install: true,
sources: [
'argz/argz.c',
'mud/mud.c',
'mud/aegis256/aegis256.c',
'src/bench.c',
'src/bind.c',
'src/common.c',

2
mud

Submodule mud updated: a91f8e2971...4d14689ff1

29
sodium.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh
mkdir -p .static
cd .static || exit 1
file=LATEST.tar.gz
url=https://download.libsodium.org/libsodium/releases
dir="$PWD"
[ -f "$file" ] || wget -q "$url/$file" -O "$file"
[ -f "$file" ] || curl -SsfLO "$url/$file"
[ -f "$file" ] || {
echo "Couldn't download $url/$file"
exit 1
}
if [ "$1" ]; then
mkdir -p "$1"
cd "$1" || exit 1
fi
rm -rf libsodium-stable
tar zxf "$dir/$file"
cd libsodium-stable || exit 1
NPROC=$(sysctl -n hw.ncpu || nproc) 2>/dev/null
./configure ${1+--host=$1} --enable-minimal --disable-dependency-tracking --enable-static --disable-shared
make "-j$((NPROC+1))"

View File

@@ -13,9 +13,14 @@
#endif
#include "../argz/argz.h"
#include "../mud/aegis256/aegis256.h"
#define STR_S(X) (((X) > 1) ? "s" : "")
#define NPUBBYTES 32
#define KEYBYTES 32
#define ABYTES 16
static unsigned long long
gt_now(void)
{
@@ -68,7 +73,7 @@ gt_bench(int argc, char **argv)
int aes = argz_is_set(bench_argz, "aes");
int chacha = argz_is_set(bench_argz, "chacha");
if (!crypto_aead_aes256gcm_is_available()) {
if (!aegis256_is_available()) {
if (aes) {
gt_log("aes is not available on your platform\n");
return 1;
@@ -76,22 +81,22 @@ gt_bench(int argc, char **argv)
chacha = 1;
}
unsigned char *buf = calloc(1, bufsize + crypto_aead_aes256gcm_ABYTES);
unsigned char *buf = calloc(1, bufsize + ABYTES);
if (!buf) {
perror("calloc");
return 1;
}
unsigned char npub[crypto_aead_aes256gcm_NPUBBYTES];
unsigned char key[crypto_aead_aes256gcm_KEYBYTES];
unsigned char npub[NPUBBYTES];
unsigned char key[KEYBYTES];
randombytes_buf(npub, sizeof(npub));
randombytes_buf(key, sizeof(key));
if (term) {
printf("\n");
printf(" %-10s %s\n", "bench", chacha ? "chacha20poly1305" : "aes256gcm");
printf(" %-10s %s\n", "bench", chacha ? "chacha20poly1305" : "aegis256");
printf(" %-10s %s\n", "libsodium", sodium_version_string());
printf("\n");
printf(" %-10s 2^(-%lu)\n", "precision", precision);
@@ -112,11 +117,6 @@ gt_bench(int argc, char **argv)
double mbps_dlt = INFINITY;
while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) {
crypto_aead_aes256gcm_state ctx;
if (!chacha)
crypto_aead_aes256gcm_beforenm(&ctx, key);
unsigned long long now = gt_now();
double mbps_old = mbps;
size_t bytes = 0;
@@ -129,9 +129,8 @@ gt_bench(int argc, char **argv)
crypto_aead_chacha20poly1305_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub, key);
} else {
crypto_aead_aes256gcm_encrypt_afternm(
buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub,
(const crypto_aead_aes256gcm_state *)&ctx);
aegis256_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, npub, key);
}
bytes += 1ULL << i;
}

View File

@@ -193,8 +193,8 @@ gt_bind(int argc, char **argv)
return 1;
}
if (fd_set_nonblock(tun_fd) ||
fd_set_nonblock(mud_fd) ||
if (//fd_set_nonblock(tun_fd) ||
//fd_set_nonblock(mud_fd) ||
fd_set_nonblock(ctl_fd)) {
gt_log("couldn't setup non-blocking fds\n");
return 1;
@@ -204,31 +204,60 @@ gt_bind(int argc, char **argv)
gt_log("running on device %s as pid %li\n", tun_name, pid);
fd_set rfds;
fd_set rfds, wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
const int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd));
int tun_can_read = 0;
int tun_can_write = 0;
int mud_can_read = 0;
int mud_can_write = 0;
int last_fd = MAX(tun_fd, mud_fd);
last_fd = 1 + MAX(last_fd, ctl_fd);
unsigned char buf[4096];
while (!gt_quit) {
long send_wait = mud_send_wait(mud);
if (tun_can_write) {
FD_CLR(tun_fd, &wfds);
} else {
FD_SET(tun_fd, &wfds);
}
if (send_wait) {
if (mud_can_write) {
FD_CLR(mud_fd, &wfds);
} else {
FD_SET(mud_fd, &wfds);
}
if (tun_can_read) {
FD_CLR(tun_fd, &rfds);
} else {
FD_SET(tun_fd, &rfds);
}
FD_SET(mud_fd, &rfds);
if (mud_can_read) {
FD_CLR(mud_fd, &rfds);
} else {
FD_SET(mud_fd, &rfds);
}
FD_SET(ctl_fd, &rfds);
struct timeval tv = {
.tv_sec = 0,
.tv_usec = send_wait,
.tv_usec = 100000,
};
const int ret = select(last_fd, &rfds, NULL, NULL, send_wait > 0 ? &tv : NULL);
if (mud_can_read && tun_can_write) {
tv.tv_usec = 0;
} else if (tun_can_read && mud_can_write) {
long send_wait = mud_send_wait(mud);
if (send_wait >= 0)
tv.tv_usec = send_wait * 1000;
}
const int ret = select(last_fd, &rfds, &wfds, NULL, &tv);
if (ret == -1) {
if (errno == EBADF) {
@@ -238,8 +267,43 @@ gt_bind(int argc, char **argv)
continue;
}
if (FD_ISSET(tun_fd, &rfds))
tun_can_read = 1;
if (FD_ISSET(tun_fd, &wfds))
tun_can_write = 1;
if (FD_ISSET(mud_fd, &rfds))
mud_can_read = 1;
if (FD_ISSET(mud_fd, &wfds))
mud_can_write = 1;
mtu = gt_setup_mtu(mud, mtu, tun_name);
if (tun_can_read && mud_can_write && !mud_send_wait(mud)) {
struct ip_common ic;
int r = tun_read(tun_fd, buf, sizeof(buf));
if (r > 0 && !ip_get_common(&ic, buf, r)) {
mud_send(mud, buf, (size_t)r, ic.tc);
mud_can_write = 0;
}
tun_can_read = 0;
}
if (mud_can_read && tun_can_write) {
int r = mud_recv(mud, buf, sizeof(buf));
if (r > 0 && ip_is_valid(buf, r)) {
tun_write(tun_fd, buf, (size_t)r);
tun_can_write = 0;
}
mud_can_read = 0;
}
if (FD_ISSET(ctl_fd, &rfds)) {
struct ctl_msg req, res = {.reply = 1};
struct sockaddr_storage ss;
@@ -299,6 +363,7 @@ gt_bind(int argc, char **argv)
res.ret = errno;
break;
case CTL_STATUS:
memcpy(res.status.tun_name, tun_name, sizeof(tun_name)); // XXX
res.status.pid = pid;
res.status.mtu = mtu;
res.status.chacha = chacha;
@@ -313,36 +378,6 @@ gt_bind(int argc, char **argv)
perror("recvfrom(ctl)");
}
}
if (FD_ISSET(mud_fd, &rfds)) {
int n = 1000;
while (n--) {
const int r = mud_recv(mud, buf, sizeof(buf));
if (r <= 0)
break;
if (ip_is_valid(buf, r))
tun_write(tun_fd, buf, (size_t)r);
}
}
if (FD_ISSET(tun_fd, &rfds) && !mud_send_wait(mud)) {
struct ip_common ic;
const int r = tun_read(tun_fd, buf, sizeof(buf));
if (r > 0 && !ip_get_common(&ic, buf, r)) {
// TODO: disable hash for now
// unsigned char hash[crypto_shorthash_BYTES];
// crypto_shorthash(hash, (const unsigned char *)&ic, sizeof(ic), hashkey);
unsigned h = 0;
// memcpy(&h, hash, sizeof(h));
mud_send(mud, buf, (size_t)r, (h << 8) | ic.tc);
}
}
}
if (gt_reload && tun_fd >= 0)

View File

@@ -13,17 +13,12 @@
int
ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req)
{
if (fd == -1) {
errno = EINVAL;
return -1;
}
if ((send(fd, req, sizeof(struct ctl_msg), 0) == -1) ||
(recv(fd, res, sizeof(struct ctl_msg), 0) == -1))
return -1;
if (res->type != req->type || !res->reply) {
errno = EINVAL;
errno = EBADMSG;
return -1;
}
@@ -58,33 +53,30 @@ ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file)
static int
ctl_bind(int fd, const char *dir, const char *file)
{
char name[10] = { [0] = '.' };
struct sockaddr_un sun;
if (str_empty(file)) {
char name[10] = { [0] = '.' };
unsigned pid = (unsigned)getpid();
for (size_t i = 1; i < sizeof(name) - 1; i++, pid >>= 4)
name[i] = "uncopyrightables"[pid & 15];
if (ctl_setsun(&sun, dir, name))
return -1;
} else {
if (ctl_setsun(&sun, dir, file))
return -1;
unlink(sun.sun_path);
file = name;
}
if (ctl_setsun(&sun, dir, file))
return -1;
if (unlink(sun.sun_path) && errno != ENOENT)
return -1;
return bind(fd, (struct sockaddr *)&sun, sizeof(sun));
}
void
ctl_delete(int fd)
{
if (fd == -1)
return;
struct sockaddr_storage ss = { 0 };
socklen_t sslen = sizeof(ss);
@@ -108,9 +100,6 @@ ctl_create(const char *dir, const char *file)
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd == -1)
return -1;
if (ctl_bind(fd, dir, file)) {
int err = errno;
close(fd);
@@ -132,9 +121,7 @@ ctl_connect(const char *dir, const char *file)
}
if (!file) {
dp = opendir(dir);
if (!dp)
if (dp = opendir(dir), !dp)
return -1;
struct dirent *d = NULL;
@@ -145,7 +132,7 @@ ctl_connect(const char *dir, const char *file)
if (file) {
closedir(dp);
return -3;
return CTL_ERROR_MANY;
}
file = &d->d_name[0];
@@ -153,7 +140,7 @@ ctl_connect(const char *dir, const char *file)
if (!file) {
closedir(dp);
return -2;
return CTL_ERROR_NONE;
}
}
@@ -171,9 +158,6 @@ ctl_connect(const char *dir, const char *file)
int fd = ctl_create(dir, NULL);
if (fd == -1)
return -1;
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun))) {
int err = errno;
ctl_delete(fd);

View File

@@ -4,6 +4,9 @@
#include <sys/socket.h>
#define CTL_ERROR_NONE (-2)
#define CTL_ERROR_MANY (-3)
enum ctl_type {
CTL_NONE = 0,
CTL_STATE,
@@ -27,6 +30,7 @@ struct ctl_msg {
} path;
struct mud_path path_status;
struct {
char tun_name[64];
long pid;
size_t mtu;
int chacha;

View File

@@ -75,7 +75,7 @@ main(int argc, char **argv)
char *help;
int (*call)(int, char **);
} cmd[] = {
{"show", "show all running tunnels", gt_show},
{"show", "show tunnel info", gt_show},
{"bench", "start a crypto bench", gt_bench},
{"bind", "start a new tunnel", gt_bind},
{"set", "change tunnel properties", gt_set},

View File

@@ -74,7 +74,28 @@ gt_path_print_status(struct mud_path *path, int term)
}
static int
gt_path_status(int fd)
gt_path_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
{
if (a->ss_family != b->ss_family)
return 1;
if (a->ss_family == AF_INET) {
struct sockaddr_in *A = (struct sockaddr_in *)a;
struct sockaddr_in *B = (struct sockaddr_in *)b;
return ((memcmp(&A->sin_addr, &B->sin_addr, sizeof(A->sin_addr))));
}
if (a->ss_family == AF_INET6) {
struct sockaddr_in6 *A = (struct sockaddr_in6 *)a;
struct sockaddr_in6 *B = (struct sockaddr_in6 *)b;
return ((memcmp(&A->sin6_addr, &B->sin6_addr, sizeof(A->sin6_addr))));
}
return 1;
}
static int
gt_path_status(int fd, int state, struct sockaddr_storage *addr)
{
struct ctl_msg req = {
.type = CTL_PATH_STATUS,
@@ -90,8 +111,10 @@ gt_path_status(int fd)
if (recv(fd, &res, sizeof(struct ctl_msg), 0) == -1)
return -1;
if (res.type != req.type)
return -2;
if (res.type != req.type) {
errno = EBADMSG;
return -1;
}
if (res.ret == EAGAIN) {
memcpy(&path[count], &res.path_status, sizeof(struct mud_path));
@@ -104,8 +127,11 @@ gt_path_status(int fd)
int term = isatty(1);
for (int i = 0; i < count; i++)
gt_path_print_status(&path[i], term);
for (int i = 0; i < count; i++) {
if ((state == MUD_EMPTY || path[i].state == state) &&
(!addr->ss_family || !gt_path_cmp_addr(addr, &path[i].local_addr)))
gt_path_print_status(&path[i], term);
}
return 0;
}
@@ -117,6 +143,9 @@ gt_path(int argc, char **argv)
struct ctl_msg req = {
.type = CTL_STATE,
.path = {
.state = MUD_EMPTY,
},
}, res = {0};
struct argz ratez[] = {
@@ -141,10 +170,10 @@ gt_path(int argc, char **argv)
case -1:
perror("path");
break;
case -2:
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case -3:
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:
@@ -153,24 +182,27 @@ gt_path(int argc, char **argv)
return 1;
}
int ret = 0;
int set_rate = argz_is_set(pathz, "rate");
if (!req.path.addr.ss_family) {
ret = gt_path_status(fd);
if (set_rate && !req.path.addr.ss_family) {
gt_log("please specify a path\n");
return 1;
}
if (ret == -2)
gt_log("bad reply from server\n");
if (argz_is_set(pathz, "up")) {
req.path.state = MUD_UP;
} else if (argz_is_set(pathz, "backup")) {
req.path.state = MUD_BACKUP;
} else if (argz_is_set(pathz, "down")) {
req.path.state = MUD_DOWN;
}
int ret;
if (!req.path.addr.ss_family ||
(req.path.state == MUD_EMPTY && !set_rate)) {
ret = gt_path_status(fd, req.path.state, &req.path.addr);
} else {
req.path.state = MUD_EMPTY;
if (argz_is_set(pathz, "up")) {
req.path.state = MUD_UP;
} else if (argz_is_set(pathz, "backup")) {
req.path.state = MUD_BACKUP;
} else if (argz_is_set(pathz, "down")) {
req.path.state = MUD_DOWN;
}
ret = ctl_reply(fd, &res, &req);
}

View File

@@ -134,10 +134,10 @@ gt_set(int argc, char **argv)
case -1:
perror("set");
break;
case -2:
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case -3:
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:

View File

@@ -12,7 +12,7 @@
#include <unistd.h>
static int
gt_show_dev_status(int fd, const char *dev)
gt_show_status(int fd)
{
struct ctl_msg res, req = {.type = CTL_STATUS};
@@ -32,17 +32,17 @@ gt_show_dev_status(int fd, const char *dev)
if (server) {
printf(term ? "server %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
: "server %s"
" %li"
" %s %"PRIu16
" %zu"
" %s"
"\n",
dev,
res.status.tun_name,
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
@@ -50,11 +50,11 @@ gt_show_dev_status(int fd, const char *dev)
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
} else {
printf(term ? "client %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
: "client %s"
" %li"
" %s %"PRIu16
@@ -62,7 +62,7 @@ gt_show_dev_status(int fd, const char *dev)
" %zu"
" %s"
"\n",
dev,
res.status.tun_name,
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
@@ -75,30 +75,6 @@ gt_show_dev_status(int fd, const char *dev)
return 0;
}
static int
gt_show_dev(const char *dev)
{
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd < 0) {
if (fd == -1)
perror("show");
return -1;
}
int ret = gt_show_dev_status(fd, dev);
if (ret == -1)
perror(dev);
if (ret == -2)
gt_log("%s: bad reply from server\n", dev);
ctl_delete(fd);
return ret;
}
int
gt_show(int argc, char **argv)
{
@@ -111,27 +87,31 @@ gt_show(int argc, char **argv)
if (argz(showz, argc, argv))
return 1;
if (dev)
return !!gt_show_dev(dev);
int fd = ctl_connect(GT_RUNDIR, dev);
DIR *dp = opendir(GT_RUNDIR);
if (!dp) {
if (errno == ENOENT)
return 0;
perror("show");
if (fd < 0) {
switch (fd) {
case -1:
perror("show");
break;
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
return 1;
}
int ret = 0;
struct dirent *d = NULL;
int ret = gt_show_status(fd);
while (d = readdir(dp), d) {
if (d->d_name[0] != '.')
ret |= !!gt_show_dev(d->d_name);
}
if (ret == -1)
perror("show");
closedir(dp);
ctl_delete(fd);
return ret;
return !!ret;
}