Implement bin/pattyd.c

Changes:

    * Implement src/conf.c, patty_conf_read(), to read a configuration
      file to support a OpenBSD-style configuration file format

    * Implement bin/pattyd.c to use patty_conf_read() to read a
      configuration file and apply its settings to a patty_daemon
      object as it is read; also implement a --standalone|-s flag to
      allow the user to start a patty server without having to write
      a configuration file

    * Refactor patty_daemon_if_add() to accept a patty_ax25_if object;
      this is necessary as bin/pattyd.c needs to be able to validate
      the addresses given in a configuration file 'if' statement

    * Refactor patty_ax25_server_new() to no longer accept a client
      socket path; instead, patty_ax25_server_start() now accepts the
      client socket path

    * Remove the client socket 'path' member from patty_ax25_server in
      src/server.c

    * Refactor patty_kiss_tnc_new() to accept only one argument, a
      patty_kiss_tnc_info object containing flags and settings needed
      to open a device, use an existing file descriptor, or change
      termios settings as appropriate

    * Remove patty_kiss_tnc_new_fd(), as its functionality now exists
      in patty_kiss_tnc_new() itself

    * Add a 'flags' field to patty_kiss_tnc_info; use this bit field
      to determine whether a path or file descriptor is provided by
      the caller

    * Make patty_ax25_if_new() accept an interface name argument, as
      names are explicitly required when declaring new interfaces in
      configuration files

    * Make patty_kiss_tnc_new() able to accept /dev/ptmx as a device
      name, regardless of whether this character device exists on a
      given platform; when provided, a pseudo TTY pair is allocated
      with openpty()

    * Refactor examples/ax25dump.c to use the new patty_kiss_tnc_new()
      calling convention

    * Refactor examples/decode.c to use the new patty_kiss_tnc_new()
      calling convention

    * Remove examples/daemon.c in favor of bin/pattyd.c

    * Rename examples/patty.conf to examples/pattyd.conf; modify to
      provide values which would actually function
This commit is contained in:
XANTRONIX Development 2020-09-01 16:38:02 -05:00 committed by XANTRONIX Industrial
parent b0e9ae6e0d
commit 639ec8beb7
21 changed files with 1127 additions and 339 deletions

View file

@ -1,5 +1,6 @@
all: all:
$(MAKE) -C src all $(MAKE) -C src all
$(MAKE) -C bin all
$(MAKE) -C examples all $(MAKE) -C examples all
install: install:
@ -7,4 +8,5 @@ install:
clean: clean:
$(MAKE) -C src clean $(MAKE) -C src clean
$(MAKE) -C bin clean
$(MAKE) -C examples clean $(MAKE) -C examples clean

23
bin/Makefile Normal file
View file

@ -0,0 +1,23 @@
include ../mk/build.mk
CC = $(CROSS)cc
INCLUDE_PATH = ../include
CFLAGS += -I$(INCLUDE_PATH)
LDFLAGS = -L../src -lpatty
PROGRAMS = pattyd
OBJS = pattyd.o
all: $(PROGRAMS)
pattyd: pattyd.o
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(OBJS): %.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
$(RM) $(PROGRAMS)

567
bin/pattyd.c Normal file
View file

