...I've been busy.
This commit is contained in:
parent
8dd5864e67
commit
4aced9e9c1
18 changed files with 384 additions and 153 deletions
|
@ -43,4 +43,7 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
|
||||||
uint8_t *ssid,
|
uint8_t *ssid,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
|
void patty_ax25_addr_hash(uint32_t *hash,
|
||||||
|
const patty_ax25_addr *addr);
|
||||||
|
|
||||||
#endif /* _PATTY_AX25_H */
|
#endif /* _PATTY_AX25_H */
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#define PATTY_AX25_FRAME_SIZE(hops, mode, infolen) \
|
#define PATTY_AX25_FRAME_SIZE(hops, mode, infolen) \
|
||||||
((sizeof(patty_ax25_addr) * (2 + hops)) \
|
((sizeof(patty_ax25_addr) * (2 + hops)) \
|
||||||
+ (mode == PATTY_SOCK_SABME? 2: 1) \
|
+ (mode == PATTY_AX25_SOCK_SABME? 2: 1) \
|
||||||
+ (infolen > 0? 1 + infolen: 0))
|
+ (infolen > 0? 1 + infolen: 0))
|
||||||
|
|
||||||
enum patty_ax25_frame_type {
|
enum patty_ax25_frame_type {
|
||||||
|
|
|
@ -47,13 +47,13 @@ patty_ax25_if *patty_ax25_if_new(int opts, void *info);
|
||||||
|
|
||||||
void patty_ax25_if_destroy(patty_ax25_if *iface);
|
void patty_ax25_if_destroy(patty_ax25_if *iface);
|
||||||
|
|
||||||
int patty_ax25_if_each_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_each(patty_ax25_if *iface,
|
||||||
int (*callback)(char *, uint8_t, void *), void *ctx);
|
int (*callback)(char *, uint8_t, void *), void *ctx);
|
||||||
|
|
||||||
int patty_ax25_if_add_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_add(patty_ax25_if *iface,
|
||||||
const char *callsign, uint8_t ssid);
|
const char *callsign, uint8_t ssid);
|
||||||
|
|
||||||
int patty_ax25_if_delete_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_delete(patty_ax25_if *iface,
|
||||||
const char *callsign, uint8_t ssid);
|
const char *callsign, uint8_t ssid);
|
||||||
|
|
||||||
ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
|
ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
|
||||||
|
|
|
@ -5,7 +5,29 @@ typedef struct _patty_ax25_route {
|
||||||
patty_ax25_addr dest,
|
patty_ax25_addr dest,
|
||||||
hops[PATTY_AX25_MAX_HOPS];
|
hops[PATTY_AX25_MAX_HOPS];
|
||||||
|
|
||||||
|
size_t nhops;
|
||||||
|
|
||||||
patty_ax25_if *iface;
|
patty_ax25_if *iface;
|
||||||
} patty_ax25_route;
|
} patty_ax25_route;
|
||||||
|
|
||||||
|
typedef struct _patty_dict patty_ax25_route_table;
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface,
|
||||||
|
const char *callsign,
|
||||||
|
uint8_t ssid);
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface);
|
||||||
|
|
||||||
|
int patty_ax25_route_add_hop(patty_ax25_route *route,
|
||||||
|
const char *callsign,
|
||||||
|
uint8_t ssid);
|
||||||
|
|
||||||
|
patty_ax25_route_table *patty_ax25_route_table_new();
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_table_find(patty_ax25_route_table *table,
|
||||||
|
patty_ax25_addr *dest);
|
||||||
|
|
||||||
|
int patty_ax25_route_table_add(patty_ax25_route_table *table,
|
||||||
|
patty_ax25_route *route);
|
||||||
|
|
||||||
#endif /* _PATTY_AX25_ROUTE_H */
|
#endif /* _PATTY_AX25_ROUTE_H */
|
||||||
|
|
|
@ -12,6 +12,8 @@ enum patty_ax25_sock_type {
|
||||||
enum patty_ax25_sock_status {
|
enum patty_ax25_sock_status {
|
||||||
PATTY_AX25_SOCK_CLOSED,
|
PATTY_AX25_SOCK_CLOSED,
|
||||||
PATTY_AX25_SOCK_LISTENING,
|
PATTY_AX25_SOCK_LISTENING,
|
||||||
|
PATTY_AX25_SOCK_PENDING_ACCEPT,
|
||||||
|
PATTY_AX25_SOCK_PENDING_CONNECT,
|
||||||
PATTY_AX25_SOCK_ESTABLISHED
|
PATTY_AX25_SOCK_ESTABLISHED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,4 +53,6 @@ typedef struct _patty_ax25_sock {
|
||||||
|
|
||||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type);
|
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type);
|
||||||
|
|
||||||
|
void patty_ax25_sock_destroy(patty_ax25_sock *sock);
|
||||||
|
|
||||||
#endif /* _PATTY_AX25_SOCK_H */
|
#endif /* _PATTY_AX25_SOCK_H */
|
||||||
|
|
|
@ -38,6 +38,8 @@ int patty_dict_each(patty_dict *dict,
|
||||||
patty_dict_callback callback,
|
patty_dict_callback callback,
|
||||||
void *ctx);
|
void *ctx);
|
||||||
|
|
||||||
|
void *patty_dict_get_with_hash(patty_dict *dict, uint32_t hash);
|
||||||
|
|
||||||
void *patty_dict_get(patty_dict *dict, void *key, size_t keysz);
|
void *patty_dict_get(patty_dict *dict, void *key, size_t keysz);
|
||||||
|
|
||||||
void *patty_dict_set_with_hash(patty_dict *dict,
|
void *patty_dict_set_with_hash(patty_dict *dict,
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define PATTY_DICT_BUCKET_SIZE 16
|
void patty_hash_init(uint32_t *hash);
|
||||||
|
|
||||||
uint32_t patty_hash(void *key, size_t size);
|
void patty_hash_data(uint32_t *hash, void *data, size_t len);
|
||||||
|
|
||||||
|
void patty_hash_end(uint32_t *hash);
|
||||||
|
|
||||||
|
uint32_t patty_hash(void *data, size_t len);
|
||||||
|
|
||||||
#endif /* _PATTY_HASH_H */
|
#endif /* _PATTY_HASH_H */
|
||||||
|
|
|
@ -8,10 +8,10 @@ CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
|
HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
|
||||||
ax25/call.h ax25/frame.h ax25/sock.h ax25/server.h \
|
ax25/call.h ax25/frame.h ax25/sock.h ax25/route.h \
|
||||||
list.h hash.h dict.h
|
ax25/server.h list.h hash.h dict.h
|
||||||
|
|
||||||
OBJS = kiss.o ax25.o if.o call.o frame.o server.o \
|
OBJS = kiss.o ax25.o if.o call.o frame.o sock.o route.o server.o \
|
||||||
list.o hash.o dict.o
|
list.o hash.o dict.o
|
||||||
|
|
||||||
EXAMPLES = decode ptmx testclient testserver
|
EXAMPLES = decode ptmx testclient testserver
|
||||||
|
|
16
src/ax25.c
16
src/ax25.c
|
@ -90,3 +90,19 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
|
||||||
error_invalid_args:
|
error_invalid_args:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (i=0; i<PATTY_AX25_CALLSIGN_LEN; i++) {
|
||||||
|
hash_byte(hash, addr->callsign[i] >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_byte(hash, PATTY_AX25_ADDRESS_SSID_NUMBER(addr->ssid));
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
16
src/dict.c
16
src/dict.c
|
@ -96,11 +96,9 @@ int patty_dict_each(patty_dict *dict, patty_dict_callback callback, void *ctx) {
|
||||||
return bucket_each_slot(0, &dict->bucket, callback, ctx);
|
return bucket_each_slot(0, &dict->bucket, callback, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *patty_dict_get(patty_dict *dict, void *key, size_t keysz) {
|
void *patty_dict_get_with_hash(patty_dict *dict, uint32_t hash) {
|
||||||
patty_dict_slot *slot;
|
patty_dict_slot *slot;
|
||||||
|
|
||||||
uint32_t hash = patty_hash(key, keysz);
|
|
||||||
|
|
||||||
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +106,10 @@ void *patty_dict_get(patty_dict *dict, void *key, size_t keysz) {
|
||||||
return slot->value;
|
return slot->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *patty_dict_get(patty_dict *dict, void *key, size_t keysz) {
|
||||||
|
return patty_dict_get_with_hash(dict, patty_hash(key, keysz));
|
||||||
|
}
|
||||||
|
|
||||||
void *patty_dict_set_with_hash(patty_dict *dict,
|
void *patty_dict_set_with_hash(patty_dict *dict,
|
||||||
void *key,
|
void *key,
|
||||||
size_t keysz,
|
size_t keysz,
|
||||||
|
@ -193,14 +195,6 @@ int patty_dict_delete(patty_dict *dict, void *key, size_t keysz) {
|
||||||
return patty_dict_delete_with_hash(dict, patty_hash(key, keysz));
|
return patty_dict_delete_with_hash(dict, patty_hash(key, keysz));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dict_item_release(void *key, size_t keysz, void *value, void *ctx) {
|
|
||||||
free(value);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void patty_dict_destroy(patty_dict *dict) {
|
void patty_dict_destroy(patty_dict *dict) {
|
||||||
(void)patty_dict_each(dict, dict_item_release, NULL);
|
|
||||||
|
|
||||||
free(dict);
|
free(dict);
|
||||||
}
|
}
|
||||||
|
|
34
src/hash.c
34
src/hash.c
|
@ -3,18 +3,34 @@
|
||||||
|
|
||||||
#include <patty/hash.h>
|
#include <patty/hash.h>
|
||||||
|
|
||||||
uint32_t patty_hash(void *key, size_t size) {
|
void patty_hash_init(uint32_t *hash) {
|
||||||
uint32_t hash = 0xffffffdf, i;
|
*hash = 0xffffffdf;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<size; i++) {
|
void patty_hash_data(uint32_t *hash, void *data, size_t len) {
|
||||||
hash += ((uint8_t *)key)[i];
|
size_t i;
|
||||||
hash += (hash << 10);
|
|
||||||
hash ^= (hash >> 6);
|
for (i=0; i<len; i++) {
|
||||||
|
uint8_t c = ((char *)data)[i];
|
||||||
|
|
||||||
|
*hash += c;
|
||||||
|
*hash += (*hash << 10);
|
||||||
|
*hash ^= (*hash >> 6);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hash += (hash << 3);
|
void patty_hash_end(uint32_t *hash) {
|
||||||
hash ^= (hash >> 11);
|
*hash += (*hash << 3);
|
||||||
hash += (hash << 15);
|
*hash ^= (*hash >> 11);
|
||||||
|
*hash += (*hash << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t patty_hash(void *data, size_t len) {
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
patty_hash_init(&hash);
|
||||||
|
patty_hash_data(&hash, data, len);
|
||||||
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
8
src/if.c
8
src/if.c
|
@ -102,7 +102,7 @@ void patty_ax25_if_destroy(patty_ax25_if *iface) {
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_ax25_if_each_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_each(patty_ax25_if *iface,
|
||||||
int (*callback)(char *, uint8_t, void *), void *ctx) {
|
int (*callback)(char *, uint8_t, void *), void *ctx) {
|
||||||
patty_list_iterator *iter;
|
patty_list_iterator *iter;
|
||||||
patty_ax25_addr *addr;
|
patty_ax25_addr *addr;
|
||||||
|
@ -168,8 +168,6 @@ static patty_ax25_addr *find_addr(patty_ax25_if *iface,
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
patty_list_finish(iter);
|
|
||||||
|
|
||||||
error_ntop:
|
error_ntop:
|
||||||
patty_list_finish(iter);
|
patty_list_finish(iter);
|
||||||
|
|
||||||
|
@ -177,7 +175,7 @@ error_list_start:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_ax25_if_add_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_add(patty_ax25_if *iface,
|
||||||
const char *callsign,
|
const char *callsign,
|
||||||
uint8_t ssid) {
|
uint8_t ssid) {
|
||||||
patty_ax25_addr *addr;
|
patty_ax25_addr *addr;
|
||||||
|
@ -211,7 +209,7 @@ error_exists:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_ax25_if_delete_addr(patty_ax25_if *iface,
|
int patty_ax25_if_addr_delete(patty_ax25_if *iface,
|
||||||
const char *callsign,
|
const char *callsign,
|
||||||
uint8_t ssid) {
|
uint8_t ssid) {
|
||||||
patty_list_item *item = iface->addrs->first;
|
patty_list_item *item = iface->addrs->first;
|
||||||
|
|
99
src/route.c
Normal file
99
src/route.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <patty/hash.h>
|
||||||
|
|
||||||
|
#include <patty/ax25.h>
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_new(patty_ax25_if *iface,
|
||||||
|
const char *callsign,
|
||||||
|
uint8_t ssid) {
|
||||||
|
patty_ax25_route *route;
|
||||||
|
|
||||||
|
if ((route = malloc(sizeof(*route))) == NULL) {
|
||||||
|
goto error_malloc_route;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(route, '\0', sizeof(*route));
|
||||||
|
|
||||||
|
if (callsign) {
|
||||||
|
if (patty_ax25_pton(callsign, ssid, &route->dest) < 0) {
|
||||||
|
goto error_pton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
route->iface = iface;
|
||||||
|
|
||||||
|
return route;
|
||||||
|
|
||||||
|
error_pton:
|
||||||
|
free(route);
|
||||||
|
|
||||||
|
error_malloc_route:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_new_default(patty_ax25_if *iface) {
|
||||||
|
return patty_ax25_route_new(iface, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int patty_ax25_route_add_hop(patty_ax25_route *route,
|
||||||
|
const char *callsign,
|
||||||
|
uint8_t ssid) {
|
||||||
|
if (route->nhops == PATTY_AX25_MAX_HOPS) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
|
||||||
|
goto error_max_hops;
|
||||||
|
}
|
||||||
|
|
||||||
|
return patty_ax25_pton(callsign, ssid, &route->hops[route->nhops++]);
|
||||||
|
|
||||||
|
error_max_hops:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
patty_ax25_route_table *patty_ax25_route_table_new() {
|
||||||
|
return patty_dict_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
patty_ax25_route *patty_ax25_route_table_find(patty_ax25_route_table *table,
|
||||||
|
patty_ax25_addr *dest) {
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
patty_hash_init(&hash);
|
||||||
|
patty_ax25_addr_hash(&hash, dest);
|
||||||
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
|
return patty_dict_get_with_hash(table, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
int patty_ax25_route_table_add(patty_ax25_route_table *table,
|
||||||
|
patty_ax25_route *route) {
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
patty_hash_init(&hash);
|
||||||
|
patty_ax25_addr_hash(&hash, &route->dest);
|
||||||
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
|
if (patty_ax25_route_table_find(table, &route->dest) != NULL) {
|
||||||
|
errno = EEXIST;
|
||||||
|
|
||||||
|
goto error_exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_dict_set_with_hash(table,
|
||||||
|
&route->dest,
|
||||||
|
sizeof(route->dest),
|
||||||
|
route,
|
||||||
|
hash) == NULL) {
|
||||||
|
goto error_dict_set_with_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_dict_set_with_hash:
|
||||||
|
error_exists:
|
||||||
|
return -1;
|
||||||
|
}
|
247
src/server.c
247
src/server.c
|
@ -27,6 +27,7 @@ struct _patty_ax25_server {
|
||||||
fds_w; /* fds select()ed for writing */
|
fds_w; /* fds select()ed for writing */
|
||||||
|
|
||||||
patty_list *ifaces;
|
patty_list *ifaces;
|
||||||
|
patty_dict *routes;
|
||||||
|
|
||||||
patty_dict *socks_by_fd,
|
patty_dict *socks_by_fd,
|
||||||
*socks_pending_accept,
|
*socks_pending_accept,
|
||||||
|
@ -107,47 +108,9 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sock_init(patty_ax25_sock *sock, enum patty_ax25_sock_type type) {
|
|
||||||
memset(sock, '\0', sizeof(*sock));
|
|
||||||
|
|
||||||
sock->status = PATTY_AX25_SOCK_CLOSED;
|
|
||||||
sock->mode = PATTY_AX25_SOCK_DM;
|
|
||||||
sock->type = type;
|
|
||||||
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
|
|
||||||
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hash_init(uint32_t *hash) {
|
|
||||||
*hash = 0xffffffdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hash_byte(uint32_t *hash, uint8_t c) {
|
|
||||||
*hash += c;
|
|
||||||
*hash += (*hash << 10);
|
|
||||||
*hash ^= (*hash >> 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hash_addr(uint32_t *hash, patty_ax25_addr *addr) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<PATTY_AX25_CALLSIGN_LEN; i++) {
|
|
||||||
hash_byte(hash, addr->callsign[i] >> 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_byte(hash, PATTY_AX25_ADDRESS_SSID_NUMBER(addr->ssid));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hash_end(uint32_t *hash) {
|
|
||||||
*hash += (*hash << 3);
|
|
||||||
*hash ^= (*hash >> 11);
|
|
||||||
*hash += (*hash << 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
static patty_ax25_sock *sock_by_fd(patty_dict *dict,
|
static patty_ax25_sock *sock_by_fd(patty_dict *dict,
|
||||||
int fd) {
|
int fd) {
|
||||||
return patty_dict_get(dict,
|
return patty_dict_get_with_hash(dict, (uint32_t)fd);
|
||||||
NULL + fd,
|
|
||||||
sizeof(fd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static patty_ax25_sock *sock_by_addr(patty_dict *dict,
|
static patty_ax25_sock *sock_by_addr(patty_dict *dict,
|
||||||
|
@ -156,9 +119,9 @@ static patty_ax25_sock *sock_by_addr(patty_dict *dict,
|
||||||
|
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
hash_init(&hash);
|
patty_hash_init(&hash);
|
||||||
hash_addr(&hash, addr);
|
patty_ax25_addr_hash(&hash, addr);
|
||||||
hash_end(&hash);
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
|
@ -179,10 +142,10 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
|
||||||
|
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
hash_init(&hash);
|
patty_hash_init(&hash);
|
||||||
hash_addr(&hash, local);
|
patty_ax25_addr_hash(&hash, local);
|
||||||
hash_addr(&hash, remote);
|
patty_ax25_addr_hash(&hash, remote);
|
||||||
hash_end(&hash);
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
|
@ -197,10 +160,11 @@ error_dict_slot_find:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
||||||
if (patty_dict_set(dict,
|
if (patty_dict_set_with_hash(dict,
|
||||||
NULL + sock->fd,
|
NULL + sock->fd,
|
||||||
sizeof(sock->fd),
|
sizeof(sock->fd),
|
||||||
sock) == NULL) {
|
sock,
|
||||||
|
(uint32_t)sock->fd) == NULL) {
|
||||||
goto error_dict_set;
|
goto error_dict_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,9 +179,9 @@ static int sock_save_by_addr(patty_dict *dict,
|
||||||
patty_ax25_addr *addr) {
|
patty_ax25_addr *addr) {
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
hash_init(&hash);
|
patty_hash_init(&hash);
|
||||||
hash_addr(&hash, addr);
|
patty_ax25_addr_hash(&hash, addr);
|
||||||
hash_end(&hash);
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
if (patty_dict_set_with_hash(dict,
|
if (patty_dict_set_with_hash(dict,
|
||||||
addr,
|
addr,
|
||||||
|
@ -239,10 +203,10 @@ static int sock_save_by_addrpair(patty_dict *dict,
|
||||||
patty_ax25_addr *remote) {
|
patty_ax25_addr *remote) {
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
hash_init(&hash);
|
patty_hash_init(&hash);
|
||||||
hash_addr(&hash, local);
|
patty_ax25_addr_hash(&hash, local);
|
||||||
hash_addr(&hash, remote);
|
patty_ax25_addr_hash(&hash, remote);
|
||||||
hash_end(&hash);
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
if (patty_dict_set_with_hash(dict,
|
if (patty_dict_set_with_hash(dict,
|
||||||
sock,
|
sock,
|
||||||
|
@ -260,32 +224,44 @@ error_dict_set_with_hash:
|
||||||
|
|
||||||
static int sock_delete(patty_ax25_server *server,
|
static int sock_delete(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock) {
|
patty_ax25_sock *sock) {
|
||||||
uint32_t hash_established,
|
if (sock->status == PATTY_AX25_SOCK_ESTABLISHED) {
|
||||||
hash_pending_connect,
|
uint32_t hash;
|
||||||
hash_pending_accept;
|
|
||||||
|
|
||||||
hash_init(&hash_established);
|
patty_hash_init(&hash);
|
||||||
hash_addr(&hash_established, &sock->local);
|
patty_ax25_addr_hash(&hash, &sock->local);
|
||||||
hash_addr(&hash_established, &sock->remote);
|
patty_ax25_addr_hash(&hash, &sock->remote);
|
||||||
hash_end(&hash_established);
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
if (patty_dict_delete_with_hash(server->socks_established, hash_established) < 0) {
|
if (patty_dict_delete_with_hash(server->socks_established, hash) < 0) {
|
||||||
goto error_dict_delete_established;
|
goto error_dict_delete_established;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_init(&hash_pending_connect);
|
|
||||||
hash_addr(&hash_pending_connect, &sock->local);
|
|
||||||
hash_end(&hash_pending_connect);
|
|
||||||
|
|
||||||
if (patty_dict_delete_with_hash(server->socks_pending_connect, hash_pending_connect) < 0) {
|
|
||||||
goto error_dict_delete_pending_connect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_init(&hash_pending_accept);
|
if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) {
|
||||||
hash_addr(&hash_pending_accept, &sock->local);
|
uint32_t hash;
|
||||||
hash_end(&hash_pending_accept);
|
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_by_fd, NULL + sock->fd, sizeof(sock->fd)) < 0) {
|
patty_hash_init(&hash);
|
||||||
|
patty_ax25_addr_hash(&hash, &sock->local);
|
||||||
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
|
if (patty_dict_delete_with_hash(server->socks_pending_connect, hash) < 0) {
|
||||||
|
goto error_dict_delete_pending_connect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock->status == PATTY_AX25_SOCK_PENDING_ACCEPT) {
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
patty_hash_init(&hash);
|
||||||
|
patty_ax25_addr_hash(&hash, &sock->local);
|
||||||
|
patty_hash_end(&hash);
|
||||||
|
|
||||||
|
if (patty_dict_delete_with_hash(server->socks_pending_accept, hash) < 0) {
|
||||||
|
goto error_dict_delete_pending_accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_dict_delete_with_hash(server->socks_by_fd, sock->fd) < 0) {
|
||||||
goto error_dict_delete_by_fd;
|
goto error_dict_delete_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,21 +270,58 @@ static int sock_delete(patty_ax25_server *server,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_dict_delete_by_fd:
|
error_dict_delete_by_fd:
|
||||||
|
error_dict_delete_pending_accept:
|
||||||
error_dict_delete_pending_connect:
|
error_dict_delete_pending_connect:
|
||||||
error_dict_delete_established:
|
error_dict_delete_established:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void watch_fd(patty_ax25_server *server, int fd) {
|
||||||
|
FD_SET(fd, &server->fds_watch);
|
||||||
|
|
||||||
|
if (server->fd_max <= fd) {
|
||||||
|
server->fd_max = fd + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_fd(patty_ax25_server *server, int fd) {
|
||||||
|
FD_CLR(fd, &server->fds_watch);
|
||||||
|
|
||||||
|
if (server->fd_max == fd + 1) {
|
||||||
|
server->fd_max--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void watch_sock(patty_ax25_server *server, patty_ax25_sock *sock) {
|
||||||
|
watch_fd(server, sock->fd);
|
||||||
|
|
||||||
|
FD_SET(sock->fd, &server->fds_socks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_sock(patty_ax25_server *server, patty_ax25_sock *sock) {
|
||||||
|
clear_fd(server, sock->fd);
|
||||||
|
|
||||||
|
FD_CLR(sock->fd, &server->fds_socks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void watch_client(patty_ax25_server *server, int fd) {
|
||||||
|
watch_fd(server, fd);
|
||||||
|
|
||||||
|
FD_SET(fd, &server->fds_clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_client(patty_ax25_server *server, int fd) {
|
||||||
|
clear_fd(server, fd);
|
||||||
|
|
||||||
|
FD_CLR(fd, &server->fds_clients);
|
||||||
|
}
|
||||||
|
|
||||||
int patty_ax25_server_add_if(patty_ax25_server *server,
|
int patty_ax25_server_add_if(patty_ax25_server *server,
|
||||||
patty_ax25_if *iface) {
|
patty_ax25_if *iface) {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||||
FD_SET(fd, &server->fds_watch);
|
watch_fd(server, fd);
|
||||||
|
|
||||||
if (server->fd_max < fd + 1) {
|
|
||||||
server->fd_max = fd + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patty_list_append(server->ifaces, iface) == NULL) {
|
if (patty_list_append(server->ifaces, iface) == NULL) {
|
||||||
|
@ -341,11 +354,7 @@ int patty_ax25_server_delete_if(patty_ax25_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||||
FD_CLR(fd, &server->fds_watch);
|
watch_fd(server, fd);
|
||||||
|
|
||||||
if (server->fd_max == fd) {
|
|
||||||
server->fd_max--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_by_fd, NULL + fd, sizeof(fd)) < 0) {
|
if (patty_dict_delete(server->socks_by_fd, NULL + fd, sizeof(fd)) < 0) {
|
||||||
goto error_dict_delete;
|
goto error_dict_delete;
|
||||||
|
@ -416,18 +425,16 @@ static int server_socket(patty_ax25_server *server,
|
||||||
|
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
|
|
||||||
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
if (read(client, &request, sizeof(request)) < 0) {
|
||||||
goto error_malloc_sock;
|
goto error_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock_init(sock, request.type);
|
if ((sock = patty_ax25_sock_new(request.type)) == NULL) {
|
||||||
|
goto error_sock_new;
|
||||||
|
}
|
||||||
|
|
||||||
if ((sock->fd = open("/dev/null", O_RDWR)) < 0) {
|
if ((sock->fd = open("/dev/null", O_RDWR)) < 0) {
|
||||||
goto error_io;
|
goto error_open;
|
||||||
}
|
|
||||||
|
|
||||||
if (read(client, &request, sizeof(request)) < 0) {
|
|
||||||
goto error_io;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.ret = sock->fd;
|
response.ret = sock->fd;
|
||||||
|
@ -442,15 +449,19 @@ static int server_socket(patty_ax25_server *server,
|
||||||
|
|
||||||
error_sock_save_by_fd:
|
error_sock_save_by_fd:
|
||||||
if (write(client, &response, sizeof(response)) < 0) {
|
if (write(client, &response, sizeof(response)) < 0) {
|
||||||
goto error_io;
|
goto error_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_io:
|
error_write:
|
||||||
free(sock);
|
close(sock->fd);
|
||||||
|
|
||||||
error_malloc_sock:
|
error_open:
|
||||||
|
patty_ax25_sock_destroy(sock);
|
||||||
|
|
||||||
|
error_sock_new:
|
||||||
|
error_read:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,12 +651,10 @@ static int server_accept(patty_ax25_server *server,
|
||||||
goto error_sock_by_fd;
|
goto error_sock_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((remote = malloc(sizeof(*remote))) == NULL) {
|
if ((remote = patty_ax25_sock_new(local->type)) == NULL) {
|
||||||
goto error_malloc_remote;
|
goto error_sock_new_remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock_init(remote, local->type);
|
|
||||||
|
|
||||||
memcpy(&remote->local, &local->local, sizeof(remote->local));
|
memcpy(&remote->local, &local->local, sizeof(remote->local));
|
||||||
|
|
||||||
if (local->type & PATTY_AX25_SOCK_PTY) {
|
if (local->type & PATTY_AX25_SOCK_PTY) {
|
||||||
|
@ -658,6 +667,8 @@ static int server_accept(patty_ax25_server *server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remote->status = PATTY_AX25_SOCK_PENDING_ACCEPT;
|
||||||
|
|
||||||
if (sock_save_by_addr(server->socks_pending_accept,
|
if (sock_save_by_addr(server->socks_pending_accept,
|
||||||
remote,
|
remote,
|
||||||
&local->local) < 0) {
|
&local->local) < 0) {
|
||||||
|
@ -681,9 +692,9 @@ error_save_by_fd:
|
||||||
error_save_by_addr:
|
error_save_by_addr:
|
||||||
error_server_accept_unix:
|
error_server_accept_unix:
|
||||||
error_server_accept_pty:
|
error_server_accept_pty:
|
||||||
free(remote);
|
patty_ax25_sock_destroy(remote);
|
||||||
|
|
||||||
error_malloc_remote:
|
error_sock_new_remote:
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -729,6 +740,8 @@ static int server_connect(patty_ax25_server *server,
|
||||||
|
|
||||||
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
|
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
|
||||||
|
|
||||||
|
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
|
||||||
|
|
||||||
if (sock_save_by_addrpair(server->socks_pending_connect,
|
if (sock_save_by_addrpair(server->socks_pending_connect,
|
||||||
sock,
|
sock,
|
||||||
&sock->local,
|
&sock->local,
|
||||||
|
@ -848,7 +861,7 @@ static int listen_unix(patty_ax25_server *server, const char *path) {
|
||||||
goto error_listen;
|
goto error_listen;
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_SET(server->fd, &server->fds_watch);
|
watch_fd(server, server->fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -864,7 +877,9 @@ error_listening:
|
||||||
static int accept_client(patty_ax25_server *server) {
|
static int accept_client(patty_ax25_server *server) {
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr addr;
|
struct sockaddr addr;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
memset(&addr, '\0', addrlen);
|
||||||
|
|
||||||
if (!FD_ISSET(server->fd, &server->fds_r)) {
|
if (!FD_ISSET(server->fd, &server->fds_r)) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -874,14 +889,15 @@ static int accept_client(patty_ax25_server *server) {
|
||||||
goto error_accept;
|
goto error_accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patty_dict_set(server->clients,
|
if (patty_dict_set_with_hash(server->clients,
|
||||||
NULL + fd,
|
NULL + fd,
|
||||||
sizeof(fd),
|
sizeof(fd),
|
||||||
NULL + fd) == NULL) {
|
NULL + fd,
|
||||||
|
(uint32_t)fd) == NULL) {
|
||||||
goto error_dict_set;
|
goto error_dict_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_SET(fd, &server->fds_clients);
|
watch_client(server, fd);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -907,15 +923,13 @@ static int handle_client(void *key,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((readlen = read(server->fd, &call, sizeof(call))) < 0) {
|
if ((readlen = read(client, &call, sizeof(call))) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (readlen == 0) {
|
} else if (readlen == 0) {
|
||||||
FD_CLR(client, &server->fds_watch);
|
clear_client(server, client);
|
||||||
FD_CLR(client, &server->fds_clients);
|
|
||||||
|
|
||||||
if (patty_dict_delete(server->clients,
|
if (patty_dict_delete_with_hash(server->clients,
|
||||||
key,
|
(uint32_t)(key - NULL)) < 0) {
|
||||||
keysz) < 0) {
|
|
||||||
goto error_dict_delete;
|
goto error_dict_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,6 +968,9 @@ static int handle_packet_rx(patty_ax25_server *server,
|
||||||
goto error_io;
|
goto error_io;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) {
|
||||||
|
fprintf(stderr, "Got SABM packet\n");
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* TODO: Handle inbound packet
|
* TODO: Handle inbound packet
|
||||||
*/
|
*/
|
||||||
|
@ -977,7 +994,7 @@ static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
|
||||||
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (readlen == 0) {
|
} else if (readlen == 0) {
|
||||||
FD_CLR(fd, &server->fds_watch);
|
clear_fd(server, fd);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1055,7 @@ static int handle_sock(void *key,
|
||||||
if ((len = read(fd, iface->tx_buf, iface->tx_bufsz)) < 0) {
|
if ((len = read(fd, iface->tx_buf, iface->tx_bufsz)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
FD_CLR(fd, &server->fds_watch);
|
clear_sock(server, sock);
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_established,
|
if (patty_dict_delete(server->socks_established,
|
||||||
NULL + fd,
|
NULL + fd,
|
||||||
|
|
29
src/sock.c
Normal file
29
src/sock.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <patty/ax25.h>
|
||||||
|
|
||||||
|
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type) {
|
||||||
|
patty_ax25_sock *sock;
|
||||||
|
|
||||||
|
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
||||||
|
goto error_malloc_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(sock, '\0', sizeof(*sock));
|
||||||
|
|
||||||
|
sock->status = PATTY_AX25_SOCK_CLOSED;
|
||||||
|
sock->mode = PATTY_AX25_SOCK_DM;
|
||||||
|
sock->type = type;
|
||||||
|
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
|
||||||
|
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
|
||||||
|
error_malloc_sock:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
|
||||||
|
free(sock);
|
||||||
|
}
|
|
@ -29,7 +29,8 @@ static void usage(int argc, char **argv, const char *message, ...) {
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
int fd;
|
int fd,
|
||||||
|
sock;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
usage(argc, argv, "No patty socket provided");
|
usage(argc, argv, "No patty socket provided");
|
||||||
|
@ -50,10 +51,30 @@ int main(int argc, char **argv) {
|
||||||
goto error_connect;
|
goto error_connect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_SOCK_PTY)) < 0) {
|
||||||
|
fprintf(stderr, "%s: %s: %s\n",
|
||||||
|
argv[0], "patty_ax25_call_socket()", strerror(errno));
|
||||||
|
|
||||||
|
goto error_call_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_ax25_call_close(fd, sock) < 0) {
|
||||||
|
fprintf(stderr, "%s: %s: %s\n",
|
||||||
|
argv[0], "patty_ax25_call_close()", strerror(errno));
|
||||||
|
|
||||||
|
goto error_call_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "got sock %d\n", sock);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_call_close:
|
||||||
|
error_call_socket:
|
||||||
|
close(fd);
|
||||||
|
|
||||||
error_connect:
|
error_connect:
|
||||||
error_socket:
|
error_socket:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -38,6 +38,10 @@ int main(int argc, char **argv) {
|
||||||
goto error_if_new;
|
goto error_if_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (patty_ax25_if_addr_add(iface, "KZ3ROX", 0) < 0) {
|
||||||
|
goto error_if_addr_add;
|
||||||
|
}
|
||||||
|
|
||||||
if (patty_ax25_server_add_if(server, iface) < 0) {
|
if (patty_ax25_server_add_if(server, iface) < 0) {
|
||||||
goto error_server_add_if;
|
goto error_server_add_if;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +59,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
error_server_run:
|
error_server_run:
|
||||||
error_server_add_if:
|
error_server_add_if:
|
||||||
|
error_if_addr_add:
|
||||||
error_if_new:
|
error_if_new:
|
||||||
patty_ax25_server_destroy(server);
|
patty_ax25_server_destroy(server);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue