diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index c40f135..f4ffe0e 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -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 }; diff --git a/src/server.c b/src/server.c index 3231a21..3d93b4f 100644 --- a/src/server.c +++ b/src/server.c @@ -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; iseq_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;