From 84ae427037a4cbc687be3bf6ada9991f25bee218 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Tue, 7 Jul 2020 17:48:18 -0400 Subject: [PATCH] Move raw frame capture to patty_ax25_if Move raw frame interface capture to patty_ax25_if, patty_ax25_sock; this resolves the issue wherein only bytes received, not sent, would be captured by a raw socket bound to a specific interface with setsockopt() --- include/patty/ax25/if.h | 7 +++ include/patty/ax25/sock.h | 4 +- src/if.c | 89 +++++++++++++++++++++++++++++++++++++++ src/server.c | 32 -------------- src/sock.c | 19 ++++++++- 5 files changed, 115 insertions(+), 36 deletions(-) diff --git a/include/patty/ax25/if.h b/include/patty/ax25/if.h index a8e575d..a3c6c1a 100644 --- a/include/patty/ax25/if.h +++ b/include/patty/ax25/if.h @@ -42,6 +42,7 @@ typedef struct _patty_ax25_if { patty_kiss_tnc *tnc; patty_ax25_addr addr; patty_list *aliases; + patty_dict *promisc_fds; } patty_ax25_if; typedef struct _patty_ax25_if_info { @@ -75,6 +76,12 @@ int patty_ax25_if_addr_add(patty_ax25_if *iface, int patty_ax25_if_addr_delete(patty_ax25_if *iface, const char *callsign, uint8_t ssid); +int patty_ax25_if_promisc_add(patty_ax25_if *iface, + int fd); + +int patty_ax25_if_promisc_delete(patty_ax25_if *iface, + int fd); + ssize_t patty_ax25_if_recv(patty_ax25_if *iface, void **buf); diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index e0ffa77..90d0ea6 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -78,8 +78,8 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock); char *patty_ax25_sock_pty(patty_ax25_sock *sock); -void patty_ax25_sock_bind_if(patty_ax25_sock *sock, - patty_ax25_if *iface); +int patty_ax25_sock_bind_if(patty_ax25_sock *sock, + patty_ax25_if *iface); ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, uint16_t control, diff --git a/src/if.c b/src/if.c index 288534d..cd6d817 100644 --- a/src/if.c +++ b/src/if.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,10 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) { goto error_list_new_aliases; } + if ((iface->promisc_fds = patty_dict_new()) == NULL) { + goto error_dict_new_promisc_fds; + } + switch (PATTY_AX25_IF_OPT_TYPE(opts)) { case PATTY_AX25_IF_KISS_TNC: if (init_tnc(iface, (patty_ax25_if_kiss_tnc_info *)info) < 0) { @@ -82,6 +87,9 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) { error_invalid_if_type: error_init: + patty_dict_destroy(iface->promisc_fds); + +error_dict_new_promisc_fds: patty_list_destroy(iface->aliases); error_list_new_aliases: @@ -108,6 +116,7 @@ void patty_ax25_if_destroy(patty_ax25_if *iface) { break; } + patty_dict_destroy(iface->promisc_fds); patty_list_destroy(iface->aliases); free(iface->tx_buf); @@ -261,10 +270,67 @@ error_ntop: return -1; } +int patty_ax25_if_promisc_add(patty_ax25_if *iface, + int fd) { + if (patty_dict_get_with_hash(iface->promisc_fds, (uint32_t)fd)) { + errno = EEXIST; + + goto error_exists; + } + + if (patty_dict_set_with_hash(iface->promisc_fds, + NULL + fd, + sizeof(fd), + NULL + fd, + (uint32_t)fd) == NULL) { + errno = ENOMEM; + + goto error_dict_set_with_hash; + } + + return 0; + +error_dict_set_with_hash: +error_exists: + return -1; +} + +int patty_ax25_if_promisc_delete(patty_ax25_if *iface, + int fd) { + if (patty_dict_delete_with_hash(iface->promisc_fds, + (uint32_t)fd) < 0) { + errno = ENOENT; + + goto error_notfound; + } + + return 0; + +error_notfound: + return -1; +} + +struct promisc_frame { + const void *buf; + size_t len; + patty_ax25_if *iface; +}; + +static int handle_promisc_frame(void *key, + size_t keysz, + void *value, + void *ctx) { + int fd = (int)(value - NULL); + struct promisc_frame *frame = ctx; + + return write(fd, frame->buf, frame->len); +} + ssize_t patty_ax25_if_recv(patty_ax25_if *iface, void **buf) { ssize_t readlen; int port; + struct promisc_frame frame; if ((readlen = patty_kiss_tnc_recv(iface->tnc, iface->rx_buf, @@ -278,8 +344,19 @@ ssize_t patty_ax25_if_recv(patty_ax25_if *iface, iface->stats.rx_frames++; iface->stats.rx_bytes += readlen; + frame.buf = iface->rx_buf; + frame.len = readlen; + frame.iface = iface; + + if (patty_dict_each(iface->promisc_fds, + handle_promisc_frame, + &frame) < 0) { + goto error_handle_promisc_frame; + } + return readlen; +error_handle_promisc_frame: error_kiss_tnc_recv: return -1; } @@ -288,6 +365,7 @@ ssize_t patty_ax25_if_send(patty_ax25_if *iface, const void *buf, size_t len) { ssize_t wrlen; + struct promisc_frame frame; if ((wrlen = patty_kiss_tnc_send(iface->tnc, buf, len, 0)) < 0) { goto error_kiss_tnc_send; @@ -296,8 +374,19 @@ ssize_t patty_ax25_if_send(patty_ax25_if *iface, iface->stats.tx_frames++; iface->stats.tx_bytes += wrlen; + frame.buf = buf; + frame.len = wrlen; + frame.iface = iface; + + if (patty_dict_each(iface->promisc_fds, + handle_promisc_frame, + &frame) < 0) { + goto error_handle_promisc_frame; + } + return wrlen; +error_handle_promisc_frame: error_kiss_tnc_send: return -1; } diff --git a/src/server.c b/src/server.c index b89e51c..7552647 100644 --- a/src/server.c +++ b/src/server.c @@ -1309,38 +1309,12 @@ 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 (sock->type != PATTY_AX25_SOCK_RAW || raw_frame->iface != sock->iface) { - 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, @@ -1350,12 +1324,6 @@ 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)) { diff --git a/src/sock.c b/src/sock.c index 3f16f05..844b987 100644 --- a/src/sock.c +++ b/src/sock.c @@ -107,6 +107,10 @@ void patty_ax25_sock_reset(patty_ax25_sock *sock) { void patty_ax25_sock_destroy(patty_ax25_sock *sock) { if (sock->fd) { + if (sock->iface) { + (void)patty_ax25_if_promisc_delete(sock->iface, sock->fd); + } + close(sock->fd); } @@ -118,9 +122,20 @@ char *patty_ax25_sock_pty(patty_ax25_sock *sock) { return sock->path; } -void patty_ax25_sock_bind_if(patty_ax25_sock *sock, - patty_ax25_if *iface) { +int patty_ax25_sock_bind_if(patty_ax25_sock *sock, + patty_ax25_if *iface) { sock->iface = iface; + + if (sock->type == PATTY_AX25_SOCK_RAW) { + if (patty_ax25_if_promisc_add(iface, sock->fd) < 0) { + goto error_if_promisc_add; + } + } + + return 0; + +error_if_promisc_add: + return -1; } static size_t copy_addr_to_tx_buf(patty_ax25_sock *sock) {