From 1fbf09c9ba185f6910a1d7c84e954f303463b0d7 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Fri, 17 Jul 2020 22:57:23 -0400 Subject: [PATCH] Refactor parameter decoding/display Changes: * Implement patty_ax25_params struct to contain all parameters supported by patty, at the interface and socket level alike * Move parameter enumerate types into include/patty/ax25.h, from include/patty/ax25/frame.h; make corrections as necessary * Reimplement patty_ax25_frame_decode_xid() to parse known XID information parameters into a patty_ax25_params object * Implement patty_print_params() in src/print.c * Refactor patty_print_frame() as patty_print_frame_header(), without a call to patty_print_hexdump(); this allows patty_print_params() to be called prior to patty_print_hexdump(), for better readability * Use patty_print_params() in examples/ax25dump.c, decode.c * Refactor usage of patty_ax25_frame_decode_xid() in src/server.c to parse XID frames into a patty_ax25_params object --- examples/ax25dump.c | 41 +++++- examples/decode.c | 41 +++++- include/patty/ax25.h | 41 ++++++ include/patty/ax25/frame.h | 35 +---- include/patty/print.h | 11 +- src/frame.c | 56 ++++++-- src/print.c | 256 ++++++++++++++++++++++++------------- src/server.c | 36 ++++-- 8 files changed, 351 insertions(+), 166 deletions(-) diff --git a/examples/ax25dump.c b/examples/ax25dump.c index 30d61dd..55fd328 100644 --- a/examples/ax25dump.c +++ b/examples/ax25dump.c @@ -92,28 +92,56 @@ int main(int argc, char **argv) { } while ((readlen = patty_kiss_tnc_recv(raw, buf, sizeof(buf), NULL)) > 0) { + ssize_t decoded, + offset = 0; + patty_ax25_frame frame; - ssize_t decoded; if ((decoded = patty_ax25_frame_decode_address(&frame, buf, readlen)) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_ax25_frame_decode_address()", strerror(errno)); goto error_ax25_frame_decode_address; + } else { + offset += decoded; } - if (patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, decoded, readlen) < 0) { + if ((decoded = patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, decoded, readlen)) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_ax25_frame_decode_control()", strerror(errno)); goto error_ax25_frame_decode_control; + } else { + offset += decoded; } - if (patty_print_frame(stdout, &frame, buf, readlen) < 0) { + if (patty_print_frame_header(stdout, &frame) < 0) { fprintf(stderr, "%s: %s: %s\n", - argv[0], "patty_print_frame()", strerror(errno)); + argv[0], "patty_print_frame_header()", strerror(errno)); - goto error_print_frame; + goto error_print; + } + + if (frame.type == PATTY_AX25_FRAME_XID) { + patty_ax25_params params; + + if (patty_ax25_frame_decode_xid(¶ms, + buf, + offset, + readlen) < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "patty_ax25_frame_decode_xid()", strerror(errno)); + + goto error_ax25_frame_decode_xid; + } + + if (patty_print_params(stdout, ¶ms) < 0) { + goto error_print; + } + } + + if (patty_print_hexdump(stdout, buf, readlen) < 0) { + goto error_print; } } @@ -125,7 +153,8 @@ int main(int argc, char **argv) { return 0; -error_print_frame: +error_print: +error_ax25_frame_decode_xid: error_ax25_frame_decode_control: error_ax25_frame_decode_address: patty_kiss_tnc_destroy(raw); diff --git a/examples/decode.c b/examples/decode.c index ab355bb..bbd68e2 100644 --- a/examples/decode.c +++ b/examples/decode.c @@ -50,7 +50,9 @@ int main(int argc, char **argv) { while (1) { ssize_t len, - decoded; + decoded, + offset = 0; + patty_ax25_frame frame; if ((len = patty_kiss_tnc_recv(tnc, buf, PATTY_KISS_BUFSZ, &port)) < 0) { @@ -67,20 +69,46 @@ int main(int argc, char **argv) { argv[0], "patty_ax25_frame_decode_address()", strerror(errno)); goto error_ax25_frame_decode_address; + } else { + offset += decoded; } - if (patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, decoded, len) < 0) { + if ((decoded = patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, offset, len)) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_ax25_frame_decode_control()", strerror(errno)); goto error_ax25_frame_decode_control; + } else { + offset += decoded; } - if (patty_print_frame(stdout, &frame, buf, len) < 0) { + if (patty_print_frame_header(stdout, &frame) < 0) { fprintf(stderr, "%s: %s: %s\n", - argv[0], "patty_print_frame()", strerror(errno)); + argv[0], "patty_print_frame_header()", strerror(errno)); - goto error_print_frame; + goto error_print; + } + + if (frame.type == PATTY_AX25_FRAME_XID) { + patty_ax25_params params; + + if (patty_ax25_frame_decode_xid(¶ms, + buf, + offset, + len) < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "patty_ax25_frame_decode_xid()", strerror(errno)); + + goto error_ax25_frame_decode_xid; + } + + if (patty_print_params(stdout, ¶ms) < 0) { + goto error_print; + } + } + + if (patty_print_hexdump(stdout, buf, len) < 0) { + goto error_print; } } @@ -90,7 +118,8 @@ int main(int argc, char **argv) { return 0; -error_print_frame: +error_print: +error_ax25_frame_decode_xid: error_ax25_frame_decode_control: error_ax25_frame_decode_address: error_kiss_tnc_recv: diff --git a/include/patty/ax25.h b/include/patty/ax25.h index af57d26..c916e48 100644 --- a/include/patty/ax25.h +++ b/include/patty/ax25.h @@ -48,6 +48,47 @@ typedef struct _patty_ax25_addr { #pragma pack(pop) +enum patty_ax25_param_type { + PATTY_AX25_PARAM_CLASSES = 2, + PATTY_AX25_PARAM_HDLC = 3, + PATTY_AX25_PARAM_INFO_TX = 5, + PATTY_AX25_PARAM_INFO_RX = 6, + PATTY_AX25_PARAM_WINDOW_TX = 7, + PATTY_AX25_PARAM_WINDOW_RX = 8, + PATTY_AX25_PARAM_ACK = 9, + PATTY_AX25_PARAM_RETRY = 10 +}; + +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) +}; + +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) +}; + +typedef struct _patty_ax25_params { + uint32_t found; + + uint32_t classes, + hdlc; + + size_t info_tx, + info_rx, + window_tx, + window_rx, + ack, + retry; +} patty_ax25_params; + typedef struct _patty_ax25_if patty_ax25_if; #include diff --git a/include/patty/ax25/frame.h b/include/patty/ax25/frame.h index efd93fe..edc9025 100644 --- a/include/patty/ax25/frame.h +++ b/include/patty/ax25/frame.h @@ -89,32 +89,6 @@ enum patty_ax25_frame_xid_group_type { PATTY_AX25_FRAME_XID_GROUP_PARAMS = 0x80 }; -enum patty_ax25_frame_xid_param_type { - PATTY_AX25_FRAME_XID_PARAM_CLASS = 2, - PATTY_AX25_FRAME_XID_PARAM_HDLC = 3, - PATTY_AX25_FRAME_XID_PARAM_INFO_TX = 5, - PATTY_AX25_FRAME_XID_PARAM_INFO_RX = 6, - PATTY_AX25_FRAME_XID_PARAM_WINDOW_TX = 7, - PATTY_AX25_FRAME_XID_PARAM_WINDOW_RX = 8, - PATTY_AX25_FRAME_XID_PARAM_ACK = 9 -}; - -enum patty_ax25_frame_xid_param_class_flags { - PATTY_AX25_FRAME_XID_PARAM_CLASS_ABM = (1 << 1), - PATTY_AX25_FRAME_XID_PARAM_CLASS_HALF_DUPLEX = (1 << 6), - PATTY_AX25_FRAME_XID_PARAM_CLASS_FULL_DUPLEX = (1 << 7) -}; - -enum patty_ax25_frame_xid_param_hdlc_flags { - PATTY_AX25_FRAME_XID_PARAM_HDLC_REJ = (1 << 1), - PATTY_AX25_FRAME_XID_PARAM_HDLC_SREJ = (1 << 2), - PATTY_AX25_FRAME_XID_PARAM_HDLC_XADDR = (1 << 8), - PATTY_AX25_FRAME_XID_PARAM_HDLC_MODULO_8 = (1 << 11), - PATTY_AX25_FRAME_XID_PARAM_HDLC_MODULO_128 = (1 << 12), - PATTY_AX25_FRAME_XID_PARAM_HDLC_TEST = (1 << 14), - PATTY_AX25_FRAME_XID_PARAM_HDLC_SYNC_TX = (1 << 18) -}; - #pragma pack(push) #pragma pack(1) @@ -131,10 +105,6 @@ typedef struct _patty_ax25_frame_xid_param { #pragma pack(pop) -typedef int (*patty_ax25_frame_xid_callback)(enum patty_ax25_frame_xid_param_type type, - uint32_t value, - void *ctx); - ssize_t patty_ax25_frame_decode_address(patty_ax25_frame *frame, void *buf, size_t len); @@ -145,11 +115,10 @@ ssize_t patty_ax25_frame_decode_control(patty_ax25_frame *frame, size_t offset, size_t len); -ssize_t patty_ax25_frame_decode_xid(patty_ax25_frame_xid_callback callback, +ssize_t patty_ax25_frame_decode_xid(patty_ax25_params *params, void *data, size_t offset, - size_t len, - void *ctx); + size_t len); ssize_t patty_ax25_frame_encode(patty_ax25_frame *frame, enum patty_ax25_frame_format format, diff --git a/include/patty/print.h b/include/patty/print.h index e018b63..ef9b255 100644 --- a/include/patty/print.h +++ b/include/patty/print.h @@ -1,11 +1,12 @@ #ifndef _PATTY_PRINT_H #define _PATTY_PRINT_H +int patty_print_frame_header(FILE *fh, + const patty_ax25_frame *frame); + +int patty_print_params(FILE *fh, + const patty_ax25_params *params); + int patty_print_hexdump(FILE *fh, void *data, size_t len); -int patty_print_frame(FILE *fh, - const patty_ax25_frame *frame, - void *buf, - size_t len); - #endif /* _PATTY_PRINT_H */ diff --git a/src/frame.c b/src/frame.c index 0ef698c..09c3f79 100644 --- a/src/frame.c +++ b/src/frame.c @@ -271,11 +271,45 @@ error: return -1; } -ssize_t decode_xid_group(patty_ax25_frame_xid_callback callback, +static void save_xid_param(patty_ax25_params *params, + enum patty_ax25_param_type type, + uint32_t value) { + switch (type) { + case PATTY_AX25_PARAM_CLASSES: + params->classes = value; break; + + case PATTY_AX25_PARAM_HDLC: + params->hdlc = value; break; + + case PATTY_AX25_PARAM_INFO_TX: + params->info_tx = (size_t)value; break; + + case PATTY_AX25_PARAM_INFO_RX: + params->info_rx = (size_t)value; break; + + case PATTY_AX25_PARAM_WINDOW_TX: + params->window_tx = (size_t)value; break; + + case PATTY_AX25_PARAM_WINDOW_RX: + params->window_rx = (size_t)value; break; + + case PATTY_AX25_PARAM_ACK: + params->ack = (size_t)value; break; + + case PATTY_AX25_PARAM_RETRY: + params->retry = (size_t)value; break; + + default: + return; + } + + params->found |= (1 << type); +} + +ssize_t decode_xid_group(patty_ax25_params *params, void *data, size_t offset, - size_t len, - void *ctx) { + size_t len) { patty_ax25_frame_xid_group *group = (patty_ax25_frame_xid_group *) ((uint8_t *)data + offset); @@ -297,6 +331,8 @@ ssize_t decode_xid_group(patty_ax25_frame_xid_callback callback, goto done; } + memset(params, '\0', sizeof(*params)); + while (offset - start < sizeof(*group) + grouplen) { patty_ax25_frame_xid_param *param = (patty_ax25_frame_xid_param *) ((uint8_t *)data + offset); @@ -308,11 +344,7 @@ ssize_t decode_xid_group(patty_ax25_frame_xid_callback callback, value |= ((uint8_t *)(param + 1))[param->len-1-i] << (i << 3); } - if (callback(param->id, - value, - ctx) < 0) { - goto error_callback; - } + save_xid_param(params, param->id, value); offset += sizeof(*param) + param->len; } @@ -327,21 +359,19 @@ done: error: errno = EIO; -error_callback: return -1; } -ssize_t patty_ax25_frame_decode_xid(patty_ax25_frame_xid_callback callback, +ssize_t patty_ax25_frame_decode_xid(patty_ax25_params *params, void *data, size_t offset, - size_t len, - void *ctx) { + size_t len) { size_t start = offset; while (offset < len) { ssize_t decoded; - if ((decoded = decode_xid_group(callback, data, offset, len, ctx)) < 0) { + if ((decoded = decode_xid_group(params, data, offset, len)) < 0) { goto error_decode_xid_group; } else { offset += decoded; diff --git a/src/print.c b/src/print.c index 3710b8a..76ed155 100644 --- a/src/print.c +++ b/src/print.c @@ -51,6 +51,173 @@ static char *frame_cr(enum patty_ax25_frame_cr cr) { return "unknown"; } +static int print_addr(FILE *fh, const patty_ax25_addr *addr) { + char buf[7]; + uint8_t ssid; + + if (patty_ax25_ntop(addr, buf, &ssid, sizeof(buf)) < 0) { + goto error_ntop; + } + + fprintf(fh, "%s", buf); + + if (ssid) { + fprintf(fh, "/%d", ssid); + } + + return 0; + +error_ntop: + return -1; +} + +static int print_frame_addrs(FILE *fh, const patty_ax25_frame *frame) { + int i; + + print_addr(fh, &frame->src); + + fprintf(fh, " > "); + + for (i=0; ihops; i++) { + print_addr(fh, &frame->repeaters[i]); + fprintf(fh, " > "); + } + + print_addr(fh, &frame->dest); + + return 0; +} + +int patty_print_frame_header(FILE *fh, + const patty_ax25_frame *frame) { + if (print_frame_addrs(fh, frame) < 0) { + goto error_io; + } + + if (PATTY_AX25_FRAME_CONTROL_I(frame->control)) { + if (fprintf(fh, " type I (%s) %s %s nr %d ns %d pf %d info %zu bytes", + frame_type(frame->type), + version(frame->version), + frame_cr(frame->cr), + (int)frame->nr, + (int)frame->ns, + (int)frame->pf, + frame->infolen) < 0) { + goto error_io; + } + } else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) { + if (fprintf(fh, " type U (%s) %s %s pf %d", + frame_type(frame->type), + version(frame->version), + frame_cr(frame->cr), + (int)frame->pf) < 0) { + goto error_io; + } + + if (PATTY_AX25_FRAME_CONTROL_UI(frame->control)) { + if (fprintf(fh, " info %zu bytes", frame->infolen) < 0) { + goto error_io; + } + } + } else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) { + if (fprintf(fh, " type S (%s) %s %s nr %d pf %d", + frame_type(frame->type), + version(frame->version), + frame_cr(frame->cr), + (int)frame->nr, + (int)frame->pf) < 0) { + goto error_io; + } + } + + return fprintf(fh, "\n"); + +error_io: + return -1; +} + +int patty_print_params(FILE *fh, + const patty_ax25_params *params) { + static const struct { + enum patty_ax25_param_classes flag; + char *name; + } classes_flags[] = { + { PATTY_AX25_PARAM_CLASSES_ABM, "ABM" }, + { PATTY_AX25_PARAM_CLASSES_HALF_DUPLEX, "half-duplex" }, + { PATTY_AX25_PARAM_CLASSES_FULL_DUPLEX, "full-duplex" }, + { 0, NULL } + }; + + static const struct { + enum patty_ax25_param_hdlc flag; + char *name; + } hdlc_flags[] = { + { PATTY_AX25_PARAM_HDLC_REJ, "REJ" }, + { PATTY_AX25_PARAM_HDLC_SREJ, "SREJ" }, + { PATTY_AX25_PARAM_HDLC_XADDR, "extended addresses" }, + { 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_SYNC_TX, "synchronous TX" }, + { 0, NULL } + }; + + struct { + enum patty_ax25_param_type flag; + size_t value; + char *name; + } fields[] = { + { PATTY_AX25_PARAM_INFO_TX, params->info_tx, "I Field Length TX" }, + { PATTY_AX25_PARAM_INFO_RX, params->info_rx, "I Field Length RX" }, + { PATTY_AX25_PARAM_WINDOW_TX, params->window_tx, "Window Size TX" }, + { PATTY_AX25_PARAM_WINDOW_RX, params->window_rx, "Window Size RX" }, + { PATTY_AX25_PARAM_ACK, params->ack, "Ack timer" }, + { PATTY_AX25_PARAM_RETRY, params->retry, "Retry" }, + { 0, 0, NULL } + }; + + int i; + + if (fprintf(fh, " XID parameters:\n") < 0) { + goto error_fprintf; + } + + if (fprintf(fh, " Classes of procedures:\n") < 0) { + goto error_fprintf; + } + + for (i=0; classes_flags[i].name; i++) { + if (params->classes & classes_flags[i].flag) { + if (fprintf(fh, " > %s\n", classes_flags[i].name) < 0) { + goto error_fprintf; + } + } + } + + fprintf(fh, " HDLC optional functions:\n"); + + for (i=0; hdlc_flags[i].name; i++) { + if (params->hdlc & hdlc_flags[i].flag) { + if (fprintf(fh, " > %s\n", hdlc_flags[i].name) < 0) { + goto error_fprintf; + } + } + } + + for (i=0; fields[i].name; i++) { + if (params->found & (1 << fields[i].flag)) { + if (fprintf(fh, " %s: %zu\n", fields[i].name, fields[i].value) < 0) { + goto error_fprintf; + } + } + } + + return 0; + +error_fprintf: + return -1; +} + int patty_print_hexdump(FILE *fh, void *data, size_t len) { size_t i; @@ -101,92 +268,3 @@ int patty_print_hexdump(FILE *fh, void *data, size_t len) { error_io: return -1; } - -static int print_addr(FILE *fh, const patty_ax25_addr *addr) { - char buf[7]; - uint8_t ssid; - - if (patty_ax25_ntop(addr, buf, &ssid, sizeof(buf)) < 0) { - goto error_ntop; - } - - fprintf(fh, "%s", buf); - - if (ssid) { - fprintf(fh, "/%d", ssid); - } - - return 0; - -error_ntop: - return -1; -} - -static int print_frame_addrs(FILE *fh, const patty_ax25_frame *frame) { - int i; - - print_addr(fh, &frame->src); - - fprintf(fh, " > "); - - for (i=0; ihops; i++) { - print_addr(fh, &frame->repeaters[i]); - fprintf(fh, " > "); - } - - print_addr(fh, &frame->dest); - - return 0; -} - -int patty_print_frame(FILE *fh, - const patty_ax25_frame *frame, - void *buf, - size_t len) { - if (print_frame_addrs(fh, frame) < 0) { - goto error_io; - } - - if (PATTY_AX25_FRAME_CONTROL_I(frame->control)) { - if (fprintf(fh, " type I (%s) %s %s nr %d ns %d pf %d info %zu bytes", - frame_type(frame->type), - version(frame->version), - frame_cr(frame->cr), - (int)frame->nr, - (int)frame->ns, - (int)frame->pf, - frame->infolen) < 0) { - goto error_io; - } - } else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) { - if (fprintf(fh, " type U (%s) %s %s pf %d", - frame_type(frame->type), - version(frame->version), - frame_cr(frame->cr), - (int)frame->pf) < 0) { - goto error_io; - } - - if (PATTY_AX25_FRAME_CONTROL_UI(frame->control)) { - if (fprintf(fh, " info %zu bytes", frame->infolen) < 0) { - goto error_io; - } - } - } else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) { - if (fprintf(fh, " type S (%s) %s %s nr %d pf %d", - frame_type(frame->type), - version(frame->version), - frame_cr(frame->cr), - (int)frame->nr, - (int)frame->pf) < 0) { - goto error_io; - } - } - - fprintf(fh, "\n"); - - return patty_print_hexdump(fh, buf, len); - -error_io: - return -1; -} diff --git a/src/server.c b/src/server.c index bc9abdc..a472de1 100644 --- a/src/server.c +++ b/src/server.c @@ -1277,7 +1277,6 @@ error_sock_delete: } static int handle_rej(patty_ax25_server *server, - patty_ax25_if *iface, patty_ax25_sock *sock, patty_ax25_frame *frame) { unsigned int i; @@ -1295,7 +1294,6 @@ error_sock_resend: } static int handle_srej(patty_ax25_server *server, - patty_ax25_if *iface, patty_ax25_sock *sock, patty_ax25_frame *frame) { /* @@ -1311,10 +1309,26 @@ error_sock_resend: return -1; } -static int handle_xid_param(enum patty_ax25_frame_xid_param_type type, - uint32_t value, - void *ctx) { +static int handle_xid(patty_ax25_server *server, + patty_ax25_sock *sock, + void *buf, + size_t offset, + size_t len) { + patty_ax25_params params; + + if (patty_ax25_frame_decode_xid(¶ms, buf, offset, len) < 0) { + goto error_io; + } + + /* + * TODO: Actually do something with the parameters received; also perhaps + * consider replying to this XID frame with another XID frame + */ + return 0; + +error_io: + return -1; } static int handle_frame(patty_ax25_server *server, @@ -1356,17 +1370,11 @@ static int handle_frame(patty_ax25_server *server, 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, iface, sock, &frame); - case PATTY_AX25_FRAME_SREJ: return handle_srej(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, sock, buf, offset, len); case PATTY_AX25_FRAME_FRMR: return 0; - case PATTY_AX25_FRAME_XID: - if (patty_ax25_frame_decode_xid(handle_xid_param, buf, offset, len, sock) < 0) { - goto error_io; - } - - break; - default: break; }