#include #include #include struct _patty_ax25_address { char callsign[7]; int ssid; int last; int repeated; }; struct _patty_ax25_frame { struct _patty_ax25_address dest; struct _patty_ax25_address src; struct _patty_ax25_address repeaters[8]; int hops; int repeated; enum patty_ax25_frame_type type; enum patty_ax25_proto proto; uint8_t control; uint8_t pid; void * info; uint16_t fcs; }; static ssize_t frame_decode_address(patty_ax25_address *address, void *data, off_t offset) { int i, space = 0; uint8_t *info = (uint8_t *)data; /* * First, unpack each callsign octet, ensuring all are within the 7 bit * ASCII space and do not have the extended bit set to 1. */ for (i=0; i<6; i++) { uint8_t c = (((uint8_t *)data) + offset)[i]; if (!PATTY_AX25_ADDRESS_OCTET_VALID(c) || !PATTY_AX25_ADDRESS_OCTET_LAST(c)) { errno = EINVAL; goto error; } if (c == ' ') { /* * Take note if we have reached the end of the call sign. */ if (space == 0) { space = 1; } address->callsign[i] = '\0'; } else { /* * If we have already reached the end of the callsign, and a * non-space character is encountered, then the address is * erroneous. */ if (space) { errno = EINVAL; goto error; } address->callsign[i] = c >> 1; } } /* * Now, unpack the data from the SSID field. */ address->repeated = PATTY_AX25_ADDRESS_SSID_REPEATED(info[7]); address->ssid = PATTY_AX25_ADDRESS_SSID_NUMBER(info[7]); address->last = PATTY_AX25_ADDRESS_OCTET_LAST(info[7]); return 7; error: return -1; } int patty_ax25_frame_decode(patty_ax25_frame *frame, void *data, size_t len) { ssize_t decoded; off_t offset = 0; memset(frame, '\0', sizeof(*frame)); if ((decoded = frame_decode_address(&frame->dest, data, offset)) < 0) { goto error_decode_dest; } else { offset += decoded; } /* * It would be considered erroneous if the destination address did have the * extension bit set to 1. */ if ((decoded = frame_decode_address(&frame->src, data, offset)) < 0) { goto error_decode_src; } else { offset += decoded; } /* * Now, if the source address is not the final address in the frame, then * begin decoding repeater addresses. */ if (!frame->src.last) { int i; for (i=0; irepeaters[i], data, offset)) < 0) { goto error_decode_repeater; } frame->hops++; if (frame->repeaters[i].last) { frame->repeated = frame->repeaters[i].repeated; break; } } /* * If the last hop does not have the address extension bit set, then * that's a big problem. */ if (frame->hops && !frame->repeaters[i-1].last) { errno = EINVAL; goto error_decode_repeater; } } return 0; error_decode_repeater: error_decode_src: error_decode_dest: return -1; }