Add a simple unix controller

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2018-01-16 16:37:01 +00:00
parent 69bcf664a8
commit 70086d295a
7 changed files with 284 additions and 26 deletions

View File

@@ -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 \

View File

@@ -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)

View File

@@ -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
View 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
View 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 *);

View File

@@ -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
View 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", &gt.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;
}