Implement better modulo-128 I and S frame support
Changes: * Split patty_ax25_frame_decode() into the following: - patty_ax25_frame_decode_address() - patty_ax25_frame_decode_control() This allows for look up an established socket for a given address pair, to determine if an SABME session is in progress, necessitating modulo-128 control decoding * Decode I and S N(R), N(S) sequence numbers, poll/final bits properly in both modulo-8 and modulo-128 mode * Perform better frame control validation * Implement the following functions in src/sock.c: - patty_ax25_sock_send_rr() - patty_ax25_sock_send_rnr() - patty_ax25_sock_send_rej() - patty_ax25_sock_send_srej() Corresponding functions have been removed from src/server.c * Implement better functions in src/sock.c for encoding frame control, with send/receive sequences associated with the socket, with modulo-128 encoding for SABME sessions Other changes: * Move or delete macros from include/patty/ax25/macros.h into include/patty/ax25.h and include/patty/ax25/frame.h * Move definitions from include/patty/ax25/proto.h to header file include/patty/ax25.h * Perform better bounds checking while decoding frames * Improve frame control printing in src/print.c; display frame type names, N(R), (NS) sequence numbers, and poll/final bits
This commit is contained in:
parent
c2766a4405
commit
a4518a839a
13 changed files with 466 additions and 381 deletions
|
@ -89,12 +89,20 @@ int main(int argc, char **argv) {
|
|||
|
||||
while ((readlen = patty_kiss_tnc_recv(raw, buf, sizeof(buf), NULL)) > 0) {
|
||||
patty_ax25_frame frame;
|
||||
ssize_t decoded;
|
||||
|
||||
if (patty_ax25_frame_decode(&frame, PATTY_AX25_FRAME_NORMAL, buf, readlen) < 0) {
|
||||
if ((decoded = patty_ax25_frame_decode_address(&frame, buf, readlen)) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
argv[0], "patty_ax25_frame_decode()", strerror(errno));
|
||||
argv[0], "patty_ax25_frame_decode_address()", strerror(errno));
|
||||
|
||||
goto error_ax25_frame_decode;
|
||||
goto error_ax25_frame_decode_address;
|
||||
}
|
||||
|
||||
if (patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, decoded, readlen) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
argv[0], "patty_ax25_frame_decode_control()", strerror(errno));
|
||||
|
||||
goto error_ax25_frame_decode_control;
|
||||
}
|
||||
|
||||
if (patty_print_frame(stdout, &frame, buf, readlen) < 0) {
|
||||
|
@ -114,7 +122,8 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
|
||||
error_print_frame:
|
||||
error_ax25_frame_decode:
|
||||
error_ax25_frame_decode_control:
|
||||
error_ax25_frame_decode_address:
|
||||
patty_kiss_tnc_destroy(raw);
|
||||
|
||||
error_kiss_tnc_new:
|
||||
|
|
|
@ -49,7 +49,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
while (1) {
|
||||
ssize_t len;
|
||||
ssize_t len,
|
||||
decoded;
|
||||
patty_ax25_frame frame;
|
||||
|
||||
if ((len = patty_kiss_tnc_recv(tnc, buf, PATTY_KISS_BUFSZ, &port)) < 0) {
|
||||
|
@ -61,11 +62,18 @@ int main(int argc, char **argv) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (patty_ax25_frame_decode(&frame, PATTY_AX25_FRAME_NORMAL, buf, len) < 0) {
|
||||
if ((decoded = patty_ax25_frame_decode_address(&frame, buf, len)) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
argv[0], "patty_ax25_frame_decode()", strerror(errno));
|
||||
argv[0], "patty_ax25_frame_decode_address()", strerror(errno));
|
||||
|
||||
goto error_ax25_frame_decode;
|
||||
goto error_ax25_frame_decode_address;
|
||||
}
|
||||
|
||||
if (patty_ax25_frame_decode_control(&frame, PATTY_AX25_FRAME_NORMAL, buf, decoded, len) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
argv[0], "patty_ax25_frame_decode_control()", strerror(errno));
|
||||
|
||||
goto error_ax25_frame_decode_control;
|
||||
}
|
||||
|
||||
if (patty_print_frame(stdout, &frame, buf, len) < 0) {
|
||||
|
@ -83,7 +91,8 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
|
||||
error_print_frame:
|
||||
error_ax25_frame_decode:
|
||||
error_ax25_frame_decode_control:
|
||||
error_ax25_frame_decode_address:
|
||||
error_kiss_tnc_recv:
|
||||
free(buf);
|
||||
|
||||
|
|
|
@ -8,11 +8,36 @@
|
|||
#include <patty/list.h>
|
||||
#include <patty/dict.h>
|
||||
|
||||
#define PATTY_AX25_ADDRESS_SIZE 7
|
||||
#define PATTY_AX25_ADDR_SIZE 7
|
||||
#define PATTY_AX25_CALLSIGN_LEN 6
|
||||
#define PATTY_AX25_IF_NAME_SIZE 8
|
||||
#define PATTY_AX25_MAX_HOPS 8
|
||||
#define PATTY_AX25_SOCK_PATH_SIZE 256
|
||||
|
||||
enum patty_ax25_version {
|
||||
PATTY_AX25_OLD,
|
||||
PATTY_AX25_2_0,
|
||||
PATTY_AX25_2_2
|
||||
};
|
||||
|
||||
enum patty_ax25_proto {
|
||||
PATTY_AX25_PROTO_UNKNOWN = 0x00,
|
||||
PATTY_AX25_PROTO_ISO_8208 = 0x01,
|
||||
PATTY_AX25_PROTO_TCP_VJ_COMPR = 0x06,
|
||||
PATTY_AX25_PROTO_TCP_VJ = 0x07,
|
||||
PATTY_AX25_PROTO_FRAGMENT = 0x08,
|
||||
PATTY_AX25_PROTO_TEXNET = 0xc3,
|
||||
PATTY_AX25_PROTO_LQP = 0xc4,
|
||||
PATTY_AX25_PROTO_APPLETALK = 0xca,
|
||||
PATTY_AX25_PROTO_APPLETALK_ARP = 0xcb,
|
||||
PATTY_AX25_PROTO_INET = 0xcc,
|
||||
PATTY_AX25_PROTO_INET_ARP = 0xcd,
|
||||
PATTY_AX25_PROTO_FLEXNET = 0xce,
|
||||
PATTY_AX25_PROTO_NETROM = 0xcf,
|
||||
PATTY_AX25_PROTO_NONE = 0xf0,
|
||||
PATTY_AX25_PROTO_ESCAPE = 0xff
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
|
@ -25,8 +50,6 @@ typedef struct _patty_ax25_addr {
|
|||
|
||||
typedef struct _patty_ax25_if patty_ax25_if;
|
||||
|
||||
#include <patty/ax25/macros.h>
|
||||
#include <patty/ax25/proto.h>
|
||||
#include <patty/ax25/frame.h>
|
||||
#include <patty/ax25/call.h>
|
||||
#include <patty/ax25/if.h>
|
||||
|
@ -34,6 +57,21 @@ typedef struct _patty_ax25_if patty_ax25_if;
|
|||
#include <patty/ax25/sock.h>
|
||||
#include <patty/ax25/server.h>
|
||||
|
||||
#define PATTY_AX25_ADDR_CHAR_VALID(c) \
|
||||
((c >= 0x20 && c <= 0x5a))
|
||||
|
||||
#define PATTY_AX25_ADDR_OCTET_LAST(c) \
|
||||
((c & 0x01) == 0x01)
|
||||
|
||||
#define PATTY_AX25_ADDR_SSID_NUMBER(c) \
|
||||
((c & 0x1e) >> 1)
|
||||
|
||||
#define PATTY_AX25_ADDR_SSID_C(c) \
|
||||
((c & 0x80) == 0x80)
|
||||
|
||||
#define PATTY_AX25_ADDR_SSID_REPEATED(c) \
|
||||
((c & 0x80) == 0x80)
|
||||
|
||||
int patty_ax25_pton(const char *callsign,
|
||||
uint8_t ssid,
|
||||
patty_ax25_addr *addr);
|
||||
|
|
|
@ -7,66 +7,88 @@
|
|||
#define PATTY_AX25_FRAME_DEFAULT_MAXLEN 256
|
||||
#define PATTY_AX25_FRAME_DEFAULT_WINDOW 8
|
||||
|
||||
#define PATTY_AX25_FRAME_SIZE(format, hops, c, infolen) \
|
||||
(((2 + hops) * sizeof(patty_ax25_addr)) \
|
||||
+ (format == PATTY_AX25_FRAME_EXTENDED? 2: 1) \
|
||||
+ (PATTY_AX25_CONTROL_INFO(c)? 1 + infolen: 0))
|
||||
|
||||
enum patty_ax25_frame_format {
|
||||
PATTY_AX25_FRAME_NORMAL,
|
||||
PATTY_AX25_FRAME_EXTENDED
|
||||
};
|
||||
|
||||
enum patty_ax25_frame_type {
|
||||
PATTY_AX25_FRAME_INFO = 0x00,
|
||||
PATTY_AX25_FRAME_SUPER = 0x01,
|
||||
PATTY_AX25_FRAME_UNNUMBERED = 0x03,
|
||||
PATTY_AX25_FRAME_UNKNOWN = 0xff
|
||||
};
|
||||
|
||||
enum patty_ax25_frame_flags {
|
||||
PATTY_AX25_FRAME_POLL = (1 << 4),
|
||||
PATTY_AX25_FRAME_FINAL = (1 << 4)
|
||||
};
|
||||
|
||||
enum patty_ax25_frame_cr {
|
||||
PATTY_AX25_FRAME_COMMAND,
|
||||
PATTY_AX25_FRAME_RESPONSE
|
||||
};
|
||||
|
||||
enum patty_ax25_frame_s_type {
|
||||
PATTY_AX25_FRAME_S_RR = 0x01,
|
||||
PATTY_AX25_FRAME_S_RNR = 0x05,
|
||||
PATTY_AX25_FRAME_S_REJ = 0x09,
|
||||
PATTY_AX25_FRAME_S_SREJ = 0x0d
|
||||
enum patty_ax25_frame_flag {
|
||||
PATTY_AX25_FRAME_POLL = 1,
|
||||
PATTY_AX25_FRAME_FINAL = 1
|
||||
};
|
||||
|
||||
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
|
||||
#define PATTY_AX25_FRAME_CONTROL_I(c) \
|
||||
((c & 0x1) == 0x00)
|
||||
|
||||
#define PATTY_AX25_FRAME_CONTROL_S(c) \
|
||||
((c & 0x03) == 0x01)
|
||||
|
||||
#define PATTY_AX25_FRAME_CONTROL_U(c) \
|
||||
((c & 0x03) == 0x03)
|
||||
|
||||
#define PATTY_AX25_FRAME_CONTROL_UI(c) \
|
||||
((c & 0xef) == 0x03)
|
||||
|
||||
#define PATTY_AX25_FRAME_CONTROL_FLAG(c) \
|
||||
((c & 0x01) >> 4)
|
||||
|
||||
#define PATTY_AX25_FRAME_SIZE(format, hops, c, infolen) \
|
||||
(((2 + hops) * sizeof(patty_ax25_addr)) \
|
||||
+ (format == PATTY_AX25_FRAME_EXTENDED? 2: 1) \
|
||||
+ (PATTY_AX25_FRAME_CONTROL_I(c)? 1 + infolen: 0))
|
||||
|
||||
#define PATTY_AX25_FRAME_S_MASK 0x0f
|
||||
#define PATTY_AX25_FRAME_U_MASK 0xef
|
||||
|
||||
enum patty_ax25_frame_type {
|
||||
PATTY_AX25_FRAME_I = 0x00,
|
||||
PATTY_AX25_FRAME_RR = 0x01,
|
||||
PATTY_AX25_FRAME_RNR = 0x05,
|
||||
PATTY_AX25_FRAME_REJ = 0x09,
|
||||
PATTY_AX25_FRAME_SREJ = 0x0d,
|
||||
PATTY_AX25_FRAME_SABM = 0x2f,
|
||||
PATTY_AX25_FRAME_SABME = 0x6f,
|
||||
PATTY_AX25_FRAME_DISC = 0x43,
|
||||
PATTY_AX25_FRAME_DM = 0x0f,
|
||||
PATTY_AX25_FRAME_UA = 0x63,
|
||||
PATTY_AX25_FRAME_FRMR = 0x87,
|
||||
PATTY_AX25_FRAME_UI = 0x03,
|
||||
PATTY_AX25_FRAME_XID = 0x8f,
|
||||
PATTY_AX25_FRAME_TEST = 0xe3,
|
||||
PATTY_AX25_FRAME_UNKNOWN = 0xff
|
||||
};
|
||||
|
||||
typedef struct _patty_ax25_frame {
|
||||
patty_ax25_addr dest,
|
||||
src,
|
||||
repeaters[7];
|
||||
repeaters[PATTY_AX25_MAX_HOPS];
|
||||
|
||||
unsigned int hops;
|
||||
|
||||
uint16_t control;
|
||||
uint8_t proto;
|
||||
uint8_t nr, ns, pf;
|
||||
enum patty_ax25_frame_type type;
|
||||
|
||||
uint8_t proto;
|
||||
void *info;
|
||||
size_t infolen;
|
||||
} patty_ax25_frame;
|
||||
|
||||
ssize_t patty_ax25_frame_decode_address(patty_ax25_frame *frame,
|
||||
void *buf,
|
||||
size_t len);
|
||||
|
||||
ssize_t patty_ax25_frame_decode_control(patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_format format,
|
||||
void *buf,
|
||||
size_t offset,
|
||||
size_t len);
|
||||
|
||||
ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_format format,
|
||||
void *buf,
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
#ifndef _PATTY_AX25_MACROS_H
|
||||
#define _PATTY_AX25_MACROS_H
|
||||
|
||||
#define PATTY_AX25_ADDRESS_CHAR_VALID(c) \
|
||||
((c >= 0x20 && c <= 0x5a))
|
||||
|
||||
#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_C(c) \
|
||||
((c & 0x80) == 0x80)
|
||||
|
||||
#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_MODIFIER(c) \
|
||||
((c & 0xe0) >> 5)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_SABM(c) \
|
||||
((c & 0xef) == 0x2f)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_DISC(c) \
|
||||
((c & 0xef) == 0x43)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_DM(c) \
|
||||
((c & 0xef) == 0x0f)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_UA(c) \
|
||||
((c & 0xef) == 0x63)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_FRMR(c) \
|
||||
((c & 0xef) == 0x47)
|
||||
|
||||
#define PATTY_AX25_CONTROL_UNNUMBERED_INFO(c) \
|
||||
((c & 0xef) == 0x03)
|
||||
|
||||
#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 */
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef _PATTY_AX25_PROTO_H
|
||||
#define _PATTY_AX25_PROTO_H
|
||||
|
||||
#define PATTY_AX25_MAX_HOPS 8
|
||||
|
||||
enum patty_ax25_version {
|
||||
PATTY_AX25_OLD,
|
||||
PATTY_AX25_2_0
|
||||
};
|
||||
|
||||
enum patty_ax25_proto {
|
||||
PATTY_AX25_PROTO_UNKNOWN = 0x00,
|
||||
PATTY_AX25_PROTO_ISO_8208 = 0x01,
|
||||
PATTY_AX25_PROTO_TCP_VJ_COMPR = 0x06,
|
||||
PATTY_AX25_PROTO_TCP_VJ = 0x07,
|
||||
PATTY_AX25_PROTO_FRAGMENT = 0x08,
|
||||
PATTY_AX25_PROTO_TEXNET = 0xc3,
|
||||
PATTY_AX25_PROTO_LQP = 0xc4,
|
||||
PATTY_AX25_PROTO_APPLETALK = 0xca,
|
||||
PATTY_AX25_PROTO_APPLETALK_ARP = 0xcb,
|
||||
PATTY_AX25_PROTO_INET = 0xcc,
|
||||
PATTY_AX25_PROTO_INET_ARP = 0xcd,
|
||||
PATTY_AX25_PROTO_FLEXNET = 0xce,
|
||||
PATTY_AX25_PROTO_NETROM = 0xcf,
|
||||
PATTY_AX25_PROTO_NONE = 0xf0,
|
||||
PATTY_AX25_PROTO_ESCAPE = 0xff
|
||||
};
|
||||
|
||||
#endif /* _PATTY_AX25_PROTO_H */
|
|
@ -58,17 +58,6 @@ typedef struct _patty_ax25_sock {
|
|||
unsigned int hops;
|
||||
} patty_ax25_sock;
|
||||
|
||||
#define PATTY_AX25_SOCK_CONTROL_SABM(sock, pf) \
|
||||
(((sock->seq_recv & 0x07) << 7) | (pf << 4) | (sock->seq_send & 0x07))
|
||||
|
||||
#define PATTY_AX25_SOCK_CONTROL_SABME(sock, pf) \
|
||||
(((sock->seq_recv & 0x7f) << 15) | (pf << 7) | (sock->seq_send & 0x7f))
|
||||
|
||||
#define PATTY_AX25_SOCK_CONTROL(sock, pf) \
|
||||
(sock->mode == PATTY_AX25_SOCK_SABME? \
|
||||
PATTY_AX25_SOCK_CONTROL_SABME(sock, pf): \
|
||||
PATTY_AX25_SOCK_CONTROL_SABM(sock, pf))
|
||||
|
||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
|
||||
enum patty_ax25_sock_type type);
|
||||
|
||||
|
@ -90,11 +79,19 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
|
|||
void *info,
|
||||
size_t infolen);
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int poll);
|
||||
ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock);
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int poll);
|
||||
ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock);
|
||||
|
||||
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll);
|
||||
ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock);
|
||||
|
||||
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_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_write(patty_ax25_sock *sock,
|
||||
void *buf,
|
||||
|
|
|
@ -7,9 +7,8 @@ CC = $(CROSS)cc
|
|||
CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
|
||||
LDFLAGS =
|
||||
|
||||
HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
|
||||
ax25/call.h ax25/frame.h ax25/sock.h ax25/route.h \
|
||||
ax25/server.h list.h hash.h dict.h print.h
|
||||
HEADERS = kiss.h ax25.h ax25/if.h ax25/call.h ax25/frame.h ax25/sock.h \
|
||||
ax25/route.h ax25/server.h list.h hash.h dict.h print.h
|
||||
|
||||
OBJS = kiss.o ax25.o if.o call.o frame.o sock.o route.o server.o \
|
||||
list.o hash.o dict.o print.o
|
||||
|
|
|
@ -21,7 +21,7 @@ int patty_ax25_pton(const char *callsign,
|
|||
|
||||
end = 1;
|
||||
} else {
|
||||
if (!PATTY_AX25_ADDRESS_CHAR_VALID(callsign[i])) {
|
||||
if (!PATTY_AX25_ADDR_CHAR_VALID(callsign[i])) {
|
||||
errno = EINVAL;
|
||||
|
||||
goto error_invalid_callsign;
|
||||
|
@ -58,7 +58,7 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
|
|||
break;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_ADDRESS_OCTET_LAST(addr->callsign[i])) {
|
||||
if (PATTY_AX25_ADDR_OCTET_LAST(addr->callsign[i])) {
|
||||
errno = EINVAL;
|
||||
|
||||
goto error_invalid_args;
|
||||
|
@ -66,7 +66,7 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
|
|||
|
||||
c = (addr->callsign[i] & 0xfe) >> 1;
|
||||
|
||||
if (!PATTY_AX25_ADDRESS_CHAR_VALID(c)) {
|
||||
if (!PATTY_AX25_ADDR_CHAR_VALID(c)) {
|
||||
errno = EINVAL;
|
||||
|
||||
goto error_invalid_args;
|
||||
|
@ -104,5 +104,5 @@ void patty_ax25_addr_hash(uint32_t *hash, const patty_ax25_addr *addr) {
|
|||
hash_byte(hash, addr->callsign[i] >> 1);
|
||||
}
|
||||
|
||||
hash_byte(hash, PATTY_AX25_ADDRESS_SSID_NUMBER(addr->ssid));
|
||||
hash_byte(hash, PATTY_AX25_ADDR_SSID_NUMBER(addr->ssid));
|
||||
}
|
||||
|
|
292
src/frame.c
292
src/frame.c
|
@ -1,19 +1,27 @@
|
|||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <patty/ax25.h>
|
||||
|
||||
static ssize_t decode_station(patty_ax25_addr *addr,
|
||||
void *data,
|
||||
off_t offset) {
|
||||
size_t offset,
|
||||
size_t len) {
|
||||
int i, space = 0;
|
||||
|
||||
if (len < offset + sizeof(patty_ax25_addr)) {
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i=0; i<PATTY_AX25_CALLSIGN_LEN; i++) {
|
||||
uint8_t b = ((uint8_t *)data + offset)[i];
|
||||
uint8_t c = b >> 1;
|
||||
|
||||
if (!PATTY_AX25_ADDRESS_CHAR_VALID(c) || PATTY_AX25_ADDRESS_OCTET_LAST(b)) {
|
||||
errno = EINVAL;
|
||||
if (!PATTY_AX25_ADDR_CHAR_VALID(c) || PATTY_AX25_ADDR_OCTET_LAST(b)) {
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
@ -21,7 +29,7 @@ static ssize_t decode_station(patty_ax25_addr *addr,
|
|||
if (c == ' ' && !space) {
|
||||
space = 1;
|
||||
} else if (c != ' ' && space) {
|
||||
errno = EINVAL;
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
@ -29,7 +37,7 @@ static ssize_t decode_station(patty_ax25_addr *addr,
|
|||
|
||||
memcpy(addr, ((uint8_t *)data) + offset, sizeof(*addr));
|
||||
|
||||
return PATTY_AX25_ADDRESS_SIZE;
|
||||
return PATTY_AX25_ADDR_SIZE;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
|
@ -37,22 +45,24 @@ error:
|
|||
|
||||
static ssize_t decode_hops(patty_ax25_frame *frame,
|
||||
void *data,
|
||||
off_t start) {
|
||||
ssize_t decoded;
|
||||
off_t offset = start;
|
||||
|
||||
int i;
|
||||
size_t offset,
|
||||
size_t len) {
|
||||
ssize_t start = offset;
|
||||
|
||||
patty_ax25_addr *addr = NULL;
|
||||
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try to count the AX.25-specified maximum number of hops in the current
|
||||
* frame.
|
||||
*/
|
||||
for (i=0; i<PATTY_AX25_MAX_HOPS; i++) {
|
||||
ssize_t decoded;
|
||||
|
||||
addr = (patty_ax25_addr *)((uint8_t *)data + offset);
|
||||
|
||||
if ((decoded = decode_station(&frame->repeaters[i], data, offset)) < 0) {
|
||||
if ((decoded = decode_station(&frame->repeaters[i], data, offset, len)) < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
offset += decoded;
|
||||
|
@ -60,7 +70,7 @@ static ssize_t decode_hops(patty_ax25_frame *frame,
|
|||
|
||||
frame->hops++;
|
||||
|
||||
if (PATTY_AX25_ADDRESS_OCTET_LAST(addr->ssid)) {
|
||||
if (PATTY_AX25_ADDR_OCTET_LAST(addr->ssid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -69,8 +79,8 @@ static ssize_t decode_hops(patty_ax25_frame *frame,
|
|||
* If the last hop does not have the address extension bit set, then
|
||||
* that's a big problem.
|
||||
*/
|
||||
if (addr && !PATTY_AX25_ADDRESS_OCTET_LAST(addr->ssid)) {
|
||||
errno = EINVAL;
|
||||
if (addr && !PATTY_AX25_ADDR_OCTET_LAST(addr->ssid)) {
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
@ -81,19 +91,19 @@ error:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t decode_address(patty_ax25_frame *frame,
|
||||
void *data,
|
||||
off_t start) {
|
||||
off_t offset = start;
|
||||
ssize_t patty_ax25_frame_decode_address(patty_ax25_frame *frame,
|
||||
void *buf,
|
||||
size_t len) {
|
||||
size_t offset = 0;
|
||||
ssize_t decoded;
|
||||
|
||||
if ((decoded = decode_station(&frame->dest, data, offset)) < 0) {
|
||||
if ((decoded = decode_station(&frame->dest, buf, offset, len)) < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
offset += decoded;
|
||||
}
|
||||
|
||||
if ((decoded = decode_station(&frame->src, data, offset)) < 0) {
|
||||
if ((decoded = decode_station(&frame->src, buf, offset, len)) < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
offset += decoded;
|
||||
|
@ -103,101 +113,149 @@ static ssize_t decode_address(patty_ax25_frame *frame,
|
|||
* If the source address is not the final address in the frame, begin
|
||||
* decoding repeater addresses.
|
||||
*/
|
||||
if (!PATTY_AX25_ADDRESS_OCTET_LAST(frame->src.ssid)) {
|
||||
if ((decoded = decode_hops(frame, data, offset)) < 0) {
|
||||
frame->hops = 0;
|
||||
|
||||
if (!PATTY_AX25_ADDR_OCTET_LAST(frame->src.ssid)) {
|
||||
if ((decoded = decode_hops(frame, buf, offset, len)) < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
offset += decoded;
|
||||
}
|
||||
}
|
||||
|
||||
return offset - start;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t decode_info(patty_ax25_frame *frame,
|
||||
void *data,
|
||||
off_t offset,
|
||||
size_t size) {
|
||||
uint8_t control = ((uint8_t *)data + offset)[0];
|
||||
size_t decoded = 0;
|
||||
|
||||
int info = 0;
|
||||
|
||||
if (PATTY_AX25_CONTROL_INFO(control)) {
|
||||
info = 1;
|
||||
} else if (PATTY_AX25_CONTROL_UNNUMBERED(control)) {
|
||||
if (PATTY_AX25_CONTROL_UNNUMBERED_INFO(control)) {
|
||||
info = 1;
|
||||
}
|
||||
} else if (!PATTY_AX25_CONTROL_SUPER(control)) {
|
||||
errno = EINVAL;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
frame->control = control;
|
||||
|
||||
decoded++;
|
||||
|
||||
/*
|
||||
* If we've received either an Info or Unnumbered Info frame, then decode
|
||||
* the Protocol Identifier field, and calculate the location and size of
|
||||
* the payload as well.
|
||||
*/
|
||||
if (info) {
|
||||
decoded++;
|
||||
|
||||
frame->proto = ((uint8_t *)data + offset)[1];
|
||||
frame->info = (void *)((uint8_t *)data + offset + decoded);
|
||||
frame->infolen = size - offset - decoded;
|
||||
|
||||
decoded += frame->infolen;
|
||||
}
|
||||
|
||||
return decoded;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_frame_decode(patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_format format,
|
||||
void *buf,
|
||||
size_t size) {
|
||||
ssize_t decoded;
|
||||
off_t offset = 0;
|
||||
|
||||
memset(frame, '\0', sizeof(*frame));
|
||||
|
||||
/*
|
||||
* First, decode the variable-length Address field.
|
||||
*/
|
||||
if ((decoded = decode_address(frame, buf, offset)) < 0) {
|
||||
errno = EIO;
|
||||
|
||||
goto error_decode;
|
||||
} else {
|
||||
offset += decoded;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, decode the remaining Control Field, optional Protocol Identifier
|
||||
* field, and Info payload that may follow.
|
||||
*/
|
||||
if ((decoded = decode_info(frame, buf, offset, size)) < 0) {
|
||||
errno = EIO;
|
||||
|
||||
goto error_decode;
|
||||
} else {
|
||||
offset += decoded;
|
||||
}
|
||||
|
||||
return offset;
|
||||
|
||||
error_decode:
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline uint8_t decode_nr(uint16_t control,
|
||||
enum patty_ax25_frame_format format) {
|
||||
switch (format) {
|
||||
case PATTY_AX25_FRAME_NORMAL: return (control & 0x00e0) >> 5;
|
||||
case PATTY_AX25_FRAME_EXTENDED: return (control & 0x7e00) >> 9;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t decode_ns(uint16_t control,
|
||||
enum patty_ax25_frame_format format) {
|
||||
switch (format) {
|
||||
case PATTY_AX25_FRAME_NORMAL: return (control & 0x000e) >> 1;
|
||||
case PATTY_AX25_FRAME_EXTENDED: return (control & 0x007e) >> 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t decode_pf(uint16_t control,
|
||||
enum patty_ax25_frame_format format) {
|
||||
switch (format) {
|
||||
case PATTY_AX25_FRAME_NORMAL: return (control & 0x0010) >> 4;
|
||||
case PATTY_AX25_FRAME_EXTENDED: return (control & 0x0100) >> 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_frame_decode_control(patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_format format,
|
||||
void *data,
|
||||
size_t offset,
|
||||
size_t len) {
|
||||
uint8_t *buf = data;
|
||||
size_t start = offset;
|
||||
|
||||
frame->control = 0;
|
||||
frame->nr = 0;
|
||||
frame->ns = 0;
|
||||
frame->pf = 0;
|
||||
frame->type = PATTY_AX25_FRAME_UNKNOWN;
|
||||
frame->proto = PATTY_AX25_PROTO_UNKNOWN;
|
||||
frame->info = NULL;
|
||||
frame->infolen = 0;
|
||||
|
||||
switch (format) {
|
||||
case PATTY_AX25_FRAME_NORMAL:
|
||||
frame->control = (uint16_t)(buf[offset++]);
|
||||
|
||||
break;
|
||||
|
||||
case PATTY_AX25_FRAME_EXTENDED:
|
||||
frame->control = (uint16_t)(buf[offset++] << 8);
|
||||
frame->control |= (uint16_t)(buf[offset++]);
|
||||
|
||||
if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) {
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (PATTY_AX25_FRAME_CONTROL_I(frame->control)) {
|
||||
frame->type = PATTY_AX25_FRAME_I;
|
||||
frame->nr = decode_nr(frame->control, format);
|
||||
frame->ns = decode_ns(frame->control, format);
|
||||
frame->pf = decode_pf(frame->control, format);
|
||||
} else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) {
|
||||
uint16_t c = frame->control & PATTY_AX25_FRAME_S_MASK;
|
||||
|
||||
switch (c) {
|
||||
case PATTY_AX25_FRAME_RR:
|
||||
case PATTY_AX25_FRAME_RNR:
|
||||
case PATTY_AX25_FRAME_REJ:
|
||||
case PATTY_AX25_FRAME_SREJ:
|
||||
frame->type = c;
|
||||
frame->nr = decode_nr(frame->control, format);
|
||||
frame->pf = decode_pf(frame->control, format);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) {
|
||||
uint16_t c = frame->control & PATTY_AX25_FRAME_U_MASK;
|
||||
|
||||
switch (c) {
|
||||
case PATTY_AX25_FRAME_SABME:
|
||||
case PATTY_AX25_FRAME_SABM:
|
||||
case PATTY_AX25_FRAME_DISC:
|
||||
case PATTY_AX25_FRAME_DM:
|
||||
case PATTY_AX25_FRAME_UA:
|
||||
case PATTY_AX25_FRAME_FRMR:
|
||||
case PATTY_AX25_FRAME_UI:
|
||||
case PATTY_AX25_FRAME_XID:
|
||||
case PATTY_AX25_FRAME_TEST:
|
||||
frame->type = c;
|
||||
frame->pf = decode_pf(frame->control, format);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
errno = EIO;
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (frame->type) {
|
||||
case PATTY_AX25_FRAME_I:
|
||||
case PATTY_AX25_FRAME_UI:
|
||||
frame->proto = buf[offset++];
|
||||
frame->info = buf + offset;
|
||||
frame->infolen = len - offset;
|
||||
|
||||
offset = len;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
return offset - start;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -316,7 +374,7 @@ ssize_t patty_ax25_frame_encode(patty_ax25_frame *frame,
|
|||
break;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_CONTROL_INFO(frame->control)) {
|
||||
if (PATTY_AX25_FRAME_CONTROL_I(frame->control) || PATTY_AX25_FRAME_CONTROL_UI(frame->control)) {
|
||||
if (1 + offset + frame->infolen > len) {
|
||||
goto error_toobig;
|
||||
}
|
||||
|
@ -358,7 +416,7 @@ ssize_t patty_ax25_frame_encode_reply_to(patty_ax25_frame *frame,
|
|||
break;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_CONTROL_INFO(reply->control)) {
|
||||
if (PATTY_AX25_FRAME_CONTROL_I(reply->control)) {
|
||||
if (len < 1 + offset + reply->infolen) {
|
||||
goto error_toobig;
|
||||
}
|
||||
|
@ -377,25 +435,17 @@ error_toobig:
|
|||
}
|
||||
|
||||
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)?
|
||||
return PATTY_AX25_ADDR_SSID_C(frame->src.ssid) ==
|
||||
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) {
|
||||
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;
|
||||
return frame->type;
|
||||
}
|
||||
|
||||
enum patty_ax25_frame_cr patty_ax25_frame_cr(patty_ax25_frame *frame) {
|
||||
return PATTY_AX25_ADDRESS_SSID_C(frame->src.ssid)?
|
||||
return PATTY_AX25_ADDR_SSID_C(frame->src.ssid)?
|
||||
PATTY_AX25_FRAME_RESPONSE:
|
||||
PATTY_AX25_FRAME_COMMAND;
|
||||
}
|
||||
|
|
50
src/print.c
50
src/print.c
|
@ -7,6 +7,30 @@
|
|||
#define printable(c) \
|
||||
(c >= 0x20 && c < 0x7f)
|
||||
|
||||
static char *frame_type_name(enum patty_ax25_frame_type type) {
|
||||
switch (type) {
|
||||
case PATTY_AX25_FRAME_I: return "I";
|
||||
case PATTY_AX25_FRAME_RR: return "RR";
|
||||
case PATTY_AX25_FRAME_RNR: return "RNR";
|
||||
case PATTY_AX25_FRAME_REJ: return "REJ";
|
||||
case PATTY_AX25_FRAME_SREJ: return "SREJ";
|
||||
case PATTY_AX25_FRAME_SABM: return "SABM";
|
||||
case PATTY_AX25_FRAME_SABME: return "SABME";
|
||||
case PATTY_AX25_FRAME_DISC: return "DISC";
|
||||
case PATTY_AX25_FRAME_DM: return "DM";
|
||||
case PATTY_AX25_FRAME_UA: return "UA";
|
||||
case PATTY_AX25_FRAME_FRMR: return "FRMR";
|
||||
case PATTY_AX25_FRAME_UI: return "UI";
|
||||
case PATTY_AX25_FRAME_XID: return "XID";
|
||||
case PATTY_AX25_FRAME_TEST: return "TEST";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int patty_print_hexdump(FILE *fh, void *data, size_t len) {
|
||||
size_t i;
|
||||
|
||||
|
@ -103,26 +127,32 @@ int patty_print_frame(FILE *fh,
|
|||
goto error_io;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_CONTROL_INFO(frame->control)) {
|
||||
if (fprintf(fh, " type I poll %d ns %d nr %d info %zu bytes",
|
||||
PATTY_AX25_CONTROL_POLL(frame->control),
|
||||
PATTY_AX25_CONTROL_SEQ_SEND(frame->control),
|
||||
PATTY_AX25_CONTROL_SEQ_RECV(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",
|
||||
frame_type_name(frame->type),
|
||||
(int)frame->nr,
|
||||
(int)frame->ns,
|
||||
(int)frame->pf,
|
||||
frame->infolen) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
} else if (PATTY_AX25_CONTROL_UNNUMBERED(frame->control)) {
|
||||
if (fprintf(fh, " type U") < 0) {
|
||||
} else if (PATTY_AX25_FRAME_CONTROL_U(frame->control)) {
|
||||
if (fprintf(fh, " type U (%s) pf %d",
|
||||
frame_type_name(frame->type),
|
||||
(int)frame->pf) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_CONTROL_UNNUMBERED_INFO(frame->control)) {
|
||||
if (PATTY_AX25_FRAME_CONTROL_UI(frame->control)) {
|
||||
if (fprintf(fh, " info %zu bytes", frame->infolen) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
}
|
||||
} else if (PATTY_AX25_CONTROL_SUPER(frame->control)) {
|
||||
if (fprintf(fh, " type S") < 0) {
|
||||
} else if (PATTY_AX25_FRAME_CONTROL_S(frame->control)) {
|
||||
if (fprintf(fh, " type S (%s) nr %d pf %d",
|
||||
frame_type_name(frame->type),
|
||||
(int)frame->nr,
|
||||
(int)frame->pf) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
}
|
||||
|
|
100
src/server.c
100
src/server.c
|
@ -305,7 +305,7 @@ static int sock_delete_by_addrpair(patty_dict *dict,
|
|||
static int sock_close(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock) {
|
||||
if (sock->status == PATTY_AX25_SOCK_ESTABLISHED) {
|
||||
if (patty_ax25_sock_send_disc(sock, 1) < 0) {
|
||||
if (patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL) < 0) {
|
||||
goto error_sock_send_disc;
|
||||
}
|
||||
|
||||
|
@ -774,7 +774,7 @@ static int server_connect(patty_ax25_server *server,
|
|||
* timeout has been exceeded or the peer has sent a UA frame to
|
||||
* acknowledge and establish the connection.
|
||||
*/
|
||||
if (patty_ax25_sock_send_sabm(sock, 1) < 0) {
|
||||
if (patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL) < 0) {
|
||||
response.ret = -1;
|
||||
response.eno = EIO;
|
||||
|
||||
|
@ -992,8 +992,7 @@ static void save_reply_addr(patty_ax25_sock *sock,
|
|||
|
||||
static int reply_to(patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame,
|
||||
patty_ax25_frame *reply,
|
||||
enum patty_ax25_frame_format format) {
|
||||
patty_ax25_frame *reply) {
|
||||
ssize_t len;
|
||||
|
||||
if ((len = patty_ax25_frame_encode_reply_to(frame,
|
||||
|
@ -1012,22 +1011,22 @@ error_toobig:
|
|||
|
||||
static int reply_dm(patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_flags flags) {
|
||||
int flag) {
|
||||
patty_ax25_frame reply = {
|
||||
.control = PATTY_AX25_FRAME_U_DM | flags,
|
||||
.control = PATTY_AX25_FRAME_DM | (flag << 4),
|
||||
.proto = PATTY_AX25_PROTO_NONE,
|
||||
.info = NULL,
|
||||
.infolen = 0
|
||||
};
|
||||
|
||||
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
|
||||
return reply_to(iface, frame, &reply);
|
||||
}
|
||||
|
||||
static int reply_ua(patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_flags flags) {
|
||||
int flag) {
|
||||
patty_ax25_frame reply = {
|
||||
.control = PATTY_AX25_FRAME_U_UA | flags,
|
||||
.control = PATTY_AX25_FRAME_UA | (flag << 4),
|
||||
.proto = PATTY_AX25_PROTO_NONE,
|
||||
.info = NULL,
|
||||
.infolen = 0
|
||||
|
@ -1038,33 +1037,20 @@ static int reply_ua(patty_ax25_if *iface,
|
|||
|
||||
patty_ax25_ntop(&frame->dest, callsign, &ssid, sizeof(callsign));
|
||||
|
||||
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
|
||||
return reply_to(iface, frame, &reply);
|
||||
}
|
||||
|
||||
static int reply_frmr(patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_flags flags) {
|
||||
int flag) {
|
||||
patty_ax25_frame reply = {
|
||||
.control = PATTY_AX25_FRAME_U_FRMR | flags,
|
||||
.control = PATTY_AX25_FRAME_FRMR | (flag << 4),
|
||||
.proto = PATTY_AX25_PROTO_NONE,
|
||||
.info = NULL,
|
||||
.infolen = 0
|
||||
};
|
||||
|
||||
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
|
||||
}
|
||||
|
||||
static int reply_rej(patty_ax25_if *iface,
|
||||
patty_ax25_frame *frame,
|
||||
enum patty_ax25_frame_flags flags) {
|
||||
patty_ax25_frame reply = {
|
||||
.control = PATTY_AX25_FRAME_U_FRMR | flags,
|
||||
.proto = PATTY_AX25_PROTO_NONE,
|
||||
.info = NULL,
|
||||
.infolen = 0
|
||||
};
|
||||
|
||||
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
|
||||
return reply_to(iface, frame, &reply);
|
||||
}
|
||||
|
||||
static int handle_sabm(patty_ax25_server *server,
|
||||
|
@ -1240,18 +1226,11 @@ error_client_by_sock:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int handle_info(patty_ax25_server *server,
|
||||
static int handle_i(patty_ax25_server *server,
|
||||
patty_ax25_if *iface,
|
||||
patty_ax25_sock *sock,
|
||||
patty_ax25_frame *frame) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = sock_by_addrpair(server->socks_established,
|
||||
&frame->dest,
|
||||
&frame->src)) == NULL) {
|
||||
/*
|
||||
* TODO: Figure out how to respond to a packet sent outside of an
|
||||
* active session
|
||||
*/
|
||||
if (sock == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1266,10 +1245,10 @@ static int handle_info(patty_ax25_server *server,
|
|||
/*
|
||||
* TODO: Validate RX and TX sequence numbers
|
||||
*/
|
||||
if (sock->seq_recv == PATTY_AX25_CONTROL_SEQ_SEND(frame->control)) {
|
||||
if (sock->seq_recv == frame->ns) {
|
||||
patty_ax25_sock_seq_recv_incr(sock);
|
||||
} else {
|
||||
return reply_rej(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||
return patty_ax25_sock_send_rej(sock);
|
||||
}
|
||||
|
||||
return write(sock->fd, frame->info, frame->infolen);
|
||||
|
@ -1301,29 +1280,44 @@ static int handle_frame(patty_ax25_server *server,
|
|||
void *buf,
|
||||
size_t len) {
|
||||
patty_ax25_frame frame;
|
||||
enum patty_ax25_frame_format format = PATTY_AX25_FRAME_NORMAL;
|
||||
|
||||
if (patty_ax25_frame_decode(&frame,
|
||||
PATTY_AX25_FRAME_NORMAL,
|
||||
buf,
|
||||
len) < 0) {
|
||||
ssize_t decoded;
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((decoded = patty_ax25_frame_decode_address(&frame, buf, len)) < 0) {
|
||||
iface->stats.dropped++;
|
||||
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) {
|
||||
return handle_sabm(server, iface, &frame);
|
||||
} else if (PATTY_AX25_CONTROL_UNNUMBERED_UA(frame.control)) {
|
||||
return handle_ua(server, iface, &frame);
|
||||
} else if (PATTY_AX25_CONTROL_UNNUMBERED_DM(frame.control)) {
|
||||
return handle_dm(server, iface, &frame);
|
||||
} else if (PATTY_AX25_CONTROL_INFO(frame.control)) {
|
||||
return handle_info(server, iface, &frame);
|
||||
} else if (PATTY_AX25_CONTROL_UNNUMBERED_DISC(frame.control)) {
|
||||
return handle_disc(server, iface, &frame);
|
||||
if ((sock = sock_by_addrpair(server->socks_established,
|
||||
&frame.dest,
|
||||
&frame.src)) != NULL) {
|
||||
if (sock->mode == PATTY_AX25_SOCK_SABME) {
|
||||
format = PATTY_AX25_FRAME_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (patty_ax25_frame_decode_control(&frame, format, buf, decoded, len) < 0) {
|
||||
iface->stats.dropped++;
|
||||
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
switch (frame.type) {
|
||||
case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame);
|
||||
case PATTY_AX25_FRAME_SABM: return handle_sabm(server, iface, &frame);
|
||||
case PATTY_AX25_FRAME_UA: return handle_ua(server, iface, &frame);
|
||||
case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, &frame);
|
||||
case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, &frame);
|
||||
case PATTY_AX25_FRAME_FRMR: return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return reply_frmr(iface, &frame, PATTY_AX25_FRAME_FINAL);
|
||||
|
||||
error_io:
|
||||
return -1;
|
||||
|
|
93
src/sock.c
93
src/sock.c
|
@ -228,26 +228,93 @@ error_toobig:
|
|||
return -1;
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int poll) {
|
||||
static uint16_t control_i(patty_ax25_sock *sock, int flag) {
|
||||
switch (sock->mode) {
|
||||
case PATTY_AX25_SOCK_SABM:
|
||||
return ((sock->seq_recv & 0x07) << 5)
|
||||
| ((sock->seq_send & 0x07))
|
||||
| (flag << 4);
|
||||
|
||||
case PATTY_AX25_SOCK_SABME:
|
||||
return ((sock->seq_recv & 0x7f) << 9)
|
||||
| ((sock->seq_send & 0x7f))
|
||||
| (flag << 8);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t control_s(patty_ax25_sock *sock,
|
||||
enum patty_ax25_frame_type type,
|
||||
int flag) {
|
||||
switch (sock->mode) {
|
||||
case PATTY_AX25_SOCK_SABM:
|
||||
return ((sock->seq_recv & 0x07) << 5)
|
||||
| (type & 0x0f)
|
||||
| (flag << 4);
|
||||
|
||||
case PATTY_AX25_SOCK_SABME:
|
||||
return ((sock->seq_recv & 0x7f) << 9)
|
||||
| (type & 0x0f)
|
||||
| (flag << 8);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t control_u(enum patty_ax25_frame_type type,
|
||||
int flag) {
|
||||
return (type & PATTY_AX25_FRAME_U_MASK)
|
||||
| (flag << 4);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
PATTY_AX25_FRAME_U_SABM
|
||||
| PATTY_AX25_FRAME_POLL,
|
||||
control_s(sock, PATTY_AX25_FRAME_RR, 1),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int poll) {
|
||||
ssize_t patty_ax25_sock_send_rnr(patty_ax25_sock *sock) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
PATTY_AX25_FRAME_U_SABME
|
||||
| PATTY_AX25_FRAME_POLL,
|
||||
control_s(sock, PATTY_AX25_FRAME_RNR, 1),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll) {
|
||||
ssize_t patty_ax25_sock_send_rej(patty_ax25_sock *sock) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
PATTY_AX25_FRAME_U_DISC
|
||||
| PATTY_AX25_FRAME_POLL,
|
||||
control_s(sock, PATTY_AX25_FRAME_REJ, 1),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_srej(patty_ax25_sock *sock) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
control_s(sock, PATTY_AX25_FRAME_SREJ, 1),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int flag) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
control_u(PATTY_AX25_FRAME_SABM, flag),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int flag) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
control_u(PATTY_AX25_FRAME_SABME, flag),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int flag) {
|
||||
return patty_ax25_sock_send(sock,
|
||||
control_u(PATTY_AX25_FRAME_DISC, flag),
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
@ -255,17 +322,19 @@ ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll) {
|
|||
ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
|
||||
void *buf,
|
||||
size_t len) {
|
||||
uint16_t control = 0x0000;
|
||||
uint16_t control;
|
||||
|
||||
if (sock->type == PATTY_AX25_SOCK_RAW) {
|
||||
return patty_ax25_if_send(sock->iface, buf, len);
|
||||
} else if (sock->mode == PATTY_AX25_SOCK_DM) {
|
||||
}
|
||||
|
||||
if (sock->mode == PATTY_AX25_SOCK_DM) {
|
||||
errno = EBADF;
|
||||
|
||||
goto error_invalid_mode;
|
||||
}
|
||||
|
||||
control = PATTY_AX25_SOCK_CONTROL(sock, 0);
|
||||
control = control_i(sock, 0);
|
||||
|
||||
if (patty_ax25_sock_send(sock, control, buf, len) < 0) {
|
||||
goto error_send;
|
||||
|
|
Loading…
Add table
Reference in a new issue