2020-09-17 22:00:00 -05:00
|
|
|
#include <stdio.h>
|
2015-07-20 23:21:45 -05:00
|
|
|
#include <stdlib.h>
|
2015-07-20 22:33:59 -05:00
|
|
|
#include <string.h>
|
2015-07-20 23:21:45 -05:00
|
|
|
#include <errno.h>
|
2015-08-09 09:50:12 -05:00
|
|
|
#include <sys/select.h>
|
2015-07-20 22:33:59 -05:00
|
|
|
|
|
|
|
#include <patty/ax25.h>
|
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
enum addr_state {
|
|
|
|
ADDR_CALLSIGN,
|
|
|
|
ADDR_SSID
|
|
|
|
};
|
|
|
|
|
2020-06-07 02:46:12 -04:00
|
|
|
int patty_ax25_pton(const char *callsign,
|
|
|
|
patty_ax25_addr *addr) {
|
2020-09-17 20:55:57 -05:00
|
|
|
size_t len = strlen(callsign);
|
2020-08-22 13:31:04 -05:00
|
|
|
|
2020-06-07 02:46:12 -04:00
|
|
|
int i,
|
2020-08-22 13:31:04 -05:00
|
|
|
o = 0,
|
|
|
|
digits = 0;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
int ssid = 0;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-09-17 21:58:56 -05:00
|
|
|
enum addr_state state = ADDR_CALLSIGN;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
if (len == 0) {
|
|
|
|
goto error_invalid_callsign;
|
2020-09-17 20:55:57 -05:00
|
|
|
} else if (len > PATTY_AX25_ADDRSTRLEN) {
|
|
|
|
len = PATTY_AX25_ADDRSTRLEN;
|
2020-08-22 13:31:04 -05:00
|
|
|
}
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
for (i=0; i<len; i++) {
|
|
|
|
uint8_t c = callsign[i];
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case ADDR_CALLSIGN:
|
2020-09-18 14:33:16 -05:00
|
|
|
if (o > PATTY_AX25_CALLSTRLEN) {
|
2020-08-22 13:31:04 -05:00
|
|
|
goto error_invalid_callsign;
|
|
|
|
}
|
|
|
|
|
2020-09-18 13:47:16 -05:00
|
|
|
if (c == '-') {
|
2020-08-22 13:31:04 -05:00
|
|
|
state = ADDR_SSID;
|
2020-09-18 13:47:16 -05:00
|
|
|
} else if (PATTY_AX25_ADDR_CHAR_VALID(c)) {
|
|
|
|
addr->callsign[o++] = (c & 0x7f) << 1;
|
2020-08-22 13:31:04 -05:00
|
|
|
} else {
|
|
|
|
goto error_invalid_callsign;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ADDR_SSID:
|
2020-09-17 21:58:56 -05:00
|
|
|
if (digits == 2) {
|
2020-08-22 13:31:04 -05:00
|
|
|
goto error_invalid_callsign;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c >= '0' && c <= '9') {
|
|
|
|
ssid *= 10;
|
|
|
|
ssid += c - '0';
|
|
|
|
|
|
|
|
digits++;
|
|
|
|
} else {
|
|
|
|
goto error_invalid_callsign;
|
|
|
|
}
|
2020-06-07 02:46:12 -04:00
|
|
|
}
|
2020-08-22 13:31:04 -05:00
|
|
|
}
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-09-18 14:33:16 -05:00
|
|
|
while (o < PATTY_AX25_CALLSTRLEN) {
|
2020-09-17 20:33:53 -05:00
|
|
|
addr->callsign[o++] = ' ' << 1;
|
2020-06-07 02:46:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
addr->ssid = (ssid & 0x0f) << 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_invalid_callsign:
|
2020-08-22 13:31:04 -05:00
|
|
|
errno = EINVAL;
|
|
|
|
|
2020-06-07 02:46:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_ax25_ntop(const patty_ax25_addr *addr,
|
|
|
|
char *dest,
|
|
|
|
size_t len) {
|
2020-08-22 13:31:04 -05:00
|
|
|
int i,
|
|
|
|
o = 0;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
int ssid = (addr->ssid & 0x1e) >> 1;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-09-18 14:33:16 -05:00
|
|
|
for (i=0; i<PATTY_AX25_CALLSTRLEN; i++) {
|
2020-06-07 02:46:12 -04:00
|
|
|
uint8_t c;
|
|
|
|
|
|
|
|
if (o == len) {
|
2020-08-22 13:31:04 -05:00
|
|
|
goto error_overflow;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = (addr->callsign[i] & 0xfe) >> 1;
|
|
|
|
|
|
|
|
if (c == ' ') {
|
2020-06-07 02:46:12 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-08-22 13:31:04 -05:00
|
|
|
dest[o++] = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ssid) {
|
2020-09-17 22:00:00 -05:00
|
|
|
int formatted;
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-09-17 22:00:00 -05:00
|
|
|
if ((formatted = snprintf(&dest[o], 1 + len - o, "-%d", ssid)) < 0) {
|
|
|
|
goto error_format_ssid;
|
|
|
|
} else {
|
|
|
|
o += formatted;
|
2020-06-07 02:46:12 -04:00
|
|
|
}
|
2020-08-22 13:31:04 -05:00
|
|
|
}
|
2020-06-07 02:46:12 -04:00
|
|
|
|
2020-09-17 22:00:00 -05:00
|
|
|
if (o > len) {
|
2020-08-22 13:31:04 -05:00
|
|
|
goto error_overflow;
|
2020-06-07 02:46:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
dest[o] = '\0';
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2020-09-17 22:00:00 -05:00
|
|
|
error_format_ssid:
|
2020-08-22 13:31:04 -05:00
|
|
|
error_overflow:
|
|
|
|
errno = EOVERFLOW;
|
|
|
|
|
2020-06-07 02:46:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2020-06-25 20:37:12 -04:00
|
|
|
|
|
|
|
static inline void hash_byte(uint32_t *hash, uint8_t c) {
|
|
|
|
*hash += c;
|
|
|
|
*hash += (*hash << 10);
|
|
|
|
*hash ^= (*hash >> 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
void patty_ax25_addr_hash(uint32_t *hash, const patty_ax25_addr *addr) {
|
|
|
|
size_t i;
|
|
|
|
|
2020-09-18 14:33:16 -05:00
|
|
|
for (i=0; i<PATTY_AX25_CALLSTRLEN; i++) {
|
2020-06-25 20:37:12 -04:00
|
|
|
hash_byte(hash, addr->callsign[i] >> 1);
|
|
|
|
}
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
hash_byte(hash, PATTY_AX25_ADDR_SSID_NUMBER(addr->ssid));
|
2020-06-25 20:37:12 -04:00
|
|
|
}
|
2020-07-14 17:02:17 -04:00
|
|
|
|
|
|
|
size_t patty_ax25_addr_copy(void *buf,
|
|
|
|
patty_ax25_addr *addr,
|
|
|
|
uint8_t ssid_flags) {
|
|
|
|
size_t encoded = 0;
|
|
|
|
|
|
|
|
memcpy(buf, addr->callsign, sizeof(addr->callsign));
|
|
|
|
|
|
|
|
encoded += sizeof(addr->callsign);
|
|
|
|
|
|
|
|
((uint8_t *)buf)[encoded++] = ssid_flags | 0x60 | (addr->ssid & 0x1e);
|
|
|
|
|
|
|
|
return encoded;
|
|
|
|
}
|