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()
This commit is contained in:
XANTRONIX Development 2020-07-07 17:48:18 -04:00 committed by XANTRONIX Industrial
parent 1888b70ed9
commit 84ae427037
5 changed files with 115 additions and 36 deletions

View file

@ -42,6 +42,7 @@ typedef struct _patty_ax25_if {
patty_kiss_tnc *tnc; patty_kiss_tnc *tnc;
patty_ax25_addr addr; patty_ax25_addr addr;
patty_list *aliases; patty_list *aliases;
patty_dict *promisc_fds;
} patty_ax25_if; } patty_ax25_if;
typedef struct _patty_ax25_if_info { 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, int patty_ax25_if_addr_delete(patty_ax25_if *iface,
const char *callsign, uint8_t ssid); 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, ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
void **buf); void **buf);

View file

@ -78,8 +78,8 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock);
char *patty_ax25_sock_pty(patty_ax25_sock *sock); char *patty_ax25_sock_pty(patty_ax25_sock *sock);
void patty_ax25_sock_bind_if(patty_ax25_sock *sock, int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
patty_ax25_if *iface); patty_ax25_if *iface);
ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
uint16_t control, uint16_t control,

View file

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <patty/ax25.h> #include <patty/ax25.h>
@ -62,6 +63,10 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
goto error_list_new_aliases; 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)) { switch (PATTY_AX25_IF_OPT_TYPE(opts)) {
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) {
@ -82,6 +87,9 @@ patty_ax25_if *patty_ax25_if_new(int opts, patty_ax25_if_info *info) {
error_invalid_if_type: error_invalid_if_type:
error_init: error_init:
patty_dict_destroy(iface->promisc_fds);
error_dict_new_promisc_fds:
patty_list_destroy(iface->aliases); patty_list_destroy(iface->aliases);
error_list_new_aliases: error_list_new_aliases:
@ -108,6 +116,7 @@ void patty_ax25_if_destroy(patty_ax25_if *iface) {
break; break;
} }
patty_dict_destroy(iface->promisc_fds);
patty_list_destroy(iface->aliases); patty_list_destroy(iface->aliases);
free(iface->tx_buf); free(iface->tx_buf);
@ -261,10 +270,67 @@ error_ntop:
return -1; 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, ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
void **buf) { void **buf) {
ssize_t readlen; ssize_t readlen;
int port; int port;
struct promisc_frame frame;
if ((readlen = patty_kiss_tnc_recv(iface->tnc, if ((readlen = patty_kiss_tnc_recv(iface->tnc,
iface->rx_buf, iface->rx_buf,
@ -278,8 +344,19 @@ ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
iface->stats.rx_frames++; iface->stats.rx_frames++;
iface->stats.rx_bytes += readlen; 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; return readlen;
error_handle_promisc_frame:
error_kiss_tnc_recv: error_kiss_tnc_recv:
return -1; return -1;
} }
@ -288,6 +365,7 @@ ssize_t patty_ax25_if_send(patty_ax25_if *iface,
const void *buf, const void *buf,
size_t len) { size_t len) {
ssize_t wrlen; ssize_t wrlen;
struct promisc_frame frame;
if ((wrlen = patty_kiss_tnc_send(iface->tnc, buf, len, 0)) < 0) { if ((wrlen = patty_kiss_tnc_send(iface->tnc, buf, len, 0)) < 0) {
goto error_kiss_tnc_send; 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_frames++;
iface->stats.tx_bytes += wrlen; 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; return wrlen;
error_handle_promisc_frame:
error_kiss_tnc_send: error_kiss_tnc_send:
return -1; return -1;
} }

View file

@ -1309,38 +1309,12 @@ error_sock_delete:
return -1; 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, static int handle_frame(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
void *buf, void *buf,
size_t len) { size_t len) {
patty_ax25_frame frame; patty_ax25_frame frame;
struct sock_raw_frame ctx = {
.buf = buf,
.len = len,
.iface = iface
};
if (patty_ax25_frame_decode(&frame, if (patty_ax25_frame_decode(&frame,
PATTY_AX25_FRAME_NORMAL, PATTY_AX25_FRAME_NORMAL,
buf, buf,
@ -1350,12 +1324,6 @@ static int handle_frame(patty_ax25_server *server,
goto error_io; 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)) { if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) {
return handle_sabm(server, iface, &frame); return handle_sabm(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_UNNUMBERED_UA(frame.control)) { } else if (PATTY_AX25_CONTROL_UNNUMBERED_UA(frame.control)) {

View file

@ -107,6 +107,10 @@ void patty_ax25_sock_reset(patty_ax25_sock *sock) {
void patty_ax25_sock_destroy(patty_ax25_sock *sock) { void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
if (sock->fd) { if (sock->fd) {
if (sock->iface) {
(void)patty_ax25_if_promisc_delete(sock->iface, sock->fd);
}
close(sock->fd); close(sock->fd);
} }
@ -118,9 +122,20 @@ char *patty_ax25_sock_pty(patty_ax25_sock *sock) {
return sock->path; return sock->path;
} }
void patty_ax25_sock_bind_if(patty_ax25_sock *sock, int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
patty_ax25_if *iface) { patty_ax25_if *iface) {
sock->iface = 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) { static size_t copy_addr_to_tx_buf(patty_ax25_sock *sock) {