From bec778de7bed2388c071c50651360c8b93337203 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Tue, 22 Sep 2020 18:47:20 -0400 Subject: [PATCH] Implement bin/tncd.c Implement bin/tncd.c to expose a network interface as a KISS TNC device over a PTY --- bin/Makefile | 7 ++- bin/tncd.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 bin/tncd.c diff --git a/bin/Makefile b/bin/Makefile index ec6eefe..c90b8bf 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -8,14 +8,14 @@ HEADERS_SUBDIR = patty/bin CFLAGS += -I$(INCLUDE_PATH) LDFLAGS = -L../src -lpatty -PROGRAMS = pattyd ax25dump +PROGRAMS = pattyd ax25dump tncd MAN8PAGES = pattyd.8 ax25dump.8 MANPAGES = $(MAN8PAGES) HEADERS = kiss.h if.h HEADERS_BUILD = $(addprefix $(INCLUDE_PATH)/$(HEADERS_SUBDIR)/, $(HEADERS)) -OBJS = pattyd.o ax25dump.o kiss.o if.o +OBJS = pattyd.o ax25dump.o kiss.o if.o tncd.o all: $(PROGRAMS) @@ -30,6 +30,9 @@ pattyd: pattyd.o kiss.o if.o ax25dump: ax25dump.o kiss.o $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) +tncd: tncd.o + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + $(OBJS): %.o: %.c $(HEADERS_BUILD) $(CC) $(CFLAGS) -c $< diff --git a/bin/tncd.c b/bin/tncd.c new file mode 100644 index 0000000..61deb77 --- /dev/null +++ b/bin/tncd.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static void usage(int argc, char **argv, const char *message, ...) { + if (message != NULL) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + fprintf(stderr, "\n"); + va_end(args); + } + + fprintf(stderr, "usage: %s /var/run/patty.sock ifname\n", argv[0]); + + exit(EX_USAGE); +} + +static int pty_promisc(patty_client *client, + const char *ifname, + char *pty, + size_t len) { + enum patty_client_call call; + + patty_client_socket_request socket_request = { + .proto = PATTY_AX25_PROTO_NONE, + .type = PATTY_AX25_SOCK_RAW + }; + + patty_client_socket_response socket_response; + patty_client_setsockopt_request setsockopt_request; + patty_client_setsockopt_response setsockopt_response; + + patty_client_setsockopt_if ifreq; + + call = PATTY_CLIENT_SOCKET; + + if (patty_client_write(client, &call, sizeof(call)) < 0) { + goto error_client_write_socket_request; + } + + if (patty_client_write(client, + &socket_request, + sizeof(socket_request)) < 0) { + goto error_client_write_socket_request; + } + + if (patty_client_read(client, + &socket_response, + sizeof(socket_response)) < 0) { + goto error_client_read_socket_response; + } + + if (socket_response.fd < 0) { + errno = socket_response.eno; + + goto error_client_socket; + } + + setsockopt_request.fd = socket_response.fd; + setsockopt_request.opt = PATTY_AX25_SOCK_IF; + setsockopt_request.len = sizeof(ifreq); + + strncpy(ifreq.name, ifname, sizeof(ifreq.name)); + ifreq.state = PATTY_AX25_SOCK_PROMISC; + + call = PATTY_CLIENT_SETSOCKOPT; + + if (patty_client_write(client, &call, sizeof(call)) < 0) { + goto error_client_write_socket_request; + } + + if (patty_client_write(client, + &setsockopt_request, + sizeof(setsockopt_request)) < 0) { + goto error_client_write_setsockopt_request; + } + + if (patty_client_write(client, + &ifreq, + sizeof(ifreq)) < 0) { + goto error_client_write_ifreq; + } + + if (patty_client_read(client, + &setsockopt_response, + sizeof(setsockopt_response)) < 0) { + goto error_client_read_setsockopt_response; + } + + if (setsockopt_response.ret < 0) { + errno = setsockopt_response.eno; + + goto error_client_setsockopt; + } + + strncpy(pty, socket_response.path, len); + + return 0; + +error_client_setsockopt: +error_client_read_setsockopt_response: +error_client_write_ifreq: +error_client_write_setsockopt_request: + /* TODO: Close socket on error */ + +error_client_socket: +error_client_read_socket_response: +error_client_write_socket_request: + return -1; +} + +int main(int argc, char **argv) { + struct option opts[] = { + { NULL, 0, NULL, 0 } + }; + + patty_client *client; + char pty[256]; + + if (getopt_long(argc, argv, "", opts, NULL) >= 0) { + usage(argc, argv, NULL); + } + + if (argc < 3) { + usage(argc, argv, "Not enough arguments provided"); + } + + if ((client = patty_client_new(argv[1])) == NULL) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "patty_client_new()", strerror(errno)); + + goto error_client_new; + } + + if (pty_promisc(client, argv[2], pty, sizeof(pty)) < 0) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "pty_promisc()", argv[2], strerror(errno)); + + goto error_pty_promisc; + } + + printf("%s\n", pty); + + while (1) { + sleep(86400); + } + + patty_client_destroy(client); + +error_pty_promisc: +error_client_new: + return 1; +}