Implement better handling of command/response bits

Implement better handling of command/response bits whilst decoding and
encoding addresses

Changes:

    * Add an enum patty_ax25_frame_cr argument to functions in
      src/sock.c which send specific types of frames

    * Detect AX.25 version >2.0 based on the command/response SSID bits

    * Simplify address copying/encoding by usage of the new function
      patty_ax25_addr_copy()

    * Implement showing AX.25 version, command/response indicator for
      frames in src/print.c
This commit is contained in:
XANTRONIX Development 2020-07-14 17:04:49 -04:00 committed by XANTRONIX Industrial
parent 79d1393e74
commit 9066fe10da
6 changed files with 99 additions and 55 deletions

View file

@ -13,6 +13,7 @@ enum patty_ax25_frame_format {
}; };
enum patty_ax25_frame_cr { enum patty_ax25_frame_cr {
PATTY_AX25_FRAME_OLD,
PATTY_AX25_FRAME_COMMAND, PATTY_AX25_FRAME_COMMAND,
PATTY_AX25_FRAME_RESPONSE PATTY_AX25_FRAME_RESPONSE
}; };
@ -72,7 +73,9 @@ typedef struct _patty_ax25_frame {
uint16_t control; uint16_t control;
uint8_t nr, ns, pf; uint8_t nr, ns, pf;
enum patty_ax25_frame_cr cr;
enum patty_ax25_frame_type type; enum patty_ax25_frame_type type;
enum patty_ax25_version version;
uint8_t proto; uint8_t proto;
void *info; void *info;

View file

@ -75,17 +75,22 @@ void patty_ax25_sock_seq_send_incr(patty_ax25_sock *sock);
void patty_ax25_sock_seq_recv_incr(patty_ax25_sock *sock); void patty_ax25_sock_seq_recv_incr(patty_ax25_sock *sock);
ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr,
uint16_t control, uint16_t control,
void *info, void *info,
size_t infolen); size_t infolen);
ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock); ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr);
ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock); ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr);
ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock); ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr);
ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock); ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr);
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag); ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag);

View file

