Refactor to adhere better to AX.25 v2.2
Changes: * Don't use a separate dict for keeping track of sockets pending accept and sockets pending connect; rely more on the semantic meaning of the enum patty_ax25_sock_status values * Ensure DISC frames are acknowledged by UA frames * Ensure a receiving system only shuts down a connection after receiving a UA frame in response to a sent DISC frame * Ensure a sending system only shuts down a connection just prior to sending a UA frame in response to a received DISC frame * Don't use the P/F flag for the connection management U frames; implicitly assume the P/F flag is set to 1, and always send frames with a true P/F flag
This commit is contained in:
parent
edfc32ce33
commit
8761a4e3c2
2 changed files with 319 additions and 234 deletions
|
@ -30,7 +30,8 @@ enum patty_ax25_sock_status {
|
|||
PATTY_AX25_SOCK_LISTENING,
|
||||
PATTY_AX25_SOCK_PENDING_ACCEPT,
|
||||
PATTY_AX25_SOCK_PENDING_CONNECT,
|
||||
PATTY_AX25_SOCK_ESTABLISHED
|
||||
PATTY_AX25_SOCK_ESTABLISHED,
|
||||
PATTY_AX25_SOCK_PROMISC
|
||||
};
|
||||
|
||||
enum patty_ax25_sock_mode {
|
||||
|
|
550
src/server.c
550
src/server.c
|
@ -29,9 +29,9 @@ struct _patty_ax25_server {
|
|||
patty_ax25_route_table *routes;
|
||||
|
||||
patty_dict *socks_by_fd,
|
||||
*socks_pending_accept,
|
||||
*socks_pending_connect,
|
||||
*socks_established;
|
||||
*socks_by_client,
|
||||
*socks_local,
|
||||
*socks_remote;
|
||||
|
||||
patty_dict *clients,
|
||||
*clients_by_sock;
|
||||
|
@ -60,16 +60,16 @@ patty_ax25_server *patty_ax25_server_new(const char *path) {
|
|||
goto error_dict_new_socks_by_fd;
|
||||
}
|
||||
|
||||
if ((server->socks_pending_accept = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_pending_accept;
|
||||
if ((server->socks_by_client = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_by_client;
|
||||
}
|
||||
|
||||
if ((server->socks_pending_connect = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_pending_connect;
|
||||
if ((server->socks_local = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_local;
|
||||
}
|
||||
|
||||
if ((server->socks_established = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_established;
|
||||
if ((server->socks_remote = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_remote;
|
||||
}
|
||||
|
||||
if ((server->clients = patty_dict_new()) == NULL) {
|
||||
|
@ -86,15 +86,15 @@ error_dict_new_clients_by_sock:
|
|||
patty_dict_destroy(server->clients);
|
||||
|
||||
error_dict_new_clients:
|
||||
patty_dict_destroy(server->socks_established);
|
||||
patty_dict_destroy(server->socks_remote);
|
||||
|
||||
error_dict_new_socks_established:
|
||||
patty_dict_destroy(server->socks_pending_connect);
|
||||
error_dict_new_socks_remote:
|
||||
patty_dict_destroy(server->socks_local);
|
||||
|
||||
error_dict_new_socks_pending_connect:
|
||||
patty_dict_destroy(server->socks_pending_accept);
|
||||
error_dict_new_socks_local:
|
||||
patty_dict_destroy(server->socks_by_client);
|
||||
|
||||
error_dict_new_socks_pending_accept:
|
||||
error_dict_new_socks_by_client:
|
||||
patty_dict_destroy(server->socks_by_fd);
|
||||
|
||||
error_dict_new_socks_by_fd:
|
||||
|
@ -116,12 +116,19 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int destroy_socks_by_client_entry(uint32_t key, void *value, void *ctx) {
|
||||
patty_dict_destroy((patty_dict *)value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void patty_ax25_server_destroy(patty_ax25_server *server) {
|
||||
patty_dict_destroy(server->clients_by_sock);
|
||||
patty_dict_destroy(server->clients);
|
||||
patty_dict_destroy(server->socks_established);
|
||||
patty_dict_destroy(server->socks_pending_connect);
|
||||
patty_dict_destroy(server->socks_pending_accept);
|
||||
patty_dict_destroy(server->socks_remote);
|
||||
patty_dict_destroy(server->socks_local);
|
||||
patty_dict_each(server->socks_by_client, destroy_socks_by_client_entry, NULL);
|
||||
patty_dict_destroy(server->socks_by_client);
|
||||
patty_dict_destroy(server->socks_by_fd);
|
||||
|
||||
patty_ax25_server_each_if(server, destroy_if, NULL);
|
||||
|
@ -185,9 +192,7 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
|
|||
}
|
||||
|
||||
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
||||
if (patty_dict_set(dict,
|
||||
(uint32_t)sock->fd,
|
||||
sock) == NULL) {
|
||||
if (patty_dict_set(dict, (uint32_t)sock->fd, sock) == NULL) {
|
||||
goto error_dict_set;
|
||||
}
|
||||
|
||||
|
@ -229,7 +234,8 @@ error_dict_set:
|
|||
|
||||
static inline int client_delete_by_sock(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
return patty_dict_delete(server->clients_by_sock, (uint32_t)sock->fd);
|
||||
return patty_dict_delete(server->clients_by_sock,
|
||||
(uint32_t)sock->fd);
|
||||
}
|
||||
|
||||
static inline uint32_t hash_addr(patty_ax25_addr *addr) {
|
||||
|
@ -254,87 +260,132 @@ static inline uint32_t hash_addrpair(patty_ax25_addr *local,
|
|||
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);
|
||||
static int sock_save_local(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
uint32_t hash = hash_addr(&sock->local);
|
||||
|
||||
if (patty_dict_set(dict,
|
||||
hash,
|
||||
sock) == NULL) {
|
||||
goto error_dict_set;
|
||||
return patty_dict_set(server->socks_local, hash, sock) == NULL? -1: 0;
|
||||
}
|
||||
|
||||
static int sock_save_remote(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
||||
|
||||
return patty_dict_set(server->socks_remote, hash, sock) == NULL? -1: 0;
|
||||
}
|
||||
|
||||
static int sock_delete_local(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
uint32_t hash = hash_addr(&sock->local);
|
||||
|
||||
return patty_dict_delete(server->socks_local, hash);
|
||||
}
|
||||
|
||||
static int sock_delete_remote(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
||||
|
||||
return patty_dict_delete(server->socks_remote, hash);
|
||||
}
|
||||
|
||||
static int sock_shutdown(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
fd_clear(server, sock->fd);
|
||||
|
||||
return sock->status == PATTY_AX25_SOCK_ESTABLISHED?
|
||||
patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL): 0;
|
||||
}
|
||||
|
||||
static int sock_save(patty_ax25_server *server,
|
||||
int client,
|
||||
patty_ax25_sock *sock) {
|
||||
patty_dict *socks;
|
||||
|
||||
switch (sock->status) {
|
||||
case PATTY_AX25_SOCK_LISTENING:
|
||||
if (sock_save_local(server, sock) < 0) {
|
||||
goto error_sock_save_local;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
||||
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||
if (sock_save_remote(server, sock) < 0) {
|
||||
goto error_sock_save_remote;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PATTY_AX25_SOCK_CLOSED:
|
||||
case PATTY_AX25_SOCK_PROMISC:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_dict_set:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sock_save_by_addrpair(patty_dict *dict,
|
||||
patty_ax25_sock *sock,
|
||||
patty_ax25_addr *local,
|
||||
patty_ax25_addr *remote) {
|
||||
uint32_t hash = hash_addrpair(local, remote);
|
||||
|
||||
if (patty_dict_set(dict,
|
||||
hash,
|
||||
sock) == NULL) {
|
||||
goto error_dict_set;
|
||||
if (client_save_by_sock(server, client, sock) < 0) {
|
||||
goto error_client_save_by_sock;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||
goto error_dict_get_socks_by_client;
|
||||
}
|
||||
|
||||
error_dict_set:
|
||||
if (sock_save_by_fd(socks, sock) < 0) {
|
||||
goto error_sock_save_by_fd;
|
||||
}
|
||||
|
||||
return sock_save_by_fd(server->socks_by_fd, sock);
|
||||
|
||||
error_sock_save_by_fd:
|
||||
error_dict_get_socks_by_client:
|
||||
error_client_save_by_sock:
|
||||
error_sock_save_remote:
|
||||
error_sock_save_local:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sock_delete_by_addr(patty_dict *dict,
|
||||
patty_ax25_addr *addr) {
|
||||
uint32_t hash = hash_addr(addr);
|
||||
|
||||
return patty_dict_delete(dict, hash);
|
||||
}
|
||||
|
||||
static int sock_delete_by_addrpair(patty_dict *dict,
|
||||
patty_ax25_addr *local,
|
||||
patty_ax25_addr *remote) {
|
||||
uint32_t hash = hash_addrpair(local, remote);
|
||||
|
||||
return patty_dict_delete(dict, hash);
|
||||
}
|
||||
|
||||
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, PATTY_AX25_FRAME_POLL) < 0) {
|
||||
goto error_sock_send_disc;
|
||||
}
|
||||
int client;
|
||||
patty_dict *socks;
|
||||
|
||||
if (sock_delete_by_addrpair(server->socks_established,
|
||||
&sock->local,
|
||||
&sock->remote) < 0) {
|
||||
goto error_sock_delete_by_addrpair_established;
|
||||
}
|
||||
switch (sock->status) {
|
||||
case PATTY_AX25_SOCK_LISTENING:
|
||||
if (sock_delete_local(server, sock) < 0) {
|
||||
goto error_sock_delete_local;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
||||
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||
if (sock_delete_remote(server, sock) < 0) {
|
||||
goto error_sock_delete_remote;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PATTY_AX25_SOCK_CLOSED:
|
||||
case PATTY_AX25_SOCK_PROMISC:
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if ((client = client_by_sock(server, sock)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
}
|
||||
|
||||
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 ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||
goto error_dict_get_socks_by_client;
|
||||
}
|
||||
|
||||
if (patty_dict_delete(socks, (uint32_t)sock->fd) < 0) {
|
||||
goto error_dict_delete_by_fd_socks;
|
||||
}
|
||||
|
||||
if (patty_dict_delete(server->socks_by_fd, (uint32_t)sock->fd) < 0) {
|
||||
goto error_dict_delete_by_fd_socks;
|
||||
goto error_dict_delete_by_fd_socks_by_fd;
|
||||
}
|
||||
|
||||
(void)client_delete_by_sock(server, sock);
|
||||
|
@ -345,11 +396,12 @@ static int sock_close(patty_ax25_server *server,
|
|||
|
||||
return 0;
|
||||
|
||||
error_dict_delete_by_fd_socks_by_fd:
|
||||
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:
|
||||
error_dict_get_socks_by_client:
|
||||
error_client_by_sock:
|
||||
error_sock_delete_remote:
|
||||
error_sock_delete_local:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -391,16 +443,11 @@ int patty_ax25_server_delete_if(patty_ax25_server *server,
|
|||
}
|
||||
|
||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||
fd_watch(server, fd);
|
||||
|
||||
if (patty_dict_delete(server->socks_by_fd, (uint32_t)fd) < 0) {
|
||||
goto error_dict_delete;
|
||||
}
|
||||
fd_clear(server, fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_dict_delete:
|
||||
error_list_splice:
|
||||
return -1;
|
||||
}
|
||||
|
@ -463,15 +510,8 @@ static int server_socket(patty_ax25_server *server,
|
|||
goto error_sock_new;
|
||||
}
|
||||
|
||||
if (sock_save_by_fd(server->socks_by_fd, sock) < 0) {
|
||||
response.ret = -1;
|
||||
response.eno = errno;
|
||||
|
||||
goto error_sock_save_by_fd;
|
||||
}
|
||||
|
||||
if (client_save_by_sock(server, client, sock) < 0) {
|
||||
goto error_client_save_by_sock;
|
||||
if (sock_save(server, client, sock) < 0) {
|
||||
goto error_sock_save;
|
||||
}
|
||||
|
||||
response.ret = sock->fd;
|
||||
|
@ -481,8 +521,7 @@ static int server_socket(patty_ax25_server *server,
|
|||
|
||||
return write(client, &response, sizeof(response));
|
||||
|
||||
error_client_save_by_sock:
|
||||
error_sock_save_by_fd:
|
||||
error_sock_save:
|
||||
patty_ax25_sock_destroy(sock);
|
||||
|
||||
error_sock_new:
|
||||
|
@ -533,9 +572,7 @@ static int server_setsockopt(patty_ax25_server *server,
|
|||
|
||||
patty_ax25_sock_bind_if(sock, iface);
|
||||
|
||||
if (sock_save_by_fd(server->socks_established, sock) < 0) {
|
||||
goto error_sock_save_by_fd;
|
||||
}
|
||||
sock->status = PATTY_AX25_SOCK_PROMISC;
|
||||
|
||||
fd_watch(server, sock->fd);
|
||||
|
||||
|
@ -558,7 +595,6 @@ error_invalid_type:
|
|||
error_invalid_opt:
|
||||
return write(client, &response, sizeof(response));
|
||||
|
||||
error_sock_save_by_fd:
|
||||
error_read:
|
||||
return -1;
|
||||
}
|
||||
|
@ -632,6 +668,10 @@ static int server_listen(patty_ax25_server *server,
|
|||
|
||||
sock->status = PATTY_AX25_SOCK_LISTENING;
|
||||
|
||||
if (sock_save_local(server, sock) < 0) {
|
||||
goto error_sock_save_local;
|
||||
}
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
||||
|
@ -639,6 +679,7 @@ error_invalid_fd:
|
|||
error_sock_by_fd:
|
||||
return write(client, &response, sizeof(response));
|
||||
|
||||
error_sock_save_local:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
@ -661,18 +702,11 @@ static int server_accept(patty_ax25_server *server,
|
|||
goto error_sock_by_fd;
|
||||
}
|
||||
|
||||
if (sock_save_by_addr(server->socks_pending_accept,
|
||||
sock,
|
||||
&sock->local) < 0) {
|
||||
goto error_save_by_addr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_sock_by_fd:
|
||||
return write(client, &response, sizeof(response));
|
||||
|
||||
error_save_by_addr:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
@ -759,11 +793,8 @@ static int server_connect(patty_ax25_server *server,
|
|||
|
||||
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
|
||||
|
||||
if (sock_save_by_addrpair(server->socks_pending_connect,
|
||||
sock,
|
||||
&sock->local,
|
||||
&sock->remote) < 0) {
|
||||
goto error_sock_save_by_addrpair;
|
||||
if (sock_save_remote(server, sock) < 0) {
|
||||
goto error_sock_save_remote;
|
||||
}
|
||||
|
||||
if (client_save_by_sock(server, client, sock) < 0) {
|
||||
|
@ -795,7 +826,7 @@ error_sock_by_fd:
|
|||
return write(client, &response, sizeof(response));
|
||||
|
||||
error_client_save_by_sock:
|
||||
error_sock_save_by_addrpair:
|
||||
error_sock_save_remote:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
@ -806,6 +837,7 @@ static int server_close(patty_ax25_server *server,
|
|||
patty_ax25_call_close_response response;
|
||||
|
||||
patty_ax25_sock *sock;
|
||||
patty_dict *socks;
|
||||
|
||||
if (read(client, &request, sizeof(request)) < 0) {
|
||||
goto error_io;
|
||||
|
@ -818,17 +850,33 @@ static int server_close(patty_ax25_server *server,
|
|||
goto error_sock_by_fd;
|
||||
}
|
||||
|
||||
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||
response.ret = -1;
|
||||
response.eno = EBADF;
|
||||
|
||||
goto error_dict_get_socks_by_client;
|
||||
}
|
||||
|
||||
if (sock_shutdown(server, sock) < 0) {
|
||||
response.ret = -1;
|
||||
response.eno = errno;
|
||||
|
||||
goto error_sock_shutdown;
|
||||
}
|
||||
|
||||
if (sock_close(server, sock) < 0) {
|
||||
response.ret = -1;
|
||||
response.eno = EBADF;
|
||||
|
||||
goto error_sock_delete;
|
||||
goto error_sock_close;
|
||||
}
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
||||
error_sock_delete:
|
||||
error_sock_close:
|
||||
error_sock_shutdown:
|
||||
error_dict_get_socks_by_client:
|
||||
error_sock_by_fd:
|
||||
return write(client, &response, sizeof(response));
|
||||
|
||||
|
@ -896,6 +944,7 @@ static int accept_client(patty_ax25_server *server) {
|
|||
int fd;
|
||||
struct sockaddr addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
patty_dict *socks;
|
||||
|
||||
memset(&addr, '\0', addrlen);
|
||||
|
||||
|
@ -907,8 +956,16 @@ static int accept_client(patty_ax25_server *server) {
|
|||
goto error_accept;
|
||||
}
|
||||
|
||||
if ((socks = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new;
|
||||
}
|
||||
|
||||
if (patty_dict_set(server->clients, (uint32_t)fd, NULL + fd) == NULL) {
|
||||
goto error_dict_set;
|
||||
goto error_dict_set_clients;
|
||||
}
|
||||
|
||||
if (patty_dict_set(server->socks_by_client, (uint32_t)fd, socks) == NULL) {
|
||||
goto error_dict_set_socks_by_client;
|
||||
}
|
||||
|
||||
fd_watch(server, fd);
|
||||
|
@ -916,13 +973,31 @@ static int accept_client(patty_ax25_server *server) {
|
|||
done:
|
||||
return 0;
|
||||
|
||||
error_dict_set:
|
||||
error_dict_set_socks_by_client:
|
||||
error_dict_set_clients:
|
||||
patty_dict_destroy(socks);
|
||||
|
||||
error_dict_new:
|
||||
close(fd);
|
||||
|
||||
error_accept:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int client_sock_close(uint32_t key, void *value, void *ctx) {
|
||||
patty_ax25_server *server = ctx;
|
||||
patty_ax25_sock *sock = value;
|
||||
|
||||
if (sock_shutdown(server, sock) < 0) {
|
||||
goto error_sock_shutdown;
|
||||
}
|
||||
|
||||
return sock_close(server, sock);
|
||||
|
||||
error_sock_shutdown:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int handle_client(uint32_t key,
|
||||
void *value,
|
||||
void *ctx) {
|
||||
|
@ -939,10 +1014,21 @@ static int handle_client(uint32_t key,
|
|||
if ((readlen = read(client, &call, sizeof(call))) < 0) {
|
||||
goto error_io;
|
||||
} else if (readlen == 0) {
|
||||
patty_dict *socks;
|
||||
|
||||
fd_clear(server, client);
|
||||
|
||||
if ((socks = patty_dict_get(server->socks_by_client, client)) != NULL) {
|
||||
(void)patty_dict_each(socks, client_sock_close, server);
|
||||
(void)patty_dict_destroy(socks);
|
||||
}
|
||||
|
||||
if (patty_dict_delete(server->socks_by_client, key) < 0) {
|
||||
goto error_dict_delete_socks_by_client;
|
||||
}
|
||||
|
||||
if (patty_dict_delete(server->clients, key) < 0) {
|
||||
goto error_dict_delete;
|
||||
goto error_dict_delete_clients;
|
||||
}
|
||||
|
||||
if (close(client) < 0) {
|
||||
|
@ -968,7 +1054,8 @@ done:
|
|||
return 0;
|
||||
|
||||
error_not_implemented:
|
||||
error_dict_delete:
|
||||
error_dict_delete_socks_by_client:
|
||||
error_dict_delete_clients:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1000,6 +1087,8 @@ static int reply_to(patty_ax25_if *iface,
|
|||
patty_ax25_frame *reply) {
|
||||
ssize_t len;
|
||||
|
||||
frame->cr = PATTY_AX25_FRAME_RESPONSE;
|
||||
|
||||
if ((len = patty_ax25_frame_encode_reply_to(frame,
|
||||
reply,
|
||||
iface->tx_buf,
|
||||
|
@ -1036,11 +1125,6 @@ static int reply_ua(patty_ax25_if *iface,
|
|||
.infolen = 0
|
||||
};
|
||||
|
||||
char callsign[7];
|
||||
uint8_t ssid;
|
||||
|
||||
patty_ax25_ntop(&frame->dest, callsign, &ssid, sizeof(callsign));
|
||||
|
||||
return reply_to(iface, frame, &reply);
|
||||
}
|
||||
|
||||
|
@ -1049,23 +1133,26 @@ static int handle_frmr(patty_ax25_server *server,
|
|||
patty_ax25_frame *frame) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = sock_by_addrpair(server->socks_pending_connect,
|
||||
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
|
||||
return sock->status == PATTY_AX25_SOCK_PENDING_CONNECT?
|
||||
patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL): 0;
|
||||
}
|
||||
|
||||
static int handle_sabm(patty_ax25_server *server,
|
||||
patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame) {
|
||||
int client;
|
||||
int client,
|
||||
created = 0;
|
||||
|
||||
patty_ax25_sock *local, *remote;
|
||||
patty_ax25_call_accept_response response;
|
||||
|
||||
if ((local = sock_by_addr(server->socks_pending_accept,
|
||||
if ((local = sock_by_addr(server->socks_local,
|
||||
&frame->dest)) == NULL) {
|
||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
}
|
||||
|
@ -1074,45 +1161,41 @@ static int handle_sabm(patty_ax25_server *server,
|
|||
goto error_client_by_sock;
|
||||
}
|
||||
|
||||
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
||||
goto error_sock_new;
|
||||
/*
|
||||
* Look to see if there is already a remote socket created based on an XID
|
||||
* packet previously received.
|
||||
*/
|
||||
if ((remote = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
/*
|
||||
* If there is no existing remote socket, we should create one, and
|
||||
* associate it with the client.
|
||||
*/
|
||||
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
||||
goto error_sock_new;
|
||||
}
|
||||
|
||||
save_reply_addr(remote, frame);
|
||||
|
||||
created = 1;
|
||||
}
|
||||
|
||||
remote->status = PATTY_AX25_SOCK_ESTABLISHED;
|
||||
remote->mode = (frame->type == PATTY_AX25_FRAME_SABM)?
|
||||
PATTY_AX25_SOCK_SABM: PATTY_AX25_SOCK_SABME;
|
||||
remote->mode = (frame->type == PATTY_AX25_FRAME_SABME)?
|
||||
PATTY_AX25_SOCK_SABME: PATTY_AX25_SOCK_SABM;
|
||||
|
||||
patty_ax25_sock_bind_if(remote, iface);
|
||||
|
||||
save_reply_addr(remote, frame);
|
||||
|
||||
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
|
||||
goto error_sock_save_by_fd;
|
||||
}
|
||||
|
||||
if (sock_save_by_addrpair(server->socks_established,
|
||||
remote,
|
||||
&remote->local,
|
||||
&remote->remote) < 0) {
|
||||
goto error_sock_save_by_addrpair;
|
||||
}
|
||||
|
||||
if (sock_delete_by_addr(server->socks_pending_accept,
|
||||
&local->local) < 0) {
|
||||
goto error_sock_delete_by_addr;
|
||||
}
|
||||
|
||||
if (frame->pf) {
|
||||
if (reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL) < 0) {
|
||||
goto error_reply_ua;
|
||||
if (created) {
|
||||
if (sock_save(server, client, remote) < 0) {
|
||||
goto error_sock_save;
|
||||
}
|
||||
}
|
||||
|
||||
fd_watch(server, remote->fd);
|
||||
|
||||
memset(&response, '\0', sizeof(response));
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
||||
memcpy(&response.peer, &frame->src, sizeof(patty_ax25_addr));
|
||||
memcpy(&response.path, &remote->path, sizeof(response.path));
|
||||
|
||||
|
@ -1120,15 +1203,10 @@ static int handle_sabm(patty_ax25_server *server,
|
|||
goto error_write;
|
||||
}
|
||||
|
||||
fd_watch(server, remote->fd);
|
||||
|
||||
return 0;
|
||||
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
|
||||
error_write:
|
||||
error_reply_ua:
|
||||
error_sock_delete_by_addr:
|
||||
error_sock_save_by_addrpair:
|
||||
error_sock_save_by_fd:
|
||||
error_sock_save:
|
||||
patty_ax25_sock_destroy(remote);
|
||||
|
||||
error_sock_new:
|
||||
|
@ -1143,34 +1221,34 @@ static int handle_ua(patty_ax25_server *server,
|
|||
patty_ax25_sock *sock;
|
||||
patty_ax25_call_connect_response response;
|
||||
|
||||
if ((sock = sock_by_addrpair(server->socks_pending_connect,
|
||||
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
}
|
||||
|
||||
if ((client = client_by_sock(server, sock)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
switch (sock->status) {
|
||||
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||
break;
|
||||
|
||||
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||
return sock_close(server, sock);
|
||||
|
||||
default:
|
||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
}
|
||||
|
||||
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
|
||||
|
||||
if (sock->mode == PATTY_AX25_SOCK_DM) {
|
||||
sock->mode = PATTY_AX25_SOCK_SABM;
|
||||
if ((client = client_by_sock(server, sock)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
}
|
||||
|
||||
if (sock_save_by_addrpair(server->socks_established,
|
||||
sock,
|
||||
&sock->local,
|
||||
&sock->remote) < 0) {
|
||||
goto error_save_by_addrpair;
|
||||
if (sock_save(server, client, sock) < 0) {
|
||||
goto error_sock_save;
|
||||
}
|
||||
|
||||
if (sock_delete_by_addrpair(server->socks_pending_connect,
|
||||
&sock->local,
|
||||
&sock->remote) < 0) {
|
||||
goto error_delete_by_addrpair;
|
||||
}
|
||||
fd_watch(server, sock->fd);
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
@ -1179,15 +1257,12 @@ static int handle_ua(patty_ax25_server *server,
|
|||
goto error_write;
|
||||
}
|
||||
|
||||
fd_watch(server, sock->fd);
|
||||
|
||||
return 0;
|
||||
|
||||
error_write:
|
||||
error_sock_save:
|
||||
patty_ax25_sock_destroy(sock);
|
||||
|
||||
error_delete_by_addrpair:
|
||||
error_save_by_addrpair:
|
||||
error_client_by_sock:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1199,26 +1274,18 @@ 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,
|
||||
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((client = client_by_sock(server, sock)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
if (sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sock_delete_by_addrpair(server->socks_pending_connect,
|
||||
&frame->dest,
|
||||
&frame->src) < 0) {
|
||||
goto error_delete_by_addrpair;
|
||||
if ((client = client_by_sock(server, sock)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
}
|
||||
|
||||
response.ret = -1;
|
||||
|
@ -1233,7 +1300,6 @@ static int handle_dm(patty_ax25_server *server,
|
|||
return 0;
|
||||
|
||||
error_write:
|
||||
error_delete_by_addrpair:
|
||||
error_client_by_sock:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1269,25 +1335,19 @@ static int handle_disc(patty_ax25_server *server,
|
|||
patty_ax25_frame *frame) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = sock_by_addrpair(server->socks_established,
|
||||
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
goto done;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sock_close(server, sock) < 0) {
|
||||
goto error_sock_delete;
|
||||
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
|
||||
return frame->pf? reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL): 0;
|
||||
}
|
||||
|
||||
done:
|
||||
if (frame->pf) {
|
||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
}
|
||||
(void)sock_close(server, sock);
|
||||
|
||||
return 0;
|
||||
|
||||
error_sock_delete:
|
||||
return -1;
|
||||
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
}
|
||||
|
||||
static int handle_rej(patty_ax25_server *server,
|
||||
|
@ -1339,18 +1399,25 @@ static int handle_xid(patty_ax25_server *server,
|
|||
}
|
||||
|
||||
/*
|
||||
* First, check if this XID packet is for a pending outbound connection.
|
||||
* First, check if this XID packet is a response to an XID used to initiate
|
||||
* an outbound connection.
|
||||
*/
|
||||
if ((remote = sock_by_addrpair(server->socks_pending_connect,
|
||||
if ((remote = sock_by_addrpair(server->socks_remote,
|
||||
&frame->dest,
|
||||
&frame->src)) != NULL) {
|
||||
if (remote->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
||||
goto reply_dm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we've received an XID packet, we can assume that the remote
|
||||
* station is capable of speaking AX.25 v2.2. Therefore, we should
|
||||
* upgrade the socket defaults accordingly, and negotiate downwards
|
||||
* as necessary.
|
||||
*/
|
||||
patty_ax25_sock_upgrade(remote);
|
||||
if (patty_ax25_sock_upgrade(remote) < 0) {
|
||||
goto error_sock_upgrade;
|
||||
}
|
||||
|
||||
if (patty_ax25_sock_params_set(remote, ¶ms) < 0) {
|
||||
goto error_sock_params_set;
|
||||
|
@ -1365,15 +1432,27 @@ static int handle_xid(patty_ax25_server *server,
|
|||
|
||||
return patty_ax25_sock_send_sabme(remote, PATTY_AX25_FRAME_POLL);
|
||||
} else {
|
||||
remote->mode = PATTY_AX25_SOCK_SABM;
|
||||
|
||||
return patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Second, check if this XID packet is for a socket pending accept.
|
||||
* Second, check if this XID packet is for a listening socket.
|
||||
*/
|
||||
if ((local = sock_by_addr(server->socks_pending_accept,
|
||||
if ((local = sock_by_addr(server->socks_local,
|
||||
&frame->dest)) != NULL) {
|
||||
int client;
|
||||
|
||||
if (local->status != PATTY_AX25_SOCK_LISTENING) {
|
||||
goto reply_dm;
|
||||
}
|
||||
|
||||
if ((client = client_by_sock(server, local)) < 0) {
|
||||
goto error_client_by_sock;
|
||||
}
|
||||
|
||||
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
||||
goto error_sock_new;
|
||||
}
|
||||
|
@ -1394,18 +1473,21 @@ static int handle_xid(patty_ax25_server *server,
|
|||
|
||||
save_reply_addr(remote, frame);
|
||||
|
||||
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
|
||||
goto error_sock_save_by_fd;
|
||||
if (sock_save(server, client, remote) < 0) {
|
||||
goto error_sock_save;
|
||||
}
|
||||
|
||||
return patty_ax25_sock_send_xid(remote, PATTY_AX25_FRAME_RESPONSE);
|
||||
}
|
||||
|
||||
reply_dm:
|
||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
|
||||
error_sock_save_by_fd:
|
||||
error_sock_save:
|
||||
error_sock_new:
|
||||
error_client_by_sock:
|
||||
error_sock_params_set:
|
||||
error_sock_upgrade:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1428,7 +1510,7 @@ static int handle_frame(patty_ax25_server *server,
|
|||
offset += decoded;
|
||||
}
|
||||
|
||||
if ((sock = sock_by_addrpair(server->socks_established,
|
||||
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||
&frame.dest,
|
||||
&frame.src)) != NULL) {
|
||||
if (sock->mode == PATTY_AX25_SOCK_SABME) {
|
||||
|
@ -1469,17 +1551,19 @@ error_io:
|
|||
static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
|
||||
int fd = patty_kiss_tnc_fd(iface->tnc);
|
||||
|
||||
void *buf;
|
||||
ssize_t readlen;
|
||||
|
||||
if (!FD_ISSET(fd, &server->fds_r)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
do {
|
||||
void *buf;
|
||||
ssize_t readlen;
|
||||
|
||||
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
||||
goto error_io;
|
||||
} else if (readlen == 0) {
|
||||
close(fd);
|
||||
|
||||
fd_clear(server, fd);
|
||||
|
||||
goto done;
|
||||
|
@ -1530,14 +1614,14 @@ static int handle_sock(uint32_t key,
|
|||
|
||||
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
|
||||
if (errno == EIO) {
|
||||
(void)sock_close(server, sock);
|
||||
(void)sock_shutdown(server, sock);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
goto error_io;
|
||||
} else if (len == 0) {
|
||||
sock_close(server, sock);
|
||||
(void)sock_shutdown(server, sock);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
@ -1555,7 +1639,7 @@ error_io:
|
|||
}
|
||||
|
||||
static int handle_socks(patty_ax25_server *server) {
|
||||
return patty_dict_each(server->socks_established, handle_sock, server);
|
||||
return patty_dict_each(server->socks_by_fd, handle_sock, server);
|
||||
}
|
||||
|
||||
int patty_ax25_server_run(patty_ax25_server *server) {
|
||||
|
|
Loading…
Add table
Reference in a new issue