Fix numerous XID negotiation bugs
Changes: * Fix Classes of Operations and HDLC parameter bit flags in include/patty/ax25.h to match the documentation after more careful analysis; resolve issues with byte order * Add support for previously missing HDLC parameters to function patty_print_params() * Fix Info TX/RX field encodings to be in bits, rather than bytes * Implement patty_ax25_sock_realloc_bufs() to reallocate buffers based on current window and I frame sizes * Implement patty_ax25_sock_params_upgrade() to upgrade a socket's parameters to the AX.25 v2.2 documented defaults; this will not change parameters if the socket is already set to v2.2 * Implement patty_ax25_sock_params_max() to upgrade a socket's parameters to the highest values supported by patty * Reimplement patty_ax25_sock_send_xid() to send highest desired parameters, rather than the values currently set on the socket * When receiving XID frames destined to listening sockets, use patty_ax25_sock_params_max() to negotiate from high to low parameters * When receiving SABME flags, use patty_ax25_sock_params_upgrade() to ensure at least base AX.25 v2.2 parameter defaults are set * Fix issue where outbound connections initiated with XID were unable to time out after N retries
This commit is contained in:
parent
c287eb7a61
commit
575adc5d31
5 changed files with 125 additions and 82 deletions
|
@ -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 {
|
||||
|
|
|
@ -17,16 +17,25 @@
|
|||
#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_TEST | PATTY_AX25_PARAM_HDLC_FCS_16 \
|
||||
| PATTY_AX25_PARAM_HDLC_SYNC_TX)
|
||||
|
||||
#define PATTY_AX25_SOCK_DEFAULT_MAXLEN 256
|
||||
#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_DEFAULT_I_LEN 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_DEFAULT_MAXLEN 4096
|
||||
#define PATTY_AX25_SOCK_2_2_DEFAULT_WINDOW 127
|
||||
#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,21 +106,24 @@ 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,
|
||||
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);
|
||||
|
||||
int patty_ax25_sock_bind_if(patty_ax25_sock *sock,
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
46
src/server.c
46
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;
|
||||
|
|
72
src/sock.c
72
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,35 +173,31 @@ 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->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_MAXLEN;
|
||||
sock->n_maxlen_rx = PATTY_AX25_SOCK_2_2_DEFAULT_MAXLEN;
|
||||
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;
|
||||
}
|
||||
|
||||
sock->version = version;
|
||||
|
||||
return init_bufs(sock);
|
||||
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_set(patty_ax25_sock *sock,
|
||||
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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue