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));
|
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) {
|
if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
|
||||||
fprintf(stderr, "%s: %s: %s\n",
|
fprintf(stderr, "%s: %s: %s\n",
|
||||||
argv[0], "patty_client_setsockopt()", strerror(errno));
|
argv[0], "patty_client_setsockopt()", strerror(errno));
|
||||||
|
|
|
@ -103,6 +103,8 @@ typedef struct _patty_ax25_sock {
|
||||||
|
|
||||||
patty_ax25_if *iface;
|
patty_ax25_if *iface;
|
||||||
|
|
||||||
|
patty_kiss_tnc *raw;
|
||||||
|
|
||||||
patty_ax25_addr local,
|
patty_ax25_addr local,
|
||||||
remote,
|
remote,
|
||||||
repeaters[PATTY_AX25_MAX_HOPS];
|
repeaters[PATTY_AX25_MAX_HOPS];
|
||||||
|
|
|
@ -58,6 +58,7 @@ typedef struct _patty_client_setsockopt_request {
|
||||||
|
|
||||||
typedef struct _patty_client_setsockopt_if {
|
typedef struct _patty_client_setsockopt_if {
|
||||||
char name[8];
|
char name[8];
|
||||||
|
int status;
|
||||||
} patty_client_setsockopt_if;
|
} patty_client_setsockopt_if;
|
||||||
|
|
||||||
typedef struct _patty_client_setsockopt_response {
|
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 patty_ax25_if_promisc_add(patty_ax25_if *iface,
|
||||||
int fd) {
|
int fd) {
|
||||||
patty_kiss_tnc *tnc;
|
|
||||||
|
|
||||||
if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) {
|
if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) {
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
|
|
||||||
goto error_exists;
|
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,
|
if (patty_dict_set(iface->promisc_fds,
|
||||||
(uint32_t)fd,
|
(uint32_t)fd,
|
||||||
tnc) == NULL) {
|
NULL) == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
|
|
||||||
goto error_dict_set;
|
goto error_dict_set;
|
||||||
|
@ -295,29 +289,13 @@ int patty_ax25_if_promisc_add(patty_ax25_if *iface,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_dict_set:
|
error_dict_set:
|
||||||
patty_kiss_tnc_destroy(tnc);
|
|
||||||
|
|
||||||
error_kiss_tnc_new_fd:
|
|
||||||
error_exists:
|
error_exists:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_ax25_if_promisc_delete(patty_ax25_if *iface,
|
int patty_ax25_if_promisc_delete(patty_ax25_if *iface,
|
||||||
int fd) {
|
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);
|
return patty_dict_delete(iface->promisc_fds, (uint32_t)fd);
|
||||||
|
|
||||||
error_notfound:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct promisc_frame {
|
struct promisc_frame {
|
||||||
|
@ -329,10 +307,10 @@ struct promisc_frame {
|
||||||
static int handle_promisc_frame(uint32_t key,
|
static int handle_promisc_frame(uint32_t key,
|
||||||
void *value,
|
void *value,
|
||||||
void *ctx) {
|
void *ctx) {
|
||||||
patty_kiss_tnc *tnc = value;
|
int fd = (int)key;
|
||||||
struct promisc_frame *frame = ctx;
|
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) {
|
ssize_t patty_ax25_if_pending(patty_ax25_if *iface) {
|
||||||
|
|
63
src/server.c
63
src/server.c
|
@ -605,6 +605,10 @@ static int server_setsockopt(patty_ax25_server *server,
|
||||||
goto error_read;
|
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) {
|
if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
|
||||||
response.ret = -1;
|
response.ret = -1;
|
||||||
response.eno = ENODEV;
|
response.eno = ENODEV;
|
||||||
|
@ -614,8 +618,6 @@ static int server_setsockopt(patty_ax25_server *server,
|
||||||
|
|
||||||
patty_ax25_sock_bind_if(sock, iface);
|
patty_ax25_sock_bind_if(sock, iface);
|
||||||
|
|
||||||
sock->status = PATTY_AX25_SOCK_PROMISC;
|
|
||||||
|
|
||||||
fd_watch(server, sock->fd);
|
fd_watch(server, sock->fd);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1732,6 +1734,34 @@ error_io:
|
||||||
return -1;
|
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,
|
static int handle_sock(uint32_t key,
|
||||||
void *value,
|
void *value,
|
||||||
void *ctx) {
|
void *ctx) {
|
||||||
|
@ -1740,6 +1770,10 @@ static int handle_sock(uint32_t key,
|
||||||
|
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
|
if (sock->type == PATTY_AX25_SOCK_RAW) {
|
||||||
|
return handle_sock_raw(server, sock);
|
||||||
|
}
|
||||||
|
|
||||||
switch (sock->status) {
|
switch (sock->status) {
|
||||||
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||||
patty_timer_tick(&sock->timer_t1, &server->elapsed);
|
patty_timer_tick(&sock->timer_t1, &server->elapsed);
|
||||||
|
@ -1821,15 +1855,14 @@ static int handle_sock(uint32_t key,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->type == PATTY_AX25_SOCK_STREAM) {
|
/*
|
||||||
/*
|
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
|
||||||
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
|
*/
|
||||||
*/
|
if (sock->vs + sock->n_window_tx == sock->vs) {
|
||||||
if (sock->vs + sock->n_window_tx == sock->vs) {
|
fd_clear(server, sock->fd);
|
||||||
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) {
|
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;
|
goto error_sock_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->type == PATTY_AX25_SOCK_STREAM) {
|
/*
|
||||||
/*
|
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
|
||||||
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
|
*/
|
||||||
*/
|
patty_timer_start(&sock->timer_t1, sock->n_ack);
|
||||||
patty_timer_start(&sock->timer_t1, sock->n_ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
36
src/sock.c
36
src/sock.c
|
@ -111,6 +111,29 @@ error_realloc_tx_buf:
|
||||||
return -1;
|
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,
|
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
|
||||||
enum patty_ax25_sock_type type) {
|
enum patty_ax25_sock_type type) {
|
||||||
patty_ax25_sock *sock;
|
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));
|
memset(sock, '\0', sizeof(*sock));
|
||||||
|
|
||||||
|
if (type == PATTY_AX25_SOCK_RAW) {
|
||||||
|
return init_raw(sock);
|
||||||
|
}
|
||||||
|
|
||||||
patty_ax25_sock_init(sock);
|
patty_ax25_sock_init(sock);
|
||||||
|
|
||||||
sock->proto = proto;
|
sock->proto = proto;
|
||||||
|
@ -160,6 +187,10 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
|
||||||
close(sock->fd);
|
close(sock->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->raw) {
|
||||||
|
patty_kiss_tnc_destroy(sock->raw);
|
||||||
|
}
|
||||||
|
|
||||||
free(sock->tx_slots);
|
free(sock->tx_slots);
|
||||||
free(sock->rx_buf);
|
free(sock->rx_buf);
|
||||||
free(sock->tx_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,
|
int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
|
||||||
patty_ax25_if *iface) {
|
patty_ax25_if *iface) {
|
||||||
sock->iface = 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) {
|
if (patty_ax25_if_promisc_add(iface, sock->fd) < 0) {
|
||||||
goto error_if_promisc_add;
|
goto error_if_promisc_add;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->flags_classes |= iface->flags_classes;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_if_promisc_add:
|
error_if_promisc_add:
|
||||||
|
|
Loading…
Add table
Reference in a new issue