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
|
||||
|
||||
bin_PROGRAMS = glorytun
|
||||
bin_PROGRAMS = glorytun glorytunctl
|
||||
|
||||
glorytun_CFLAGS = $(libsodium_CFLAGS)
|
||||
glorytun_LDADD = $(libsodium_LIBS)
|
||||
@@ -9,6 +9,8 @@ glorytun_SOURCES = \
|
||||
src/common.c \
|
||||
src/ip.h \
|
||||
src/str.h \
|
||||
src/ctl.c \
|
||||
src/ctl.h \
|
||||
src/main.c \
|
||||
src/option.c \
|
||||
src/option.h \
|
||||
@@ -19,6 +21,18 @@ glorytun_SOURCES = \
|
||||
mud/mud.h \
|
||||
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 = \
|
||||
LICENSE \
|
||||
README.md \
|
||||
|
||||
22
meson.build
22
meson.build
@@ -12,21 +12,31 @@ conf_data.set('prefix', prefix)
|
||||
conf_data.set('bindir', bindir)
|
||||
|
||||
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/iface.c',
|
||||
'src/option.c',
|
||||
'src/tun.c',
|
||||
'src/ctl.c',
|
||||
'mud/mud.c',
|
||||
'src/main.c'
|
||||
]
|
||||
|
||||
deps = [
|
||||
],
|
||||
dependencies: [
|
||||
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)
|
||||
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
#include <unistd.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 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 *);
|
||||
71
src/main.c
71
src/main.c
@@ -1,24 +1,17 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "db.h"
|
||||
#include "ctl.h"
|
||||
#include "iface.h"
|
||||
#include "ip.h"
|
||||
#include "option.h"
|
||||
#include "str.h"
|
||||
#include "tun.h"
|
||||
#include "iface.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <signal.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"
|
||||
|
||||
@@ -26,10 +19,6 @@
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifndef PACKAGE_VERSION
|
||||
#define PACKAGE_VERSION "unknown"
|
||||
#endif
|
||||
|
||||
#define GT_MTU(X) ((X)-28)
|
||||
|
||||
static struct {
|
||||
@@ -79,6 +68,9 @@ fd_set_nonblock(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fd == -1)
|
||||
return;
|
||||
|
||||
do {
|
||||
ret = fcntl(fd, F_GETFL, 0);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
@@ -377,24 +369,31 @@ main(int argc, char **argv)
|
||||
|
||||
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);
|
||||
|
||||
fd_set_nonblock(tun_fd);
|
||||
fd_set_nonblock(mud_fd);
|
||||
|
||||
if (icmp_fd != -1)
|
||||
fd_set_nonblock(icmp_fd);
|
||||
fd_set_nonblock(ctl_fd);
|
||||
|
||||
gt_log("running...\n");
|
||||
|
||||
fd_set 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) {
|
||||
FD_SET(tun_fd, &rfds);
|
||||
FD_SET(mud_fd, &rfds);
|
||||
FD_SET(ctl_fd, &rfds);
|
||||
|
||||
if (icmp_fd != -1)
|
||||
FD_SET(icmp_fd, &rfds);
|
||||
@@ -407,11 +406,13 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (icmp_fd != -1 && FD_ISSET(icmp_fd, &rfds)) {
|
||||
struct ip_common ic;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t sl = sizeof(ss);
|
||||
|
||||
ssize_t r = recvfrom(icmp_fd, gt.buf.data, gt.buf.size, 0,
|
||||
(struct sockaddr *)&ss, &sl);
|
||||
struct ip_common ic;
|
||||
|
||||
if (!ip_get_common(&ic, gt.buf.data, r)) {
|
||||
int mtu = ip_get_mtu(&ic, gt.buf.data, r);
|
||||
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)) {
|
||||
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