From 73ae096b2d676e0845e085e1f46bd3c3830a9940 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Thu, 2 Jul 2020 23:33:34 -0400 Subject: [PATCH] Implement openif(), raw packet interface access --- include/patty/ax25/call.h | 19 ++++++++ src/call.c | 35 +++++++++++++++ src/server.c | 94 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/include/patty/ax25/call.h b/include/patty/ax25/call.h index 1358809..22f51d2 100644 --- a/include/patty/ax25/call.h +++ b/include/patty/ax25/call.h @@ -8,6 +8,7 @@ enum patty_ax25_call { PATTY_AX25_CALL_LISTEN, PATTY_AX25_CALL_ACCEPT, PATTY_AX25_CALL_CONNECT, + PATTY_AX25_CALL_OPENIF, PATTY_AX25_CALL_CLOSE, PATTY_AX25_CALL_SENDTO, PATTY_AX25_CALL_RECVFROM, @@ -103,6 +104,24 @@ int patty_ax25_call_connect(int server, int fd, patty_ax25_addr *peer); +/* + * openif() + */ +typedef struct _patty_ax25_call_openif_request { + char name[8]; +} patty_ax25_call_openif_request; + +typedef struct _patty_ax25_call_openif_response { + int fd; + int eno; + char path[PATTY_AX25_SOCK_PATH_SIZE]; +} patty_ax25_call_openif_response; + +int patty_ax25_call_openif(int server, + char *name, + char *path, + size_t len); + /* * close() */ diff --git a/src/call.c b/src/call.c index a8faf58..211f90c 100644 --- a/src/call.c +++ b/src/call.c @@ -180,6 +180,41 @@ error_io: return -1; } +int patty_ax25_call_openif(int server, + char *name, + char *path, + size_t len) { + enum patty_ax25_call call = PATTY_AX25_CALL_OPENIF; + + patty_ax25_call_openif_request request; + patty_ax25_call_openif_response response; + + memcpy(request.name, name, sizeof(request.name)); + + if (write(server, &call, sizeof(call)) < 0) { + goto error_io; + } + + if (write(server, &request, sizeof(request)) < 0) { + goto error_io; + } + + if (read(server, &response, sizeof(response)) < 0) { + goto error_io; + } + + if (path) { + strncpy(path, response.path, len); + } + + errno = response.eno; + + return response.fd; + +error_io: + return -1; +} + int patty_ax25_call_close(int server, int fd) { enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE; diff --git a/src/server.c b/src/server.c index f9ff778..1905e89 100644 --- a/src/server.c +++ b/src/server.c @@ -722,6 +722,65 @@ error_io: return -1; } +static int server_openif(patty_ax25_server *server, + int client) { + patty_ax25_call_openif_request request; + patty_ax25_call_openif_response response; + + patty_ax25_sock *sock; + patty_ax25_if *iface; + + if (read(client, &request, sizeof(request)) < 0) { + goto error_io; + } + + if ((sock = patty_ax25_sock_new(PATTY_AX25_SOCK_RAW, + PATTY_AX25_PROTO_NONE)) == NULL) { + response.fd = -1; + response.eno = errno; + + goto error_sock_new; + } + + if ((iface = patty_ax25_server_get_if(server, request.name)) == NULL) { + response.fd = -1; + response.eno = ENODEV; + + goto error_get_if; + } + + patty_ax25_sock_bind_if(sock, iface); + + watch_fd(server, sock->fd); + + if (sock_save_by_fd(server->socks_by_fd, sock) < 0) { + response.fd = -1; + response.eno = errno; + + goto error_sock_save_by_fd; + } + + if (sock_save_by_fd(server->socks_established, sock) < 0) { + response.fd = -1; + response.eno = errno; + + goto error_sock_save_by_fd; + } + + response.fd = sock->fd; + response.eno = 0; + + strncpy(response.path, sock->path, sizeof(response.path)); + +error_get_if: +error_sock_new: + return write(client, &response, sizeof(response)); + +error_sock_save_by_fd: +error_io: + return -1; +} + static int server_close(patty_ax25_server *server, int client) { patty_ax25_call_close_request request; @@ -769,6 +828,7 @@ static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = { server_listen, server_accept, server_connect, + server_openif, server_close, NULL, NULL @@ -1225,12 +1285,38 @@ error_sock_delete: return -1; } +struct sock_raw_frame { + void *buf; + size_t len; + patty_ax25_if *iface; +}; + +static int handle_sock_raw(void *key, + size_t keysz, + void *value, + void *ctx) { + patty_ax25_sock *sock = value; + struct sock_raw_frame *raw_frame = ctx; + + if (raw_frame->iface != sock->iface || !(sock->opts & PATTY_AX25_SOCK_RAW)) { + return 0; + } + + return write(sock->fd, raw_frame->buf, raw_frame->len); +} + static int handle_frame(patty_ax25_server *server, patty_ax25_if *iface, void *buf, size_t len) { patty_ax25_frame frame; + struct sock_raw_frame ctx = { + .buf = buf, + .len = len, + .iface = iface + }; + if (patty_ax25_frame_decode(&frame, PATTY_AX25_FRAME_NORMAL, buf, @@ -1240,6 +1326,12 @@ static int handle_frame(patty_ax25_server *server, goto error_io; } + if (patty_dict_each(server->socks_established, + handle_sock_raw, + &ctx) < 0) { + goto error_io; + } + if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) { return handle_sabm(server, iface, &frame); } else if (PATTY_AX25_CONTROL_UNNUMBERED_UA(frame.control)) { @@ -1317,7 +1409,7 @@ static int handle_sock(void *key, ssize_t len; - if (!FD_ISSET(fd, &server->fds_r)) { + if (!FD_ISSET(fd, &server->fds_r) || sock->opts & PATTY_AX25_SOCK_RAW) { goto done; }