Implement support for sending frames with SOCK_RAW

Changes:

    * When associating a promiscuous socket with an interface, rather
      than creating a patty_kiss_tnc object, simply store the socket
      file descriptor and use patty_kiss_frame_send() to send incoming
      or outgoing frames for that interface to the promiscuous socket

    * Add special initialization code in src/sock.c for SOCK_RAW; don't
      allocate any buffers, but instead set a few flags and otherwise
      use 0-initialized defaults

    * Implement handle_sock_raw() in src/server.c to check to see if any
      raw frames are pending, and if so, send them to the associated
      interface if provided by setsockopt()

    * Make patty_ax25_sock_bind_if() only call the function
      patty_ax25_if_add_promisc() only if the socket status is PROMISC;
      this allows support for non-promiscuous sockets used for outbound
      purposes
This commit is contained in:
XANTRONIX Development 2020-08-05 02:05:15 -04:00 committed by XANTRONIX Industrial
parent c417461a0b
commit d0d17b58fb
6 changed files with 88 additions and 44 deletions

View file

@ -61,6 +61,8 @@ int main(int argc, char **argv) {
strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
ifreq.status = PATTY_AX25_SOCK_PROMISC;
if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_client_setsockopt()", strerror(errno));

View file

@ -103,6 +103,8 @@ typedef struct _patty_ax25_sock {
patty_ax25_if *iface;
patty_kiss_tnc *raw;
patty_ax25_addr local,
remote,
repeaters[PATTY_AX25_MAX_HOPS];

View file

@ -58,6 +58,7 @@ typedef struct _patty_client_setsockopt_request {
typedef struct _patty_client_setsockopt_if {
char name[8];
int status;
} patty_client_setsockopt_if;
typedef struct _patty_client_setsockopt_response {

View file

@ -272,21 +272,15 @@ error_ntop:
int patty_ax25_if_promisc_add(patty_ax25_if *iface,
int fd) {
patty_kiss_tnc *tnc;
if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) {
errno = EEXIST;
goto error_exists;
}
if ((tnc = patty_kiss_tnc_new_fd(fd)) == NULL) {
goto error_kiss_tnc_new_fd;
}
if (patty_dict_set(iface->promisc_fds,
(uint32_t)fd,
tnc) == NULL) {
NULL) == NULL) {
errno = ENOMEM;
goto error_dict_set;
@ -295,29 +289,13 @@ int patty_ax25_if_promisc_add(patty_ax25_if *iface,
return 0;
error_dict_set:
patty_kiss_tnc_destroy(tnc);
error_kiss_tnc_new_fd:
error_exists:
return -1;
}
int patty_ax25_if_promisc_delete(patty_ax25_if *iface,
int fd) {
patty_kiss_tnc *tnc;
if ((tnc = patty_dict_get(iface->promisc_fds, (uint32_t)fd)) == NULL) {
errno = ENOENT;
goto error_notfound;
}
patty_kiss_tnc_destroy(tnc);
return patty_dict_delete(iface->promisc_fds, (uint32_t)fd);
error_notfound:
return -1;
}
struct promisc_frame {
@ -329,10 +307,10 @@ struct promisc_frame {
static int handle_promisc_frame(uint32_t key,
void *value,
void *ctx) {
patty_kiss_tnc *tnc = value;
int fd = (int)key;
struct promisc_frame *frame = ctx;
return patty_kiss_tnc_send(tnc, frame->buf, frame->len, 0);
return patty_kiss_frame_send(fd, frame->buf, frame->len, 0);
}
ssize_t patty_ax25_if_pending(patty_ax25_if *iface) {

View file

@ -605,6 +605,10 @@ static int server_setsockopt(patty_ax25_server *server,
goto error_read;
}
if (data.status == PATTY_AX25_SOCK_PROMISC) {
sock->status = PATTY_AX25_SOCK_PROMISC;
}
if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
response.ret = -1;
response.eno = ENODEV;
@ -614,8 +618,6 @@ static int server_setsockopt(patty_ax25_server *server,
patty_ax25_sock_bind_if(sock, iface);
sock->status = PATTY_AX25_SOCK_PROMISC;
fd_watch(server, sock->fd);
break;
@ -1732,6 +1734,34 @@ error_io:
return -1;
}
static int handle_sock_raw(patty_ax25_server *server,
patty_ax25_sock *sock) {
ssize_t len;
int port;
if (!FD_ISSET(sock->fd, &server->fds_r) || sock->iface == NULL) {
return 0;
}
if ((len = patty_kiss_tnc_recv(sock->raw,
sock->iface->tx_buf,
sock->iface->mtu,
&port)) < 0) {
goto error_io;
}
if (patty_ax25_if_send(sock->iface,
sock->iface->tx_buf,
len) < 0) {
goto error_io;
}
return 0;
error_io:
return -1;
}
static int handle_sock(uint32_t key,
void *value,
void *ctx) {
@ -1740,6 +1770,10 @@ static int handle_sock(uint32_t key,
ssize_t len;
if (sock->type == PATTY_AX25_SOCK_RAW) {
return handle_sock_raw(server, sock);
}
switch (sock->status) {
case PATTY_AX25_SOCK_PENDING_CONNECT:
patty_timer_tick(&sock->timer_t1, &server->elapsed);
@ -1821,15 +1855,14 @@ static int handle_sock(uint32_t key,
goto done;
}
if (sock->type == PATTY_AX25_SOCK_STREAM) {
/*
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
*/
if (sock->vs + sock->n_window_tx == sock->vs) {
fd_clear(server, sock->fd);
/*
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
*/
if (sock->vs + sock->n_window_tx == sock->vs) {
fd_clear(server, sock->fd);
goto done;
}
return patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_COMMAND, 1);
goto done;
}
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
@ -1850,12 +1883,10 @@ static int handle_sock(uint32_t key,
goto error_sock_write;
}
if (sock->type == PATTY_AX25_SOCK_STREAM) {
/*
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
*/
patty_timer_start(&sock->timer_t1, sock->n_ack);
}
/*
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
*/
patty_timer_start(&sock->timer_t1, sock->n_ack);
done:
return 0;

View file

@ -111,6 +111,29 @@ error_realloc_tx_buf:
return -1;
}
static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
if ((sock->raw = patty_kiss_tnc_new_fd(sock->fd)) == NULL) {
goto error_kiss_tnc_new_fd;
}
sock->proto = PATTY_AX25_PROTO_NONE;
sock->type = PATTY_AX25_SOCK_RAW;
return sock;
error_kiss_tnc_new_fd:
(void)close(sock->fd);
error_bind_pty:
free(sock);
return NULL;
}
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
enum patty_ax25_sock_type type) {
patty_ax25_sock *sock;
@ -121,6 +144,10 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
memset(sock, '\0', sizeof(*sock));
if (type == PATTY_AX25_SOCK_RAW) {
return init_raw(sock);
}
patty_ax25_sock_init(sock);
sock->proto = proto;
@ -160,6 +187,10 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
close(sock->fd);
}
if (sock->raw) {
patty_kiss_tnc_destroy(sock->raw);
}
free(sock->tx_slots);
free(sock->rx_buf);
free(sock->tx_buf);
@ -315,15 +346,14 @@ char *patty_ax25_sock_pty(patty_ax25_sock *sock) {
int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
patty_ax25_if *iface) {
sock->iface = iface;
sock->flags_classes |= iface->flags_classes;
if (sock->type == PATTY_AX25_SOCK_RAW) {
if (sock->status == PATTY_AX25_SOCK_PROMISC) {
if (patty_ax25_if_promisc_add(iface, sock->fd) < 0) {
goto error_if_promisc_add;
}
}
sock->flags_classes |= iface->flags_classes;
return 0;
error_if_promisc_add: