Making significant headway towards a working server

This commit is contained in:
XANTRONIX Development 2020-06-26 22:44:19 -04:00 committed by XANTRONIX Industrial
parent 22366f2d0c
commit bdb73c8805
14 changed files with 294 additions and 64 deletions

View file

@ -40,10 +40,28 @@ typedef struct _patty_ax25_if {
tx_bufsz;
patty_kiss_tnc *tnc;
patty_list *addrs;
patty_ax25_addr addr;
patty_list *aliases;
} patty_ax25_if;
patty_ax25_if *patty_ax25_if_new(int opts, void *info);
typedef struct _patty_ax25_if_info {
patty_ax25_addr addr;
} patty_ax25_if_info;
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_PATH
};
typedef struct _patty_ax25_if_kiss_tnc_info {
patty_ax25_addr addr;
enum patty_ax25_if_kiss_tnc_info_type type;
int fd;
char path[256];
} patty_ax25_if_kiss_tnc_info;
patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info);
void patty_ax25_if_destroy(patty_ax25_if *iface);

View file

@ -22,7 +22,7 @@ enum patty_ax25_proto {
PATTY_AX25_PROTO_INET_ARP = 0xcd,
PATTY_AX25_PROTO_FLEXNET = 0xce,
PATTY_AX25_PROTO_NETROM = 0xcf,
PATTY_AX25_PROTO_RAW = 0xf0,
PATTY_AX25_PROTO_NONE = 0xf0,
PATTY_AX25_PROTO_ESCAPE = 0xff
};

View file

@ -29,6 +29,8 @@ 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,
patty_ax25_route *route);

View file

@ -6,7 +6,7 @@
typedef struct _patty_ax25_server patty_ax25_server;
patty_ax25_server *patty_ax25_server_new();
patty_ax25_server *patty_ax25_server_new(const char *path);
void patty_ax25_server_destroy(patty_ax25_server *server);

View file

@ -55,4 +55,6 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type);
void patty_ax25_sock_destroy(patty_ax25_sock *sock);
int patty_ax25_sock_send_sabm(patty_ax25_sock *sock);
#endif /* _PATTY_AX25_SOCK_H */

View file

@ -29,13 +29,13 @@ enum patty_kiss_command {
typedef struct _patty_kiss_tnc patty_kiss_tnc;
patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd);
patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd);
patty_kiss_tnc *patty_kiss_tnc_open(const char *device);
patty_kiss_tnc *patty_kiss_tnc_new(const char *device);
int patty_kiss_tnc_fd(patty_kiss_tnc *tnc);
void patty_kiss_tnc_close(patty_kiss_tnc *tnc);
void patty_kiss_tnc_destroy(patty_kiss_tnc *tnc);
size_t patty_kiss_tnc_dropped(patty_kiss_tnc *tnc);

View file

