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:
parent
c417461a0b
commit
d0d17b58fb
6 changed files with 88 additions and 44 deletions
|
@ -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));
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 {
|
||||
|
|
28
src/if.c
28
src/if.c
|
@ -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) {
|
||||
|
|
43
src/server.c
43
src/server.c
|
@ -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,16 +1855,15 @@ 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);
|
||||
|
||||
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) {
|
||||
if (errno == EIO) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
|
|
36
src/sock.c
36
src/sock.c
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue