Add a simple unix controller
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
16
Makefile.am
16
Makefile.am
@@ -1,6 +1,6 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4 --install
|
ACLOCAL_AMFLAGS = -I m4 --install
|
||||||
|
|
||||||
bin_PROGRAMS = glorytun
|
bin_PROGRAMS = glorytun glorytunctl
|
||||||
|
|
||||||
glorytun_CFLAGS = $(libsodium_CFLAGS)
|
glorytun_CFLAGS = $(libsodium_CFLAGS)
|
||||||
glorytun_LDADD = $(libsodium_LIBS)
|
glorytun_LDADD = $(libsodium_LIBS)
|
||||||
@@ -9,6 +9,8 @@ glorytun_SOURCES = \
|
|||||||
src/common.c \
|
src/common.c \
|
||||||
src/ip.h \
|
src/ip.h \
|
||||||
src/str.h \
|
src/str.h \
|
||||||
|
src/ctl.c \
|
||||||
|
src/ctl.h \
|
||||||
src/main.c \
|
src/main.c \
|
||||||
src/option.c \
|
src/option.c \
|
||||||
src/option.h \
|
src/option.h \
|
||||||
@@ -19,6 +21,18 @@ glorytun_SOURCES = \
|
|||||||
mud/mud.h \
|
mud/mud.h \
|
||||||
mud/mud.c
|
mud/mud.c
|
||||||
|
|
||||||
|
glorytunctl_CFLAGS =
|
||||||
|
glorytunctl_LDADD =
|
||||||
|
glorytunctl_SOURCES = \
|
||||||
|
src/common.h \
|
||||||
|
src/common.c \
|
||||||
|
src/str.h \
|
||||||
|
src/ctl.c \
|
||||||
|
src/ctl.h \
|
||||||
|
src/mainctl.c \
|
||||||
|
src/option.c \
|
||||||
|
src/option.h
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
LICENSE \
|
LICENSE \
|
||||||
README.md \
|
README.md \
|
||||||
|
|||||||
22
meson.build
22
meson.build
@@ -12,21 +12,31 @@ conf_data.set('prefix', prefix)
|
|||||||
conf_data.set('bindir', bindir)
|
conf_data.set('bindir', bindir)
|
||||||
|
|
||||||
add_global_arguments('-DPACKAGE_VERSION="'+meson.project_version()+'"', language : 'c')
|
add_global_arguments('-DPACKAGE_VERSION="'+meson.project_version()+'"', language : 'c')
|
||||||
|
add_global_arguments('-DPACKAGE_NAME="'+meson.project_name()+'"', language : 'c')
|
||||||
|
|
||||||
src = [
|
executable('glorytun', install: true,
|
||||||
|
sources: [
|
||||||
'src/common.c',
|
'src/common.c',
|
||||||
'src/iface.c',
|
'src/iface.c',
|
||||||
'src/option.c',
|
'src/option.c',
|
||||||
'src/tun.c',
|
'src/tun.c',
|
||||||
|
'src/ctl.c',
|
||||||
'mud/mud.c',
|
'mud/mud.c',
|
||||||
'src/main.c'
|
'src/main.c'
|
||||||
]
|
],
|
||||||
|
dependencies: [
|
||||||
deps = [
|
|
||||||
dependency('libsodium', version : '>=1.0.4')
|
dependency('libsodium', version : '>=1.0.4')
|
||||||
]
|
]
|
||||||
|
)
|
||||||
|
|
||||||
executable('glorytun', install: true, sources: src, dependencies: deps)
|
executable('glorytunctl', install: true,
|
||||||
|
sources: [
|
||||||
|
'src/common.c',
|
||||||
|
'src/option.c',
|
||||||
|
'src/ctl.c',
|
||||||
|
'src/mainctl.c'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
systemd = dependency('systemd', required: false)
|
systemd = dependency('systemd', required: false)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,14 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef PACKAGE_NAME
|
||||||
|
#define PACKAGE_NAME "glorytun"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PACKAGE_VERSION
|
||||||
|
#define PACKAGE_VERSION "0.0.0"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
|
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
#define ALIGN_SIZE (1<<4)
|
#define ALIGN_SIZE (1<<4)
|
||||||
|
|||||||
79
src/ctl.c
Normal file
79
src/ctl.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "ctl.h"
|
||||||
|
#include "str.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
ctl_init(const char *dir, const char *file)
|
||||||
|
{
|
||||||
|
if (str_empty(dir) || str_empty(file)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mkdir(dir, 0700) == -1 && errno != EEXIST) {
|
||||||
|
perror("mkdir");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *strs[] = {dir, "/", file};
|
||||||
|
char *path = str_cat(strs, 3);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
|
if (fd == -1) {
|
||||||
|
int err = errno;
|
||||||
|
free(path);
|
||||||
|
errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un sun = {
|
||||||
|
.sun_family = AF_UNIX,
|
||||||
|
};
|
||||||
|
|
||||||
|
str_cpy(sun.sun_path, path, sizeof(sun.sun_path) - 1);
|
||||||
|
free(path);
|
||||||
|
unlink(sun.sun_path);
|
||||||
|
|
||||||
|
if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
|
||||||
|
int err = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ctl_connect(int fd, const char *dir, const char *file)
|
||||||
|
{
|
||||||
|
if (fd < 0 || str_empty(dir) || str_empty(file)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *strs[] = {dir, "/", file};
|
||||||
|
char *path = str_cat(strs, 3);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct sockaddr_un sun = {
|
||||||
|
.sun_family = AF_UNIX,
|
||||||
|
};
|
||||||
|
|
||||||
|
str_cpy(sun.sun_path, path, sizeof(sun.sun_path) - 1);
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
return connect(fd, (struct sockaddr *)&sun, sizeof(sun));
|
||||||
|
}
|
||||||
19
src/ctl.h
Normal file
19
src/ctl.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum ctl_type {
|
||||||
|
CTL_UNKNOWN,
|
||||||
|
CTL_PING,
|
||||||
|
CTL_PONG,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ctl_msg {
|
||||||
|
enum ctl_type type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
enum ctl_type type;
|
||||||
|
} unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int ctl_init (const char *, const char *);
|
||||||
|
int ctl_connect (int, const char *, const char *);
|
||||||
73
src/main.c
73
src/main.c
@@ -1,24 +1,17 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include "db.h"
|
#include "ctl.h"
|
||||||
|
#include "iface.h"
|
||||||
#include "ip.h"
|
#include "ip.h"
|
||||||
#include "option.h"
|
#include "option.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "iface.h"
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <netinet/in.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
#include "../mud/mud.h"
|
#include "../mud/mud.h"
|
||||||
|
|
||||||
@@ -26,10 +19,6 @@
|
|||||||
#define O_CLOEXEC 0
|
#define O_CLOEXEC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PACKAGE_VERSION
|
|
||||||
#define PACKAGE_VERSION "unknown"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GT_MTU(X) ((X)-28)
|
#define GT_MTU(X) ((X)-28)
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
@@ -79,6 +68,9 @@ fd_set_nonblock(int fd)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = fcntl(fd, F_GETFL, 0);
|
ret = fcntl(fd, F_GETFL, 0);
|
||||||
} while (ret == -1 && errno == EINTR);
|
} while (ret == -1 && errno == EINTR);
|
||||||
@@ -377,24 +369,31 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
gt_setup_mtu(mud, tun_name);
|
gt_setup_mtu(mud, tun_name);
|
||||||
|
|
||||||
|
int ctl_fd = ctl_init("/run/" PACKAGE_NAME, tun_name);
|
||||||
|
|
||||||
|
if (ctl_fd == -1) {
|
||||||
|
perror("gt_setup_ctl");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int mud_fd = mud_get_fd(mud);
|
int mud_fd = mud_get_fd(mud);
|
||||||
|
|
||||||
fd_set_nonblock(tun_fd);
|
fd_set_nonblock(tun_fd);
|
||||||
fd_set_nonblock(mud_fd);
|
fd_set_nonblock(mud_fd);
|
||||||
|
fd_set_nonblock(icmp_fd);
|
||||||
if (icmp_fd != -1)
|
fd_set_nonblock(ctl_fd);
|
||||||
fd_set_nonblock(icmp_fd);
|
|
||||||
|
|
||||||
gt_log("running...\n");
|
gt_log("running...\n");
|
||||||
|
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
|
|
||||||
int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, icmp_fd));
|
int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, MAX(ctl_fd, icmp_fd)));
|
||||||
|
|
||||||
while (!gt.quit) {
|
while (!gt.quit) {
|
||||||
FD_SET(tun_fd, &rfds);
|
FD_SET(tun_fd, &rfds);
|
||||||
FD_SET(mud_fd, &rfds);
|
FD_SET(mud_fd, &rfds);
|
||||||
|
FD_SET(ctl_fd, &rfds);
|
||||||
|
|
||||||
if (icmp_fd != -1)
|
if (icmp_fd != -1)
|
||||||
FD_SET(icmp_fd, &rfds);
|
FD_SET(icmp_fd, &rfds);
|
||||||
@@ -407,11 +406,13 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (icmp_fd != -1 && FD_ISSET(icmp_fd, &rfds)) {
|
if (icmp_fd != -1 && FD_ISSET(icmp_fd, &rfds)) {
|
||||||
|
struct ip_common ic;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
socklen_t sl = sizeof(ss);
|
socklen_t sl = sizeof(ss);
|
||||||
|
|
||||||
ssize_t r = recvfrom(icmp_fd, gt.buf.data, gt.buf.size, 0,
|
ssize_t r = recvfrom(icmp_fd, gt.buf.data, gt.buf.size, 0,
|
||||||
(struct sockaddr *)&ss, &sl);
|
(struct sockaddr *)&ss, &sl);
|
||||||
struct ip_common ic;
|
|
||||||
if (!ip_get_common(&ic, gt.buf.data, r)) {
|
if (!ip_get_common(&ic, gt.buf.data, r)) {
|
||||||
int mtu = ip_get_mtu(&ic, gt.buf.data, r);
|
int mtu = ip_get_mtu(&ic, gt.buf.data, r);
|
||||||
if (mtu > 0) {
|
if (mtu > 0) {
|
||||||
@@ -421,6 +422,40 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(ctl_fd, &rfds)) {
|
||||||
|
struct ctl_msg msg;
|
||||||
|
struct ctl_msg reply;
|
||||||
|
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
socklen_t sl = sizeof(ss);
|
||||||
|
|
||||||
|
ssize_t r = recvfrom(ctl_fd, &msg, sizeof(msg), 0,
|
||||||
|
(struct sockaddr *)&ss, &sl);
|
||||||
|
|
||||||
|
if (r == (ssize_t)sizeof(msg)) {
|
||||||
|
switch (msg.type) {
|
||||||
|
case CTL_PING:
|
||||||
|
reply = (struct ctl_msg){
|
||||||
|
.type = CTL_PONG,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reply = (struct ctl_msg){
|
||||||
|
.type = CTL_UNKNOWN,
|
||||||
|
.unknown = {
|
||||||
|
.type = msg.type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sendto(ctl_fd, &reply, sizeof(reply), 0,
|
||||||
|
(const struct sockaddr *)&ss, sl) == -1)
|
||||||
|
perror("sendto(ctl)");
|
||||||
|
} else if (r == -1 && errno != EAGAIN) {
|
||||||
|
perror("recvfrom(ctl)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FD_ISSET(tun_fd, &rfds)) {
|
if (FD_ISSET(tun_fd, &rfds)) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
|
|||||||
93
src/mainctl.c
Normal file
93
src/mainctl.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "ctl.h"
|
||||||
|
#include "option.h"
|
||||||
|
#include "str.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#ifndef PACKAGE_VERSION
|
||||||
|
#define PACKAGE_VERSION "unknown"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *dev;
|
||||||
|
int version;
|
||||||
|
} gt = {};
|
||||||
|
|
||||||
|
static int
|
||||||
|
gt_setup_option(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
struct option opts[] = {
|
||||||
|
{ "dev", >.dev, option_str },
|
||||||
|
{ "version", NULL, option_option },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
if (option(opts, argc, argv))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
gt.version = option_is_set(opts, "version");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (gt_setup_option(argc, argv))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (gt.version) {
|
||||||
|
gt_print(PACKAGE_VERSION "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctl_fd = ctl_init("/run/" PACKAGE_NAME, "client");
|
||||||
|
|
||||||
|
if (ctl_fd == -1) {
|
||||||
|
perror("ctl_init");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctl_connect(ctl_fd, "/run/" PACKAGE_NAME, gt.dev) == -1) {
|
||||||
|
perror("ctl_connect");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ctl_msg msg = {
|
||||||
|
.type = CTL_PING,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (send(ctl_fd, &msg, sizeof(msg), 0) == -1) {
|
||||||
|
perror("send");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ctl_msg reply;
|
||||||
|
|
||||||
|
if (recv(ctl_fd, &reply, sizeof(reply), 0) == -1) {
|
||||||
|
perror("recv");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (reply.type) {
|
||||||
|
case CTL_PONG:
|
||||||
|
gt_print("PONG!\n");
|
||||||
|
break;
|
||||||
|
case CTL_UNKNOWN:
|
||||||
|
gt_print("Unknown command: %i\n", reply.unknown.type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gt_print("Bad reply from server: %i\n", reply.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ctl_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user