I'm in a world of hurt

This commit is contained in:
XANTRONIX Development 2020-06-27 23:54:09 -04:00 committed by XANTRONIX Industrial
parent d983672619
commit 4478241319
6 changed files with 288 additions and 60 deletions

View file

@ -12,11 +12,33 @@
+ (mode == PATTY_AX25_SOCK_SABME? 2: 1) \
+ (infolen > 0? 1 + infolen: 0))
enum patty_ax25_frame_format {
PATTY_AX25_FRAME_NORMAL,
PATTY_AX25_FRAME_EXTENDED
};
enum patty_ax25_frame_type {
PATTY_AX25_FRAME_UNKNOWN,
PATTY_AX25_FRAME_INFO,
PATTY_AX25_FRAME_SUPER,
PATTY_AX25_FRAME_UNNUMBERED
PATTY_AX25_FRAME_INFO = 0x00,
PATTY_AX25_FRAME_SUPER = 0x01,
PATTY_AX25_FRAME_UNNUMBERED = 0x03,
PATTY_AX25_FRAME_UNKNOWN = 0xff
};
enum patty_ax25_frame_u_type {
PATTY_AX25_FRAME_U_SABME = 0x6f,
PATTY_AX25_FRAME_U_SABM = 0x2f,
PATTY_AX25_FRAME_U_DISC = 0x43,
PATTY_AX25_FRAME_U_DM = 0x0f,
PATTY_AX25_FRAME_U_UA = 0x63,
PATTY_AX25_FRAME_U_FRMR = 0x87,
PATTY_AX25_FRAME_U_UI = 0x03,
PATTY_AX25_FRAME_U_XID = 0x8f,
PATTY_AX25_FRAME_U_TEST = 0xe3
};
enum patty_ax25_frame_u_flags {
PATTY_AX25_FRAME_U_POLL = (1 << 4),
PATTY_AX25_FRAME_U_FINAL = (1 << 4)
};
enum patty_ax25_frame_cr {
@ -34,19 +56,42 @@ typedef struct _patty_ax25_frame {
uint16_t control;
uint8_t proto;
enum patty_ax25_version version;
enum patty_ax25_frame_type type;
enum patty_ax25_frame_cr cr;
void *info;
size_t len;
size_t infolen;
} patty_ax25_frame;
ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
void *data,
enum patty_ax25_frame_format format,
void *src,
size_t len);
ssize_t patty_ax25_frame_encode(patty_ax25_frame *frame,
enum patty_ax25_frame_format format,
void *dest,
size_t len);
enum patty_ax25_version patty_ax25_frame_version(patty_ax25_frame *frame);
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);
ssize_t patty_ax25_frame_info(patty_ax25_frame *frame,
void **info);
void patty_ax25_frame_copy_reply_address(patty_ax25_frame *rx,
patty_ax25_frame *tx);
void patty_ax25_frame_set(patty_ax25_frame *frame,
uint16_t control,
uint8_t proto,
void *info,
size_t infolen);
void patty_ax25_frame_set_ui(patty_ax25_frame *frame,
uint8_t flags,
uint8_t proto,
void *info,
size_t infolen);
#endif /* _PATTY_AX25_FRAME_H */

View file

@ -55,8 +55,9 @@ enum patty_ax25_if_kiss_tnc_info_type {
};
typedef struct _patty_ax25_if_kiss_tnc_info {
patty_ax25_addr addr;
patty_ax25_addr addr;
enum patty_ax25_if_kiss_tnc_info_type type;
int fd;
char path[256];
} patty_ax25_if_kiss_tnc_info;

View file