@ -0,0 +1,567 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <getopt.h>
#include <unistd.h>
#include <sysexits.h>
#include <errno.h>
#include <patty/ax25.h>
#include <patty/daemon.h>
#include <patty/conf.h>
#define DEFAULT_CONFIG_FILE "/etc/patty/pattyd.conf"
#define DEFAULT_IFNAME "kiss0"
static int 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 [-f] [-c pattyd.conf]\n"
" %s [-f] -s patty.sock MYCALL /dev/ttyXYZ [tioflags ...]\n",
argv[0], argv[0]);
return EX_USAGE;
}
static int handle_sock(patty_daemon *daemon,
int lineno,
int argc,
char **argv) {
if (argc != 2) {
fprintf(stderr, "Invalid arguments for 'sock' on line %d\n", lineno);
goto error_invalid_args;
}
if (patty_daemon_set_sock_path(daemon, argv[1]) < 0) {
fprintf(stderr, "Line %d: unable to set socket path to %s: %s",
lineno, argv[1], strerror(errno));
goto error_set_sock_path;
}
return 0;
error_set_sock_path:
error_invalid_args:
return -1;
}
static int handle_pid(patty_daemon *daemon,
int lineno,
int argc,
char **argv) {
if (argc != 2) {
fprintf(stderr, "Invalid arguments for 'sock' on line %d\n", lineno);
goto error_invalid_args;
}
if (patty_daemon_set_pidfile(daemon, argv[1]) < 0) {
fprintf(stderr, "Line %d: Unable to set pidfile to %s: %s",
lineno, argv[1], strerror(errno));
goto error_set_pidfile;
}
return 0;
error_set_pidfile:
error_invalid_args:
return -1;
}
struct if_context {
patty_daemon *daemon;
patty_ax25_addr addr;
patty_kiss_tnc_info info;
};
static int handle_if_ax25(struct if_context *ctx,
int lineno,
char *opt,
char *value) {
if (patty_ax25_pton(value, &ctx->addr) < 0) {
fprintf(stderr, "Line %d: Invalid interface address '%s'\n",
lineno, value);
goto error_pton;
}
return 0;
error_pton:
return -1;
}
static int handle_if_kiss(struct if_context *ctx,
int lineno,
char *opt,
char *value) {
ctx->info.flags |= PATTY_KISS_TNC_DEVICE;
ctx->info.device = value;
return 0;
}
static int handle_if_baud(struct if_context *ctx,
int lineno,
char *opt,
char *value) {
ctx->info.flags |= PATTY_KISS_TNC_BAUD;
ctx->info.baud = atoi(value);
return 0;
}
static int handle_if_flow(struct if_context *ctx,
int lineno,
char *opt,
char *value) {
if (strcmp(value, "xonxoff") == 0) {
ctx->info.flow = PATTY_KISS_TNC_FLOW_XONXOFF;
} else if (strcmp(value, "crtscts") == 0) {
ctx->info.flow = PATTY_KISS_TNC_FLOW_CRTSCTS;
} else {
fprintf(stderr, "Line %d: Invalid flow control '%s'\n",
lineno, value);
goto error_invalid_flow;
}
ctx->info.flags |= PATTY_KISS_TNC_FLOW;
return 0;
error_invalid_flow:
return -1;
}
struct if_opt_handler {
char *name;
int (*func)(struct if_context *, int, char *, char *);
};
static struct if_opt_handler if_opt_handlers[] = {
{ "ax25", handle_if_ax25 },
{ "kiss", handle_if_kiss },
{ "baud", handle_if_baud },
{ "flow", handle_if_flow },
{ NULL, NULL }
};
static int handle_if_opt(struct if_context *ctx,
int lineno,
char *opt,
char *value) {
int i;
for (i=0; if_opt_handlers[i].name; i++) {
if (strcmp(opt, if_opt_handlers[i].name) == 0) {
return if_opt_handlers[i].func(ctx, lineno, opt, value);
}
}
fprintf(stderr, "Line %d: Invalid interface option '%s'\n",
lineno, opt);
return -1;
}
static int handle_if(patty_daemon *daemon,
int lineno,
int argc,
char **argv) {
char *name;
struct if_context ctx;
patty_ax25_if *iface;
int i;
if (argc < 2) {
fprintf(stderr, "Line %d: No interface name provided\n", lineno);
goto error_no_ifname;
}
if (argc < 3) {
fprintf(stderr, "Line %d: No interface options provided\n", lineno);
goto error_no_options;
}
if (argc % 2 != 0) {
fprintf(stderr, "Line %d: Invalid number of values provided\n", lineno);
goto error_invalid_values;
}
memset(&ctx, '\0', sizeof(ctx));
ctx.daemon = daemon;
name = argv[1];
for (i=2; i<argc; i+=2) {
char *opt = argv[i],
*value = argv[i+1];
if (handle_if_opt(&ctx, lineno, opt, value) < 0) {
goto error_handle_if_opt;
}
}
if ((iface = patty_ax25_if_new(PATTY_AX25_IF_KISS_TNC,
name,
&ctx.info,
&ctx.addr)) == NULL) {
goto error_if_new;
} else {
int fd = patty_kiss_tnc_fd(iface->tnc);
char *pty;
if (isatty(fd) && (pty = ptsname(fd)) != NULL) {
printf("if %s pty %s\n", name, pty);
}
}
if (patty_daemon_if_add(daemon, iface) < 0) {
fprintf(stderr, "Line %d: Unable to create interface %s: %s\n",
lineno, name, strerror(errno));
goto error_daemon_if_add;
}
return 0;
error_daemon_if_add:
patty_ax25_if_destroy(iface);
error_if_new:
error_handle_if_opt:
error_invalid_values:
error_no_options:
error_no_ifname:
return -1;
}
static int handle_route(patty_daemon *daemon,
int lineno,
int argc,
char **argv) {
if (argc < 2) {
fprintf(stderr, "Line %d: Invalid route declaration\n", lineno);
goto error_invalid_route;
}
if (strcmp(argv[1], "default") == 0) {
if (argc != 4 || strcmp(argv[2], "if") != 0) {
fprintf(stderr, "Line %d: Invalid default route declaration\n",
lineno);
goto error_invalid_route;
}
if (patty_daemon_route_add_default(daemon, argv[3]) < 0) {
fprintf(stderr, "Line %d: Unable to add default route for interface %s: %s\n",
lineno, argv[3], strerror(errno));
goto error_daemon_route_add;
}
} else if (strcmp(argv[1], "station") == 0) {
if (argc < 7 || strcmp(argv[3], "if") != 0 || strcmp(argv[5], "path") != 0) {
fprintf(stderr, "Line %d: Invalid station route declaration\n",
lineno);
goto error_invalid_route;
}
if (patty_daemon_route_add(daemon,
argv[4],
argv[2],
(const char **)&argv[6],
argc - 6) < 0) {
fprintf(stderr, "Line %d: Unable to add route for interface %s: %s\n",
lineno, argv[4], strerror(errno));
goto error_daemon_route_add;
}
} else {
fprintf(stderr, "Line %d: Invalid route type '%s'\n",
lineno, argv[1]);
goto error_invalid_route;
}
return 0;
error_daemon_route_add:
error_invalid_route:
return -1;
}
struct config_handler {
const char *name;
int (*func)(patty_daemon *, int, int, char **);
};
struct config_handler handlers[] = {
{ "sock", handle_sock },
{ "pid", handle_pid },
{ "if", handle_if },
{ "route", handle_route },
{ NULL, NULL }
};
static int handle_config_line(patty_conf_file *file,
patty_list *line,
void *ctx) {
patty_daemon *daemon = ctx;
patty_list_item *item = line->first;
int argc = (int)line->length,
i = 0,
ret = 0,
lineno = 0;
char **argv;
if (!item) {
return 0;
}
if ((argv = malloc((argc + 1) * sizeof(char *))) == NULL) {
goto error_malloc_argv;
}
while (item) {
patty_conf_token *token = item->value;
if (lineno == 0) {
lineno = token->lineno;
}
argv[i++] = token->text;
item = item->next;
}
argv[argc] = NULL;
for (i=0; handlers[i].name; i++) {
if (strcmp(argv[0], handlers[i].name) == 0) {
ret = handlers[i].func(daemon, lineno, argc, argv);
goto done;
}
}
fprintf(stderr, "Unknown configuration value '%s'\n", argv[0]);
done:
free(argv);
return ret;
error_malloc_argv:
return -1;
}
static int handle_simple_config(patty_daemon *daemon,
int argc,
char *argv0,
char **argv) {
patty_ax25_if *iface;
patty_ax25_addr addr;
patty_kiss_tnc_info info = {
.flags = PATTY_KISS_TNC_DEVICE,
.device = argv[2]
};
int i;
for (i=3; i<argc; i++) {
if (strcmp(argv[i], "crtscts") == 0) {
info.flags |= PATTY_KISS_TNC_FLOW;
info.flow = PATTY_KISS_TNC_FLOW_CRTSCTS;
} else if (strcmp(argv[i], "xonxoff") == 0) {
info.flags |= PATTY_KISS_TNC_FLOW;
info.flow = PATTY_KISS_TNC_FLOW_XONXOFF;
} else if (argv[i][0] >= '0' && argv[i][0] <= '9') {
int baud = atoi(argv[i]);
info.flags |= PATTY_KISS_TNC_BAUD;
info.baud = baud;
} else {
fprintf(stderr, "%s: Invalid device setting '%s'\n",
argv0, argv[i]);
goto error_invalid_device_setting;
}
}
if (patty_daemon_set_sock_path(daemon, argv[0]) < 0) {
fprintf(stderr, "%s: Unable to set socket path to %s: %s\n",
argv0, argv[0], strerror(errno));
goto error_set_sock_path;
}
if (patty_ax25_pton(argv[1], &addr) < 0) {
fprintf(stderr, "%s: Invalid callsign '%s'\n",
argv0, argv[1]);
goto error_invalid_callsign;
}
if ((iface = patty_ax25_if_new(PATTY_AX25_IF_KISS_TNC,
DEFAULT_IFNAME,
&info,
&addr)) == NULL) {
fprintf(stderr, "%s: Unable to create network interface %s: %s\n",
argv0, DEFAULT_IFNAME, strerror(errno));
goto error_if_new;
} else {
int fd = patty_kiss_tnc_fd(iface->tnc);
char *pty;
if (isatty(fd) && (pty = ptsname(fd)) != NULL) {
printf("if %s pty %s\n", DEFAULT_IFNAME, pty);
}
}
if (patty_daemon_if_add(daemon, iface) < 0) {
fprintf(stderr, "%s: Unable to add interface %s: %s\n",
argv0, DEFAULT_IFNAME, strerror(errno));
goto error_daemon_if_add;
}
if (patty_daemon_route_add_default(daemon, DEFAULT_IFNAME) < 0) {
fprintf(stderr, "%s: Unable to add default route to %s: %s\n",
argv0, DEFAULT_IFNAME, strerror(errno));
goto error_daemon_route_add_default;
}
return 0;
error_daemon_route_add_default:
error_daemon_if_add:
error_if_new:
error_invalid_callsign:
error_invalid_device_setting:
error_set_sock_path:
return -1;
}
enum flags {
FLAG_FG,
FLAG_STANDALONE,
FLAG_COUNT
};
int main(int argc, char **argv) {
int ret = 0,
index,
ch,
flags[FLAG_COUNT];
struct option opts[] = {
{ "fg", no_argument, &flags[FLAG_FG], 1 },
{ "config", required_argument, NULL, 'c' },
{ "standalone", no_argument, &flags[FLAG_STANDALONE], 1 },
{ NULL, no_argument, NULL, 0 }
};
char *config_file = DEFAULT_CONFIG_FILE;
patty_daemon *daemon;
memset(flags, '\0', sizeof(flags));
if ((daemon = patty_daemon_new()) == NULL) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_new()", strerror(errno));
goto error_daemon_new;
}
while ((ch = getopt_long(argc, argv, "fc:s", opts, &index)) >= 0) {
switch (ch) {
case '?':
ret = usage(argc, argv, NULL);
goto error_invalid_args;
case 'c':
config_file = optarg;
break;
case 's':
flags[FLAG_STANDALONE] = 1;
break;
default:
break;
}
}
if (flags[FLAG_STANDALONE]) {
if (argc - optind < 1) {
ret = usage(argc, argv, "No socket path provided");
goto error_config;
} else if (argc - optind < 2) {
ret = usage(argc, argv, "No device path provided");
goto error_config;
} else if (argc - optind < 3) {
ret = usage(argc, argv, "No callsign provided");
goto error_config;
}
if (handle_simple_config(daemon,
argc - optind,
argv[0],
argv + optind) < 0) {
goto error_config;
}
} else if (patty_conf_read(config_file, handle_config_line, daemon) < 0) {
if (errno) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "patty_conf_read()", config_file, strerror(errno));
}
goto error_config;
}
if (patty_daemon_run(daemon) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_run()", strerror(errno));
goto error_daemon_run;
}
patty_daemon_destroy(daemon);
return 0;
error_daemon_run:
error_config:
error_invalid_args:
patty_daemon_destroy(daemon);
error_daemon_new:
return ret;
}