@ -109,6 +109,18 @@ ssize_t patty_ax25_frame_decode_address(patty_ax25_frame *frame,
offset += decoded; offset += decoded;
} }
if (PATTY_AX25_ADDR_SSID_C(frame->dest.ssid) != PATTY_AX25_ADDR_SSID_C(frame->src.ssid)) {
frame->cr = PATTY_AX25_ADDR_SSID_C(frame->dest.ssid)?
PATTY_AX25_FRAME_COMMAND:
PATTY_AX25_FRAME_RESPONSE;
frame->version = PATTY_AX25_2_0;
} else {
frame->cr = PATTY_AX25_FRAME_OLD;
frame->version = PATTY_AX25_OLD;
}
/* /*
* If the source address is not the final address in the frame, begin * If the source address is not the final address in the frame, begin
* decoding repeater addresses. * decoding repeater addresses.
@ -313,29 +325,21 @@ static ssize_t encode_reply_address(patty_ax25_frame *frame,
hops = frame->hops > PATTY_AX25_MAX_HOPS? hops = frame->hops > PATTY_AX25_MAX_HOPS?
PATTY_AX25_MAX_HOPS: frame->hops; PATTY_AX25_MAX_HOPS: frame->hops;
uint8_t *buf = dest;
if ((2 + hops) * sizeof(patty_ax25_addr) > len) { if ((2 + hops) * sizeof(patty_ax25_addr) > len) {
goto error_toobig; goto error_toobig;
} }
memcpy((uint8_t *)dest + offset, &frame->src, sizeof(patty_ax25_addr)); offset += patty_ax25_addr_copy(buf + offset, &frame->src, 0x00);
offset += sizeof(patty_ax25_addr); offset += patty_ax25_addr_copy(buf + offset, &frame->dest, 0x80);
((uint8_t *)dest)[offset-1] &= ~1;
memcpy((uint8_t *)dest + offset, &frame->dest, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)dest)[offset-1] &= ~1;
for (i=0; i<hops; i++) { for (i=0; i<hops; i++) {
if (frame->repeaters[i].callsign[0] == '\0') { if (frame->repeaters[i].callsign[0] == '\0') {
break; break;
} }
memcpy((uint8_t *)dest + offset, offset += patty_ax25_addr_copy(buf + offset, &frame->repeaters[hops-1-i], 0);
&frame->repeaters[hops-1-i],
sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)dest)[offset-1] &= ~1;
} }
((uint8_t *)dest)[offset-1] |= 1; ((uint8_t *)dest)[offset-1] |= 1;
@ -435,9 +439,7 @@ error_toobig:
} }
enum patty_ax25_version patty_ax25_frame_version(patty_ax25_frame *frame) { enum patty_ax25_version patty_ax25_frame_version(patty_ax25_frame *frame) {
return PATTY_AX25_ADDR_SSID_C(frame->src.ssid) == return frame->version;
PATTY_AX25_ADDR_SSID_C(frame->dest.ssid)?
PATTY_AX25_2_0: PATTY_AX25_OLD;
} }
enum patty_ax25_frame_type patty_ax25_frame_type(patty_ax25_frame *frame) { enum patty_ax25_frame_type patty_ax25_frame_type(patty_ax25_frame *frame) {
@ -445,9 +447,7 @@ enum patty_ax25_frame_type patty_ax25_frame_type(patty_ax25_frame *frame) {
} }
enum patty_ax25_frame_cr patty_ax25_frame_cr(patty_ax25_frame *frame) { enum patty_ax25_frame_cr patty_ax25_frame_cr(patty_ax25_frame *frame) {
return PATTY_AX25_ADDR_SSID_C(frame->src.ssid)? return frame->cr;
PATTY_AX25_FRAME_RESPONSE:
PATTY_AX25_FRAME_COMMAND;
} }
ssize_t patty_ax25_frame_info(patty_ax25_frame *frame, ssize_t patty_ax25_frame_info(patty_ax25_frame *frame,

View file

@ -7,7 +7,7 @@
#define printable(c) \ #define printable(c) \
(c >= 0x20 && c < 0x7f) (c >= 0x20 && c < 0x7f)
static char *frame_type_name(enum patty_ax25_frame_type type) { static char *frame_type(enum patty_ax25_frame_type type) {
switch (type) { switch (type) {
case PATTY_AX25_FRAME_I: return "I"; case PATTY_AX25_FRAME_I: return "I";
case PATTY_AX25_FRAME_RR: return "RR"; case PATTY_AX25_FRAME_RR: return "RR";
@ -31,6 +31,26 @@ static char *frame_type_name(enum patty_ax25_frame_type type) {
return "unknown"; 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 "command";
case PATTY_AX25_FRAME_RESPONSE: return "response";
case PATTY_AX25_FRAME_OLD: return "?";
}
return "unknown";
}
int patty_print_hexdump(FILE *fh, void *data, size_t len) { int patty_print_hexdump(FILE *fh, void *data, size_t len) {
size_t i; size_t i;
@ -128,8 +148,10 @@ int patty_print_frame(FILE *fh,
} }
if (PATTY_AX25_FRAME_CONTROL_I(frame->control)) { if (PATTY_AX25_FRAME_CONTROL_I(frame->control)) {
if (fprintf(fh, " type I (%s) nr %d ns %d pf %d info %zu bytes", if (fprintf(fh, " type I (%s) %s %s nr %d ns %d pf %d info %zu bytes",
frame_type_name(frame->type), frame_type(frame->type),
version(frame->version),
frame_cr(frame->cr),
(int)frame->nr, (int)frame->nr,
(int)frame->ns, (int)frame->ns,
(int)frame->pf, (int)frame->pf,
@ -137,8 +159,10 @@ int patty_print_frame(FILE *fh,
goto error_io; goto error_io;
} }
} else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) { } else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) {
if (fprintf(fh, " type U (%s) pf %d", if (fprintf(fh, " type U (%s) %s %s pf %d",
frame_type_name(frame->type), frame_type(frame->type),
version(frame->version),
frame_cr(frame->cr),
(int)frame->pf) < 0) { (int)frame->pf) < 0) {
goto error_io; goto error_io;
} }
@ -149,8 +173,10 @@ int patty_print_frame(FILE *fh,
} }
} }
} else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) { } else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) {
if (fprintf(fh, " type S (%s) nr %d pf %d", if (fprintf(fh, " type S (%s) %s %s nr %d pf %d",
frame_type_name(frame->type), frame_type(frame->type),
version(frame->version),
frame_cr(frame->cr),
(int)frame->nr, (int)frame->nr,
(int)frame->pf) < 0) { (int)frame->pf) < 0) {
goto error_io; goto error_io;

View file

@ -1244,7 +1244,7 @@ static int handle_i(patty_ax25_server *server,
if (sock->seq_recv == frame->ns) { if (sock->seq_recv == frame->ns) {
patty_ax25_sock_seq_recv_incr(sock); patty_ax25_sock_seq_recv_incr(sock);
} else { } else {
return patty_ax25_sock_send_rej(sock); return patty_ax25_sock_send_rej(sock, PATTY_AX25_FRAME_RESPONSE);
} }
if (write(sock->fd, frame->info, frame->infolen) < 0) { if (write(sock->fd, frame->info, frame->infolen) < 0) {
@ -1252,7 +1252,7 @@ static int handle_i(patty_ax25_server *server,
} }
if (frame->pf) { if (frame->pf) {
return patty_ax25_sock_send_rr(sock); return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE);
} }
return 0; return 0;

View file

@ -154,29 +154,27 @@ void patty_ax25_sock_seq_recv_incr(patty_ax25_sock *sock) {
} }
} }
static size_t copy_addr_to_tx_buf(patty_ax25_sock *sock) { static size_t addr_copy_to_tx_buf(patty_ax25_sock *sock,
void *buf = sock->iface->tx_buf; enum patty_ax25_frame_cr cr) {
uint8_t *buf = sock->iface->tx_buf;
size_t offset = 0;
uint8_t flags_remote = 0x00,
flags_local = 0x00;
unsigned int i; unsigned int i;
size_t offset = 0; switch (cr) {
case PATTY_AX25_FRAME_COMMAND: flags_remote = 0x80; break;
case PATTY_AX25_FRAME_RESPONSE: flags_local = 0x80; break;
case PATTY_AX25_FRAME_OLD: break;
}
memcpy((uint8_t *)buf + offset, &sock->remote, sizeof(patty_ax25_addr)); offset += patty_ax25_addr_copy(buf + offset, &sock->remote, flags_remote);
offset += sizeof(patty_ax25_addr); offset += patty_ax25_addr_copy(buf + offset, &sock->local, flags_local);
((uint8_t *)buf)[offset-1] &= ~1;
memcpy((uint8_t *)buf + offset, &sock->local, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)buf)[offset-1] &= ~1;
for (i=0; i<sock->hops; i++) { for (i=0; i<sock->hops; i++) {
memcpy((uint8_t *)buf + offset, offset += patty_ax25_addr_copy(buf + offset, &sock->repeaters[i], 0);
&sock->repeaters[i],
sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)buf)[offset-1] &= ~1;
} }
((uint8_t *)buf)[offset-1] |= 1; ((uint8_t *)buf)[offset-1] |= 1;
@ -196,6 +194,7 @@ static inline int toobig(patty_ax25_sock *sock,
} }
ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr,
uint16_t control, uint16_t control,
void *info, void *info,
size_t infolen) { size_t infolen) {
@ -206,7 +205,7 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
goto error_toobig; goto error_toobig;
} }
offset = copy_addr_to_tx_buf(sock); offset = addr_copy_to_tx_buf(sock, cr);
if (sock->mode == PATTY_AX25_SOCK_SABME) { if (sock->mode == PATTY_AX25_SOCK_SABME) {
buf[offset++] = (control & 0xff00) >> 8; buf[offset++] = (control & 0xff00) >> 8;
@ -270,29 +269,37 @@ static uint16_t control_u(enum patty_ax25_frame_type type,
| (flag << 4); | (flag << 4);
} }
ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock) { ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
cr,
control_s(sock, PATTY_AX25_FRAME_RR, 1), control_s(sock, PATTY_AX25_FRAME_RR, 1),
NULL, NULL,
0); 0);
} }
ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock) { ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
cr,
control_s(sock, PATTY_AX25_FRAME_RNR, 1), control_s(sock, PATTY_AX25_FRAME_RNR, 1),
NULL, NULL,
0); 0);
} }
ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock) { ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
cr,
control_s(sock, PATTY_AX25_FRAME_REJ, 1), control_s(sock, PATTY_AX25_FRAME_REJ, 1),
NULL, NULL,
0); 0);
} }
ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock) { ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock,
enum patty_ax25_frame_cr cr) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
cr,
control_s(sock, PATTY_AX25_FRAME_SREJ, 1), control_s(sock, PATTY_AX25_FRAME_SREJ, 1),
NULL, NULL,
0); 0);
@ -300,6 +307,7 @@ ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock) {
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag) { ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_COMMAND,
control_u(PATTY_AX25_FRAME_SABM, flag), control_u(PATTY_AX25_FRAME_SABM, flag),
NULL, NULL,
0); 0);
@ -307,6 +315,7 @@ ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag) {
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int flag) { ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int flag) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_COMMAND,
control_u(PATTY_AX25_FRAME_SABME, flag), control_u(PATTY_AX25_FRAME_SABME, flag),
NULL, NULL,
0); 0);
@ -314,6 +323,7 @@ ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int flag) {
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int flag) { ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int flag) {
return patty_ax25_sock_send(sock, return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_COMMAND,
control_u(PATTY_AX25_FRAME_DISC, flag), control_u(PATTY_AX25_FRAME_DISC, flag),
NULL, NULL,
0); 0);
@ -336,7 +346,7 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
control = control_i(sock, 0); control = control_i(sock, 0);
if (patty_ax25_sock_send(sock, control, buf, len) < 0) { if (patty_ax25_sock_send(sock, PATTY_AX25_FRAME_RESPONSE, control, buf, len) < 0) {
goto error_send; goto error_send;
} }