@ -121,17 +121,17 @@ static int frame_fprint(FILE *stream,
goto error_io;
}
if (frame->type == PATTY_AX25_FRAME_INFO) {
if (PATTY_AX25_CONTROL_INFO(frame->control)) {
if (fprintf(stream, " type I poll %d ns %d nr %d info %zu",
PATTY_AX25_CONTROL_POLL(frame->control),
PATTY_AX25_CONTROL_SEQ_SEND(frame->control),
PATTY_AX25_CONTROL_SEQ_RECV(frame->control),
frame->len) < 0) {
frame->infolen) < 0) {
goto error_io;
}
} else if (frame->type == PATTY_AX25_FRAME_UNNUMBERED) {
} else if (PATTY_AX25_CONTROL_UNNUMBERED(frame->control)) {
if (fprintf(stream, " type U info %zu",
frame->len) < 0) {
frame->infolen) < 0) {
goto error_io;
}
}
@ -141,7 +141,7 @@ static int frame_fprint(FILE *stream,
}
if (frame->info) {
if (hexdump_fprint(stream, frame->info, frame->len) < 0) {
if (hexdump_fprint(stream, frame->info, frame->infolen) < 0) {
goto error_io;
}
}
@ -189,7 +189,7 @@ int main(int argc, char **argv) {
break;
}
if (patty_ax25_frame_decode(&frame, buf, len) < 0) {
if (patty_ax25_frame_decode(&frame, PATTY_AX25_FRAME_NORMAL, buf, len) < 0) {
perror("Unable to decode frame");
goto error_ax25_frame_decode;

View file

@ -99,20 +99,6 @@ static ssize_t decode_address(patty_ax25_frame *frame,
offset += decoded;
}
/*
* Determine whether the current frame is a Command or Response, and which
* version of AX.25 this frame adheres to.
*/
if (PATTY_AX25_ADDRESS_SSID_C(frame->src.ssid)) {
frame->cr = PATTY_AX25_FRAME_RESPONSE;
frame->version = PATTY_AX25_ADDRESS_SSID_C(frame->dest.ssid)?
PATTY_AX25_2_0: PATTY_AX25_OLD;
} else {
frame->cr = PATTY_AX25_FRAME_COMMAND;
frame->version = PATTY_AX25_ADDRESS_SSID_C(frame->src.ssid)?
PATTY_AX25_OLD: PATTY_AX25_2_0;
}
/*
* If the source address is not the final address in the frame, begin
* decoding repeater addresses.
@ -141,20 +127,12 @@ static ssize_t decode_info(patty_ax25_frame *frame,
int info = 0;
if (PATTY_AX25_CONTROL_INFO(control)) {
frame->type = PATTY_AX25_FRAME_INFO;
info = 1;
} else if (PATTY_AX25_CONTROL_SUPER(control)) {
frame->type = PATTY_AX25_FRAME_SUPER;
} else if (PATTY_AX25_CONTROL_UNNUMBERED(control)) {
frame->type = PATTY_AX25_FRAME_UNNUMBERED;
if (PATTY_AX25_CONTROL_UNNUMBERED_INFO(control)) {
info = 1;
}
} else {
frame->type = PATTY_AX25_FRAME_UNKNOWN;
errno = EINVAL;
goto error;
@ -172,11 +150,11 @@ static ssize_t decode_info(patty_ax25_frame *frame,
if (info) {
decoded++;
frame->proto = ((uint8_t *)data + offset)[1];
frame->info = (void *)((uint8_t *)data + offset + decoded);
frame->len = size - offset - decoded;
frame->proto = ((uint8_t *)data + offset)[1];
frame->info = (void *)((uint8_t *)data + offset + decoded);
frame->infolen = size - offset - decoded;
decoded += frame->len;
decoded += frame->infolen;
}
return decoded;
@ -186,7 +164,8 @@ error:
}
ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
void *data,
enum patty_ax25_frame_format format,
void *src,
size_t size) {
ssize_t decoded;
off_t offset = 0;
@ -196,7 +175,7 @@ ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
/*
* First, decode the variable-length Address field.
*/
if ((decoded = decode_address(frame, data, offset)) < 0) {
if ((decoded = decode_address(frame, src, offset)) < 0) {
errno = EIO;
goto error_decode;
@ -208,7 +187,7 @@ ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
* Next, decode the remaining Control Field, optional Protocol Identifier
* field, and Info payload that may follow.
*/
if ((decoded = decode_info(frame, data, offset, size)) < 0) {
if ((decoded = decode_info(frame, src, offset, size)) < 0) {
errno = EIO;
goto error_decode;
@ -222,6 +201,109 @@ error_decode:
return -1;
}
static ssize_t encode_address(patty_ax25_frame *frame,
void *dest,
size_t len) {
size_t i,
offset = 0,
hops = frame->hops > PATTY_AX25_MAX_HOPS?
PATTY_AX25_MAX_HOPS: frame->hops;
if ((2 + hops) * sizeof(patty_ax25_addr) > len) {
goto error_toobig;
}
memcpy((uint8_t *)dest + offset, &frame->dest, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)dest)[offset-1] &= ~1;
memcpy((uint8_t *)dest + offset, &frame->src, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
((uint8_t *)dest)[offset-1] &= ~1;
for (i=0; i<hops; i++) {
if (frame->repeaters[i].callsign[0] == '\0') {
break;
}
memcpy((uint8_t *)dest + offset,
&frame->repeaters[i],
sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
}
((uint8_t *)dest)[offset-1] |= 1;
return offset;
error_toobig:
return -1;
}
ssize_t patty_ax25_frame_encode(patty_ax25_frame *frame,
enum patty_ax25_frame_format format,
void *dest,
size_t len) {
size_t offset = 0;
offset = encode_address(frame, dest, len);
switch (format) {
case PATTY_AX25_FRAME_NORMAL:
((uint8_t *)dest)[offset++] = frame->control;
break;
case PATTY_AX25_FRAME_EXTENDED:
((uint8_t *)dest)[offset++] = (frame->control & 0xff00) >> 8;
((uint8_t *)dest)[offset++] = frame->control & 0xf00ff;
break;
}
if (PATTY_AX25_CONTROL_INFO(frame->control)) {
if (1 + offset + frame->infolen > len) {
goto error_toobig;
}
((uint8_t *)dest)[offset++] = frame->proto;
memcpy((uint8_t *)dest + offset, frame->info, frame->infolen);
offset += frame->infolen;
}
return offset;
error_toobig:
return -1;
}
enum patty_ax25_version patty_ax25_frame_version(patty_ax25_frame *frame) {
return PATTY_AX25_ADDRESS_SSID_C(frame->src.ssid) ==
PATTY_AX25_ADDRESS_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) {
if (PATTY_AX25_CONTROL_INFO(frame->control)) {
return PATTY_AX25_FRAME_INFO;
} else if (PATTY_AX25_CONTROL_SUPER(frame->control)) {
return PATTY_AX25_FRAME_SUPER;
} else if (PATTY_AX25_CONTROL_UNNUMBERED(frame->control)) {
return PATTY_AX25_FRAME_UNNUMBERED;
}
return PATTY_AX25_FRAME_UNKNOWN;
}
enum patty_ax25_frame_cr patty_ax25_frame_cr(patty_ax25_frame *frame) {
return PATTY_AX25_ADDRESS_SSID_C(frame->src.ssid)?
PATTY_AX25_FRAME_RESPONSE:
PATTY_AX25_FRAME_COMMAND;
}
ssize_t patty_ax25_frame_info(patty_ax25_frame *frame,
void **info) {
if (frame == NULL || frame->info == NULL || info == NULL) {
@ -232,8 +314,47 @@ ssize_t patty_ax25_frame_info(patty_ax25_frame *frame,
*info = frame->info;
return frame->len;
return frame->infolen;
error_invalid_args:
return -1;
}
void patty_ax25_frame_copy_reply_address(patty_ax25_frame *rx,
patty_ax25_frame *tx) {
size_t i,
max = rx->hops > PATTY_AX25_MAX_HOPS? PATTY_AX25_MAX_HOPS: rx->hops;
memcpy(&tx->dest, &rx->src, sizeof(patty_ax25_addr));
memcpy(&tx->src, &rx->dest, sizeof(patty_ax25_addr));
memset(&tx->repeaters, '\0', sizeof(tx->repeaters));
for (i=0; i<max; i++) {
memcpy(&tx->repeaters[i], &rx->repeaters[max-i-1], sizeof(patty_ax25_addr));
}
tx->hops = rx->hops;
}
void patty_ax25_frame_set(patty_ax25_frame *frame,
uint16_t control,
uint8_t proto,
void *info,
size_t infolen) {
frame->control = control;
frame->proto = proto;
frame->info = info;
frame->infolen = infolen;
}
void patty_ax25_frame_set_ui(patty_ax25_frame *frame,
uint8_t flags,
uint8_t proto,
void *info,
size_t infolen) {
frame->control = PATTY_AX25_FRAME_U_UI | flags;
frame->proto = proto;
frame->info = info;
frame->infolen = infolen;
}

View file

@ -287,6 +287,19 @@ error_dict_delete_established:
return -1;
}
static int sock_delete_by_addrpair(patty_dict *dict,
patty_ax25_addr *local,
patty_ax25_addr *remote) {
uint32_t hash;
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, local);
patty_ax25_addr_hash(&hash, remote);
patty_hash_end(&hash);
return patty_dict_delete_with_hash(dict, hash);
}
static inline void watch_fd(patty_ax25_server *server, int fd) {
FD_SET(fd, &server->fds_watch);
@ -1028,23 +1041,69 @@ static int handle_clients(patty_ax25_server *server) {
return patty_dict_each(server->clients, handle_client, server);
}
static int handle_packet_rx(patty_ax25_server *server,
patty_ax25_if *iface,
void *buf,
size_t len) {
patty_ax25_frame frame;
static void copy_reply_repeaters(patty_ax25_addr *to,
patty_ax25_addr *from,
unsigned int hops) {
unsigned int i,
max = hops > PATTY_AX25_MAX_HOPS?
PATTY_AX25_MAX_HOPS: hops;
if (patty_ax25_frame_decode(&frame, buf, len) < 0) {
memset(to, '\0', PATTY_AX25_MAX_HOPS * sizeof(patty_ax25_addr));
for (i=0; i<max; i++) {
memcpy(&to[i], &from[i-max-1], sizeof(patty_ax25_addr));
}
}
static int handle_frame_rx(patty_ax25_server *server,
patty_ax25_if *iface,
void *buf,
size_t len) {
patty_ax25_frame frame_rx,
frame_tx;
if (patty_ax25_frame_decode(&frame_rx, buf, len) < 0) {
goto error_io;
}
if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) {
fprintf(stderr, "Got SABM packet\n");
}
if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame_rx.control)) {
patty_ax25_sock *sock;
/*
* TODO: Handle inbound packet
*/
if ((sock = sock_by_addr(server->socks_pending_accept,
&frame_rx.dest)) == NULL) {
if (send_dm(iface, &frame.src, &frame.dest, NULL) < 0) {
goto error_io;
}
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
sock->mode = PATTY_AX25_SOCK_SABM;
memcpy(&sock->local, &frame.dest, sizeof(patty_ax25_sock));
memcpy(&sock->remote, &frame.src, sizeof(patty_ax25_sock));
copy_reply_repeaters(&sock->repeaters,
&frame.repeaters,
sock->hops);
if (sock_delete_by_addrpair(server->socks_pending_accept,
&sock->local,
&sock->remote) < 0) {
goto error_io;
}
if (sock_save_by_addrpair(server->socks_established,
sock,
&sock->local,
&sock->remote) < 0) {
goto error_io;
}
} else {
if (send_frmr(iface, &frame.src, &frame.dest, NULL) < 0) {
goto error_io;
}
}
}
return 0;
@ -1070,7 +1129,7 @@ static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
goto done;
}
if (handle_packet_rx(server, iface, buf, readlen) < 0) {
if (handle_frame_rx(server, iface, buf, readlen) < 0) {
goto error_io;
}

View file

@ -34,9 +34,11 @@ static size_t copy_addr_to_buf(patty_ax25_sock *sock, uint8_t *buf, size_t offse
memcpy(&buf[offset], &sock->remote, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
buf[offset-1] &= ~1;
memcpy(&buf[offset], &sock->local, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
buf[offset-1] &= ~1;
for (i=0; i<sock->hops; i++) {
memcpy(&buf[offset], &sock->repeaters[i], sizeof(patty_ax25_addr));