View file

@ -7,7 +7,7 @@ INCLUDE_PATH = ../include
CFLAGS += -I$(INCLUDE_PATH) CFLAGS += -I$(INCLUDE_PATH)
LDFLAGS = -L../src -lpatty -lutil LDFLAGS = -L../src -lpatty -lutil
EXAMPLES = daemon connect listen login ax25dump decode EXAMPLES = connect listen login ax25dump decode
all: $(EXAMPLES) all: $(EXAMPLES)

View file

@ -37,7 +37,9 @@ int main(int argc, char **argv) {
patty_kiss_tnc *raw; patty_kiss_tnc *raw;
int fd; patty_kiss_tnc_info info = {
.flags = PATTY_KISS_TNC_FD
};
if (argc < 2) { if (argc < 2) {
usage(argc, argv, "No patty socket provided"); usage(argc, argv, "No patty socket provided");
@ -52,7 +54,7 @@ int main(int argc, char **argv) {
goto error_client_new; goto error_client_new;
} }
if ((fd = patty_client_socket(client, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW)) < 0) { if ((info.fd = patty_client_socket(client, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW)) < 0) {
fprintf(stderr, "%s: %s: %s\n", fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_client_socket()", strerror(errno)); argv[0], "patty_client_socket()", strerror(errno));
@ -63,16 +65,16 @@ int main(int argc, char **argv) {
ifreq.state = PATTY_AX25_SOCK_PROMISC; ifreq.state = PATTY_AX25_SOCK_PROMISC;
if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) { if (patty_client_setsockopt(client, info.fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
fprintf(stderr, "%s: %s: %s\n", fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_client_setsockopt()", strerror(errno)); argv[0], "patty_client_setsockopt()", strerror(errno));
goto error_client_setsockopt; goto error_client_setsockopt;
} }
if ((raw = patty_kiss_tnc_new_fd(fd, NULL)) == NULL) { if ((raw = patty_kiss_tnc_new(&info)) == NULL) {
fprintf(stderr, "%s: fd %d: %s: %s\n", fprintf(stderr, "%s: fd %d: %s: %s\n",
argv[0], fd, "patty_kiss_tnc_new_fd()", strerror(errno)); argv[0], info.fd, "patty_kiss_tnc_new_fd()", strerror(errno));
goto error_kiss_tnc_new_fd; goto error_kiss_tnc_new_fd;
} }
@ -137,7 +139,7 @@ error_ax25_frame_decode_address:
patty_kiss_tnc_destroy(raw); patty_kiss_tnc_destroy(raw);
patty_client_close(client, fd); patty_client_close(client, info.fd);
patty_client_destroy(client); patty_client_destroy(client);
@ -149,7 +151,7 @@ error_io:
error_kiss_tnc_new_fd: error_kiss_tnc_new_fd:
error_client_setsockopt: error_client_setsockopt:
error_client_socket: error_client_socket:
(void)patty_client_close(client, fd); (void)patty_client_close(client, info.fd);
error_client_new: error_client_new:
return 1; return 1;

View file

@ -1,157 +0,0 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <patty/ax25.h>
#include <patty/daemon.h>
#include "../src/config.h"
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 /dev/ttyXX|kiss.cap [path.sock] callsign\n", argv[0]);
exit(1);
}
int main(int argc, char **argv) {
patty_daemon *daemon;
patty_ax25_if_kiss_tnc_info info = {
.type = PATTY_AX25_IF_KISS_TNC_INFO_FD,
.flags = PATTY_KISS_TNC_BAUD
| PATTY_KISS_TNC_FLOW,
.baud = B9600,
.flow = PATTY_KISS_TNC_FLOW_CRTSCTS
};
if (argc < 2) {
usage(argc, argv, "No TNC device or KISS dump file provided");
} else if (argc < 3) {
usage(argc, argv, "No socket path provided");
} else if (argc < 4) {
usage(argc, argv, "No station callsign provided");
} else if (argc > 4) {
usage(argc, argv, "Too many arguments provided");
}
if (strcmp(argv[1], "/dev/ptmx") == 0) {
int ptysub;
char ptyname[256];
if (openpty(&info.fd, &ptysub, ptyname, NULL, NULL) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "openpty()", strerror(errno));
goto error_open;
}
if (grantpt(info.fd) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], ptyname, "grantpt()", strerror(errno));
goto error_grantpt;
}
if (unlockpt(info.fd) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], ptyname, "unlockpt()", strerror(errno));
goto error_unlockpt;
}
fprintf(stderr, "pts %s\n", ptyname);
} else {
if ((info.fd = open(argv[1], O_RDWR | O_NOCTTY)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "open()", argv[1], strerror(errno));
goto error_open;
}
}
errno = 0;
if ((daemon = patty_daemon_new()) == NULL) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_new()", strerror(errno));
goto error_daemon_new;
}
if (argc >= 3) {
if (patty_daemon_set_sock_path(daemon, argv[2]) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_set_sock_path()", strerror(errno));
goto error_daemon_set_sock_path;
}
}
if (patty_daemon_init(daemon) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_init()", strerror(errno));
goto error_daemon_init;
}
if (patty_daemon_if_add(daemon,
PATTY_AX25_IF_KISS_TNC,
(patty_ax25_if_info *)&info,
argv[3]) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_if_add()", strerror(errno));
goto error_daemon_if_add;
}
if (patty_daemon_route_add_default(daemon, "kiss0") < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_route_add_default()", strerror(errno));
goto error_daemon_route_add_default;
}
if (patty_daemon_run(daemon) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], argv[1], "patty_daemon_run()", strerror(errno));
goto error_daemon_run;
}
patty_daemon_destroy(daemon);
return 0;
error_daemon_run:
error_daemon_route_add_default:
error_daemon_if_add:
error_daemon_set_sock_path:
error_daemon_init:
patty_daemon_destroy(daemon);
error_daemon_new:
error_grantpt:
error_unlockpt:
close(info.fd);
error_open:
return 1;
}

View file

@ -28,15 +28,21 @@ int main(int argc, char **argv) {
void *buf; void *buf;
int port; int port;
patty_kiss_tnc_info info;
if (argc > 2) { if (argc > 2) {
usage(argc, argv, NULL); usage(argc, argv, NULL);
} }
tnc = (argc == 2)? if (argc == 2) {
patty_kiss_tnc_new(argv[1], NULL): info.flags |= PATTY_KISS_TNC_DEVICE;
patty_kiss_tnc_new_fd(0, NULL); info.device = argv[1];
} else {
info.flags |= PATTY_KISS_TNC_FD;
info.fd = 0;
}
if (tnc == NULL) { if ((tnc = patty_kiss_tnc_new(&info)) == NULL) {
perror("Unable to open TNC"); perror("Unable to open TNC");
goto error_kiss_tnc_open; goto error_kiss_tnc_open;

View file

@ -1,6 +0,0 @@
sock /var/run/patty.sock
pid /var/run/patty.pid
if tnc0 ax25 KZ3ROX kiss /dev/ttyUSB0 baud 9600
route default if tnc0
route station GB9BLM path KX5UXQ WX3RKR
listen tnc0 ssid 0 exec /usr/bin/login -l -h @peer

5
examples/pattyd.conf Normal file
View file

@ -0,0 +1,5 @@
sock /var/run/patty.sock
pid /var/run/patty.pid
if kiss0 ax25 N7MMX kiss /dev/ttyUSB0 baud 9600
route default if kiss0
route station GB9BLM if kiss0 path KX4EHF WX9KIP

View file

@ -52,25 +52,10 @@ typedef struct _patty_ax25_if {
patty_dict *promisc_fds; patty_dict *promisc_fds;
} patty_ax25_if; } patty_ax25_if;
enum patty_ax25_if_kiss_tnc_info_type {
PATTY_AX25_IF_KISS_TNC_INFO_FD,
PATTY_AX25_IF_KISS_TNC_INFO_PATH
};
typedef struct _patty_ax25_if_kiss_tnc_info {
int flags;
speed_t baud;
enum patty_kiss_tnc_flow flow;
enum patty_ax25_if_kiss_tnc_info_type type;
int fd;
char path[256];
} patty_ax25_if_kiss_tnc_info;
typedef void patty_ax25_if_info; typedef void patty_ax25_if_info;
patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type, patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
const char *name,
patty_ax25_if_info *info, patty_ax25_if_info *info,
patty_ax25_addr *addr); patty_ax25_addr *addr);

View file

@ -3,7 +3,7 @@
typedef struct _patty_ax25_server patty_ax25_server; typedef struct _patty_ax25_server patty_ax25_server;
patty_ax25_server *patty_ax25_server_new(const char *path); patty_ax25_server *patty_ax25_server_new();
void patty_ax25_server_destroy(patty_ax25_server *server); void patty_ax25_server_destroy(patty_ax25_server *server);
@ -35,7 +35,7 @@ int patty_ax25_server_route_each(patty_ax25_server *server,
int (*callback)(patty_ax25_route *, void *), int (*callback)(patty_ax25_route *, void *),
void *ctx); void *ctx);
int patty_ax25_server_start(patty_ax25_server *server); int patty_ax25_server_start(patty_ax25_server *server, const char *path);
int patty_ax25_server_stop(patty_ax25_server *server); int patty_ax25_server_stop(patty_ax25_server *server);

22
include/patty/conf.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef _PATTY_CONF_H
#define _PATTY_CONF_H
#include <patty/list.h>
typedef struct _patty_conf_file patty_conf_file;
typedef struct _patty_conf_token {
char *text;
size_t lineno,
column,
len;
} patty_conf_token;
typedef int (*patty_conf_handler)(patty_conf_file *, patty_list *, void *);
int patty_conf_read(const char *file,
patty_conf_handler handler,
void *ctx);
#endif /* _PATTY_CONF_H */

View file

