Since we broke off, I'm using lipstick again
This commit is contained in:
parent
775c2c5283
commit
22874e6e06
5 changed files with 269 additions and 113 deletions
|
@ -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 */
|
||||
|
|
97
include/patty/ax25/macros.h
Normal file
97
include/patty/ax25/macros.h
Normal 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 */
|
|
@ -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
147
src/ax25.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue