From 2b1bc4c30e1042877a91c90ee657bd2206ae60a1 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 1 Jul 2020 20:15:46 -0400 Subject: [PATCH] Well, I have WORKING FREAKING SESSIONS BAYBEE --- include/patty/ax25/macros.h | 2 +- src/server.c | 238 ++++++++++++++++++++---------------- 2 files changed, 132 insertions(+), 108 deletions(-) diff --git a/include/patty/ax25/macros.h b/include/patty/ax25/macros.h index e6e4ec0..d20f2fb 100644 --- a/include/patty/ax25/macros.h +++ b/include/patty/ax25/macros.h @@ -50,7 +50,7 @@ (((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x0f)) #define PATTY_AX25_CONTROL_UNNUMBERED_DISC(c) \ - (((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x03)) + (((c & 0xe0) == 0x40) && ((c & 0x0f) == 0x03)) #define PATTY_AX25_CONTROL_UNNUMBERED_DM(c) \ (((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f)) diff --git a/src/server.c b/src/server.c index 4a33011..400ef02 100644 --- a/src/server.c +++ b/src/server.c @@ -117,6 +117,28 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) { return 0; } +static inline void watch_fd(patty_ax25_server *server, int fd) { + FD_SET(fd, &server->fds_watch); + + if (server->fd_max <= fd) { + server->fd_max = fd + 1; + } +} + +static inline void clear_fd(patty_ax25_server *server, int fd) { + int i; + + FD_CLR(fd, &server->fds_watch); + + for (i=0; i<8*sizeof(&server->fds_watch); i++) { + if (FD_ISSET(i, &server->fds_watch)) { + server->fd_max = i; + } + } + + server->fd_max++; +} + static patty_ax25_sock *sock_by_fd(patty_dict *dict, int fd) { return patty_dict_get_with_hash(dict, (uint32_t)fd); @@ -161,15 +183,33 @@ error_dict_set: return -1; } -static int sock_save_by_addr(patty_dict *dict, - patty_ax25_sock *sock, - patty_ax25_addr *addr) { +static inline uint32_t hash_addr(patty_ax25_addr *addr) { uint32_t hash; patty_hash_init(&hash); patty_ax25_addr_hash(&hash, addr); patty_hash_end(&hash); + return hash; +} + +static inline uint32_t hash_addrpair(patty_ax25_addr *local, + patty_ax25_addr *remote) { + uint32_t hash; + + patty_hash_init(&hash); + patty_ax25_addr_hash(&hash, local); + patty_ax25_addr_hash(&hash, remote); + patty_hash_end(&hash); + + return hash; +} + +static int sock_save_by_addr(patty_dict *dict, + patty_ax25_sock *sock, + patty_ax25_addr *addr) { + uint32_t hash = hash_addr(addr); + if (patty_dict_set_with_hash(dict, addr, sizeof(*addr), @@ -188,12 +228,7 @@ static int sock_save_by_addrpair(patty_dict *dict, patty_ax25_sock *sock, patty_ax25_addr *local, patty_ax25_addr *remote) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, local); - patty_ax25_addr_hash(&hash, remote); - patty_hash_end(&hash); + uint32_t hash = hash_addrpair(local, remote); if (patty_dict_set_with_hash(dict, sock, @@ -209,67 +244,9 @@ error_dict_set_with_hash: return -1; } -static int sock_delete(patty_ax25_server *server, - patty_ax25_sock *sock) { - if (sock->status == PATTY_AX25_SOCK_ESTABLISHED) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, &sock->local); - patty_ax25_addr_hash(&hash, &sock->remote); - patty_hash_end(&hash); - - if (patty_dict_delete_with_hash(server->socks_established, hash) < 0) { - goto error_dict_delete_established; - } - } - - if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, &sock->local); - patty_hash_end(&hash); - - if (patty_dict_delete_with_hash(server->socks_pending_connect, hash) < 0) { - goto error_dict_delete_pending_connect; - } - } - - if (sock->status == PATTY_AX25_SOCK_PENDING_ACCEPT) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, &sock->local); - patty_hash_end(&hash); - - if (patty_dict_delete_with_hash(server->socks_pending_accept, hash) < 0) { - goto error_dict_delete_pending_accept; - } - } - - if (patty_dict_delete_with_hash(server->socks_by_fd, sock->fd) < 0) { - goto error_dict_delete_by_fd; - } - - free(sock); - - return 0; - -error_dict_delete_by_fd: -error_dict_delete_pending_accept: -error_dict_delete_pending_connect: -error_dict_delete_established: - return -1; -} - static int sock_delete_by_addr(patty_dict *dict, patty_ax25_addr *addr) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, addr); - patty_hash_end(&hash); + uint32_t hash = hash_addr(addr); return patty_dict_delete_with_hash(dict, hash); } @@ -277,38 +254,59 @@ static int sock_delete_by_addr(patty_dict *dict, static int sock_delete_by_addrpair(patty_dict *dict, patty_ax25_addr *local, patty_ax25_addr *remote) { - uint32_t hash; - - patty_hash_init(&hash); - patty_ax25_addr_hash(&hash, local); - patty_ax25_addr_hash(&hash, remote); - patty_hash_end(&hash); + uint32_t hash = hash_addrpair(local, remote); return patty_dict_delete_with_hash(dict, hash); } -static inline void watch_fd(patty_ax25_server *server, int fd) { - FD_SET(fd, &server->fds_watch); +static int sock_close(patty_ax25_server *server, + patty_ax25_sock *sock) { + if (sock->status == PATTY_AX25_SOCK_ESTABLISHED) { + if (patty_ax25_sock_send_disc(sock, 1) < 0) { + goto error_sock_send_disc; + } - if (server->fd_max <= fd) { - server->fd_max = fd + 1; + if (sock_delete_by_addrpair(server->socks_established, + &sock->local, + &sock->remote) < 0) { + goto error_sock_delete_by_addrpair_established; + } } -} -static inline void clear_fd(patty_ax25_server *server, int fd) { - FD_CLR(fd, &server->fds_watch); - - if (server->fd_max == fd + 1) { - server->fd_max--; + if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) { + if (sock_delete_by_addrpair(server->socks_pending_connect, + &sock->local, + &sock->remote) < 0) { + goto error_sock_delete_by_addrpair_pending_connect; + } } -} -static inline void watch_sock(patty_ax25_server *server, patty_ax25_sock *sock) { - watch_fd(server, sock->fd); -} + if (sock->status == PATTY_AX25_SOCK_PENDING_ACCEPT) { + if (sock_delete_by_addr(server->socks_pending_accept, + &sock->local) < 0) { + goto error_sock_delete_by_addr_pending_accept; + } + } + + if (patty_dict_delete_with_hash(server->socks_by_fd, sock->fd) < 0) { + goto error_dict_delete_by_fd_socks; + } + + (void)patty_dict_delete_with_hash(server->clients_by_sock, sock->fd); -static inline void clear_sock(patty_ax25_server *server, patty_ax25_sock *sock) { clear_fd(server, sock->fd); + + patty_ax25_sock_destroy(sock); + + return 0; + +error_dict_delete_by_fd_clients: +error_dict_delete_by_fd_socks: +error_sock_delete_by_addr_pending_accept: +error_sock_delete_by_addrpair_pending_connect: +error_sock_delete_by_addrpair_established: +error_sock_send_disc: + return -1; } int patty_ax25_server_add_if(patty_ax25_server *server, @@ -741,25 +739,19 @@ static int server_close(patty_ax25_server *server, goto error_sock_by_fd; } - if (sock_delete(server, sock) < 0) { + if (sock_close(server, sock) < 0) { response.ret = -1; response.eno = EBADF; goto error_sock_delete; } - if (close(request.socket) < 0) { - response.ret = -1; - response.eno = errno; - - goto error_close; - } - response.ret = 0; response.eno = 0; error_close: error_sock_delete: +error_sock_send_disc: error_sock_by_fd: if (write(client, &response, sizeof(response)) < 0) { goto error_io; @@ -1058,7 +1050,7 @@ static int handle_sabm(patty_ax25_server *server, goto error_write; } - watch_sock(server, remote); + watch_fd(server, remote->fd); return 0; @@ -1115,7 +1107,7 @@ static int handle_ua(patty_ax25_server *server, goto error_write; } - watch_sock(server, sock); + watch_fd(server, sock->fd); return 0; @@ -1135,6 +1127,12 @@ static int handle_dm(patty_ax25_server *server, patty_ax25_sock *sock; patty_ax25_call_connect_response response; + if ((sock = sock_by_addrpair(server->socks_established, + &frame->dest, + &frame->src)) != NULL) { + return sock_close(server, sock); + } + if ((sock = sock_by_addrpair(server->socks_pending_connect, &frame->dest, &frame->src)) == NULL) { @@ -1192,6 +1190,10 @@ static int handle_info(patty_ax25_server *server, goto done; } + /* + * TODO: Validate RX and TX sequence numbers + */ + if (write(sock->fd, frame->info, frame->infolen) < 0) { goto error_write; } @@ -1203,6 +1205,27 @@ error_write: return -1; } +static int handle_disc(patty_ax25_server *server, + patty_ax25_if *iface, + patty_ax25_frame *frame) { + patty_ax25_sock *sock; + + if ((sock = sock_by_addrpair(server->socks_established, + &frame->dest, + &frame->src)) == NULL) { + return reply_frmr(iface, frame, PATTY_AX25_FRAME_U_FINAL); + } + + if (sock_close(server, sock) < 0) { + goto error_sock_delete; + } + + return reply_dm(iface, frame, PATTY_AX25_FRAME_U_FINAL); + +error_sock_delete: + return -1; +} + static int handle_frame(patty_ax25_server *server, patty_ax25_if *iface, void *buf, @@ -1226,6 +1249,8 @@ static int handle_frame(patty_ax25_server *server, return handle_dm(server, iface, &frame); } else if (PATTY_AX25_CONTROL_INFO(frame.control)) { return handle_info(server, iface, &frame); + } else if (PATTY_AX25_CONTROL_UNNUMBERED_DISC(frame.control)) { + return handle_disc(server, iface, &frame); } return 0; @@ -1304,15 +1329,15 @@ static int handle_sock(void *key, } if ((len = read(sock->fd, sock->buf, sock->bufsz)) < 0) { + if (errno == EIO) { + (void)sock_close(server, sock); + + goto done; + } + goto error_io; } else if (len == 0) { - clear_sock(server, sock); - - if (patty_dict_delete(server->socks_established, - NULL + fd, - sizeof(fd)) < 0) { - goto error_dict_delete; - } + sock_close(server, sock); goto done; } @@ -1325,7 +1350,6 @@ done: return 0; error_sock_write: -error_dict_delete: error_io: return -1; }