@ -10,8 +10,6 @@ patty_daemon *patty_daemon_new();
void patty_daemon_destroy(patty_daemon *daemon); void patty_daemon_destroy(patty_daemon *daemon);
int patty_daemon_init(patty_daemon *daemon);
int patty_daemon_run(patty_daemon *daemon); int patty_daemon_run(patty_daemon *daemon);
int patty_daemon_set_sock_path(patty_daemon *daemon, const char *path); int patty_daemon_set_sock_path(patty_daemon *daemon, const char *path);
@ -19,9 +17,7 @@ int patty_daemon_set_sock_path(patty_daemon *daemon, const char *path);
int patty_daemon_set_pidfile(patty_daemon *daemon, const char *path); int patty_daemon_set_pidfile(patty_daemon *daemon, const char *path);
int patty_daemon_if_add(patty_daemon *daemon, int patty_daemon_if_add(patty_daemon *daemon,
enum patty_ax25_if_type type, patty_ax25_if *iface);
patty_ax25_if_info *info,
const char *callsign);
int patty_daemon_route_add(patty_daemon *daemon, int patty_daemon_route_add(patty_daemon *daemon,
const char *ifname, const char *ifname,

View file

@ -35,8 +35,10 @@ ssize_t patty_kiss_frame_send(int fd,
typedef struct _patty_kiss_tnc patty_kiss_tnc; typedef struct _patty_kiss_tnc patty_kiss_tnc;
#define PATTY_KISS_TNC_BAUD (1 << 0) #define PATTY_KISS_TNC_DEVICE (1 << 0)
#define PATTY_KISS_TNC_FLOW (1 << 1) #define PATTY_KISS_TNC_FD (1 << 1)
#define PATTY_KISS_TNC_BAUD (1 << 2)
#define PATTY_KISS_TNC_FLOW (1 << 3)
enum patty_kiss_tnc_flow { enum patty_kiss_tnc_flow {
PATTY_KISS_TNC_FLOW_NONE, PATTY_KISS_TNC_FLOW_NONE,
@ -47,15 +49,13 @@ enum patty_kiss_tnc_flow {
typedef struct _patty_kiss_tnc_info { typedef struct _patty_kiss_tnc_info {
int flags; int flags;
const char *device;
int fd;
speed_t baud; speed_t baud;
enum patty_kiss_tnc_flow flow; enum patty_kiss_tnc_flow flow;
} patty_kiss_tnc_info; } patty_kiss_tnc_info;
patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd, patty_kiss_tnc *patty_kiss_tnc_new(patty_kiss_tnc_info *info);
patty_kiss_tnc_info *info);
patty_kiss_tnc *patty_kiss_tnc_new(const char *device,
patty_kiss_tnc_info *info);
int patty_kiss_tnc_fd(patty_kiss_tnc *tnc); int patty_kiss_tnc_fd(patty_kiss_tnc *tnc);

View file

@ -9,11 +9,11 @@ LDFLAGS = -lutil
HEADERS = kiss.h ax25.h client.h ax25/if.h ax25/frame.h \ HEADERS = kiss.h ax25.h client.h ax25/if.h ax25/frame.h \
ax25/sock.h ax25/route.h ax25/server.h daemon.h list.h \ ax25/sock.h ax25/route.h ax25/server.h daemon.h list.h \
hash.h dict.h timer.h print.h hash.h dict.h timer.h print.h conf.h
OBJS = kiss.o ax25.o client.o if.o frame.o \ OBJS = kiss.o ax25.o client.o if.o frame.o \
sock.o route.o server.o daemon.o list.o \ sock.o route.o server.o daemon.o list.o \
hash.o dict.o timer.o print.o hash.o dict.o timer.o print.o conf.o
VERSION_MAJOR = 0 VERSION_MAJOR = 0
VERSION_MINOR = 0.1 VERSION_MINOR = 0.1

358
src/conf.c Normal file
View file

@ -0,0 +1,358 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <patty/list.h>
#include <patty/conf.h>
enum state {
STRING,
STRING_SINGLE_QUOTE,
STRING_DOUBLE_QUOTE,
DELIM,
COMMENT
};
enum escape {
ESCAPE_OFF,
ESCAPE_ON
};
struct _patty_conf_file {
const char *path;
size_t size;
void *buf;
};
static int file_read(patty_conf_file *file, const char *path) {
int fd;
struct stat st;
size_t offset,
left;
if ((fd = open(path, O_RDONLY)) < 0) {
goto error_open;
}
if (fstat(fd, &st) < 0) {
goto error_fstat;
}
if ((file->buf = malloc(st.st_size)) == NULL) {
goto error_malloc_buf;
}
offset = 0;
left = st.st_size;
while (1) {
ssize_t len;
if ((len = read(fd,
(uint8_t *)file->buf + offset,
left > st.st_blksize? st.st_blksize: left)) < 0) {
goto error_read;
} else if (len < st.st_blksize) {
break;
} else {
offset += len;
left -= len;
}
}
(void)close(fd);
file->size = st.st_size;
file->path = path;
return 0;
error_read:
free(file->buf);
error_malloc_buf:
error_fstat:
(void)close(fd);
error_open:
return -1;
}
static void file_free(patty_conf_file *file) {
free(file->buf);
}
static void token_start(patty_conf_token *token,
char *text,
size_t lineno,
size_t column) {
token->text = text;
token->lineno = lineno;
token->column = column;
token->len = 0;
}
static int token_save(patty_list *list, patty_conf_token *token) {
patty_conf_token *copy;
if ((copy = malloc(sizeof(*token))) == NULL) {
goto error_malloc;
}
memcpy(copy, token, sizeof(*copy));
memset(token, '\0', sizeof(*token));
if (patty_list_append(list, copy) == NULL) {
goto error_list_append;
}
return 0;
error_list_append:
free(copy);
error_malloc:
return -1;
}
static void line_destroy(patty_list *list) {
patty_list_item *item = list->first;
while (item) {
patty_list_item *next = item->next;
free(item->value);
free(item);
item = next;
}
free(list);
}
static inline int start_of_string(enum state old, enum state state) {
switch (state) {
case STRING:
case STRING_SINGLE_QUOTE:
case STRING_DOUBLE_QUOTE:
if (old == DELIM) {
return 1;
}
default:
break;
}
return 0;
}
static inline int end_of_string(enum state old, enum state state) {
switch (old) {
case STRING:
case STRING_SINGLE_QUOTE:
case STRING_DOUBLE_QUOTE:
if (state == DELIM || state == COMMENT) {
return 1;
}
default:
break;
}
return 0;
}
static inline int within_string(enum state old, enum state state) {
switch (state) {
case STRING:
if (old != STRING_SINGLE_QUOTE && old != STRING_DOUBLE_QUOTE) {
return 1;
}
break;
case STRING_SINGLE_QUOTE:
case STRING_DOUBLE_QUOTE:
if (old == state) {
return 1;
}
default:
break;
}
return 0;
}
static inline int char_delim(uint8_t c) {
return (c == ' ' || c == '\r' || c == '\n' || c == '\t')? 1: 0;
}
int patty_conf_read(const char *path,
patty_conf_handler handler,
void *ctx) {
patty_conf_file file;
patty_list *line;
patty_conf_token token;
enum state state = STRING;
enum escape escape = ESCAPE_OFF;
size_t i,
o,
lineno = 1,
column = 0;
if (file_read(&file, path) < 0) {
goto error_file_read;
}
if ((line = patty_list_new()) == NULL) {
goto error_list_new;
}
token_start(&token, file.buf, lineno, column);
for (i=0, o=0; i<file.size; i++) {
enum state old = state;
uint8_t c = ((uint8_t *)file.buf)[i];
if (c == '\n') {
lineno++;
column = 1;
} else {
column++;
}
switch (state) {
case STRING:
if (c == '\\' && escape == ESCAPE_OFF) {
escape = ESCAPE_ON;
} else if (char_delim(c)) {
state = DELIM;
} else if (c == '\'') {
state = STRING_SINGLE_QUOTE;
} else if (c == '"') {
state = STRING_DOUBLE_QUOTE;
} else if (c == '#') {
state = COMMENT;
}
break;
case STRING_SINGLE_QUOTE:
if (c == '\'') {
state = STRING;
}
break;
case STRING_DOUBLE_QUOTE:
if (c == '\\' && escape == ESCAPE_OFF) {
escape = ESCAPE_ON;
} else if (c == '"' && escape == ESCAPE_OFF) {
state = STRING;
}
break;
case DELIM:
if (c == '\\' && escape == ESCAPE_OFF) {
escape = ESCAPE_ON;
} else if (c == '\'') {
state = STRING_SINGLE_QUOTE;
} else if (c == '"') {
state = STRING_DOUBLE_QUOTE;
} else if (c == '#') {
state = COMMENT;
} else if (!char_delim(c)) {
state = STRING;
}
break;
case COMMENT:
if (c == '\n') {
state = DELIM;
}
break;
}
if (start_of_string(old, state)) {
token_start(&token,
(char *)file.buf + o,
lineno,
column);
}
if (within_string(old, state)) {
if (escape == ESCAPE_OFF) {
((char *)file.buf)[o++] = c;
token.len++;
}
} else if (end_of_string(old, state)) {
((char *)file.buf)[o++] = '\0';
if (token_save(line, &token) < 0) {
goto error_token_save;
}
}
if (c == '\n' && escape == ESCAPE_OFF) {
if (line->length > 0) {
if (handler(&file, line, ctx) < 0) {
goto error_handler;
}
line_destroy(line);
if ((line = patty_list_new()) == NULL) {
goto error_list_new;
}
}
}
if (escape == ESCAPE_ON) {
escape = ESCAPE_OFF;
}
}
if (token.len) {
((char *)file.buf)[o++] = '\0';
if (token_save(line, &token) < 0) {
goto error_token_save;
}
}
if (line->length > 0) {
if (handler(&file, line, ctx) < 0) {
goto error_handler;
}
}
line_destroy(line);
file_free(&file);
return 0;
error_handler:
error_token_save:
patty_list_destroy(line);
error_list_new:
file_free(&file);
error_file_read:
return -1;
}

View file

@ -1,5 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <patty/ax25.h> #include <patty/ax25.h>
#include <patty/daemon.h> #include <patty/daemon.h>
@ -28,8 +29,15 @@ patty_daemon *patty_daemon_new() {
goto error_set_pidfile; goto error_set_pidfile;
} }
if ((daemon->server = patty_ax25_server_new()) == NULL) {
goto error_server_new;
}
return daemon; return daemon;
error_server_new:
free(daemon->pidfile);
error_set_pidfile: error_set_pidfile:
free(daemon->sock_path); free(daemon->sock_path);
@ -41,24 +49,23 @@ error_malloc:
} }
void patty_daemon_destroy(patty_daemon *daemon) { void patty_daemon_destroy(patty_daemon *daemon) {
if (daemon->server) {
patty_ax25_server_destroy(daemon->server); patty_ax25_server_destroy(daemon->server);
}
if (daemon->sock_path) {
free(daemon->sock_path);
}
if (daemon->pidfile) {
free(daemon->pidfile);
}
free(daemon); free(daemon);
} }
int patty_daemon_init(patty_daemon *daemon) {
if ((daemon->server = patty_ax25_server_new(daemon->sock_path)) == NULL) {
goto error_server_new;
}
return 0;
error_server_new:
return -1;
}
int patty_daemon_run(patty_daemon *daemon) { int patty_daemon_run(patty_daemon *daemon) {
if (patty_ax25_server_start(daemon->server) < 0) { if (patty_ax25_server_start(daemon->server, daemon->sock_path) < 0) {
goto error_server_start; goto error_server_start;
} }
@ -110,25 +117,8 @@ error_strdup:
} }
int patty_daemon_if_add(patty_daemon *daemon, int patty_daemon_if_add(patty_daemon *daemon,
enum patty_ax25_if_type type, patty_ax25_if *iface) {
patty_ax25_if_info *info,
const char *callsign) {
patty_ax25_if *iface;
patty_ax25_addr addr;
if (patty_ax25_pton(callsign, &addr) < 0) {
goto error_pton;
}
if ((iface = patty_ax25_if_new(type, info, &addr)) == NULL) {
goto error_if_new;
}
return patty_ax25_server_if_add(daemon->server, iface); return patty_ax25_server_if_add(daemon->server, iface);
error_if_new:
error_pton:
return -1;
} }
int patty_daemon_route_add(patty_daemon *daemon, int patty_daemon_route_add(patty_daemon *daemon,

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -7,22 +6,13 @@
#include <patty/ax25.h> #include <patty/ax25.h>
static int init_tnc(patty_ax25_if *iface, patty_ax25_if_kiss_tnc_info *info) { static int init_tnc(patty_ax25_if *iface, patty_kiss_tnc_info *info) {
static char *prefix = "kiss"; if ((iface->tnc = patty_kiss_tnc_new(info)) == NULL) {
static int number = 0;
iface->tnc = (info->type == PATTY_AX25_IF_KISS_TNC_INFO_FD)?
patty_kiss_tnc_new_fd(info->fd, (patty_kiss_tnc_info *)info):
patty_kiss_tnc_new(info->path, (patty_kiss_tnc_info *)info);
if (iface->tnc == NULL) {
goto error_kiss_tnc_new; goto error_kiss_tnc_new;
} }
iface->type = PATTY_AX25_IF_KISS_TNC; iface->type = PATTY_AX25_IF_KISS_TNC;
snprintf(iface->name, sizeof(iface->name), "%s%d", prefix, number++);
return 0; return 0;
error_kiss_tnc_new: error_kiss_tnc_new:
@ -34,6 +24,7 @@ static void destroy_tnc(patty_ax25_if *iface) {
} }
patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type, patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
const char *name,
patty_ax25_if_info *info, patty_ax25_if_info *info,
patty_ax25_addr *addr) { patty_ax25_addr *addr) {
patty_ax25_if *iface; patty_ax25_if *iface;
@ -44,6 +35,8 @@ patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
memset(iface, '\0', sizeof(*iface)); memset(iface, '\0', sizeof(*iface));
strncpy(iface->name, name, sizeof(iface->name));
if (addr->callsign[0] == '\0') { if (addr->callsign[0] == '\0') {
errno = EINVAL; errno = EINVAL;
@ -78,7 +71,7 @@ patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
switch (type) { switch (type) {
case PATTY_AX25_IF_KISS_TNC: case PATTY_AX25_IF_KISS_TNC:
if (init_tnc(iface, (patty_ax25_if_kiss_tnc_info *)info) < 0) { if (init_tnc(iface, info) < 0) {
goto error_init; goto error_init;
} }

View file

@ -13,6 +13,8 @@
#include <patty/kiss.h> #include <patty/kiss.h>
#include "config.h"
enum kiss_flags { enum kiss_flags {
KISS_NONE = 0, KISS_NONE = 0,
KISS_FRAME = 1 << 0, KISS_FRAME = 1 << 0,
@ -120,8 +122,7 @@ error_io:
return -1; return -1;
} }
patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd, patty_kiss_tnc *patty_kiss_tnc_new(patty_kiss_tnc_info *info) {
patty_kiss_tnc_info *info) {
patty_kiss_tnc *tnc; patty_kiss_tnc *tnc;
if ((tnc = malloc(sizeof(*tnc))) == NULL) { if ((tnc = malloc(sizeof(*tnc))) == NULL) {
@ -132,8 +133,54 @@ patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd,
goto error_malloc_buf; goto error_malloc_buf;
} }
if (isatty(fd) && ptsname(fd) == NULL) { if (info->flags & PATTY_KISS_TNC_DEVICE) {
if (tcgetattr(fd, &tnc->attrs) < 0) { struct stat st;
if (strcmp(info->device, "/dev/ptmx") == 0) {
int ptysub;
if (openpty(&tnc->fd, &ptysub, NULL, NULL, NULL) < 0) {
goto error_open;
}
} else if (stat(info->device, &st) < 0) {
goto error_stat;
} else if ((st.st_mode & S_IFMT) == S_IFSOCK) {
struct sockaddr_un addr;
if (strlen(info->device) > sizeof(addr.sun_path)) {
errno = EOVERFLOW;
goto error_overflow;
}
if ((tnc->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, info->device, sizeof(addr.sun_path)-1);
if (connect(tnc->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
} else {
if ((tnc->fd = open(info->device, O_RDWR | O_NOCTTY)) < 0) {
goto error_open;
}
}
tnc->opts |= TNC_CLOSE_ON_DESTROY;
} else if (info->flags & PATTY_KISS_TNC_FD) {
tnc->fd = info->fd;
} else {
errno = EINVAL;
goto error_no_fd;
}
if (isatty(tnc->fd) && ptsname(tnc->fd) == NULL) {
if (tcgetattr(tnc->fd, &tnc->attrs) < 0) {
goto error_tcgetattr; goto error_tcgetattr;
} }
@ -141,7 +188,6 @@ patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd,
cfmakeraw(&tnc->attrs); cfmakeraw(&tnc->attrs);
if (info) {
if (info->flags & PATTY_KISS_TNC_BAUD) { if (info->flags & PATTY_KISS_TNC_BAUD) {
cfsetspeed(&tnc->attrs, info->baud); cfsetspeed(&tnc->attrs, info->baud);
} }
@ -162,20 +208,18 @@ patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd,
break; break;
} }
} }
}
if (tcflush(fd, TCIOFLUSH) < 0) { if (tcflush(tnc->fd, TCIOFLUSH) < 0) {
goto error_tcflush; goto error_tcflush;
} }
if (tcsetattr(fd, TCSANOW, &tnc->attrs) < 0) { if (tcsetattr(tnc->fd, TCSANOW, &tnc->attrs) < 0) {
goto error_tcsetattr; goto error_tcsetattr;
} }
} else { } else {
errno = 0; errno = 0;
} }
tnc->fd = fd;
tnc->opts = TNC_NONE; tnc->opts = TNC_NONE;
tnc->bufsz = PATTY_KISS_BUFSZ; tnc->bufsz = PATTY_KISS_BUFSZ;
tnc->offset = 0; tnc->offset = 0;
@ -187,6 +231,18 @@ patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd,
error_tcflush: error_tcflush:
error_tcsetattr: error_tcsetattr:
error_tcgetattr: error_tcgetattr:
error_connect:
if (info->flags & PATTY_KISS_TNC_DEVICE) {
(void)close(tnc->fd);
}
error_open:
error_no_fd:
error_socket:
error_overflow:
error_stat:
free(tnc->buf);
error_malloc_buf: error_malloc_buf:
free(tnc); free(tnc);
@ -194,61 +250,6 @@ error_malloc_tnc:
return NULL; return NULL;
} }
patty_kiss_tnc *patty_kiss_tnc_new(const char *device,
patty_kiss_tnc_info *info) {
patty_kiss_tnc *tnc;
int fd;
struct stat st;
if (stat(device, &st) < 0) {
goto error_stat;
}
if ((st.st_mode & S_IFMT) == S_IFSOCK) {
struct sockaddr_un addr;
if (strlen(device) > sizeof(addr.sun_path)) {
errno = EOVERFLOW;
goto error_overflow;
}
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, device, sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
} else {
if ((fd = open(device, O_RDWR | O_NOCTTY)) < 0) {
goto error_open;
}
}
if ((tnc = patty_kiss_tnc_new_fd(fd, info)) == NULL) {
goto error_tnc_new_fd;
}
tnc->opts |= TNC_CLOSE_ON_DESTROY;
return tnc;
error_tnc_new_fd:
error_connect:
close(fd);
error_socket:
error_overflow:
error_open:
error_stat:
return NULL;
}
int patty_kiss_tnc_fd(patty_kiss_tnc *tnc) { int patty_kiss_tnc_fd(patty_kiss_tnc *tnc) {
return tnc->fd; return tnc->fd;
} }
@ -259,7 +260,7 @@ void patty_kiss_tnc_destroy(patty_kiss_tnc *tnc) {
} }
if (tnc->opts & TNC_CLOSE_ON_DESTROY) { if (tnc->opts & TNC_CLOSE_ON_DESTROY) {
close(tnc->fd); (void)close(tnc->fd);
} }
free(tnc->buf); free(tnc->buf);

View file

@ -16,8 +16,6 @@
typedef int (*patty_ax25_server_call)(patty_ax25_server *, int); typedef int (*patty_ax25_server_call)(patty_ax25_server *, int);
struct _patty_ax25_server { struct _patty_ax25_server {
char path[PATTY_AX25_SOCK_PATH_SIZE];
int fd, /* fd of UNIX domain socket */ int fd, /* fd of UNIX domain socket */
fd_max; fd_max;
@ -38,7 +36,7 @@ struct _patty_ax25_server {
*clients_by_sock; *clients_by_sock;
}; };
patty_ax25_server *patty_ax25_server_new(const char *path) { patty_ax25_server *patty_ax25_server_new() {
patty_ax25_server *server; patty_ax25_server *server;
if ((server = malloc(sizeof(*server))) == NULL) { if ((server = malloc(sizeof(*server))) == NULL) {
@ -47,8 +45,6 @@ patty_ax25_server *patty_ax25_server_new(const char *path) {
memset(server, '\0', sizeof(*server)); memset(server, '\0', sizeof(*server));
strncpy(server->path, path, sizeof(server->path)-1);
if ((server->ifaces = patty_list_new()) == NULL) { if ((server->ifaces = patty_list_new()) == NULL) {
goto error_list_new_ifaces; goto error_list_new_ifaces;
} }
@ -2296,8 +2292,8 @@ static int handle_socks(patty_ax25_server *server) {
return patty_dict_each(server->socks_by_fd, handle_sock, server); return patty_dict_each(server->socks_by_fd, handle_sock, server);
} }
int patty_ax25_server_start(patty_ax25_server *server) { int patty_ax25_server_start(patty_ax25_server *server, const char *path) {
return listen_unix(server, server->path); return listen_unix(server, path);
} }
int patty_ax25_server_stop(patty_ax25_server *server) { int patty_ax25_server_stop(patty_ax25_server *server) {

View file

@ -130,8 +130,13 @@ static patty_ax25_sock *init_dgram(patty_ax25_sock *sock,
} }
static patty_ax25_sock *init_raw(patty_ax25_sock *sock) { static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
if ((sock->raw = patty_kiss_tnc_new_fd(sock->fd, NULL)) == NULL) { patty_kiss_tnc_info info = {
goto error_kiss_tnc_new_fd; .flags = PATTY_KISS_TNC_FD,
.fd = sock->fd
};
if ((sock->raw = patty_kiss_tnc_new(&info)) == NULL) {
goto error_kiss_tnc_new;
} }
sock->proto = PATTY_AX25_PROTO_NONE; sock->proto = PATTY_AX25_PROTO_NONE;
@ -140,7 +145,7 @@ static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
return sock; return sock;
error_kiss_tnc_new_fd: error_kiss_tnc_new:
(void)close(sock->fd); (void)close(sock->fd);
return NULL; return NULL;