Implement src/daemon.c

Implement src/daemon.c to provide a high level method to instantiate a
patty server

Changes:

    * Refactor src/server.c, src/route.c, src/if.c methods which accept
      callsign arguments to use a patty_ax25_addr pointer instead; this
      has significantly reduced the number of redundant calls to
      patty_ax25_pton()

    * Decouple patty_ax25_addr from patty_ax25_if_info types when
      creating new interfaces with patty_ax25_if_new(); instead, take a
      separate patty_ax25_addr argument

    * Split patty_ax25_server_run() into the following methods:

          - patty_ax25_server_start()
          - patty_ax25_server_stop()
          - patty_ax25_server_event_handle()

      This is intended to allow possible integration into other event
      loops.

    * Implement src/daemon.c to allow quick instantiation of a server,
      interfaces, and routes, and to encapsulate the setting of
      configuration variables; callsigns and interface names are handled
      as character strings

    * Rename examples/server.c to examples/daemon.c; reimplement in
      terms of the patty_daemon code

    *
This commit is contained in:
XANTRONIX Development 2020-08-24 22:56:38 -05:00 committed by XANTRONIX Industrial
parent 0fecccd7c3
commit 9734c97f35
11 changed files with 328 additions and 236 deletions

View file

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

View file

@ -11,6 +11,7 @@
#include <errno.h> #include <errno.h>
#include <patty/ax25.h> #include <patty/ax25.h>
#include <patty/daemon.h>
static void usage(int argc, char **argv, const char *message, ...) { static void usage(int argc, char **argv, const char *message, ...) {
if (message != NULL) { if (message != NULL) {
@ -28,9 +29,7 @@ static void usage(int argc, char **argv, const char *message, ...) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
patty_ax25_server *server; patty_daemon *daemon;
patty_ax25_if *iface;
patty_ax25_route *route;
patty_ax25_if_kiss_tnc_info info = { patty_ax25_if_kiss_tnc_info info = {
.type = PATTY_AX25_IF_KISS_TNC_INFO_FD .type = PATTY_AX25_IF_KISS_TNC_INFO_FD
@ -64,52 +63,85 @@ int main(int argc, char **argv) {
} }
fprintf(stderr, "pts %s\n", pts); fprintf(stderr, "pts %s\n", pts);
} else {
struct termios t;
memset(&t, '\0', sizeof(t));
t.c_cflag = CS8 | CREAD | HUPCL | CRTSCTS;
t.c_iflag = IGNPAR;
t.c_cc[VTIME] = 0;
t.c_cc[VMIN] = 1;
cfsetspeed(&t, B9600);
if (tcsetattr(info.fd, TCSANOW, &t) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], argv[1], "tcsetattr()", strerror(errno));
}
} }
errno = 0; errno = 0;
patty_ax25_pton(argv[3], 0, &info.addr); if ((daemon = patty_daemon_new()) == NULL) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_new()", strerror(errno));
if ((server = patty_ax25_server_new(argc >= 3? argv[2]: PATTY_AX25_SERVER_PATH)) == NULL) { goto error_daemon_new;
goto error_server_new;
} }
if ((iface = patty_ax25_if_new(PATTY_AX25_IF_KISS_TNC, if (argc >= 3) {
(patty_ax25_if_info *)&info)) == NULL) { if (patty_daemon_set_sock_path(daemon, argv[2]) < 0) {
goto error_if_new; fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_set_sock_path()", strerror(errno));
goto error_daemon_set_sock_path;
}
} }
if (patty_ax25_server_add_if(server, iface) < 0) { if (patty_daemon_init(daemon) < 0) {
goto error_server_add_if; fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_init()", strerror(errno));
goto error_daemon_init;
} }
if ((route = patty_ax25_route_new_default(iface)) == NULL) { if (patty_daemon_if_add(daemon,
goto error_route_new_default; 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_ax25_server_add_route(server, route) < 0) { if (patty_daemon_route_add_default(daemon, "kiss0") < 0) {
goto error_server_add_route; fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_daemon_route_add_default()", strerror(errno));
goto error_daemon_route_add_default;
} }
if (patty_ax25_server_run(server) < 0) { if (patty_daemon_run(daemon) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n", fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], argv[1], "patty_ax25_server_run()", strerror(errno)); argv[0], argv[1], "patty_daemon_run()", strerror(errno));
goto error_server_run; goto error_daemon_run;
} }
patty_ax25_server_destroy(server); patty_daemon_destroy(daemon);
return 0; return 0;
error_server_run: error_daemon_run:
error_server_add_route: error_daemon_route_add_default:
error_route_new_default: error_daemon_if_add:
error_server_add_if: error_daemon_set_sock_path:
error_if_new: error_daemon_init:
patty_ax25_server_destroy(server); patty_daemon_destroy(daemon);
error_server_new: error_daemon_new:
close(info.fd); close(info.fd);
error_open: error_open:

View file

@ -9,16 +9,10 @@
#define PATTY_AX25_IF_DEFAULT_CLASSES \ #define PATTY_AX25_IF_DEFAULT_CLASSES \
(PATTY_AX25_PARAM_CLASSES_HALF_DUPLEX) (PATTY_AX25_PARAM_CLASSES_HALF_DUPLEX)
#define PATTY_AX25_IF_OPT_TYPE_MASK 0x1f
#define PATTY_AX25_IF_OPT_TYPE(n) \
((n) & PATTY_AX25_IF_OPT_TYPE_MASK)
#define PATTY_AX25_IF_DEFAULT_MTU 4096 #define PATTY_AX25_IF_DEFAULT_MTU 4096
#define PATTY_AX25_IF_DEFAULT_MRU 4096 #define PATTY_AX25_IF_DEFAULT_MRU 4096
enum patty_ax25_if_type { enum patty_ax25_if_type {
PATTY_AX25_IF_UNKNOWN,
PATTY_AX25_IF_KISS_TNC, PATTY_AX25_IF_KISS_TNC,
PATTY_AX25_IF_HDLC PATTY_AX25_IF_HDLC
}; };
@ -58,40 +52,35 @@ typedef struct _patty_ax25_if {
patty_dict *promisc_fds; patty_dict *promisc_fds;
} patty_ax25_if; } patty_ax25_if;
typedef struct _patty_ax25_if_info {
patty_ax25_addr addr;
unsigned int flags;
} patty_ax25_if_info;
enum patty_ax25_if_kiss_tnc_info_type { enum patty_ax25_if_kiss_tnc_info_type {
PATTY_AX25_IF_KISS_TNC_INFO_NONE,
PATTY_AX25_IF_KISS_TNC_INFO_FD, PATTY_AX25_IF_KISS_TNC_INFO_FD,
PATTY_AX25_IF_KISS_TNC_INFO_PATH PATTY_AX25_IF_KISS_TNC_INFO_PATH
}; };
typedef struct _patty_ax25_if_kiss_tnc_info { typedef struct _patty_ax25_if_kiss_tnc_info {
patty_ax25_addr addr;
unsigned int flags;
enum patty_ax25_if_kiss_tnc_info_type type; enum patty_ax25_if_kiss_tnc_info_type type;
int fd; int fd;
char path[256]; char path[256];
} patty_ax25_if_kiss_tnc_info; } patty_ax25_if_kiss_tnc_info;
patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info); typedef void patty_ax25_if_info;
patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
patty_ax25_if_info *info,
patty_ax25_addr *addr);
void patty_ax25_if_destroy(patty_ax25_if *iface); void patty_ax25_if_destroy(patty_ax25_if *iface);
int patty_ax25_if_addr_each(patty_ax25_if *iface, int patty_ax25_if_addr_each(patty_ax25_if *iface,
int (*callback)(char *, void *), void *ctx); int (*callback)(patty_ax25_addr *, void *),
void *ctx);
int patty_ax25_if_addr_add(patty_ax25_if *iface, const char *callsign); int patty_ax25_if_addr_add(patty_ax25_if *iface, patty_ax25_addr *addr);
int patty_ax25_if_addr_delete(patty_ax25_if *iface, const char *callsign); int patty_ax25_if_addr_delete(patty_ax25_if *iface, patty_ax25_addr *addr);
int patty_ax25_if_addr_match(patty_ax25_if *iface, int patty_ax25_if_addr_match(patty_ax25_if *iface, patty_ax25_addr *addr);
const patty_ax25_addr *addr);
int patty_ax25_if_promisc_add(patty_ax25_if *iface, int patty_ax25_if_promisc_add(patty_ax25_if *iface,
int fd); int fd);

View file

@ -2,37 +2,40 @@
#define _PATTY_AX25_ROUTE_H #define _PATTY_AX25_ROUTE_H
typedef struct _patty_ax25_route { typedef struct _patty_ax25_route {
patty_ax25_addr dest,
hops[PATTY_AX25_MAX_HOPS];
size_t nhops;
patty_ax25_if *iface; patty_ax25_if *iface;
patty_ax25_addr dest,
repeaters[PATTY_AX25_MAX_HOPS];
size_t hops;
} patty_ax25_route; } patty_ax25_route;
typedef struct _patty_dict patty_ax25_route_table; typedef struct _patty_dict patty_ax25_route_table;
patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface, patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface,
const char *callsign); patty_ax25_addr *dest,
patty_ax25_addr *repeaters,
int hops);
patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface); patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface);
int patty_ax25_route_add_hop(patty_ax25_route *route,
const char *callsign);
patty_ax25_route_table *patty_ax25_route_table_new(); patty_ax25_route_table *patty_ax25_route_table_new();
void patty_ax25_route_table_destroy(patty_ax25_route_table *table); void patty_ax25_route_table_destroy(patty_ax25_route_table *table);
patty_ax25_route *patty_ax25_route_table_find(patty_ax25_route_table *table,
patty_ax25_addr *dest);
patty_ax25_route *patty_ax25_route_table_default(patty_ax25_route_table *table);
int patty_ax25_route_table_add(patty_ax25_route_table *table, int patty_ax25_route_table_add(patty_ax25_route_table *table,
patty_ax25_route *route); patty_ax25_route *route);
int patty_ax25_route_table_delete(patty_ax25_route_table *route, int patty_ax25_route_table_delete(patty_ax25_route_table *route,
patty_ax25_addr *dest); patty_ax25_addr *dest);
patty_ax25_route *patty_ax25_route_table_find(patty_ax25_route_table *table,
patty_ax25_addr *dest);
patty_ax25_route *patty_ax25_route_table_default(patty_ax25_route_table *table);
int patty_ax25_route_table_each(patty_ax25_route_table *table,
int (*callback)(patty_ax25_route *, void *),
void *ctx);
#endif /* _PATTY_AX25_ROUTE_H */ #endif /* _PATTY_AX25_ROUTE_H */

View file

@ -1,31 +1,44 @@
#ifndef _PATTY_AX25_SERVER_H #ifndef _PATTY_AX25_SERVER_H
#define _PATTY_AX25_SERVER_H #define _PATTY_AX25_SERVER_H
#define PATTY_AX25_SERVER_PATH "/var/run/patty/patty.sock"
#define PATTY_AX25_SERVER_CLIENT_PATH_FORMAT "/var/run/patty/%d.sock"
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(const char *path);
void patty_ax25_server_destroy(patty_ax25_server *server); void patty_ax25_server_destroy(patty_ax25_server *server);
int patty_ax25_server_add_if(patty_ax25_server *server, int patty_ax25_server_if_add(patty_ax25_server *server,
patty_ax25_if *iface); patty_ax25_if *iface);
int patty_ax25_server_delete_if(patty_ax25_server *server, int patty_ax25_server_if_delete(patty_ax25_server *server,
patty_ax25_if *iface); const char *ifname);
patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server, patty_ax25_if *patty_ax25_server_if_get(patty_ax25_server *server,
const char *name); const char *ifname);
int patty_ax25_server_each_if(patty_ax25_server *server, int patty_ax25_server_if_each(patty_ax25_server *server,
int (*callback)(patty_ax25_if *, void *), int (*callback)(patty_ax25_if *, void *),
void *ctx); void *ctx);
int patty_ax25_server_add_route(patty_ax25_server *server, int patty_ax25_server_route_add(patty_ax25_server *server,
patty_ax25_route *route); patty_ax25_route *route);
int patty_ax25_server_run(patty_ax25_server *server); int patty_ax25_server_route_delete(patty_ax25_server *server,
patty_ax25_addr *dest);
patty_ax25_route *patty_ax25_server_route_find(patty_ax25_server *server,
patty_ax25_addr *dest);
patty_ax25_route *patty_ax25_server_route_default(patty_ax25_server *server);
int patty_ax25_server_route_each(patty_ax25_server *server,
int (*callback)(patty_ax25_route *, void *),
void *ctx);
int patty_ax25_server_start(patty_ax25_server *server);
int patty_ax25_server_stop(patty_ax25_server *server);
int patty_ax25_server_event_handle(patty_ax25_server *server);
#endif /* _PATTY_AX25_SERVER_H */ #endif /* _PATTY_AX25_SERVER_H */

35
include/patty/daemon.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef _PATTY_DAEMON_H
#define _PATTY_DAEMON_H
#define PATTY_AX25_DAEMON_SOCK_PATH "/var/run/patty/patty.sock"
#define PATTY_AX25_DAEMON_PIDFILE "/var/run/patty/patty.pid"
typedef struct _patty_daemon patty_daemon;
patty_daemon *patty_daemon_new();
void patty_daemon_destroy(patty_daemon *daemon);
int patty_daemon_init(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_pidfile(patty_daemon *daemon, const char *path);
int patty_daemon_if_add(patty_daemon *daemon,
enum patty_ax25_if_type type,
patty_ax25_if_info *info,
const char *callsign);
int patty_daemon_route_add(patty_daemon *daemon,
const char *ifname,
const char *dest,
const char **repeaters,
int hops);
int patty_daemon_route_add_default(patty_daemon *daemon,
const char *ifname);
#endif /* _PATTY_DAEMON_H */

View file

@ -8,12 +8,12 @@ CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
LDFLAGS = LDFLAGS =
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 list.h hash.h dict.h \ ax25/sock.h ax25/route.h ax25/server.h daemon.h list.h \
timer.h print.h hash.h dict.h timer.h print.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 list.o hash.o dict.o \ sock.o route.o server.o daemon.o list.o \
timer.o print.o hash.o dict.o timer.o print.o
VERSION_MAJOR = 0 VERSION_MAJOR = 0
VERSION_MINOR = 0.1 VERSION_MINOR = 0.1

View file

@ -1,3 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <patty/ax25.h>
#include <patty/daemon.h> #include <patty/daemon.h>
struct _patty_daemon { struct _patty_daemon {
@ -14,6 +18,8 @@ patty_daemon *patty_daemon_new() {
goto error_malloc; goto error_malloc;
} }
memset(daemon, '\0', sizeof(*daemon));
if (patty_daemon_set_sock_path(daemon, PATTY_AX25_DAEMON_SOCK_PATH) < 0) { if (patty_daemon_set_sock_path(daemon, PATTY_AX25_DAEMON_SOCK_PATH) < 0) {
goto error_set_sock_path; goto error_set_sock_path;
} }
@ -36,6 +42,8 @@ error_malloc:
void patty_daemon_destroy(patty_daemon *daemon) { void patty_daemon_destroy(patty_daemon *daemon) {
patty_ax25_server_destroy(daemon->server); patty_ax25_server_destroy(daemon->server);
free(daemon);
} }
int patty_daemon_init(patty_daemon *daemon) { int patty_daemon_init(patty_daemon *daemon) {
@ -65,6 +73,9 @@ int patty_daemon_run(patty_daemon *daemon) {
return 0; return 0;
error_server_event_handle: error_server_event_handle:
patty_ax25_server_stop(daemon->server);
error_server_start:
return -1; return -1;
} }
@ -98,26 +109,33 @@ error_strdup:
return -1; return -1;
} }
int patty_ax25_daemon_if_add(patty_ax25_daemon *daemon, int patty_daemon_if_add(patty_daemon *daemon,
int opts, enum patty_ax25_if_type type,
patty_ax25_if_info *info) { patty_ax25_if_info *info,
const char *callsign) {
patty_ax25_if *iface; patty_ax25_if *iface;
patty_ax25_addr addr;
if ((iface = patty_ax25_if_new(opts, info)) == NULL) { if (patty_ax25_pton(callsign, &addr) < 0) {
goto error_pton;
}
if ((iface = patty_ax25_if_new(type, info, &addr)) == NULL) {
goto error_if_new; goto error_if_new;
} }
return patty_ax25_server_add_if(daemon->server, iface); return patty_ax25_server_if_add(daemon->server, iface);
error_if_new: error_if_new:
error_pton:
return -1; return -1;
} }
int patty_ax25_daemon_route_add(patty_ax25_daemon *daemon, int patty_daemon_route_add(patty_daemon *daemon,
const char *ifname, const char *ifname,
const char *dest, const char *dest,
const char **repeaters, const char **repeaters,
int hops) { int hops) {
patty_ax25_route *route; patty_ax25_route *route;
patty_ax25_if *iface; patty_ax25_if *iface;
@ -131,7 +149,7 @@ int patty_ax25_daemon_route_add(patty_ax25_daemon *daemon,
goto error_malloc_route; goto error_malloc_route;
} }
memset(&route, '\0', sizeof(route)); memset(route, '\0', sizeof(*route));
route->iface = iface; route->iface = iface;
@ -157,7 +175,7 @@ error_server_if_get:
return -1; return -1;
} }
int patty_daemon_route_add_default(patty_ax25_daemon *daemon, int patty_daemon_route_add_default(patty_daemon *daemon,
const char *ifname) { const char *ifname) {
return patty_daemon_route_add(daemon, ifname, NULL, NULL, 0); return patty_daemon_route_add(daemon, ifname, NULL, NULL, 0);
} }

