Well, I have WORKING FREAKING SESSIONS BAYBEE

This commit is contained in:
XANTRONIX Development 2020-07-01 20:15:46 -04:00 committed by XANTRONIX Industrial
parent 22bf692a61
commit 2b1bc4c30e
2 changed files with 132 additions and 108 deletions

View file

@ -50,7 +50,7 @@
(((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x0f)) (((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_DISC(c) \ #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) \ #define PATTY_AX25_CONTROL_UNNUMBERED_DM(c) \
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f)) (((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f))

View file

@ -117,6 +117,28 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) {
return 0; 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, static patty_ax25_sock *sock_by_fd(patty_dict *dict,
int fd) { int fd) {
return patty_dict_get_with_hash(dict, (uint32_t)fd); return patty_dict_get_with_hash(dict, (uint32_t)fd);
@ -161,15 +183,33 @@ error_dict_set:
return -1; return -1;
} }
static int sock_save_by_addr(patty_dict *dict, static inline uint32_t hash_addr(patty_ax25_addr *addr) {
patty_ax25_sock *sock,
patty_ax25_addr *addr) {
uint32_t hash; uint32_t hash;
patty_hash_init(&hash); patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, addr); patty_ax25_addr_hash(&hash, addr);
patty_hash_end(&hash); 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, if (patty_dict_set_with_hash(dict,
addr, addr,
sizeof(*addr), sizeof(*addr),
@ -188,12 +228,7 @@ static int sock_save_by_addrpair(patty_dict *dict,
patty_ax25_sock *sock, patty_ax25_sock *sock,
patty_ax25_addr *local, patty_ax25_addr *local,
patty_ax25_addr *remote) { patty_ax25_addr *remote) {
uint32_t hash; uint32_t hash = hash_addrpair(local, remote);
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, local);
patty_ax25_addr_hash(&hash, remote);
patty_hash_end(&hash);
if (patty_dict_set_with_hash(dict, if (patty_dict_set_with_hash(dict,
sock, sock,
@ -209,67 +244,9 @@ error_dict_set_with_hash:
return -1; 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, static int sock_delete_by_addr(patty_dict *dict,
patty_ax25_addr *addr) { patty_ax25_addr *addr) {
uint32_t hash; uint32_t hash = hash_addr(addr);
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, addr);
patty_hash_end(&hash);
return patty_dict_delete_with_hash(dict, hash); 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, static int sock_delete_by_addrpair(patty_dict *dict,
patty_ax25_addr *local, patty_ax25_addr *local,
patty_ax25_addr *remote) { patty_ax25_addr *remote) {
uint32_t hash; uint32_t hash = hash_addrpair(local, remote);
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, local);
patty_ax25_addr_hash(&hash, remote);
patty_hash_end(&hash);
return patty_dict_delete_with_hash(dict, hash); return patty_dict_delete_with_hash(dict, hash);
} }
static inline void watch_fd(patty_ax25_server *server, int fd) { static int sock_close(patty_ax25_server *server,
FD_SET(fd, &server->fds_watch); 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) { if (sock_delete_by_addrpair(server->socks_established,
server->fd_max = fd + 1; &sock->local,
&sock->remote) < 0) {
goto error_sock_delete_by_addrpair_established;
} }
} }
static inline void clear_fd(patty_ax25_server *server, int fd) { if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) {
FD_CLR(fd, &server->fds_watch); if (sock_delete_by_addrpair(server->socks_pending_connect,
&sock->local,
if (server->fd_max == fd + 1) { &sock->remote) < 0) {
server->fd_max--; goto error_sock_delete_by_addrpair_pending_connect;
} }
} }
static inline void watch_sock(patty_ax25_server *server, patty_ax25_sock *sock) { if (sock->status == PATTY_AX25_SOCK_PENDING_ACCEPT) {
watch_fd(server, sock->fd); if (sock_delete_by_addr(server->socks_pending_accept,
&sock->local) < 0) {
goto error_sock_delete_by_addr_pending_accept;
}
} }
static inline void clear_sock(patty_ax25_server *server, patty_ax25_sock *sock) { 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);
clear_fd(server, sock->fd); 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, 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; goto error_sock_by_fd;
} }
if (sock_delete(server, sock) < 0) { if (sock_close(server, sock) < 0) {
response.ret = -1; response.ret = -1;
response.eno = EBADF; response.eno = EBADF;
goto error_sock_delete; goto error_sock_delete;
} }
if (close(request.socket) < 0) {
response.ret = -1;
response.eno = errno;
goto error_close;
}
response.ret = 0; response.ret = 0;
response.eno = 0; response.eno = 0;
error_close: error_close:
error_sock_delete: error_sock_delete:
error_sock_send_disc:
error_sock_by_fd: error_sock_by_fd:
if (write(client, &response, sizeof(response)) < 0) { if (write(client, &response, sizeof(response)) < 0) {
goto error_io; goto error_io;
@ -1058,7 +1050,7 @@ static int handle_sabm(patty_ax25_server *server,
goto error_write; goto error_write;
} }
watch_sock(server, remote); watch_fd(server, remote->fd);
return 0; return 0;
@ -1115,7 +1107,7 @@ static int handle_ua(patty_ax25_server *server,
goto error_write; goto error_write;
} }
watch_sock(server, sock); watch_fd(server, sock->fd);
return 0; return 0;
@ -1135,6 +1127,12 @@ static int handle_dm(patty_ax25_server *server,
patty_ax25_sock *sock; patty_ax25_sock *sock;
patty_ax25_call_connect_response response; 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, if ((sock = sock_by_addrpair(server->socks_pending_connect,
&frame->dest, &frame->dest,
&frame->src)) == NULL) { &frame->src)) == NULL) {
@ -1192,6 +1190,10 @@ static int handle_info(patty_ax25_server *server,
goto done; goto done;
} }
/*
* TODO: Validate RX and TX sequence numbers
*/
if (write(sock->fd, frame->info, frame->infolen) < 0) { if (write(sock->fd, frame->info, frame->infolen) < 0) {
goto error_write; goto error_write;
} }
@ -1203,6 +1205,27 @@ error_write:
return -1; 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, static int handle_frame(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
void *buf, void *buf,
@ -1226,6 +1249,8 @@ static int handle_frame(patty_ax25_server *server,
return handle_dm(server, iface, &frame); return handle_dm(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_INFO(frame.control)) { } else if (PATTY_AX25_CONTROL_INFO(frame.control)) {
return handle_info(server, iface, &frame); return handle_info(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_UNNUMBERED_DISC(frame.control)) {
return handle_disc(server, iface, &frame);
} }
return 0; return 0;
@ -1304,15 +1329,15 @@ static int handle_sock(void *key,
} }
if ((len = read(sock->fd, sock->buf, sock->bufsz)) < 0) { if ((len = read(sock->fd, sock->buf, sock->bufsz)) < 0) {
if (errno == EIO) {
(void)sock_close(server, sock);
goto done;
}
goto error_io; goto error_io;
} else if (len == 0) { } else if (len == 0) {
clear_sock(server, sock); sock_close(server, sock);
if (patty_dict_delete(server->socks_established,
NULL + fd,
sizeof(fd)) < 0) {
goto error_dict_delete;
}
goto done; goto done;
} }
@ -1325,7 +1350,6 @@ done:
return 0; return 0;
error_sock_write: error_sock_write:
error_dict_delete:
error_io: error_io:
return -1; return -1;
} }