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
This commit is contained in:
XANTRONIX Development 2020-07-17 22:57:23 -04:00 committed by XANTRONIX Industrial
parent a722b8f9b3
commit 1fbf09c9ba
8 changed files with 351 additions and 166 deletions

View file

@ -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(&params,
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, &params) < 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);

View file

@ -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(&params,
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, &params) < 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:

View file

@ -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 <patty/ax25/frame.h>

View file

@ -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,

View file

@ -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 */

View file

@ -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;

View file

@ -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; i<frame->hops; 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; i<frame->hops; 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;
}

View file

@ -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(&params, 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;
}