@ -162,8 +162,8 @@ int main(int argc, char **argv) {
}
tnc = (argc == 2)?
patty_kiss_tnc_open(argv[1]):
patty_kiss_tnc_open_fd(0);
patty_kiss_tnc_new(argv[1]):
patty_kiss_tnc_new_fd(0);
if (tnc == NULL) {
perror("Unable to open TNC");
@ -204,7 +204,7 @@ int main(int argc, char **argv) {
free(buf);
patty_kiss_tnc_close(tnc);
patty_kiss_tnc_destroy(tnc);
return 0;
@ -214,7 +214,7 @@ error_kiss_tnc_recv:
free(buf);
error_malloc_buf:
patty_kiss_tnc_close(tnc);
patty_kiss_tnc_destroy(tnc);
error_kiss_tnc_open:
return 127;

View file

@ -5,12 +5,16 @@
#include <patty/ax25.h>
static int init_tnc(patty_ax25_if *iface, const char *device) {
static int init_tnc(patty_ax25_if *iface, patty_ax25_if_kiss_tnc_info *info) {
static char *prefix = "kiss";
static int number = 0;
if ((iface->tnc = patty_kiss_tnc_open(device)) == NULL) {
goto error_kiss_tnc_open;
iface->tnc = (info->type == PATTY_AX25_IF_KISS_TNC_INFO_FD)?
patty_kiss_tnc_new_fd(info->fd):
patty_kiss_tnc_new(info->path);
if (iface->tnc == NULL) {
goto error_kiss_tnc_new;
}
iface->type = PATTY_AX25_IF_KISS_TNC;
@ -19,15 +23,15 @@ static int init_tnc(patty_ax25_if *iface, const char *device) {
return 0;
error_kiss_tnc_open:
error_kiss_tnc_new:
return -1;
}
static void close_tnc(patty_ax25_if *iface) {
patty_kiss_tnc_close(iface->tnc);
static void destroy_tnc(patty_ax25_if *iface) {
patty_kiss_tnc_destroy(iface->tnc);
}
patty_ax25_if *patty_ax25_if_new(int opts, void *info) {
patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
patty_ax25_if *iface;
if ((iface = malloc(sizeof(*iface))) == NULL) {
@ -36,6 +40,12 @@ patty_ax25_if *patty_ax25_if_new(int opts, void *info) {
memset(iface, '\0', sizeof(*iface));
if (info->addr.callsign[0] == '\0') {
errno = EINVAL;
goto error_invalid_address;
}
if ((iface->rx_buf = malloc(PATTY_AX25_IF_BUFSZ)) == NULL) {
goto error_malloc_rx_buf;
} else {
@ -48,13 +58,13 @@ patty_ax25_if *patty_ax25_if_new(int opts, void *info) {
iface->tx_bufsz = PATTY_AX25_IF_BUFSZ;
}
if ((iface->addrs = patty_list_new()) == NULL) {
goto error_list_new;
if ((iface->aliases = patty_list_new()) == NULL) {
goto error_list_new_aliases;
}
switch (PATTY_AX25_IF_OPT_TYPE(opts)) {
case PATTY_AX25_IF_KISS_TNC:
if (init_tnc(iface, (const char *)info) < 0) {
if (init_tnc(iface, (patty_ax25_if_kiss_tnc_info *)info) < 0) {
goto error_init;
}
@ -66,13 +76,15 @@ patty_ax25_if *patty_ax25_if_new(int opts, void *info) {
goto error_invalid_if_type;
}
memcpy(&iface->addr, &info->addr, sizeof(iface->addr));
return iface;
error_invalid_if_type:
error_init:
patty_list_destroy(iface->addrs);
patty_list_destroy(iface->aliases);
error_list_new:
error_list_new_aliases:
free(iface->tx_buf);
error_malloc_tx_buf:
@ -82,20 +94,21 @@ error_malloc_rx_buf:
free(iface);
error_malloc_iface:
error_invalid_address:
return NULL;
}
void patty_ax25_if_destroy(patty_ax25_if *iface) {
switch (iface->type) {
case PATTY_AX25_IF_KISS_TNC:
close_tnc(iface);
destroy_tnc(iface);
break;
default:
break;
}
patty_list_destroy(iface->addrs);
patty_list_destroy(iface->aliases);
free(iface->tx_buf);
free(iface->rx_buf);
@ -107,14 +120,22 @@ int patty_ax25_if_addr_each(patty_ax25_if *iface,
patty_list_iterator *iter;
patty_ax25_addr *addr;
if ((iter = patty_list_start(iface->addrs)) == NULL) {
char buf[7];
uint8_t ssid;
if (patty_ax25_ntop(&iface->addr, buf, &ssid, sizeof(buf)) < 0) {
goto error_ntop_addr;
}
if (callback(buf, ssid, ctx) < 0) {
goto error_callback_addr;
}
if ((iter = patty_list_start(iface->aliases)) == NULL) {
goto error_list_start;
}
while ((addr = patty_list_next(iter)) != NULL) {
char buf[7];
uint8_t ssid;
if (patty_ax25_ntop(addr, buf, &ssid, sizeof(buf)) < 0) {
goto error_ntop;
}
@ -133,6 +154,8 @@ error_ntop:
patty_list_finish(iter);
error_list_start:
error_callback_addr:
error_ntop_addr:
return -1;
}
@ -142,14 +165,22 @@ static patty_ax25_addr *find_addr(patty_ax25_if *iface,
patty_list_iterator *iter;
patty_ax25_addr *addr;
if ((iter = patty_list_start(iface->addrs)) == NULL) {
char buf[7];
uint8_t addr_ssid;
if (patty_ax25_ntop(&iface->addr, buf, &addr_ssid, sizeof(buf)) < 0) {
goto error_ntop_addr;
}
if (strncmp(buf, callsign, sizeof(buf)) == 0 && addr_ssid == ssid) {
return &iface->addr;
}
if ((iter = patty_list_start(iface->aliases)) == NULL) {
goto error_list_start;
}
while ((addr = patty_list_next(iter)) != NULL) {
char buf[7];
uint8_t addr_ssid;
if (patty_ax25_ntop(addr, buf, &addr_ssid, sizeof(buf)) < 0) {
goto error_ntop;
}
@ -157,7 +188,6 @@ static patty_ax25_addr *find_addr(patty_ax25_if *iface,
if (strncmp(buf, callsign, sizeof(buf)) != 0) {
continue;
}
if (addr_ssid != ssid) {
continue;
@ -172,6 +202,7 @@ error_ntop:
patty_list_finish(iter);
error_list_start:
error_ntop_addr:
return NULL;
}
@ -194,7 +225,7 @@ int patty_ax25_if_addr_add(patty_ax25_if *iface,
goto error_pton;
}
if ((patty_list_append(iface->addrs, addr)) == NULL) {
if ((patty_list_append(iface->aliases, addr)) == NULL) {
goto error_list_append;
}
@ -212,7 +243,7 @@ error_exists:
int patty_ax25_if_addr_delete(patty_ax25_if *iface,
const char *callsign,
uint8_t ssid) {
patty_list_item *item = iface->addrs->first;
patty_list_item *item = iface->aliases->first;
int i = 0;
while (item) {
@ -226,7 +257,7 @@ int patty_ax25_if_addr_delete(patty_ax25_if *iface,
}
if (strncmp(buf, callsign, sizeof(buf)) == 0 && addr_ssid == ssid) {
if (patty_list_splice(iface->addrs, i) == NULL) {
if (patty_list_splice(iface->aliases, i) == NULL) {
goto error_list_splice;
}
}

View file

@ -17,8 +17,14 @@ enum kiss_flags {
KISS_ESCAPE = 1 << 2
};
enum tnc_opts {
TNC_NONE = 0,
TNC_CLOSE_ON_DESTROY = 1 << 0
};
struct _patty_kiss_tnc {
int fd;
int fd,
opts;
void *buf,
*frame;
@ -30,7 +36,7 @@ struct _patty_kiss_tnc {
ssize_t readlen;
};
patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd) {
patty_kiss_tnc *patty_kiss_tnc_new_fd(int fd) {
patty_kiss_tnc *tnc;
if ((tnc = malloc(sizeof(*tnc))) == NULL) {
@ -42,6 +48,7 @@ patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd) {
}
tnc->fd = fd;
tnc->opts = TNC_NONE;
tnc->bufsz = PATTY_KISS_BUFSZ;
tnc->offset = 0;
tnc->dropped = 0;
@ -56,7 +63,7 @@ error_malloc_tnc:
return NULL;
}
patty_kiss_tnc *patty_kiss_tnc_open(const char *device) {
patty_kiss_tnc *patty_kiss_tnc_new(const char *device) {
patty_kiss_tnc *tnc;
int fd;
@ -64,13 +71,15 @@ patty_kiss_tnc *patty_kiss_tnc_open(const char *device) {
goto error_open;
}
if ((tnc = patty_kiss_tnc_open_fd(fd)) == NULL) {
goto error_tnc_open_fd;
if ((tnc = patty_kiss_tnc_new_fd(fd)) == NULL) {
goto error_tnc_new_fd;
}
tnc->opts |= TNC_CLOSE_ON_DESTROY;
return tnc;
error_tnc_open_fd:
error_tnc_new_fd:
close(fd);
error_open:
@ -81,10 +90,13 @@ int patty_kiss_tnc_fd(patty_kiss_tnc *tnc) {
return tnc->fd;
}
void patty_kiss_tnc_close(patty_kiss_tnc *tnc) {
close(tnc->fd);
free(tnc->buf);
free(tnc);
void patty_kiss_tnc_destroy(patty_kiss_tnc *tnc) {
if (tnc->opts & TNC_CLOSE_ON_DESTROY) {
close(tnc->fd);
}
free(tnc->buf);
free(tnc);
}
static void tnc_drop(patty_kiss_tnc *tnc) {
@ -107,6 +119,8 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
enum kiss_flags flags = KISS_NONE;
if (tnc->offset == tnc->readlen) {
errno = 0;
return 0;
}
@ -208,6 +222,8 @@ done:
if (flags & KISS_FRAME) {
tnc_drop(tnc);
errno = 0;
return 0;
}

View file

@ -64,12 +64,33 @@ 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 *route;
uint32_t hash;
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, dest);
patty_hash_end(&hash);
route = patty_dict_get_with_hash(table, hash);
if (route) {
return route;
}
return patty_ax25_route_table_default(table);
}
patty_ax25_route *patty_ax25_route_table_default(patty_ax25_route_table *table) {
patty_ax25_addr empty;
uint32_t hash;
memset(&empty, '\0', sizeof(empty));
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, &empty);
patty_hash_end(&hash);
return patty_dict_get_with_hash(table, hash);
}

View file

@ -15,6 +15,8 @@
typedef int (*patty_ax25_server_call)(patty_ax25_server *, int);
struct _patty_ax25_server {
char path[PATTY_AX25_SOCK_PATH_SIZE];
int fd, /* fd of UNIX domain socket */
fd_max;
@ -38,7 +40,7 @@ struct _patty_ax25_server {
*clients_by_sock;
};
patty_ax25_server *patty_ax25_server_new() {
patty_ax25_server *patty_ax25_server_new(const char *path) {
patty_ax25_server *server;
if ((server = malloc(sizeof(*server))) == NULL) {
@ -47,6 +49,8 @@ patty_ax25_server *patty_ax25_server_new() {
memset(server, '\0', sizeof(*server));
strncpy(server->path, path, PATTY_AX25_SOCK_PATH_SIZE);
if ((server->ifaces = patty_list_new()) == NULL) {
goto error_list_new_ifaces;
}
@ -717,6 +721,8 @@ static int server_connect(patty_ax25_server *server,
patty_ax25_call_connect_response response;
patty_ax25_sock *sock;
patty_ax25_route *route;
patty_ax25_if *iface;
if (read(client, &request, sizeof(request)) < 0) {
goto error_io;
@ -750,6 +756,43 @@ static int server_connect(patty_ax25_server *server,
break;
}
if (sock->local.callsign[0]) {
/*
* If there is an address already bound to this socket, locate the
* appropriate route.
*/
route = patty_ax25_route_table_find(server->routes, &sock->local);
} else {
/*
* Otherwise, locate the default route.
*/
route = patty_ax25_route_table_default(server->routes);
}
/*
* If no route could be found, then assume the network is down or not
* configured.
*/
if (route == NULL) {
response.ret = -1;
response.eno = ENETDOWN;
goto error_network_down;
}
iface = sock->iface = route->iface;
/*
* If there is no local address bound to this sock, then bind the
* address of the default route interface.
*/
if (sock->local.callsign[0] == '\0') {
memcpy(&sock->local, &iface->addr, sizeof(sock->local));
}
/*
* Bind the requested remote address to the socket.
*/
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
@ -767,9 +810,17 @@ static int server_connect(patty_ax25_server *server,
* timeout has been exceeded or the peer has sent a UA frame to
* acknowledge and establish the connection.
*/
if (patty_ax25_sock_send_sabm(sock) < 0) {
response.ret = -1;
response.eno = EIO;
goto error_sock_send_sabm;
}
return 0;
error_sock_send_sabm:
error_network_down:
error_invalid_status:
error_sock_by_fd:
if (write(client, &response, sizeof(response)) < 0) {
@ -956,11 +1007,18 @@ static int handle_client(void *key,
goto error_io;
}
if (server_calls[call] == NULL) {
errno = ENOSYS;
goto error_not_implemented;
}
return server_calls[call](server, client);
done:
return 0;
error_not_implemented:
error_dict_delete:
error_io:
return -1;
@ -1101,7 +1159,7 @@ static int handle_socks(patty_ax25_server *server) {
}
int patty_ax25_server_run(patty_ax25_server *server) {
if (listen_unix(server, PATTY_AX25_SERVER_PATH) < 0) {
if (listen_unix(server, server->path) < 0) {
goto error_listen_unix;
}
@ -1109,11 +1167,10 @@ int patty_ax25_server_run(patty_ax25_server *server) {
int nready;
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
memcpy(&server->fds_w, &server->fds_watch, sizeof(server->fds_w));
if ((nready = select( server->fd_max,
&server->fds_r,
&server->fds_w,
NULL,
NULL,
NULL)) < 0) {
goto error_io;

View file

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <patty/ax25.h>
@ -27,3 +28,38 @@ error_malloc_sock:
void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
free(sock);
}
static size_t copy_addr_to_buf(patty_ax25_sock *sock, uint8_t *buf, size_t offset) {
size_t i;
memcpy(&buf[offset], &sock->remote, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
memcpy(&buf[offset], &sock->local, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
for (i=0; i<sock->hops; i++) {
memcpy(&buf[offset], &sock->repeaters[i], sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
if (i == sock->hops - 1) {
buf[offset - 1] |= 0x01;
}
}
return offset;
}
int patty_ax25_sock_send_sabm(patty_ax25_sock *sock) {
size_t offset = 0;
uint8_t *buf = (uint8_t *)(sock->iface->tx_buf);
offset = copy_addr_to_buf(sock, buf, offset);
buf[offset++] = PATTY_AX25_PROTO_NONE;
buf[offset++] = 0x3f;
return patty_ax25_if_send(sock->iface,
buf,
offset);
}

View file

@ -32,10 +32,15 @@ int main(int argc, char **argv) {
int fd,
sock;
patty_ax25_addr peer;
char path[256];
if (argc != 2) {
usage(argc, argv, "No patty socket provided");
}
patty_ax25_pton("GB9BLM", 0, &peer);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
@ -58,14 +63,14 @@ int main(int argc, char **argv) {
goto error_call_socket;
}
if (patty_ax25_call_close(fd, sock) < 0) {
if (patty_ax25_call_connect(fd, sock, &peer, path) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_close()", strerror(errno));
argv[0], "patty_ax25_call_connect()", strerror(errno));
goto error_call_close;
}
fprintf(stderr, "got sock %d\n", sock);
fprintf(stderr, "connected sock %d\n", sock);
close(fd);

View file

@ -1,8 +1,13 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <patty/ax25.h>
@ -17,7 +22,7 @@ static void usage(int argc, char **argv, const char *message, ...) {
va_end(args);
}
fprintf(stderr, "usage: %s /dev/ttyXX|kiss.cap\n", argv[0]);
fprintf(stderr, "usage: %s /dev/ttyXX|kiss.cap [path.sock]\n", argv[0]);
exit(1);
}
@ -27,22 +32,57 @@ int main(int argc, char **argv) {
patty_ax25_if *iface;
patty_ax25_route *route;
if (argc != 2) {
patty_ax25_if_kiss_tnc_info info = {
.type = PATTY_AX25_IF_KISS_TNC_INFO_FD
};
if (argc < 2) {
usage(argc, argv, "No TNC device or KISS dump file provided");
} else if (argc > 3) {
usage(argc, argv, "Too many arguments provided");
}
if ((server = patty_ax25_server_new()) == NULL) {
if ((info.fd = open(argv[1], O_RDWR)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "open()", argv[1], strerror(errno));
goto error_open;
}
if (isatty(info.fd) && grantpt(info.fd) == 0 && unlockpt(info.fd) == 0) {
char name[256];
struct termios t;
if (ptsname_r(info.fd, name, sizeof(name)) < 0) {
goto error_open;
}
if (tcgetattr(info.fd, &t) < 0) {
goto error_open;
}
cfmakeraw(&t);
if (tcsetattr(info.fd, TCSANOW, &t) < 0) {
goto error_open;
}
fprintf(stderr, "pts %s\n", name);
}
errno = 0;
patty_ax25_pton("KZ3ROX", 0, &info.addr);
if ((server = patty_ax25_server_new(argc == 3? argv[2]: PATTY_AX25_SERVER_PATH)) == NULL) {
goto error_server_new;
}
if ((iface = patty_ax25_if_new(PATTY_AX25_IF_KISS_TNC, argv[1])) == NULL) {
if ((iface = patty_ax25_if_new(PATTY_AX25_IF_KISS_TNC,
(patty_ax25_if_info *)&info)) == NULL) {
goto error_if_new;
}
if (patty_ax25_if_addr_add(iface, "KZ3ROX", 0) < 0) {
goto error_if_addr_add;
}
if (patty_ax25_server_add_if(server, iface) < 0) {
goto error_server_add_if;
}
@ -70,10 +110,12 @@ error_server_run:
error_server_add_route:
error_route_new_default:
error_server_add_if:
error_if_addr_add:
error_if_new:
patty_ax25_server_destroy(server);
error_server_new:
close(info.fd);
error_open:
return 1;
}