patty/src/if.c

281 lines
5.8 KiB
C
Raw Normal View History

2015-07-25 00:26:23 -05:00
#include <stdio.h>
2015-07-24 21:49:57 -05:00
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <patty/ax25.h>
static int init_tnc(patty_ax25_if *iface, const char *device) {
static char *prefix = "kiss";
static int number = 0;
2015-07-24 21:49:57 -05:00
if ((iface->tnc = patty_kiss_tnc_open(device)) == NULL) {
2015-07-24 21:49:57 -05:00
goto error_kiss_tnc_open;
}
2020-06-07 02:46:12 -04:00
iface->type = PATTY_AX25_IF_KISS_TNC;
2015-07-24 21:49:57 -05:00
2015-07-25 00:26:23 -05:00
snprintf(iface->name, sizeof(iface->name), "%s%d", prefix, number++);
return 0;
2015-07-24 21:49:57 -05:00
error_kiss_tnc_open:
return -1;
2015-07-24 21:49:57 -05:00
}
static void close_tnc(patty_ax25_if *iface) {
2015-07-24 21:49:57 -05:00
patty_kiss_tnc_close(iface->tnc);
}
2020-06-24 23:56:31 -04:00
patty_ax25_if *patty_ax25_if_new(int opts, void *info) {
2015-07-24 21:49:57 -05:00
patty_ax25_if *iface;
if ((iface = malloc(sizeof(*iface))) == NULL) {
goto error_malloc_iface;
}
memset(iface, '\0', sizeof(*iface));
if ((iface->rx_buf = malloc(PATTY_AX25_IF_BUFSZ)) == NULL) {
goto error_malloc_rx_buf;
} else {
iface->rx_bufsz = PATTY_AX25_IF_BUFSZ;
}
if ((iface->tx_buf = malloc(PATTY_AX25_IF_BUFSZ)) == NULL) {
goto error_malloc_tx_buf;
} else {
iface->tx_bufsz = PATTY_AX25_IF_BUFSZ;
}
if ((iface->addrs = patty_list_new()) == NULL) {
goto error_list_new;
}
2015-07-24 21:49:57 -05:00
switch (PATTY_AX25_IF_OPT_TYPE(opts)) {
case PATTY_AX25_IF_KISS_TNC:
if (init_tnc(iface, (const char *)info) < 0) {
goto error_init;
}
2015-07-24 21:49:57 -05:00
break;
default:
2015-07-24 21:49:57 -05:00
errno = EINVAL;
goto error_invalid_if_type;
2015-07-24 21:49:57 -05:00
}
return iface;
2015-07-24 21:49:57 -05:00
error_invalid_if_type:
error_init:
patty_list_destroy(iface->addrs);
2015-07-24 21:49:57 -05:00
error_list_new:
free(iface->tx_buf);
error_malloc_tx_buf:
free(iface->rx_buf);
error_malloc_rx_buf:
free(iface);
2015-07-24 21:49:57 -05:00
error_malloc_iface:
2015-07-24 21:49:57 -05:00
return NULL;
}
void patty_ax25_if_destroy(patty_ax25_if *iface) {
switch (iface->type) {
case PATTY_AX25_IF_KISS_TNC:
close_tnc(iface);
break;
2015-07-24 21:49:57 -05:00
default:
break;
2015-07-24 21:49:57 -05:00
}
patty_list_destroy(iface->addrs);
free(iface->tx_buf);
free(iface->rx_buf);
free(iface);
2015-07-24 21:49:57 -05:00
}
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
int patty_ax25_if_each_addr(patty_ax25_if *iface,
int (*callback)(char *, uint8_t, void *), void *ctx) {
2015-07-25 00:26:23 -05:00
patty_list_iterator *iter;
2020-06-07 02:46:12 -04:00
patty_ax25_addr *addr;
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
if ((iter = patty_list_start(iface->addrs)) == NULL) {
2015-07-25 00:26:23 -05:00
goto error_list_start;
}
2020-06-07 02:46:12 -04:00
while ((addr = patty_list_next(iter)) != NULL) {
char buf[7];
uint8_t ssid;
if (patty_ax25_ntop(addr, buf, &ssid, sizeof(buf)) < 0) {
goto error_ntop;
}
if (callback(buf, ssid, ctx) < 0) {
2015-07-25 00:26:23 -05:00
goto error_callback;
}
}
patty_list_finish(iter);
return 0;
error_callback:
2020-06-07 02:46:12 -04:00
error_ntop:
2015-07-25 00:26:23 -05:00
patty_list_finish(iter);
error_list_start:
return -1;
}
2020-06-07 02:46:12 -04:00
static patty_ax25_addr *find_addr(patty_ax25_if *iface,
const char *callsign,
uint8_t ssid) {
2015-07-25 00:26:23 -05:00
patty_list_iterator *iter;
2020-06-07 02:46:12 -04:00
patty_ax25_addr *addr;
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
if ((iter = patty_list_start(iface->addrs)) == NULL) {
2015-07-25 00:26:23 -05:00
goto error_list_start;
}
2020-06-07 02:46:12 -04:00
while ((addr = patty_list_next(iter)) != NULL) {
char buf[7];
uint8_t addr_ssid;
if (patty_ax25_ntop(addr, buf, &addr_ssid, sizeof(buf)) < 0) {
goto error_ntop;
}
if (strncmp(buf, callsign, sizeof(buf)) != 0) {
2015-07-25 00:26:23 -05:00
continue;
}
2020-06-07 02:46:12 -04:00
if (addr_ssid != ssid) {
2015-07-25 00:26:23 -05:00
continue;
}
patty_list_finish(iter);
2020-06-07 02:46:12 -04:00
return addr;
2015-07-25 00:26:23 -05:00
}
patty_list_finish(iter);
2020-06-07 02:46:12 -04:00
error_ntop:
patty_list_finish(iter);
2015-07-25 00:26:23 -05:00
error_list_start:
return NULL;
}
2020-06-07 02:46:12 -04:00
int patty_ax25_if_add_addr(patty_ax25_if *iface,
const char *callsign,
uint8_t ssid) {
patty_ax25_addr *addr;
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
if (find_addr(iface, callsign, ssid) != NULL) {
2015-07-25 00:26:23 -05:00
errno = EEXIST;
goto error_exists;
}
2020-06-07 02:46:12 -04:00
if ((addr = malloc(sizeof(*addr))) == NULL) {
goto error_malloc_addr;
2015-07-25 00:26:23 -05:00
}
2020-06-07 02:46:12 -04:00
if (patty_ax25_pton(callsign, ssid, addr) < 0) {
goto error_pton;
}
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
if ((patty_list_append(iface->addrs, addr)) == NULL) {
2015-07-25 00:26:23 -05:00
goto error_list_append;
}
return 0;
error_list_append:
2020-06-07 02:46:12 -04:00
error_pton:
free(addr);
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
error_malloc_addr:
2015-07-25 00:26:23 -05:00
error_exists:
return -1;
}
2020-06-07 02:46:12 -04:00
int patty_ax25_if_delete_addr(patty_ax25_if *iface,
const char *callsign,
uint8_t ssid) {
patty_list_item *item = iface->addrs->first;
2015-07-25 00:26:23 -05:00
int i = 0;
while (item) {
2020-06-07 02:46:12 -04:00
char buf[7];
uint8_t addr_ssid;
patty_ax25_addr *addr = item->value;
if (patty_ax25_ntop(addr, buf, &addr_ssid, sizeof(buf)) < 0) {
goto error_ntop;
}
2015-07-25 00:26:23 -05:00
2020-06-07 02:46:12 -04:00
if (strncmp(buf, callsign, sizeof(buf)) == 0 && addr_ssid == ssid) {
if (patty_list_splice(iface->addrs, i) == NULL) {
2015-07-25 00:26:23 -05:00
goto error_list_splice;
}
}
item = item->next;
i++;
}
return 0;
error_list_splice:
2020-06-07 02:46:12 -04:00
error_ntop:
2015-07-25 00:26:23 -05:00
return -1;
}
ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
void **buf) {
ssize_t readlen;
int port;
if ((readlen = patty_kiss_tnc_recv(iface->tnc,
iface->rx_buf,
iface->rx_bufsz,
&port)) < 0) {
goto error_kiss_tnc_recv;
}
*buf = iface->rx_buf;
return readlen;
error_kiss_tnc_recv:
return -1;
}
ssize_t patty_ax25_if_send(patty_ax25_if *iface,
const void *buf,
size_t len) {
ssize_t wrlen;
if ((wrlen = patty_kiss_tnc_send(iface->tnc, buf, len, 0)) < 0) {
goto error_kiss_tnc_send;
}
return wrlen;
error_kiss_tnc_send:
return -1;
}