sockaddr: decode AX.25 socket addresses
* defs.h (print_ax25_addr): New prototype. * print_fields.h (PRINT_FIELD_AX25_ADDR): New macro. * sockaddr.c: Include <linux/ax25.h>. (check_ax25_address, ax25_addr2str, print_ax25_addr_raw, print_ax25_addr, print_sockaddr_data_ax25): New functions. (sa_printers) <[AF_AX25]>: New printer. * tests/net-sockaddr.c (AX25_ADDR): New macro. (check_ax25): New function. (main): Use it to check AX.25 socket address decoding.
This commit is contained in:
parent
cbbf708b4d
commit
92d020787f
1
defs.h
1
defs.h
@ -891,6 +891,7 @@ print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name
|
||||
extern bool
|
||||
decode_inet_addr(struct tcb *, kernel_ulong_t addr,
|
||||
unsigned int len, int family, const char *var_name);
|
||||
extern void print_ax25_addr(const void /* ax25_address */ *addr);
|
||||
extern const char *get_sockaddr_by_inode(struct tcb *, int fd, unsigned long inode);
|
||||
extern bool print_sockaddr_by_inode(struct tcb *, int fd, unsigned long inode);
|
||||
extern void print_dirfd(struct tcb *, int);
|
||||
|
@ -183,6 +183,12 @@
|
||||
STRACE_PRINTF("%s%s=inet_addr(\"%s\")", (prefix_), #field_, \
|
||||
inet_ntoa((where_).field_))
|
||||
|
||||
#define PRINT_FIELD_AX25_ADDR(prefix_, where_, field_) \
|
||||
do { \
|
||||
STRACE_PRINTF("%s%s=", (prefix_), #field_); \
|
||||
print_ax25_addr(&(where_).field_); \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_FIELD_NET_PORT(prefix_, where_, field_) \
|
||||
STRACE_PRINTF("%s%s=htons(%u)", (prefix_), #field_, \
|
||||
ntohs((where_).field_))
|
||||
|
160
sockaddr.c
160
sockaddr.c
@ -39,6 +39,7 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "netlink.h"
|
||||
#include <linux/ax25.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
@ -189,6 +190,164 @@ print_sockaddr_data_in6(const void *const buf, const int addrlen)
|
||||
PRINT_FIELD_U(", ", *sa_in6, sin6_scope_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we can print an AX.25 address in its native form, otherwise it
|
||||
* makes sense to print it in raw also (or in raw only).
|
||||
*/
|
||||
enum xlat_style
|
||||
check_ax25_address(const ax25_address *addr)
|
||||
{
|
||||
enum xlat_style ret = XLAT_STYLE_DEFAULT;
|
||||
bool space_seen = false;
|
||||
bool char_seen = false;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(addr->ax25_call) - 1; i++) {
|
||||
unsigned char c = addr->ax25_call[i];
|
||||
|
||||
/* The lowest bit should be zero */
|
||||
if (c & 1)
|
||||
ret = XLAT_STYLE_VERBOSE;
|
||||
|
||||
c >>= 1;
|
||||
|
||||
if (c == ' ')
|
||||
space_seen = true;
|
||||
else
|
||||
char_seen = true;
|
||||
|
||||
/* Sane address contains only numbers and uppercase letters */
|
||||
if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && c != ' ')
|
||||
ret = XLAT_STYLE_VERBOSE;
|
||||
if (c != ' ' && space_seen)
|
||||
ret = XLAT_STYLE_VERBOSE;
|
||||
|
||||
/* non-printable chars */
|
||||
if (c < ' ' || c > 0x7e
|
||||
/* characters used for printing comments */
|
||||
|| c == '*' || c == '/')
|
||||
return XLAT_STYLE_RAW;
|
||||
}
|
||||
|
||||
if (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1] & ~0x1e)
|
||||
ret = XLAT_STYLE_VERBOSE;
|
||||
|
||||
if (!char_seen && addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1])
|
||||
ret = XLAT_STYLE_VERBOSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Convert a (presumably) valid AX.25 to a string */
|
||||
static const char *
|
||||
ax25_addr2str(const ax25_address *addr)
|
||||
{
|
||||
static char buf[ARRAY_SIZE(addr->ax25_call) + sizeof("-15")];
|
||||
char *p = buf;
|
||||
size_t end;
|
||||
|
||||
for (end = ARRAY_SIZE(addr->ax25_call) - 1; end; end--)
|
||||
if ((addr->ax25_call[end - 1] >> 1) != ' ')
|
||||
break;
|
||||
|
||||
for (size_t i = 0; i < end; i++)
|
||||
*p++ = ((unsigned char) addr->ax25_call[i]) >> 1;
|
||||
|
||||
*p++ = '-';
|
||||
|
||||
unsigned char ssid = (addr->ax25_call[ARRAY_SIZE(addr->ax25_call) - 1]
|
||||
>> 1) & 0xf;
|
||||
|
||||
if (ssid > 9) {
|
||||
*p++ = '1';
|
||||
ssid -= 10;
|
||||
}
|
||||
|
||||
*p++ = ssid + '0';
|
||||
*p = '\0';
|
||||
|
||||
if (buf[0] == '-' && buf[1] == '0')
|
||||
return "*";
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
print_ax25_addr_raw(const ax25_address *addr)
|
||||
{
|
||||
PRINT_FIELD_HEX_ARRAY("{", *addr, ax25_call);
|
||||
tprints("}");
|
||||
}
|
||||
|
||||
void
|
||||
print_ax25_addr(const void /* ax25_address */ *addr_void)
|
||||
{
|
||||
const ax25_address *addr = addr_void;
|
||||
enum xlat_style xs = check_ax25_address(addr);
|
||||
|
||||
if (xs == XLAT_STYLE_DEFAULT)
|
||||
xs = xlat_verbose(xlat_verbosity);
|
||||
|
||||
if (xs != XLAT_STYLE_ABBREV)
|
||||
print_ax25_addr_raw(addr);
|
||||
|
||||
if (xs == XLAT_STYLE_RAW)
|
||||
return;
|
||||
|
||||
const char *addr_str = ax25_addr2str(addr);
|
||||
|
||||
(xs == XLAT_STYLE_VERBOSE ? tprints_comment : tprints)(addr_str);
|
||||
}
|
||||
|
||||
static void
|
||||
print_sockaddr_data_ax25(const void *const buf, const int addrlen)
|
||||
{
|
||||
const struct full_sockaddr_ax25 *const sax25 = buf;
|
||||
size_t addrlen_us = MAX(addrlen, 0);
|
||||
bool full = sax25->fsa_ax25.sax25_ndigis ||
|
||||
(addrlen_us > sizeof(struct sockaddr_ax25));
|
||||
|
||||
if (full)
|
||||
tprints("fsa_ax25={");
|
||||
|
||||
tprints("sax25_call=");
|
||||
print_ax25_addr(&sax25->fsa_ax25.sax25_call);
|
||||
PRINT_FIELD_D(", ", sax25->fsa_ax25, sax25_ndigis);
|
||||
|
||||
if (!full)
|
||||
return;
|
||||
|
||||
tprints("}");
|
||||
|
||||
size_t has_digis = MIN((addrlen_us - sizeof(sax25->fsa_ax25))
|
||||
/ sizeof(sax25->fsa_digipeater[0]),
|
||||
ARRAY_SIZE(sax25->fsa_digipeater));
|
||||
size_t want_digis = MIN(
|
||||
(unsigned int) MAX(sax25->fsa_ax25.sax25_ndigis, 0),
|
||||
ARRAY_SIZE(sax25->fsa_digipeater));
|
||||
size_t digis = MIN(has_digis, want_digis);
|
||||
|
||||
if (want_digis == 0)
|
||||
goto digis_end;
|
||||
|
||||
tprints(", fsa_digipeater=[");
|
||||
for (size_t i = 0; i < digis; i++) {
|
||||
if (i)
|
||||
tprints(", ");
|
||||
|
||||
print_ax25_addr(sax25->fsa_digipeater + i);
|
||||
}
|
||||
|
||||
if (want_digis > has_digis)
|
||||
tprintf("%s/* ??? */", digis ? ", " : "");
|
||||
|
||||
tprints("]");
|
||||
|
||||
digis_end:
|
||||
if (addrlen_us > (has_digis * sizeof(sax25->fsa_digipeater[0])
|
||||
+ sizeof(sax25->fsa_ax25)))
|
||||
tprints(", ...");
|
||||
}
|
||||
|
||||
static void
|
||||
print_sockaddr_data_ipx(const void *const buf, const int addrlen)
|
||||
{
|
||||
@ -426,6 +585,7 @@ static const struct {
|
||||
} sa_printers[] = {
|
||||
[AF_UNIX] = { print_sockaddr_data_un, SIZEOF_SA_FAMILY + 1 },
|
||||
[AF_INET] = { print_sockaddr_data_in, sizeof(struct sockaddr_in) },
|
||||
[AF_AX25] = { print_sockaddr_data_ax25, sizeof(struct sockaddr_ax25) },
|
||||
[AF_IPX] = { print_sockaddr_data_ipx, sizeof(struct sockaddr_ipx) },
|
||||
[AF_INET6] = { print_sockaddr_data_in6, SIN6_MIN_LEN },
|
||||
[AF_NETLINK] = { print_sockaddr_data_nl, SIZEOF_SA_FAMILY + 1 },
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include "netlink.h"
|
||||
#include <linux/ax25.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
@ -289,6 +290,149 @@ check_ipx(void)
|
||||
c_ipx.sipx_type, len, ret);
|
||||
}
|
||||
|
||||
/* for a bit more compact AX.25 address definitions */
|
||||
#define AX25_ADDR(c_, s_) \
|
||||
{ { (c_)[0] << 1, (c_)[1] << 1, (c_)[2] << 1, \
|
||||
(c_)[3] << 1, (c_)[4] << 1, (c_)[5] << 1, (s_) << 1 } } \
|
||||
/* End of AX25_ADDR definition */
|
||||
|
||||
static void
|
||||
check_ax25(void)
|
||||
{
|
||||
const struct full_sockaddr_ax25 ax25 = {
|
||||
.fsa_ax25 = {
|
||||
.sax25_family = AF_AX25,
|
||||
.sax25_call = AX25_ADDR("VALID ", 13),
|
||||
.sax25_ndigis = 8,
|
||||
},
|
||||
.fsa_digipeater = {
|
||||
AX25_ADDR("SPA CE", 0),
|
||||
AX25_ADDR("SSID ", 16),
|
||||
AX25_ADDR(" ", 0),
|
||||
AX25_ADDR("NULL\0", 3),
|
||||
AX25_ADDR("A-B-C", 4),
|
||||
AX25_ADDR(",}]\"\\'", 5),
|
||||
AX25_ADDR("DASH-0", 6),
|
||||
AX25_ADDR("\n\tABCD", 7),
|
||||
},
|
||||
};
|
||||
const ax25_address aux_addrs[] = {
|
||||
AX25_ADDR("VALID2", 7),
|
||||
AX25_ADDR("OK ", 15),
|
||||
AX25_ADDR("FINE ", 2),
|
||||
AX25_ADDR("smalls", 9),
|
||||
};
|
||||
|
||||
enum { AX25_ALIGN = ALIGNOF(struct full_sockaddr_ax25), };
|
||||
size_t size = sizeof(ax25);
|
||||
size_t surplus = ROUNDUP(sizeof(ax25_address), AX25_ALIGN);
|
||||
void *sax_void = midtail_alloc(size, surplus);
|
||||
struct full_sockaddr_ax25 *sax = sax_void;
|
||||
long rc;
|
||||
|
||||
fill_memory(sax, size);
|
||||
sax->fsa_ax25.sax25_family = AF_AX25;
|
||||
rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1);
|
||||
printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205"
|
||||
"\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n",
|
||||
sizeof(struct sockaddr_ax25) - 1, sprintrc(rc));
|
||||
|
||||
memcpy(sax, &ax25, sizeof(ax25));
|
||||
rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25));
|
||||
printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13"
|
||||
", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n",
|
||||
sizeof(struct sockaddr_ax25), sprintrc(rc));
|
||||
|
||||
sax->fsa_ax25.sax25_ndigis = 0;
|
||||
rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25));
|
||||
printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13"
|
||||
", sax25_ndigis=0}, %zu) = %s\n",
|
||||
sizeof(struct sockaddr_ax25), sprintrc(rc));
|
||||
|
||||
sax->fsa_ax25.sax25_ndigis = 8;
|
||||
size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1;
|
||||
rc = connect(-1, sax_void, size);
|
||||
printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13"
|
||||
", sax25_ndigis=8}, fsa_digipeater"
|
||||
"=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\""
|
||||
"} /* SPA CE-0 */"
|
||||
", {ax25_call=\"\\xa6\\xa6\\x92\\x88\\x40\\x40\\x20\""
|
||||
"} /* SSID-0 */"
|
||||
", *"
|
||||
", /* ??? */], ...}, %zu) = %s\n",
|
||||
size, sprintrc(rc));
|
||||
|
||||
sax->fsa_digipeater[2].ax25_call[6] = 0x4;
|
||||
size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4;
|
||||
rc = connect(-1, sax_void, size);
|
||||
printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13"
|
||||
", sax25_ndigis=8}, fsa_digipeater"
|
||||
"=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\""
|
||||
"} /* SPA CE-0 */"
|
||||
", {ax25_call=\"\\xa6\\xa6\\x92\\x88\\x40\\x40\\x20\""
|
||||
"} /* SSID-0 */"
|
||||
", {ax25_call=\"\\x40\\x40\\x40\\x40\\x40\\x40\\x04\"} /* -2 */"
|
||||
", {ax25_call=\"\\x9c\\xaa\\x98\\x98\\x00\\x00\\x06\"}"
|
||||
", /* ??? */]}, %zu) = %s\n",
|
||||
size, sprintrc(rc));
|
||||
|
||||
memcpy(sax->fsa_digipeater, aux_addrs, sizeof(aux_addrs));
|
||||
sax->fsa_digipeater[2].ax25_call[6] = 0xa5;
|
||||
sax->fsa_digipeater[4].ax25_call[5] = 0x40;
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
size = sizeof(ax25) + sizeof(ax25_address) * (i / 2);
|
||||
rc = connect(-1, sax_void, size);
|
||||
printf("connect(-1, {sa_family=AF_AX25"
|
||||
", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}"
|
||||
", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */"
|
||||
", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\""
|
||||
"} /* smalls-9 */"
|
||||
", {ax25_call=\"\\x%s\\x%s\\x84\\x5a\\x86\\x40\\x08\""
|
||||
"} /* %sB-C-4 */"
|
||||
", {ax25_call=\"\\x58\\xfa\\xba\\x44\\x%s\\x%s\\x0a\""
|
||||
"}%s"
|
||||
", {ax25_call=\"\\x88\\x82\\xa6\\x90\\x5a\\x%s\\x0c\""
|
||||
"}%s"
|
||||
"%s]%s}, %zu) = %s\n"
|
||||
, sax->fsa_ax25.sax25_ndigis
|
||||
, i
|
||||
? "{ax25_call=\"\\x8c\\x92\\x9c\\x8a\\x40\\x41\\x04\"}"
|
||||
: "{ax25_call=\"\\x8c\\x92\\x9c\\x8a\\x40\\x40\\xa5\"}"
|
||||
, i ? "40" : "82"
|
||||
, i ? "40" : "5a"
|
||||
, i ? " " : "A-"
|
||||
, i ? "54" : "b8"
|
||||
, i ? "5e" : "4e"
|
||||
, i ? "" : " /* ,}]\"\\'-5 */"
|
||||
, i ? "fe" : "60"
|
||||
, i ? "" : " /* DASH-0-6 */"
|
||||
, i == 1
|
||||
? ""
|
||||
: ", {ax25_call=\"\\x14\\x12\\x82\\x84\\x86\\x88\\x0e\"}"
|
||||
, i > 1 ? ", ..." : ""
|
||||
, size, sprintrc(rc));
|
||||
|
||||
if (i == 1) {
|
||||
sax_void = (char *) sax_void - surplus;
|
||||
memmove(sax_void, sax, sizeof(ax25));
|
||||
sax = sax_void;
|
||||
}
|
||||
|
||||
sax->fsa_ax25.sax25_ndigis = 7 + 2 * i;
|
||||
|
||||
sax->fsa_digipeater[2].ax25_call[5] = 0x41;
|
||||
sax->fsa_digipeater[2].ax25_call[6] = 0x4;
|
||||
|
||||
sax->fsa_digipeater[4].ax25_call[0] = 0x40;
|
||||
sax->fsa_digipeater[4].ax25_call[1] = 0x40;
|
||||
|
||||
sax->fsa_digipeater[5].ax25_call[4] = '*' << 1;
|
||||
sax->fsa_digipeater[5].ax25_call[5] = '/' << 1;
|
||||
|
||||
sax->fsa_digipeater[6].ax25_call[5] = 0xfe;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_nl(void)
|
||||
{
|
||||
@ -554,6 +698,7 @@ main(void)
|
||||
check_in();
|
||||
check_in6();
|
||||
check_ipx();
|
||||
check_ax25();
|
||||
check_nl();
|
||||
check_ll();
|
||||
#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
|
||||
|
Loading…
Reference in New Issue
Block a user