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_LISTENING,
PATTY_AX25_SOCK_PENDING_ACCEPT, PATTY_AX25_SOCK_PENDING_ACCEPT,
PATTY_AX25_SOCK_PENDING_CONNECT, PATTY_AX25_SOCK_PENDING_CONNECT,
PATTY_AX25_SOCK_PENDING_DISCONNECT,
PATTY_AX25_SOCK_ESTABLISHED, PATTY_AX25_SOCK_ESTABLISHED,
PATTY_AX25_SOCK_PROMISC PATTY_AX25_SOCK_PROMISC
}; };

View file

@ -292,8 +292,13 @@ static int sock_shutdown(patty_ax25_server *server,
patty_ax25_sock *sock) { patty_ax25_sock *sock) {
fd_clear(server, sock->fd); fd_clear(server, sock->fd);
return sock->status == PATTY_AX25_SOCK_ESTABLISHED? if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL): 0; 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, static int sock_save(patty_ax25_server *server,
@ -318,6 +323,7 @@ static int sock_save(patty_ax25_server *server,
break; break;
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
case PATTY_AX25_SOCK_CLOSED: case PATTY_AX25_SOCK_CLOSED:
case PATTY_AX25_SOCK_PROMISC: case PATTY_AX25_SOCK_PROMISC:
break; break;
@ -360,6 +366,7 @@ static int sock_close(patty_ax25_server *server,
case PATTY_AX25_SOCK_PENDING_ACCEPT: case PATTY_AX25_SOCK_PENDING_ACCEPT:
case PATTY_AX25_SOCK_PENDING_CONNECT: case PATTY_AX25_SOCK_PENDING_CONNECT:
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
case PATTY_AX25_SOCK_ESTABLISHED: case PATTY_AX25_SOCK_ESTABLISHED:
if (sock_delete_remote(server, sock) < 0) { if (sock_delete_remote(server, sock) < 0) {
goto error_sock_delete_remote; 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, static int handle_frmr(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
patty_ax25_sock *sock; if (sock == NULL) {
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
return 0; return 0;
} }
@ -1216,14 +1220,12 @@ error_client_by_sock:
static int handle_ua(patty_ax25_server *server, static int handle_ua(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
int client; int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response; patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_remote, if (sock == NULL) {
&frame->dest,
&frame->src)) == NULL) {
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); 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: case PATTY_AX25_SOCK_PENDING_CONNECT:
break; break;
case PATTY_AX25_SOCK_ESTABLISHED: case PATTY_AX25_SOCK_PENDING_DISCONNECT:
return sock_close(server, sock); return sock_close(server, sock);
case PATTY_AX25_SOCK_ESTABLISHED:
return 0;
default: default:
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); 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, static int handle_dm(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
int client; int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response; patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_remote, if (sock == NULL || sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
&frame->dest,
&frame->src)) == NULL) {
return 0;
}
if (sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
return 0; return 0;
} }
@ -1332,22 +1331,27 @@ error_write:
static int handle_disc(patty_ax25_server *server, static int handle_disc(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
patty_ax25_sock *sock; if (sock == NULL) {
goto reply_dm;
if ((sock = sock_by_addrpair(server->socks_remote,
&frame->dest,
&frame->src)) == NULL) {
return 0;
}
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); (void)sock_close(server, sock);
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL); return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
return 0;
default:
break;
}
reply_dm:
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
} }
static int handle_rej(patty_ax25_server *server, static int handle_rej(patty_ax25_server *server,
@ -1355,6 +1359,10 @@ static int handle_rej(patty_ax25_server *server,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
unsigned int i; unsigned int i;
if (sock == NULL) {
return 0;
}
for (i=frame->nr; i<sock->seq_send; i++) { for (i=frame->nr; i<sock->seq_send; i++) {
if (patty_ax25_sock_resend(sock, i) < 0) { if (patty_ax25_sock_resend(sock, i) < 0) {
goto error_sock_resend; goto error_sock_resend;
@ -1370,6 +1378,10 @@ error_sock_resend:
static int handle_srej(patty_ax25_server *server, static int handle_srej(patty_ax25_server *server,
patty_ax25_sock *sock, patty_ax25_sock *sock,
patty_ax25_frame *frame) { patty_ax25_frame *frame) {
if (sock == NULL) {
return 0;
}
/* /*
* TODO: Read the fine print of section 4.3.2.4 * 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) { 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_I: return handle_i(server, iface, sock, &frame);
case PATTY_AX25_FRAME_REJ: return handle_rej(server, 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_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_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: default:
break; break;