diff --git a/include/patty/ax25.h b/include/patty/ax25.h index b9cf766..596f271 100644 --- a/include/patty/ax25.h +++ b/include/patty/ax25.h @@ -60,20 +60,29 @@ enum patty_ax25_param_type { PATTY_AX25_PARAM_RETRY = 10 }; +/* + * Note: These values are byte swapped from their listed order as per + * AX.25 v2.2 Section 4.3.37 "Exchange Identification (XID) Frame"; bits 0-7 + * are in the first byte, 8-15 in the second, and 16-23 in the third. + * The bit positions are shown in their original order (plus one) in the + * aforementioned figure in the AX.25 v2.2 spec. + */ enum patty_ax25_param_classes { - PATTY_AX25_PARAM_CLASSES_ABM = (1 << 0), - PATTY_AX25_PARAM_CLASSES_HALF_DUPLEX = (1 << 5), - PATTY_AX25_PARAM_CLASSES_FULL_DUPLEX = (1 << 6) + PATTY_AX25_PARAM_CLASSES_ABM = (1 << 0) << 8, + PATTY_AX25_PARAM_CLASSES_HALF_DUPLEX = (1 << 5) << 8, + PATTY_AX25_PARAM_CLASSES_FULL_DUPLEX = (1 << 6) << 8 }; enum patty_ax25_param_hdlc { - PATTY_AX25_PARAM_HDLC_REJ = (1 << 1), - PATTY_AX25_PARAM_HDLC_SREJ = (1 << 2), - PATTY_AX25_PARAM_HDLC_XADDR = (1 << 8), - PATTY_AX25_PARAM_HDLC_MODULO_8 = (1 << 11), - PATTY_AX25_PARAM_HDLC_MODULO_128 = (1 << 12), - PATTY_AX25_PARAM_HDLC_TEST = (1 << 14), - PATTY_AX25_PARAM_HDLC_SYNC_TX = (1 << 18) + PATTY_AX25_PARAM_HDLC_REJ = (1 << 1) << 16, + PATTY_AX25_PARAM_HDLC_SREJ = (1 << 2) << 16, + PATTY_AX25_PARAM_HDLC_XADDR = (1 << 7) << 16, + PATTY_AX25_PARAM_HDLC_MODULO_8 = (1 << 10), + PATTY_AX25_PARAM_HDLC_MODULO_128 = (1 << 11), + PATTY_AX25_PARAM_HDLC_TEST = (1 << 13), + PATTY_AX25_PARAM_HDLC_FCS_16 = (1 << 15), + PATTY_AX25_PARAM_HDLC_SYNC_TX = (1 << 17) >> 16, + PATTY_AX25_PARAM_HDLC_SREJ_MULTI = (1 << 21) >> 16 }; typedef struct _patty_ax25_params { diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index 3de1273..da5c770 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -15,18 +15,27 @@ | PATTY_AX25_PARAM_HDLC_TEST | PATTY_AX25_PARAM_HDLC_SYNC_TX) #define PATTY_AX25_SOCK_2_2_DEFAULT_HDLC \ - (PATTY_AX25_PARAM_HDLC_REJ | PATTY_AX25_PARAM_HDLC_SREJ \ - | PATTY_AX25_PARAM_HDLC_XADDR | PATTY_AX25_PARAM_HDLC_MODULO_128 \ - | PATTY_AX25_PARAM_HDLC_TEST | PATTY_AX25_PARAM_HDLC_SYNC_TX) + (PATTY_AX25_PARAM_HDLC_REJ | PATTY_AX25_PARAM_HDLC_SREJ \ + | PATTY_AX25_PARAM_HDLC_XADDR | PATTY_AX25_PARAM_HDLC_MODULO_128 \ + | PATTY_AX25_PARAM_HDLC_TEST | PATTY_AX25_PARAM_HDLC_FCS_16 \ + | PATTY_AX25_PARAM_HDLC_SYNC_TX) -#define PATTY_AX25_SOCK_DEFAULT_MAXLEN 256 -#define PATTY_AX25_SOCK_DEFAULT_WINDOW 4 -#define PATTY_AX25_SOCK_DEFAULT_WINDOW_SABME 32 -#define PATTY_AX25_SOCK_DEFAULT_RETRY 10 -#define PATTY_AX25_SOCK_DEFAULT_ACK 3000 +#define PATTY_AX25_SOCK_2_2_MAX_HDLC \ + (PATTY_AX25_PARAM_HDLC_REJ | PATTY_AX25_PARAM_HDLC_SREJ \ + | PATTY_AX25_PARAM_HDLC_XADDR | PATTY_AX25_PARAM_HDLC_MODULO_128 \ + | PATTY_AX25_PARAM_HDLC_TEST | PATTY_AX25_PARAM_HDLC_FCS_16 \ + | PATTY_AX25_PARAM_HDLC_SYNC_TX | PATTY_AX25_PARAM_HDLC_SREJ_MULTI) -#define PATTY_AX25_SOCK_2_2_DEFAULT_MAXLEN 4096 -#define PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW 127 +#define PATTY_AX25_SOCK_DEFAULT_I_LEN 256 +#define PATTY_AX25_SOCK_DEFAULT_WINDOW 4 +#define PATTY_AX25_SOCK_DEFAULT_RETRY 10 +#define PATTY_AX25_SOCK_DEFAULT_ACK 3000 + +#define PATTY_AX25_SOCK_2_2_DEFAULT_I_LEN 256 +#define PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW 32 + +#define PATTY_AX25_SOCK_2_2_MAX_I_LEN 1536 +#define PATTY_AX25_SOCK_2_2_MAX_WINDOW 127 enum patty_ax25_sock_type { PATTY_AX25_SOCK_STREAM, @@ -97,20 +106,23 @@ typedef struct _patty_ax25_sock { unsigned int hops; } patty_ax25_sock; -void patty_ax25_sock_init(patty_ax25_sock *sock); - patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, enum patty_ax25_sock_type type); void patty_ax25_sock_destroy(patty_ax25_sock *sock); -int patty_ax25_sock_reset(patty_ax25_sock *sock); +void patty_ax25_sock_init(patty_ax25_sock *sock); -int patty_ax25_sock_upgrade(patty_ax25_sock *sock, - enum patty_ax25_version version); +void patty_ax25_sock_reset(patty_ax25_sock *sock); -int patty_ax25_sock_params_set(patty_ax25_sock *sock, - patty_ax25_params *params); +void patty_ax25_sock_params_upgrade(patty_ax25_sock *sock); + +void patty_ax25_sock_params_max(patty_ax25_sock *sock); + +int patty_ax25_sock_params_negotiate(patty_ax25_sock *sock, + patty_ax25_params *params); + +int patty_ax25_sock_realloc_bufs(patty_ax25_sock *sock); char *patty_ax25_sock_pty(patty_ax25_sock *sock); diff --git a/src/print.c b/src/print.c index 182a1a0..f960dd6 100644 --- a/src/print.c +++ b/src/print.c @@ -158,7 +158,9 @@ int patty_print_params(FILE *fh, { PATTY_AX25_PARAM_HDLC_MODULO_8, "modulo 8" }, { PATTY_AX25_PARAM_HDLC_MODULO_128, "modulo 128" }, { PATTY_AX25_PARAM_HDLC_TEST, "TEST" }, + { PATTY_AX25_PARAM_HDLC_FCS_16, "16-bit FCS" }, { PATTY_AX25_PARAM_HDLC_SYNC_TX, "synchronous TX" }, + { PATTY_AX25_PARAM_HDLC_SREJ_MULTI, "multiple SREJ" }, { 0, NULL } }; diff --git a/src/server.c b/src/server.c index 0f77271..353db56 100644 --- a/src/server.c +++ b/src/server.c @@ -1213,8 +1213,18 @@ static int handle_sabm(patty_ax25_server *server, } remote->status = PATTY_AX25_SOCK_ESTABLISHED; - remote->mode = (frame->type == PATTY_AX25_FRAME_SABME)? - PATTY_AX25_SOCK_SABME: PATTY_AX25_SOCK_SABM; + + if (frame->type == PATTY_AX25_FRAME_SABME) { + patty_ax25_sock_params_upgrade(remote); + + remote->mode = PATTY_AX25_SOCK_SABME; + } else { + remote->mode = PATTY_AX25_SOCK_SABM; + } + + if (patty_ax25_sock_realloc_bufs(remote) < 0) { + goto error_sock_realloc_bufs; + } patty_ax25_sock_bind_if(remote, iface); @@ -1235,6 +1245,7 @@ static int handle_sabm(patty_ax25_server *server, return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL); error_respond_accept: +error_sock_realloc_bufs: error_sock_save: patty_ax25_sock_destroy(remote); @@ -1273,6 +1284,10 @@ static int handle_ua(patty_ax25_server *server, return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); } + if (patty_ax25_sock_realloc_bufs(sock) < 0) { + goto error_sock_realloc_bufs; + } + patty_timer_stop(&sock->timer_t1); patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); @@ -1292,8 +1307,7 @@ static int handle_ua(patty_ax25_server *server, return respond_connect(client, 0, 0); error_sock_save: - patty_ax25_sock_destroy(sock); - +error_sock_realloc_bufs: error_client_by_sock: return -1; } @@ -1482,17 +1496,14 @@ static int handle_xid(patty_ax25_server *server, * upgrade the socket defaults accordingly, and negotiate downwards * as necessary. */ - if (patty_ax25_sock_upgrade(remote, PATTY_AX25_2_2) < 0) { - goto error_sock_upgrade; - } - - if (patty_ax25_sock_params_set(remote, ¶ms) < 0) { + if (patty_ax25_sock_params_negotiate(remote, ¶ms) < 0) { int client; if ((client = client_by_sock(server, remote)) < 0) { goto error_client_by_sock; } + patty_ax25_sock_init(remote); patty_ax25_sock_reset(remote); return respond_connect(client, -1, errno); @@ -1540,9 +1551,9 @@ static int handle_xid(patty_ax25_server *server, patty_ax25_sock_bind_if(remote, iface); - patty_ax25_sock_upgrade(remote, PATTY_AX25_2_2); + patty_ax25_sock_params_max(remote); - if (patty_ax25_sock_params_set(remote, ¶ms) < 0) { + if (patty_ax25_sock_params_negotiate(remote, ¶ms) < 0) { patty_ax25_sock_destroy(remote); return respond_accept(client, -1, errno, NULL, NULL); @@ -1563,7 +1574,6 @@ reply_dm: error_sock_save: error_sock_new: error_client_by_sock: -error_sock_upgrade: error_io: return -1; } @@ -1699,9 +1709,16 @@ static int handle_sock(uint32_t key, return ret; } else { - (void)sock_shutdown(server, sock); + int client; - return sock_close(server, sock); + if ((client = client_by_sock(server, sock)) < 0) { + goto error_client_by_sock; + } + + (void)sock_shutdown(server, sock); + (void)sock_close(server, sock); + + return respond_connect(client, -1, ETIMEDOUT); } } @@ -1795,6 +1812,7 @@ static int handle_sock(uint32_t key, done: return 0; +error_client_by_sock: error_sock_write: error_io: return -1; diff --git a/src/sock.c b/src/sock.c index eee1c80..43f5f17 100644 --- a/src/sock.c +++ b/src/sock.c @@ -93,17 +93,6 @@ error_realloc_tx_buf: return -1; } -void patty_ax25_sock_init(patty_ax25_sock *sock) { - sock->status = PATTY_AX25_SOCK_CLOSED; - sock->mode = PATTY_AX25_SOCK_DM; - sock->n_maxlen_tx = PATTY_AX25_SOCK_DEFAULT_MAXLEN; - sock->n_maxlen_rx = PATTY_AX25_SOCK_DEFAULT_MAXLEN; - sock->n_window_tx = PATTY_AX25_SOCK_DEFAULT_WINDOW; - sock->n_window_rx = PATTY_AX25_SOCK_DEFAULT_WINDOW; - sock->n_ack = PATTY_AX25_SOCK_DEFAULT_ACK; - sock->n_retry = PATTY_AX25_SOCK_DEFAULT_RETRY; -} - patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, enum patty_ax25_sock_type type) { patty_ax25_sock *sock; @@ -159,10 +148,23 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) { free(sock); } +void patty_ax25_sock_init(patty_ax25_sock *sock) { + sock->status = PATTY_AX25_SOCK_CLOSED; + sock->mode = PATTY_AX25_SOCK_DM; + sock->n_maxlen_tx = PATTY_AX25_SOCK_DEFAULT_I_LEN; + sock->n_maxlen_rx = PATTY_AX25_SOCK_DEFAULT_I_LEN; + sock->n_window_tx = PATTY_AX25_SOCK_DEFAULT_WINDOW; + sock->n_window_rx = PATTY_AX25_SOCK_DEFAULT_WINDOW; + sock->n_ack = PATTY_AX25_SOCK_DEFAULT_ACK; + sock->n_retry = PATTY_AX25_SOCK_DEFAULT_RETRY; + sock->retries = PATTY_AX25_SOCK_DEFAULT_RETRY; + sock->pending = 0; +} + /* * AX.25 v2.2 Specification, Section 6.5 "Resetting Procedure" */ -int patty_ax25_sock_reset(patty_ax25_sock *sock) { +void patty_ax25_sock_reset(patty_ax25_sock *sock) { sock->seq_send = 0; sock->seq_recv = 0; sock->retries = sock->n_retry; @@ -171,36 +173,32 @@ int patty_ax25_sock_reset(patty_ax25_sock *sock) { patty_timer_clear(&sock->timer_t1); patty_timer_clear(&sock->timer_t2); patty_timer_clear(&sock->timer_t3); - - return 0; } -int patty_ax25_sock_upgrade(patty_ax25_sock *sock, - enum patty_ax25_version version) { - if (sock->version >= version) { - return 0; +void patty_ax25_sock_params_upgrade(patty_ax25_sock *sock) { + if (sock->version >= PATTY_AX25_2_2) { + return; } - switch (version) { - case PATTY_AX25_OLD: - case PATTY_AX25_2_0: - break; - - case PATTY_AX25_2_2: - sock->flags_hdlc = PATTY_AX25_SOCK_2_2_DEFAULT_HDLC; - sock->n_maxlen_tx = PATTY_AX25_SOCK_2_2_DEFAULT_MAXLEN; - sock->n_maxlen_rx = PATTY_AX25_SOCK_2_2_DEFAULT_MAXLEN; - sock->n_window_tx = PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW; - sock->n_window_rx = PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW; - } - - sock->version = version; - - return init_bufs(sock); + sock->version = PATTY_AX25_2_2; + sock->flags_hdlc = PATTY_AX25_SOCK_2_2_DEFAULT_HDLC; + sock->n_maxlen_tx = PATTY_AX25_SOCK_2_2_DEFAULT_I_LEN; + sock->n_maxlen_rx = PATTY_AX25_SOCK_2_2_DEFAULT_I_LEN; + sock->n_window_tx = PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW; + sock->n_window_rx = PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW; } -int patty_ax25_sock_params_set(patty_ax25_sock *sock, - patty_ax25_params *params) { +void patty_ax25_sock_params_max(patty_ax25_sock *sock) { + sock->version = PATTY_AX25_2_2; + sock->flags_hdlc = PATTY_AX25_SOCK_2_2_MAX_HDLC; + sock->n_maxlen_tx = PATTY_AX25_SOCK_2_2_MAX_I_LEN; + sock->n_maxlen_rx = PATTY_AX25_SOCK_2_2_MAX_I_LEN; + sock->n_window_tx = PATTY_AX25_SOCK_2_2_MAX_WINDOW; + sock->n_window_rx = PATTY_AX25_SOCK_2_2_MAX_WINDOW; +} + +int patty_ax25_sock_params_negotiate(patty_ax25_sock *sock, + patty_ax25_params *params) { if (params->flags & PATTY_AX25_PARAM_CLASSES) { if (!(params->classes & PATTY_AX25_PARAM_CLASSES_ABM)) { goto error_notsup; @@ -251,7 +249,7 @@ int patty_ax25_sock_params_set(patty_ax25_sock *sock, } if (params->flags & PATTY_AX25_PARAM_INFO_RX) { - if (sock->n_maxlen_tx > params->info_rx) { + if (sock->n_maxlen_tx > params->info_rx >> 3) { sock->n_maxlen_tx = params->info_rx >> 3; } } @@ -274,7 +272,7 @@ int patty_ax25_sock_params_set(patty_ax25_sock *sock, } } - return init_bufs(sock); + return 0; error_notsup: errno = ENOTSUP; @@ -287,6 +285,10 @@ error_invalid: return -1; } +int patty_ax25_sock_realloc_bufs(patty_ax25_sock *sock) { + return init_bufs(sock); +} + char *patty_ax25_sock_pty(patty_ax25_sock *sock) { return sock->pty; } @@ -559,9 +561,9 @@ ssize_t patty_ax25_sock_send_xid(patty_ax25_sock *sock, | (1 << PATTY_AX25_PARAM_RETRY); params.classes = sock->flags_classes; - params.hdlc = sock->flags_hdlc; - params.info_rx = sock->n_maxlen_rx << 3; - params.window_rx = sock->n_window_rx; + params.hdlc = PATTY_AX25_SOCK_2_2_MAX_HDLC; + params.info_rx = PATTY_AX25_SOCK_2_2_MAX_I_LEN << 3; + params.window_rx = PATTY_AX25_SOCK_2_2_MAX_WINDOW; params.ack = sock->n_ack; params.retry = sock->n_retry;