diff --git a/src/bind.c b/src/bind.c index 47e1e0e..ef22b95 100644 --- a/src/bind.c +++ b/src/bind.c @@ -271,59 +271,49 @@ gt_bind(int argc, char **argv) } if (FD_ISSET(ctl_fd, &rfds)) { - struct ctl_msg msg, reply = {.type = CTL_REPLY}; + struct ctl_msg req, res = {.reply = 1}; struct sockaddr_storage ss; socklen_t sl = sizeof(ss); - ssize_t r = recvfrom(ctl_fd, &msg, sizeof(msg), 0, + ssize_t r = recvfrom(ctl_fd, &req, sizeof(req), 0, (struct sockaddr *)&ss, &sl); - if (r == (ssize_t)sizeof(msg)) { - switch (msg.type) { + if (r == (ssize_t)sizeof(req)) { + res.type = req.type; + + switch (req.type) { + case CTL_NONE: + break; case CTL_PATH_ADD: - if (mud_add_path(mud, (struct sockaddr *)&msg.path_addr)) { - reply.reply = errno; - perror("mud_add_path"); - } + if (mud_add_path(mud, (struct sockaddr *)&req.path_addr)) + res.ret = errno; break; case CTL_PATH_DEL: - if (mud_del_path(mud, (struct sockaddr *)&msg.path_addr)) { - reply.reply = errno; - perror("mud_del_path"); - } + if (mud_del_path(mud, (struct sockaddr *)&req.path_addr)) + res.ret = errno; break; case CTL_MTU: - reply.reply = (int)mud_set_mtu(mud, GT_MTU((size_t)msg.mtu)); - mtu = gt_setup_mtu(mud, tun_name); + mud_set_mtu(mud, GT_MTU((size_t)req.mtu)); + res.mtu = gt_setup_mtu(mud, tun_name); + mtu = res.mtu; break; case CTL_TIMEOUT: - reply.reply = mud_set_send_timeout(mud, msg.timeout); + if (mud_set_send_timeout(mud, req.timeout)) + res.ret = errno; break; case CTL_TIMETOLERANCE: - reply.reply = mud_set_time_tolerance(mud, msg.timetolerance); + if (mud_set_time_tolerance(mud, req.timetolerance)) + res.ret = errno; break; case CTL_STATUS: - reply = (struct ctl_msg){ - .type = CTL_STATUS_REPLY, - .status = { - .mtu = mtu, - .mtu_auto = (icmp_fd != -1), - .chacha = chacha, - .bind = bind_addr, - .peer = peer_addr, - }, - }; - break; - default: - reply = (struct ctl_msg){ - .type = CTL_UNKNOWN, - .unknown = { - .type = msg.type, - }, - }; + res.status.mtu = mtu; + res.status.mtu_auto = (icmp_fd != -1); + res.status.chacha = chacha; + res.status.bind = bind_addr; + res.status.peer = peer_addr; break; } - if (sendto(ctl_fd, &reply, sizeof(reply), 0, + if (sendto(ctl_fd, &res, sizeof(res), 0, (const struct sockaddr *)&ss, sl) == -1) perror("sendto(ctl)"); } else if (r == -1 && errno != EAGAIN) { diff --git a/src/ctl.c b/src/ctl.c index f559473..ff4bbef 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -8,6 +8,26 @@ #include #include +int +ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req) +{ + 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 = EINTR; + return -1; + } + + if (res->ret) { + errno = res->ret; + return -1; + } + + return 0; +} + static int ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file) { diff --git a/src/ctl.h b/src/ctl.h index 1011c14..09de687 100644 --- a/src/ctl.h +++ b/src/ctl.h @@ -3,23 +3,19 @@ #include enum ctl_type { - CTL_UNKNOWN, + CTL_NONE = 0, CTL_PATH_ADD, CTL_PATH_DEL, CTL_STATUS, - CTL_STATUS_REPLY, CTL_MTU, CTL_TIMEOUT, CTL_TIMETOLERANCE, - CTL_REPLY, }; struct ctl_msg { enum ctl_type type; + int reply, ret; union { - struct { - enum ctl_type type; - } unknown; struct sockaddr_storage path_addr; struct { size_t mtu; @@ -31,10 +27,10 @@ struct ctl_msg { int mtu; unsigned long timeout; unsigned long timetolerance; - int reply; }; }; int ctl_create (const char *, const char *); int ctl_connect (int, const char *, const char *); +int ctl_reply (int, struct ctl_msg *, struct ctl_msg *); void ctl_delete (int); diff --git a/src/path.c b/src/path.c index fcd0e86..1eaed7c 100644 --- a/src/path.c +++ b/src/path.c @@ -25,15 +25,15 @@ gt_path(int argc, char **argv) if (argz(pathz, argc, argv)) return 1; - struct ctl_msg msg; + struct ctl_msg req, res = {0}; if (argz_is_set(pathz, "up")) { - msg = (struct ctl_msg){ + req = (struct ctl_msg){ .type = CTL_PATH_ADD, .path_addr = addr, }; } else if (argz_is_set(pathz, "down")) { - msg = (struct ctl_msg){ + req = (struct ctl_msg){ .type = CTL_PATH_DEL, .path_addr = addr, }; @@ -55,30 +55,14 @@ gt_path(int argc, char **argv) return 1; } - struct ctl_msg reply; + int ret = 0; - if ((send(fd, &msg, sizeof(msg), 0) == -1) || - (recv(fd, &reply, sizeof(reply), 0) == -1)) { - perror("send/recv"); - ctl_delete(fd); - return 1; - } - - switch (reply.type) { - case CTL_REPLY: - if (reply.reply) { - errno = reply.reply; - perror("error"); - } - break; - case CTL_UNKNOWN: - printf("unknown command: %i\n", reply.unknown.type); - break; - default: - gt_log("bad reply from server: %i\n", reply.type); + if (ctl_reply(fd, &res, &req)) { + perror(dev); + ret = 1; } ctl_delete(fd); - return 0; + return ret; } diff --git a/src/set.c b/src/set.c index 8a165d2..3a6abd6 100644 --- a/src/set.c +++ b/src/set.c @@ -7,30 +7,6 @@ #include "../argz/argz.h" -static ssize_t -gt_reply(int fd, struct ctl_msg *res, struct ctl_msg *req) -{ - if ((send(fd, req, sizeof(struct ctl_msg), 0) == -1) || - (recv(fd, res, sizeof(struct ctl_msg), 0) == -1)) { - int err = errno; - ctl_delete(fd); - errno = err; - return -1; - } - - if (res->type == CTL_REPLY) { - if (res->reply < 0) { - errno = res->reply; - return -1; - } - } else { - errno = EINTR; - return -1; - } - - return 0; -} - static int gt_set_mtu(int fd, size_t mtu) { @@ -39,10 +15,10 @@ gt_set_mtu(int fd, size_t mtu) .mtu = mtu, }; - int ret = gt_reply(fd, &res, &req); + int ret = ctl_reply(fd, &res, &req); if (!ret) - printf("new mtu: %i\n", res.reply); + printf("new mtu: %i\n", res.mtu); return ret; } @@ -55,7 +31,7 @@ gt_set_timeout(int fd, unsigned long timeout) .timeout = timeout, }; - return gt_reply(fd, &res, &req); + return ctl_reply(fd, &res, &req); } static int @@ -66,7 +42,7 @@ gt_set_timetolerance(int fd, unsigned long timetolerance) .timetolerance = timetolerance, }; - return gt_reply(fd, &res, &req); + return ctl_reply(fd, &res, &req); } int @@ -100,22 +76,24 @@ gt_set(int argc, char **argv) return 1; } + int ret = 0; + if (mtu && gt_set_mtu(fd, mtu)) { perror("mtu"); - return 1; + ret = 1; } - if (timeout && gt_set_timeout(fd, timeout)) { + if (!ret && timeout && gt_set_timeout(fd, timeout)) { perror("timeout"); - return 1; + ret = 1; } - if (timetolerance && gt_set_timetolerance(fd, timetolerance)) { + if (!ret && timetolerance && gt_set_timetolerance(fd, timetolerance)) { perror("timetolerance"); - return 1; + ret = 1; } ctl_delete(fd); - return 0; + return ret; } diff --git a/src/show.c b/src/show.c index 8bdc54f..82043da 100644 --- a/src/show.c +++ b/src/show.c @@ -44,37 +44,31 @@ gt_show_tunnel(int fd, const char *dev) return -1; } - struct ctl_msg reply, msg = { - .type = CTL_STATUS, - }; + struct ctl_msg res, req = {.type = CTL_STATUS}; - if ((send(fd, &msg, sizeof(msg), 0) == -1) || - (recv(fd, &reply, sizeof(reply), 0) == -1)) { + if (ctl_reply(fd, &res, &req)) { perror(dev); return -1; } - if (reply.type != CTL_STATUS_REPLY) - return -1; - char bindstr[INET6_ADDRSTRLEN] = {0}; char peerstr[INET6_ADDRSTRLEN] = {0}; - if (gt_ss_addr(bindstr, sizeof(bindstr), &reply.status.bind) || - gt_ss_addr(peerstr, sizeof(peerstr), &reply.status.peer)) + if (gt_ss_addr(bindstr, sizeof(bindstr), &res.status.bind) || + gt_ss_addr(peerstr, sizeof(peerstr), &res.status.peer)) return -1; - if (reply.status.peer.ss_family == 0) { + if (res.status.peer.ss_family == 0) { printf("server %s:\n" " bind: %s port %hu\n" " mtu: %zu\n" " auto mtu: %s\n" " cipher: %s\n", dev, - bindstr, gt_ss_port(&reply.status.bind), - reply.status.mtu, - reply.status.mtu_auto ? "enabled" : "disabled", - reply.status.chacha ? "chacha20poly1305" : "aes256gcm"); + bindstr, gt_ss_port(&res.status.bind), + res.status.mtu, + res.status.mtu_auto ? "enabled" : "disabled", + res.status.chacha ? "chacha20poly1305" : "aes256gcm"); } else { printf("client %s:\n" " bind: %s port %hu\n" @@ -83,11 +77,11 @@ gt_show_tunnel(int fd, const char *dev) " auto mtu: %s\n" " cipher: %s\n", dev, - bindstr, gt_ss_port(&reply.status.bind), - peerstr, gt_ss_port(&reply.status.peer), - reply.status.mtu, - reply.status.mtu_auto ? "enabled" : "disabled", - reply.status.chacha ? "chacha20poly1305" : "aes256gcm"); + bindstr, gt_ss_port(&res.status.bind), + peerstr, gt_ss_port(&res.status.peer), + res.status.mtu, + res.status.mtu_auto ? "enabled" : "disabled", + res.status.chacha ? "chacha20poly1305" : "aes256gcm"); } return 0;