Prevent UA frame from terminating socket w/o DISC

Changes:

    * Add a "pending disconnect" state to enum patty_ax25_sock_state
     (PATTY_AX25_SOCK_PENDING_DISCONNECT), used when an originating
     system sends a DISC frame, pending a UA response

    * When handling a UA frame, rather than terminating a socket in the
      established state implicitly, check for a "pending disconnect"
      state explicitly

Other changes:

    * When a remote socket has already been obtained in handle_frame()
      in src/server.c, pass that socket to any other method that would
      otherwise be looking up the same socket
This commit is contained in:
XANTRONIX Development 2020-07-22 22:52:10 -04:00 committed by XANTRONIX Industrial
parent 8761a4e3c2
commit e06a9d195e
2 changed files with 50 additions and 37 deletions

View file

@ -30,6 +30,7 @@ enum patty_ax25_sock_status {
PATTY_AX25_SOCK_LISTENING,
PATTY_AX25_SOCK_PENDING_ACCEPT,
PATTY_AX25_SOCK_PENDING_CONNECT,
PATTY_AX25_SOCK_PENDING_DISCONNECT,
PATTY_AX25_SOCK_ESTABLISHED,
PATTY_AX25_SOCK_PROMISC
};

View file

@ -292,8 +292,13 @@ 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;
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
return 0;
}
sock->status = PATTY_AX25_SOCK_PENDING_DISCONNECT;
return patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL);
}
static int sock_save(patty_ax25_server *server,
@ -318,6 +323,7 @@ static int sock_save(patty_ax25_server *server,
break;
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
case PATTY_AX25_SOCK_CLOSED:
case PATTY_AX25_SOCK_PROMISC:
break;
@ -360,6 +366,7 @@ static int sock_close(patty_ax25_server *server,
case PATTY_AX25_SOCK_PENDING_ACCEPT:
case PATTY_AX25_SOCK_PENDING_CONNECT:
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
case PATTY_AX25_SOCK_ESTABLISHED:
if (sock_delete_remote(server, sock) < 0) {
goto error_sock_delete_remote;
@ -1130,12 +1137,9 @@ static int reply_ua(patty_ax25_if *iface,
static int handle_frmr(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
patty_ax25_sock *sock;
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
if (sock == NULL) {
return 0;
}
@ -1216,14 +1220,12 @@ error_client_by_sock:
static int handle_ua(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
if (sock == NULL) {
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
}
@ -1231,9 +1233,12 @@ static int handle_ua(patty_ax25_server *server,
case PATTY_AX25_SOCK_PENDING_CONNECT:
break;
case PATTY_AX25_SOCK_ESTABLISHED:
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
return sock_close(server, sock);
case PATTY_AX25_SOCK_ESTABLISHED:
return 0;
default:
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
}
@ -1269,18 +1274,12 @@ error_client_by_sock:
static int handle_dm(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
return 0;
}
if (sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
if (sock == NULL || sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
return 0;
}
@ -1332,22 +1331,27 @@ error_write:
static int handle_disc(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
patty_ax25_sock *sock;
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
return 0;
if (sock == NULL) {
goto reply_dm;
}
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
return frame->pf? reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL): 0;
switch (sock->status) {
case PATTY_AX25_SOCK_ESTABLISHED:
(void)sock_close(server, sock);
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
return 0;
default:
break;
}
(void)sock_close(server, sock);
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
reply_dm:
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
}
static int handle_rej(patty_ax25_server *server,
@ -1355,6 +1359,10 @@ static int handle_rej(patty_ax25_server *server,
patty_ax25_frame *frame) {
unsigned int i;
if (sock == NULL) {
return 0;
}
for (i=frame->nr; i<sock->seq_send; i++) {
if (patty_ax25_sock_resend(sock, i) < 0) {
goto error_sock_resend;
@ -1370,6 +1378,10 @@ error_sock_resend:
static int handle_srej(patty_ax25_server *server,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
if (sock == NULL) {
return 0;
}
/*
* TODO: Read the fine print of section 4.3.2.4
*/
@ -1525,16 +1537,16 @@ static int handle_frame(patty_ax25_server *server,
}
switch (frame.type) {
case PATTY_AX25_FRAME_UA: return handle_ua(server, iface, &frame);
case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, &frame);
case PATTY_AX25_FRAME_SABM:
case PATTY_AX25_FRAME_SABME: return handle_sabm(server, iface, &frame);
case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, &frame);
case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame);
case PATTY_AX25_FRAME_REJ: return handle_rej(server, sock, &frame);
case PATTY_AX25_FRAME_SREJ: return handle_srej(server, sock, &frame);
case PATTY_AX25_FRAME_XID: return handle_xid(server, iface, &frame, buf, offset, len);
case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, &frame);
case PATTY_AX25_FRAME_SABM:
case PATTY_AX25_FRAME_SABME: return handle_sabm(server, iface, &frame);
case PATTY_AX25_FRAME_UA: return handle_ua(server, iface, sock, &frame);
case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, sock, &frame);
case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, sock, &frame);
case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, sock, &frame);
default:
break;