101
src/if.c
View file

@ -33,7 +33,9 @@ static void destroy_tnc(patty_ax25_if *iface) {
patty_kiss_tnc_destroy(iface->tnc); patty_kiss_tnc_destroy(iface->tnc);
} }
patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) { patty_ax25_if *patty_ax25_if_new(enum patty_ax25_if_type type,
patty_ax25_if_info *info,
patty_ax25_addr *addr) {
patty_ax25_if *iface; patty_ax25_if *iface;
if ((iface = malloc(sizeof(*iface))) == NULL) { if ((iface = malloc(sizeof(*iface))) == NULL) {
@ -42,7 +44,7 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
memset(iface, '\0', sizeof(*iface)); memset(iface, '\0', sizeof(*iface));
if (info->addr.callsign[0] == '\0') { if (addr->callsign[0] == '\0') {
errno = EINVAL; errno = EINVAL;
goto error_invalid_address; goto error_invalid_address;
@ -74,7 +76,7 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
goto error_dict_new_promisc_fds; goto error_dict_new_promisc_fds;
} }
switch (PATTY_AX25_IF_OPT_TYPE(opts)) { 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, (patty_ax25_if_kiss_tnc_info *)info) < 0) {
goto error_init; goto error_init;
@ -83,12 +85,12 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
break; break;
default: default:
errno = EINVAL; errno = ENOSYS;
goto error_invalid_if_type; goto error_invalid_if_type;
} }
memcpy(&iface->addr, &info->addr, sizeof(iface->addr)); memcpy(&iface->addr, addr, sizeof(iface->addr));
return iface; return iface;
@ -132,27 +134,18 @@ void patty_ax25_if_destroy(patty_ax25_if *iface) {
} }
int patty_ax25_if_addr_each(patty_ax25_if *iface, int patty_ax25_if_addr_each(patty_ax25_if *iface,
int (*callback)(char *, void *), void *ctx) { int (*callback)(patty_ax25_addr *, void *),
void *ctx) {
patty_list_item *item = iface->aliases->first; patty_list_item *item = iface->aliases->first;
char buf[PATTY_AX25_ADDRESS_LEN+1]; if (callback(&iface->addr, ctx) < 0) {
goto error_callback;
if (patty_ax25_ntop(&iface->addr, buf, sizeof(buf)) < 0) {
goto error_ntop_addr;
}
if (callback(buf, ctx) < 0) {
goto error_callback_addr;
} }
while (item) { while (item) {
patty_ax25_addr *addr = item->value; patty_ax25_addr *addr = item->value;
if (patty_ax25_ntop(addr, buf, sizeof(buf)) < 0) { if (callback(addr, ctx) < 0) {
goto error_ntop;
}
if (callback(buf, ctx) < 0) {
goto error_callback; goto error_callback;
} }
@ -162,97 +155,70 @@ int patty_ax25_if_addr_each(patty_ax25_if *iface,
return 0; return 0;
error_callback: error_callback:
error_ntop:
error_callback_addr:
error_ntop_addr:
return -1; return -1;
} }
static patty_ax25_addr *find_addr(patty_ax25_if *iface, static patty_ax25_addr *find_addr(patty_ax25_if *iface,
const char *callsign) { patty_ax25_addr *addr) {
patty_list_item *item = iface->aliases->first; patty_list_item *item = iface->aliases->first;
char buf[PATTY_AX25_ADDRESS_LEN+1];
if (patty_ax25_ntop(&iface->addr, buf, sizeof(buf)) < 0) {
goto error_ntop_addr;
}
if (strncmp(buf, callsign, sizeof(buf)) == 0) {
return &iface->addr;
}
while (item) { while (item) {
patty_ax25_addr *addr = item->value; patty_ax25_addr *cur = item->value;
if (patty_ax25_ntop(addr, buf, sizeof(buf)) < 0) { if (memcpy(&addr->callsign,
goto error_ntop; &cur->callsign,
sizeof(addr->callsign)) == 0) {
return addr;
} }
if (strncmp(buf, callsign, sizeof(buf)) != 0) {
goto next;
}
return addr;
next:
item = item->next; item = item->next;
} }
error_ntop:
error_ntop_addr:
return NULL; return NULL;
} }
int patty_ax25_if_addr_add(patty_ax25_if *iface, int patty_ax25_if_addr_add(patty_ax25_if *iface,
const char *callsign) { patty_ax25_addr *addr) {
patty_ax25_addr *addr; patty_ax25_addr *alias;
if (find_addr(iface, callsign) != NULL) { if (find_addr(iface, addr) != NULL) {
errno = EADDRINUSE; errno = EADDRINUSE;
goto error_exists; goto error_exists;
} }
if ((addr = malloc(sizeof(*addr))) == NULL) { if ((alias = malloc(sizeof(*alias))) == NULL) {
goto error_malloc_addr; goto error_malloc_alias;
} }
if (patty_ax25_pton(callsign, addr) < 0) { memcpy(&alias->callsign, &addr->callsign, sizeof(alias->callsign));
goto error_pton;
}
addr->ssid = 0; addr->ssid = 0;
if ((patty_list_append(iface->aliases, addr)) == NULL) { if ((patty_list_append(iface->aliases, alias)) == NULL) {
goto error_list_append; goto error_list_append;
} }
return 0; return 0;
error_list_append: error_list_append:
error_pton: free(alias);
free(addr);
error_malloc_addr: error_malloc_alias:
error_exists: error_exists:
return -1; return -1;
} }
int patty_ax25_if_addr_delete(patty_ax25_if *iface, int patty_ax25_if_addr_delete(patty_ax25_if *iface, patty_ax25_addr *addr) {
const char *callsign) {
patty_list_item *item = iface->aliases->first; patty_list_item *item = iface->aliases->first;
int i = 0; int i = 0;
while (item) { while (item) {
char buf[PATTY_AX25_ADDRESS_LEN+1]; patty_ax25_addr *alias = item->value;
patty_ax25_addr *addr = item->value; if (memcmp(&addr->callsign,
&alias->callsign,
if (patty_ax25_ntop(addr, buf, sizeof(buf)) < 0) { sizeof(addr->callsign)) == 0) {
goto error_ntop;
}
if (strncmp(buf, callsign, sizeof(buf)) == 0) {
if (patty_list_splice(iface->aliases, i) == NULL) { if (patty_list_splice(iface->aliases, i) == NULL) {
goto error_list_splice; goto error_list_splice;
} }
@ -265,12 +231,11 @@ int patty_ax25_if_addr_delete(patty_ax25_if *iface,
return 0; return 0;
error_list_splice: error_list_splice:
error_ntop:
return -1; return -1;
} }
int patty_ax25_if_addr_match(patty_ax25_if *iface, int patty_ax25_if_addr_match(patty_ax25_if *iface,
const patty_ax25_addr *addr) { patty_ax25_addr *addr) {
patty_list_item *item; patty_list_item *item;
if (memcmp(&iface->addr.callsign, if (memcmp(&iface->addr.callsign,

View file

@ -8,48 +8,44 @@
#include <patty/ax25.h> #include <patty/ax25.h>
patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface, patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface,
const char *callsign) { patty_ax25_addr *dest,
patty_ax25_addr *repeaters,
int hops) {
patty_ax25_route *route; patty_ax25_route *route;
int i;
if (hops >= PATTY_AX25_MAX_HOPS) {
errno = EOVERFLOW;
goto error_max_hops;
}
if ((route = malloc(sizeof(*route))) == NULL) { if ((route = malloc(sizeof(*route))) == NULL) {
goto error_malloc_route; goto error_malloc_route;
} }
memset(route, '\0', sizeof(*route)); memset(route, '\0', sizeof(*route));
if (callsign) { route->iface = iface;
if (patty_ax25_pton(callsign, &route->dest) < 0) {
goto error_pton; if (dest) {
} patty_ax25_addr_copy(&route->dest, dest, 0);
} }
route->iface = iface; for (i=0; i<hops; i++) {
patty_ax25_addr_copy(&route->repeaters, &repeaters[i], 0);
}
return route; return route;
error_pton:
free(route);
error_malloc_route: error_malloc_route:
error_max_hops:
return NULL; return NULL;
} }
patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface) { patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface) {
return patty_ax25_route_new(iface, NULL); return patty_ax25_route_new(iface, NULL, NULL, 0);
}
int patty_ax25_route_add_hop(patty_ax25_route *route,
const char *callsign) {
if (route->nhops == PATTY_AX25_MAX_HOPS) {
errno = ENOMEM;
goto error_max_hops;
}
return patty_ax25_pton(callsign, &route->hops[route->nhops++]);
error_max_hops:
return -1;
} }
patty_ax25_route_table *patty_ax25_route_table_new() { patty_ax25_route_table *patty_ax25_route_table_new() {
@ -92,6 +88,28 @@ patty_ax25_route *patty_ax25_route_table_default(patty_ax25_route_table *table)
return patty_dict_get(table, hash); return patty_dict_get(table, hash);
} }
struct dict_ctx_wrapper {
int (*callback)(patty_ax25_route *route, void *);
void *ctx;
};
static int each_dict_callback(uint32_t key, void *value, void *ctx) {
struct dict_ctx_wrapper *wrapper = ctx;
return wrapper->callback(value, wrapper->ctx);
}
int patty_ax25_route_table_each(patty_ax25_route_table *table,
int (*callback)(patty_ax25_route *, void *),
void *ctx) {
struct dict_ctx_wrapper wrapper = {
.callback = callback,
.ctx = ctx
};
return patty_dict_each(table, each_dict_callback, &wrapper);
}
int patty_ax25_route_table_add(patty_ax25_route_table *table, int patty_ax25_route_table_add(patty_ax25_route_table *table,
patty_ax25_route *route) { patty_ax25_route *route) {
uint32_t hash; uint32_t hash;

View file

@ -132,7 +132,7 @@ void patty_ax25_server_destroy(patty_ax25_server *server) {
patty_dict_destroy(server->socks_by_client); patty_dict_destroy(server->socks_by_client);
patty_dict_destroy(server->socks_by_fd); patty_dict_destroy(server->socks_by_fd);
patty_ax25_server_each_if(server, destroy_if, NULL); patty_ax25_server_if_each(server, destroy_if, NULL);
patty_ax25_route_table_destroy(server->routes); patty_ax25_route_table_destroy(server->routes);
patty_list_destroy(server->ifaces); patty_list_destroy(server->ifaces);
@ -432,7 +432,7 @@ static inline void sock_flow_start(patty_ax25_server *server,
fd_watch(server, sock->fd); fd_watch(server, sock->fd);
} }
int patty_ax25_server_add_if(patty_ax25_server *server, int patty_ax25_server_if_add(patty_ax25_server *server,
patty_ax25_if *iface) { patty_ax25_if *iface) {
int fd; int fd;
@ -450,14 +450,20 @@ error_list_append:
return -1; return -1;
} }
int patty_ax25_server_delete_if(patty_ax25_server *server, int patty_ax25_server_if_delete(patty_ax25_server *server,
patty_ax25_if *iface) { const char *ifname) {
patty_list_item *item = server->ifaces->first; patty_list_item *item = server->ifaces->first;
int fd, i = 0; int fd, i = 0;
while (item) { while (item) {
if (item->value == iface) { patty_ax25_if *iface = item->value;
if (strncmp(iface->name, ifname, sizeof(iface->name)) == 0) {
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
fd_clear(server, fd);
}
if (patty_list_splice(server->ifaces, i) == NULL) { if (patty_list_splice(server->ifaces, i) == NULL) {
goto error_list_splice; goto error_list_splice;
} }
@ -469,17 +475,13 @@ int patty_ax25_server_delete_if(patty_ax25_server *server,
i++; i++;
} }
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
fd_clear(server, fd);
}
return 0; return 0;
error_list_splice: error_list_splice:
return -1; return -1;
} }
patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server, patty_ax25_if *patty_ax25_server_if_get(patty_ax25_server *server,
const char *name) { const char *name) {
patty_list_item *item = server->ifaces->first; patty_list_item *item = server->ifaces->first;
@ -496,7 +498,7 @@ patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server,
return NULL; return NULL;
} }
int patty_ax25_server_each_if(patty_ax25_server *server, int patty_ax25_server_if_each(patty_ax25_server *server,
int (*callback)(patty_ax25_if *, void *), int (*callback)(patty_ax25_if *, void *),
void *ctx) { void *ctx) {
patty_list_item *item = server->ifaces->first; patty_list_item *item = server->ifaces->first;
@ -517,11 +519,31 @@ error_callback:
return -1; return -1;
} }
int patty_ax25_server_add_route(patty_ax25_server *server, int patty_ax25_server_route_add(patty_ax25_server *server,
patty_ax25_route *route) { patty_ax25_route *route) {
return patty_ax25_route_table_add(server->routes, route); return patty_ax25_route_table_add(server->routes, route);
} }
int patty_ax25_server_route_delete(patty_ax25_server *server,
patty_ax25_addr *dest) {
return patty_ax25_route_table_delete(server->routes, dest);
}
patty_ax25_route *patty_ax25_server_route_find(patty_ax25_server *server,
patty_ax25_addr *dest) {
return patty_ax25_route_table_find(server->routes, dest);
}
patty_ax25_route *patty_ax25_server_route_default(patty_ax25_server *server) {
return patty_ax25_route_table_default(server->routes);
}
int patty_ax25_server_route_each(patty_ax25_server *server,
int (*callback)(patty_ax25_route *, void *),
void *ctx) {
return patty_ax25_route_table_each(server->routes, callback, ctx);
}
static int respond_accept(int client, static int respond_accept(int client,
int ret, int ret,
int eno) { int eno) {
@ -665,7 +687,7 @@ static int server_setsockopt(patty_ax25_server *server,
goto error_read; goto error_read;
} }
if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) { if ((iface = patty_ax25_server_if_get(server, data.name)) == NULL) {
response.ret = -1; response.ret = -1;
response.eno = ENODEV; response.eno = ENODEV;
@ -2274,66 +2296,63 @@ 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_run(patty_ax25_server *server) { int patty_ax25_server_start(patty_ax25_server *server) {
if (listen_unix(server, server->path) < 0) { return listen_unix(server, server->path);
goto error_listen_unix; }
int patty_ax25_server_stop(patty_ax25_server *server) {
return close(server->fd);
}
int patty_ax25_server_event_handle(patty_ax25_server *server) {
int nready;
struct timeval timeout = { 1, 0 };
struct timespec before,
after;
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) {
goto error_clock_gettime;
} }
while (1) { if ((nready = select( server->fd_max,
int nready; &server->fds_r,
NULL,
NULL,
&timeout)) < 0) {
goto error_io;
}
struct timeval timeout = { 1, 0 }; if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) {
goto error_clock_gettime;
}
struct timespec before, patty_timer_sub(&after, &before, &server->elapsed);
after;
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r)); if (handle_socks(server) < 0) {
goto error_io;
}
if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) { if (nready > 0) {
goto error_clock_gettime; if (handle_clients(server) < 0) {
}
if ((nready = select( server->fd_max,
&server->fds_r,
NULL,
NULL,
&timeout)) < 0) {
goto error_io; goto error_io;
} }
if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) { if (handle_ifaces(server) < 0) {
goto error_clock_gettime;
}
patty_timer_sub(&after, &before, &server->elapsed);
if (handle_socks(server) < 0) {
goto error_io; goto error_io;
} }
if (nready > 0) { if (accept_client(server) < 0) {
if (handle_clients(server) < 0) { goto error_io;
goto error_io;
}
if (handle_ifaces(server) < 0) {
goto error_io;
}
if (accept_client(server) < 0) {
goto error_io;
}
} }
} }
close(server->fd);
return 0; return 0;
error_clock_gettime: error_clock_gettime:
error_io: error_io:
close(server->fd);
error_listen_unix:
return -1; return -1;
} }