Since we broke off, I'm using lipstick again

This commit is contained in:
XANTRONIX Development 2015-07-17 00:45:14 +00:00
parent 775c2c5283
commit 22874e6e06
5 changed files with 269 additions and 113 deletions

View file

@ -1,6 +1,13 @@
#ifndef _PATTY_AX25_H
#define _PATTY_AX25_H
#include <stdint.h>
#include <sys/types.h>
#include <patty/ax25/macros.h>
#define PATTY_AX25_MAX_HOPS 8
enum patty_ax25_proto {
PATTY_AX25_PROTO_ISO_8208 = 0x01,
PATTY_AX25_PROTO_TCP_VJ_COMPR = 0x06,
@ -18,120 +25,16 @@ enum patty_ax25_proto {
PATTY_AX25_PROTO_ESCAPE = 0xff
};
typedef struct _patty_ax25_address {
char callsign[6];
unsigned int extension :1;
unsigned int ssid :4;
unsigned int reserved :2;
unsigned int repeated :1;
} patty_ax25_address;
enum patty_ax25_frame_type {
PATTY_AX25_FRAME_INFO,
PATTY_AX25_FRAME_SUPER,
PATTY_AX25_FRAME_UNNUMBERED
};
#define PATTY_AX25_CONTROL_INFO(c) \
((c & 0x01) == 0)
typedef struct _patty_ax25_address patty_ax25_address;
#define PATTY_AX25_CONTROL_INFO_RESET(c) \
(c = 0x00)
typedef struct _patty_ax25_frame patty_ax25_frame;
#define PATTY_AX25_CONTROL_SUPER(c) \
((c & 0x03) == 0x01)
#define PATTY_AX25_CONTROL_SUPER_RESET(c) \
(c = 0x01)
#define PATTY_AX25_CONTROL_SUPER_RR(c) \
((c & 0x0f) == 0x01)
#define PATTY_AX25_CONTROL_SUPER_RNR(c) \
((c & 0x0f) == 0x05)
#define PATTY_AX25_CONTROL_SUPER_REJ(c) \
((c & 0x0f) == 0x09)
#define PATTY_AX25_CONTROL_UNNUMBERED(c) \
((c & 0x03) == 0x03)
#define PATTY_AX25_CONTROL_UNNUMBERED_RESET(c) \
(c = 0x03)
#define PATTY_AX25_CONTROL_UNNUMBERED_SABM(c) \
(((c & 0xe0) == 0x10) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_DISC(c) \
(((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x03))
#define PATTY_AX25_CONTROL_UNNUMBERED_DM(c) \
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_UA(c) \
(((c & 0xe0) == 0x30) && ((c & 0x0f) == 0x03))
#define PATTY_AX25_CONTROL_UNNUMBERED_FRMR(c) \
(((c & 0xe0) == 0x40) && ((c & 0x0f) == 0x07))
#define PATTY_AX25_CONTROL_UNNUMBERED_UI(c) \
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x02))
#define PATTY_AX25_CONTROL_SEQ_SEND(c) \
((c & 0x0e) >> 1)
#define PATTY_AX25_CONTROL_SEQ_RECV(c) \
((c & 0xe0) >> 5)
#define PATTY_AX25_CONTROL_POLL(c) \
((c & 0x10) >> 4)
#define PATTY_AX25_CONTROL_FINAL(c) \
PATTY_AX25_CONTROL_POLL(c)
#define PATTY_AX25_FRMR_Z(frmr) \
((frmr[0] & 0x08) >> 3)
#define PATTY_AX25_FRMR_Y(frmr) \
((frmr[0] & 0x04) >> 2)
#define PATTY_AX25_FRMR_X(frmr) \
((frmr[0] & 0x02) >> 1)
#define PATTY_AX25_FRMR_W(frmr) \
(frmr[0] & 0x01)
#define PATTY_AX25_FRMR_VR(frmr) \
((frmr[1] & 0xe0) >> 5)
#define PATTY_AX25_FRMR_CR(frmr) \
((frmr[1] & 0x10) >> 4)
#define PATTY_AX25_FRMR_VS(frmr) \
((frmr[1] & 0x0e) >> 1)
#define PATTY_AX25_FRMR_CTRL(frmr) \
(frmr[2])
typedef struct _patty_ax25_control_info {
unsigned int control :1;
unsigned int seq_send :3;
unsigned int poll :1;
unsigned int seq_recv :3;
} patty_ax25_control_info;
typedef struct _patty_ax25_control_super {
unsigned int control :2;
unsigned int function :2;
unsigned int poll :1;
unsigned int seq_recv :3;
} patty_ax25_control_super;
typedef struct _patty_ax25_control_unnumbered {
unsigned int control :2;
unsigned int modifier :2;
unsigned int poll :1;
unsigned int modifier2 :3;
} patty_ax25_control_unnumbered;
typedef struct _patty_ax25_packet {
patty_ax25_address dest;
patty_ax25_address src;
patty_ax25_address hops[8];
} patty_ax25_packet;
int patty_ax25_frame_decode(patty_ax25_frame *frame, void *data, size_t len);
#endif /* _PATTY_AX25_H */

View file

@ -0,0 +1,97 @@
#ifndef _PATTY_AX25_MACROS_H
#define _PATTY_AX25_MACROS_H
#define PATTY_AX25_ADDRESS_OCTET_VALID(c) \
((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == ' '))
#define PATTY_AX25_ADDRESS_OCTET_LAST(c) \
((c & 0x01) == 0x01)
#define PATTY_AX25_ADDRESS_SSID_NUMBER(c) \
((c & 0x1e) >> 1)
#define PATTY_AX25_ADDRESS_SSID_REPEATED(c) \
((c & 0x80) == 0x80)
#define PATTY_AX25_CONTROL_INFO(c) \
((c & 0x01) == 0)
#define PATTY_AX25_CONTROL_INFO_RESET(c) \
(c = 0x00)
#define PATTY_AX25_CONTROL_SUPER(c) \
((c & 0x03) == 0x01)
#define PATTY_AX25_CONTROL_SUPER_RESET(c) \
(c = 0x01)
#define PATTY_AX25_CONTROL_SUPER_RR(c) \
((c & 0x0f) == 0x01)
#define PATTY_AX25_CONTROL_SUPER_RNR(c) \
((c & 0x0f) == 0x05)
#define PATTY_AX25_CONTROL_SUPER_REJ(c) \
((c & 0x0f) == 0x09)
#define PATTY_AX25_CONTROL_UNNUMBERED(c) \
((c & 0x03) == 0x03)
#define PATTY_AX25_CONTROL_UNNUMBERED_RESET(c) \
(c = 0x03)
#define PATTY_AX25_CONTROL_UNNUMBERED_SABM(c) \
(((c & 0xe0) == 0x10) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_DISC(c) \
(((c & 0xe0) == 0x20) && ((c & 0x0f) == 0x03))
#define PATTY_AX25_CONTROL_UNNUMBERED_DM(c) \
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_UA(c) \
(((c & 0xe0) == 0x30) && ((c & 0x0f) == 0x03))
#define PATTY_AX25_CONTROL_UNNUMBERED_FRMR(c) \
(((c & 0xe0) == 0x40) && ((c & 0x0f) == 0x07))
#define PATTY_AX25_CONTROL_UNNUMBERED_UI(c) \
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x02))
#define PATTY_AX25_CONTROL_SEQ_SEND(c) \
((c & 0x0e) >> 1)
#define PATTY_AX25_CONTROL_SEQ_RECV(c) \
((c & 0xe0) >> 5)
#define PATTY_AX25_CONTROL_POLL(c) \
((c & 0x10) >> 4)
#define PATTY_AX25_CONTROL_FINAL(c) \
PATTY_AX25_CONTROL_POLL(c)
#define PATTY_AX25_FRMR_Z(frmr) \
((frmr[0] & 0x08) >> 3)
#define PATTY_AX25_FRMR_Y(frmr) \
((frmr[0] & 0x04) >> 2)
#define PATTY_AX25_FRMR_X(frmr) \
((frmr[0] & 0x02) >> 1)
#define PATTY_AX25_FRMR_W(frmr) \
(frmr[0] & 0x01)
#define PATTY_AX25_FRMR_VR(frmr) \
((frmr[1] & 0xe0) >> 5)
#define PATTY_AX25_FRMR_CR(frmr) \
((frmr[1] & 0x10) >> 4)
#define PATTY_AX25_FRMR_VS(frmr) \
((frmr[1] & 0x0e) >> 1)
#define PATTY_AX25_FRMR_CTRL(frmr) \
(frmr[2])
#endif /* _PATTY_AX25_MACROS_H */

View file

@ -8,7 +8,7 @@ CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
LDFLAGS =
HEADERS = kiss.h ax25.h
OBJS = kiss.o test.o
OBJS = kiss.o ax25.o test.o
PROGRAM = test

147
src/ax25.c Normal file
View file

@ -0,0 +1,147 @@
#include <string.h>
#include <errno.h>
#include <patty/ax25.h>
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; i<PATTY_AX25_MAX_HOPS; i++) {
if ((decoded = frame_decode_address(&frame->repeaters[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;
}

View file

@ -111,6 +111,15 @@ static ssize_t tnc_decode(patty_kiss_tnc *tnc, void *frame, size_t *len, int *po
for (i=0, b=0; i<tnc->buflen; i++) {
unsigned char c = ((unsigned char *)tnc->buf)[i];
/*
* If the first byte is not a frame end, then that's a bad thing.
*/
if (i == 0 && c != PATTY_KISS_FEND) {
errno = EIO;
goto error_io;
}
/*
* Not all KISS TNCs will emit a type byte at the start of a frame
* to the host; if the low nybble has a value of zero, then presume