#include #include #include #include #define printable(c) \ (c >= 0x20 && c < 0x7f) static char *frame_type(enum patty_ax25_frame_type type) { switch (type) { case PATTY_AX25_FRAME_I: return "I"; case PATTY_AX25_FRAME_RR: return "RR"; case PATTY_AX25_FRAME_RNR: return "RNR"; case PATTY_AX25_FRAME_REJ: return "REJ"; case PATTY_AX25_FRAME_SREJ: return "SREJ"; case PATTY_AX25_FRAME_SABM: return "SABM"; case PATTY_AX25_FRAME_SABME: return "SABME"; case PATTY_AX25_FRAME_DISC: return "DISC"; case PATTY_AX25_FRAME_DM: return "DM"; case PATTY_AX25_FRAME_UA: return "UA"; case PATTY_AX25_FRAME_FRMR: return "FRMR"; case PATTY_AX25_FRAME_UI: return "UI"; case PATTY_AX25_FRAME_XID: return "XID"; case PATTY_AX25_FRAME_TEST: return "TEST"; default: break; } return "unknown"; } static char *version(enum patty_ax25_version version) { switch (version) { case PATTY_AX25_2_0: return "v2.0"; case PATTY_AX25_2_2: return "v2.2"; case PATTY_AX25_OLD: return "old"; } return "unknown"; } static char *frame_cr(enum patty_ax25_frame_cr cr) { switch (cr) { case PATTY_AX25_FRAME_COMMAND: return "C"; case PATTY_AX25_FRAME_RESPONSE: return "R"; case PATTY_AX25_FRAME_OLD: return "?"; } 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->flags & (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; for (i=0; i