From ab2c2835425af48283169790b9f87db6a2470a0d Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Fri, 3 Jul 2020 15:21:32 -0400 Subject: [PATCH] Refactor socket(), openif() as setsockopt() Other changes: * Fix blocking on disconnects when a raw socket is bound to an interface --- examples/testclient-connect.c | 2 +- examples/testclient-listen.c | 2 +- examples/testclient-promisc.c | 15 +++- include/patty/ax25/call.h | 48 ++++++----- include/patty/ax25/sock.h | 19 +++-- src/call.c | 78 +++++++++-------- src/server.c | 154 ++++++++++++++++++---------------- src/sock.c | 25 +++--- 8 files changed, 192 insertions(+), 151 deletions(-) diff --git a/examples/testclient-connect.c b/examples/testclient-connect.c index 67948da..b25c41c 100644 --- a/examples/testclient-connect.c +++ b/examples/testclient-connect.c @@ -61,7 +61,7 @@ int main(int argc, char **argv) { goto error_connect; } - if ((sock = patty_ax25_call_socket(fd, 0, PATTY_AX25_PROTO_NONE, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) { + if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_ax25_call_socket()", strerror(errno)); diff --git a/examples/testclient-listen.c b/examples/testclient-listen.c index c0316e7..37d8554 100644 --- a/examples/testclient-listen.c +++ b/examples/testclient-listen.c @@ -64,7 +64,7 @@ int main(int argc, char **argv) { goto error_connect; } - if ((local = patty_ax25_call_socket(fd, 0, PATTY_AX25_PROTO_NONE, NULL, 0)) < 0) { + if ((local = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM, NULL, 0)) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_ax25_call_socket()", strerror(errno)); diff --git a/examples/testclient-promisc.c b/examples/testclient-promisc.c index 03e774b..fd309a4 100644 --- a/examples/testclient-promisc.c +++ b/examples/testclient-promisc.c @@ -30,6 +30,7 @@ static void usage(int argc, char **argv, const char *message, ...) { int main(int argc, char **argv) { struct sockaddr_un addr; + patty_ax25_call_setsockopt_if ifreq; int fd, sock, @@ -62,13 +63,22 @@ int main(int argc, char **argv) { goto error_connect; } - if ((sock = patty_ax25_call_openif(fd, "kiss0", path, sizeof(path))) < 0) { + if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW, path, sizeof(path))) < 0) { fprintf(stderr, "%s: %s: %s\n", - argv[0], "patty_ax25_call_openif()", strerror(errno)); + argv[0], "patty_ax25_call_socket()", strerror(errno)); goto error_call_socket; } + strncpy(ifreq.name, "kiss0", sizeof(ifreq.name)); + + if (patty_ax25_call_setsockopt(fd, sock, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "patty_ax25_call_setsockopt()", strerror(errno)); + + goto error_call_setsockopt; + } + if ((pty = open(path, O_RDWR)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], path, "open()", strerror(errno)); @@ -107,6 +117,7 @@ error_ax25_frame_decode: error_open_pty: patty_ax25_call_close(fd, sock); +error_call_setsockopt: error_call_socket: close(fd); diff --git a/include/patty/ax25/call.h b/include/patty/ax25/call.h index 22f51d2..03c7f4e 100644 --- a/include/patty/ax25/call.h +++ b/include/patty/ax25/call.h @@ -4,11 +4,11 @@ enum patty_ax25_call { PATTY_AX25_CALL_NONE, PATTY_AX25_CALL_SOCKET, + PATTY_AX25_CALL_SETSOCKOPT, PATTY_AX25_CALL_BIND, PATTY_AX25_CALL_LISTEN, PATTY_AX25_CALL_ACCEPT, PATTY_AX25_CALL_CONNECT, - PATTY_AX25_CALL_OPENIF, PATTY_AX25_CALL_CLOSE, PATTY_AX25_CALL_SENDTO, PATTY_AX25_CALL_RECVFROM, @@ -19,8 +19,8 @@ enum patty_ax25_call { * socket() */ typedef struct _patty_ax25_call_socket_request { - int opts; int proto; + int type; } patty_ax25_call_socket_request; typedef struct _patty_ax25_response_socket { @@ -30,11 +30,35 @@ typedef struct _patty_ax25_response_socket { } patty_ax25_call_socket_response; int patty_ax25_call_socket(int server, - int opts, int proto, + int type, char *path, size_t len); +/* + * setsockopt() + */ +typedef struct _patty_ax25_call_setsockopt_request { + int fd; + int opt; + size_t len; +} patty_ax25_call_setsockopt_request; + +typedef struct _patty_ax25_call_setsockopt_if { + char name[8]; +} patty_ax25_call_setsockopt_if; + +typedef struct _patty_ax25_call_setsockopt_response { + int ret; + int eno; +} patty_ax25_call_setsockopt_response; + +int patty_ax25_call_setsockopt(int server, + int fd, + int opt, + void *data, + size_t len); + /* * bind() */ @@ -104,24 +128,6 @@ int patty_ax25_call_connect(int server, int fd, patty_ax25_addr *peer); -/* - * openif() - */ -typedef struct _patty_ax25_call_openif_request { - char name[8]; -} patty_ax25_call_openif_request; - -typedef struct _patty_ax25_call_openif_response { - int fd; - int eno; - char path[PATTY_AX25_SOCK_PATH_SIZE]; -} patty_ax25_call_openif_response; - -int patty_ax25_call_openif(int server, - char *name, - char *path, - size_t len); - /* * close() */ diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index 5a44257..e0ffa77 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -3,10 +3,9 @@ #define PATTY_AX25_SOCK_BUFSZ 4096 -enum patty_ax25_sock_opts { - PATTY_AX25_SOCK_NONE, - PATTY_AX25_SOCK_PTY = 1 << 0, - PATTY_AX25_SOCK_RAW = 1 << 1 +enum patty_ax25_sock_type { + PATTY_AX25_SOCK_STREAM, + PATTY_AX25_SOCK_RAW }; enum patty_ax25_sock_status { @@ -23,11 +22,15 @@ enum patty_ax25_sock_mode { PATTY_AX25_SOCK_SABME }; +enum patty_ax25_sock_opt { + PATTY_AX25_SOCK_IF +}; + typedef struct _patty_ax25_sock { - enum patty_ax25_sock_opts opts; + enum patty_ax25_proto proto; + enum patty_ax25_sock_type type; enum patty_ax25_sock_status status; enum patty_ax25_sock_mode mode; - enum patty_ax25_proto proto; time_t timer_ack, timer_response, @@ -66,8 +69,8 @@ typedef struct _patty_ax25_sock { PATTY_AX25_SOCK_CONTROL_SABME(sock, flag): \ PATTY_AX25_SOCK_CONTROL_SABM(sock, flag)) -patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts, - enum patty_ax25_proto proto); +patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, + enum patty_ax25_sock_type type); void patty_ax25_sock_reset(patty_ax25_sock *sock); diff --git a/src/call.c b/src/call.c index 211f90c..c53fb60 100644 --- a/src/call.c +++ b/src/call.c @@ -5,14 +5,14 @@ #include int patty_ax25_call_socket(int server, - int opts, int proto, + int type, char *path, size_t len) { enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET; patty_ax25_call_socket_request request = { - opts, proto + proto, type }; patty_ax25_call_socket_response response; @@ -41,6 +41,45 @@ error_io: return -1; } +int patty_ax25_call_setsockopt(int server, + int fd, + int opt, + void *data, + size_t len) { + enum patty_ax25_call call = PATTY_AX25_CALL_SETSOCKOPT; + + patty_ax25_call_setsockopt_request request = { + .fd = fd, + .opt = opt, + .len = len + }; + + patty_ax25_call_setsockopt_response response; + + if (write(server, &call, sizeof(call)) < 0) { + goto error_io; + } + + if (write(server, &request, sizeof(request)) < 0) { + goto error_io; + } + + if (write(server, data, len) < 0) { + goto error_io; + } + + if (read(server, &response, sizeof(response)) < 0) { + goto error_io; + } + + errno = response.eno; + + return response.ret; + +error_io: + return -1; +} + int patty_ax25_call_bind(int server, int fd, patty_ax25_addr *peer) { @@ -180,41 +219,6 @@ error_io: return -1; } -int patty_ax25_call_openif(int server, - char *name, - char *path, - size_t len) { - enum patty_ax25_call call = PATTY_AX25_CALL_OPENIF; - - patty_ax25_call_openif_request request; - patty_ax25_call_openif_response response; - - memcpy(request.name, name, sizeof(request.name)); - - if (write(server, &call, sizeof(call)) < 0) { - goto error_io; - } - - if (write(server, &request, sizeof(request)) < 0) { - goto error_io; - } - - if (read(server, &response, sizeof(response)) < 0) { - goto error_io; - } - - if (path) { - strncpy(path, response.path, len); - } - - errno = response.eno; - - return response.fd; - -error_io: - return -1; -} - int patty_ax25_call_close(int server, int fd) { enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE; diff --git a/src/server.c b/src/server.c index 5982ab7..0d5d8b3 100644 --- a/src/server.c +++ b/src/server.c @@ -245,10 +245,10 @@ static int sock_save_by_addrpair(patty_dict *dict, uint32_t hash = hash_addrpair(local, remote); if (patty_dict_set_with_hash(dict, - sock, - sizeof(*sock), - sock, - hash) == NULL) { + NULL + sock->fd, + sizeof(*sock), + sock, + hash) == NULL) { goto error_dict_set_with_hash; } @@ -428,7 +428,7 @@ static int server_socket(patty_ax25_server *server, goto error_read; } - if ((sock = patty_ax25_sock_new(request.opts, request.proto)) == NULL) { + if ((sock = patty_ax25_sock_new(request.proto, request.type)) == NULL) { goto error_sock_new; } @@ -463,6 +463,79 @@ error_read: return -1; } +static int server_setsockopt(patty_ax25_server *server, + int client) { + patty_ax25_call_setsockopt_request request; + patty_ax25_call_setsockopt_response response; + + patty_ax25_sock *sock; + + if (read(client, &request, sizeof(request)) < 0) { + goto error_read; + } + + if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) { + response.ret = -1; + response.eno = EBADF; + + goto error_sock_by_fd; + } + + switch (request.opt) { + case PATTY_AX25_SOCK_IF: { + patty_ax25_call_setsockopt_if data; + patty_ax25_if *iface; + + if (sock->type != PATTY_AX25_SOCK_RAW) { + response.ret = -1; + response.eno = EINVAL; + + goto error_invalid_type; + } + + if (read(client, &data, request.len) < 0) { + goto error_read; + } + + if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) { + response.ret = -1; + response.eno = ENODEV; + + goto error_get_if; + } + + patty_ax25_sock_bind_if(sock, iface); + + if (sock_save_by_fd(server->socks_established, sock) < 0) { + goto error_sock_save_by_fd; + } + + watch_fd(server, sock->fd); + + break; + } + + default: + response.ret = -1; + response.eno = EINVAL; + + goto error_invalid_opt; + } + + response.ret = 0; + response.eno = 0; + +error_sock_by_fd: +error_get_if: +error_invalid_type: +error_invalid_opt: + return write(client, &response, sizeof(response)); + +error_sock_save_by_fd: +error_read: + return -1; +} + static int server_bind(patty_ax25_server *server, int client) { patty_ax25_call_bind_request request; @@ -701,65 +774,6 @@ error_io: return -1; } -static int server_openif(patty_ax25_server *server, - int client) { - patty_ax25_call_openif_request request; - patty_ax25_call_openif_response response; - - patty_ax25_sock *sock; - patty_ax25_if *iface; - - if (read(client, &request, sizeof(request)) < 0) { - goto error_io; - } - - if ((sock = patty_ax25_sock_new(PATTY_AX25_SOCK_RAW, - PATTY_AX25_PROTO_NONE)) == NULL) { - response.fd = -1; - response.eno = errno; - - goto error_sock_new; - } - - if ((iface = patty_ax25_server_get_if(server, request.name)) == NULL) { - response.fd = -1; - response.eno = ENODEV; - - goto error_get_if; - } - - patty_ax25_sock_bind_if(sock, iface); - - watch_fd(server, sock->fd); - - if (sock_save_by_fd(server->socks_by_fd, sock) < 0) { - response.fd = -1; - response.eno = errno; - - goto error_sock_save_by_fd; - } - - if (sock_save_by_fd(server->socks_established, sock) < 0) { - response.fd = -1; - response.eno = errno; - - goto error_sock_save_by_fd; - } - - response.fd = sock->fd; - response.eno = 0; - - strncpy(response.path, sock->path, sizeof(response.path)); - -error_get_if: -error_sock_new: - return write(client, &response, sizeof(response)); - -error_sock_save_by_fd: -error_io: - return -1; -} - static int server_close(patty_ax25_server *server, int client) { patty_ax25_call_close_request request; @@ -799,11 +813,11 @@ error_io: static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = { NULL, server_socket, + server_setsockopt, server_bind, server_listen, server_accept, server_connect, - server_openif, server_close, NULL, NULL @@ -1042,7 +1056,7 @@ static int handle_sabm(patty_ax25_server *server, goto error_lookup_client; } - if ((remote = patty_ax25_sock_new(local->opts, local->proto)) == NULL) { + if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) { goto error_sock_new; } @@ -1273,7 +1287,7 @@ static int handle_sock_raw(void *key, patty_ax25_sock *sock = value; struct sock_raw_frame *raw_frame = ctx; - if (raw_frame->iface != sock->iface || !(sock->opts & PATTY_AX25_SOCK_RAW)) { + if (sock->type != PATTY_AX25_SOCK_RAW || raw_frame->iface != sock->iface) { return 0; } @@ -1380,11 +1394,9 @@ static int handle_sock(void *key, patty_ax25_server *server = ctx; patty_ax25_sock *sock = value; - int fd = (int)(key - NULL); - ssize_t len; - if (!FD_ISSET(fd, &server->fds_r) || sock->opts & PATTY_AX25_SOCK_RAW) { + if (!FD_ISSET(sock->fd, &server->fds_r)) { goto done; } @@ -1415,7 +1427,7 @@ error_io: } static int handle_socks(patty_ax25_server *server) { - return patty_dict_each(server->socks_by_fd, handle_sock, server); + return patty_dict_each(server->socks_established, handle_sock, server); } int patty_ax25_server_run(patty_ax25_server *server) { diff --git a/src/sock.c b/src/sock.c index 3e035bb..9bc562d 100644 --- a/src/sock.c +++ b/src/sock.c @@ -41,8 +41,6 @@ static int bind_pty(patty_ax25_sock *sock) { goto error_tcsetattr; } - sock->opts |= PATTY_AX25_SOCK_PTY; - return 0; error_tcsetattr: @@ -56,8 +54,8 @@ error_open: return -1; } -patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts, - enum patty_ax25_proto proto) { +patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, + enum patty_ax25_sock_type type) { patty_ax25_sock *sock; if ((sock = malloc(sizeof(*sock))) == NULL) { @@ -75,10 +73,10 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts, } sock->bufsz = PATTY_AX25_SOCK_BUFSZ; + sock->proto = proto; + sock->type = type; sock->status = PATTY_AX25_SOCK_CLOSED; sock->mode = PATTY_AX25_SOCK_DM; - sock->opts = opts; - sock->proto = proto; sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN; sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW; @@ -95,9 +93,16 @@ error_malloc_sock: } void patty_ax25_sock_reset(patty_ax25_sock *sock) { - sock->opts &= ~PATTY_AX25_SOCK_PTY; - sock->status = PATTY_AX25_SOCK_CLOSED; - sock->mode = PATTY_AX25_SOCK_DM; + sock->status = PATTY_AX25_SOCK_CLOSED; + sock->mode = PATTY_AX25_SOCK_DM; + sock->timer_ack = 0; + sock->timer_response = 0; + sock->timer_keepalive = 0; + sock->n_maxlen = 0; + sock->n_retry = 0; + sock->n_window = 0; + sock->seq_send = 0; + sock->seq_recv = 0; } void patty_ax25_sock_destroy(patty_ax25_sock *sock) { @@ -225,7 +230,7 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock, size_t len) { uint16_t control = 0x0000; - if (sock->opts & PATTY_AX25_SOCK_RAW) { + if (sock->type == PATTY_AX25_SOCK_RAW) { return patty_ax25_if_send(sock->iface, buf, len); }