2020-06-16 18:48:29 -04:00
|
|
|
#define _GNU_SOURCE
|
2020-06-16 01:59:47 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
2020-06-25 01:04:04 -04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2020-06-16 01:59:47 -04:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <patty/ax25.h>
|
2020-07-08 17:12:40 -04:00
|
|
|
#include <patty/hash.h>
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
typedef int (*patty_ax25_server_call)(patty_ax25_server *, int);
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
struct _patty_ax25_server {
|
2020-06-26 22:44:19 -04:00
|
|
|
char path[PATTY_AX25_SOCK_PATH_SIZE];
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
int fd, /* fd of UNIX domain socket */
|
|
|
|
fd_max;
|
|
|
|
|
|
|
|
struct timeval timeout;
|
|
|
|
|
2020-07-03 00:13:09 -04:00
|
|
|
fd_set fds_watch, /* fds to monitor with select() */
|
2020-07-06 23:58:25 -04:00
|
|
|
fds_r; /* fds select()ed for reading */
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
patty_list *ifaces;
|
2020-06-25 22:20:39 -04:00
|
|
|
patty_ax25_route_table *routes;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
patty_dict *socks_by_fd,
|
2020-07-22 22:02:26 -04:00
|
|
|
*socks_by_client,
|
|
|
|
*socks_local,
|
|
|
|
*socks_remote;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
patty_dict *clients,
|
|
|
|
*clients_by_sock;
|
2020-06-16 18:48:29 -04:00
|
|
|
};
|
|
|
|
|
2020-06-26 22:44:19 -04:00
|
|
|
patty_ax25_server *patty_ax25_server_new(const char *path) {
|
2020-06-24 23:56:31 -04:00
|
|
|
patty_ax25_server *server;
|
|
|
|
|
|
|
|
if ((server = malloc(sizeof(*server))) == NULL) {
|
|
|
|
goto error_malloc_server;
|
|
|
|
}
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
memset(server, '\0', sizeof(*server));
|
|
|
|
|
2020-06-26 22:44:19 -04:00
|
|
|
strncpy(server->path, path, PATTY_AX25_SOCK_PATH_SIZE);
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
if ((server->ifaces = patty_list_new()) == NULL) {
|
|
|
|
goto error_list_new_ifaces;
|
|
|
|
}
|
|
|
|
|
2020-06-25 22:20:39 -04:00
|
|
|
if ((server->routes = patty_ax25_route_table_new()) == NULL) {
|
|
|
|
goto error_route_table_new;
|
|
|
|
}
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
if ((server->socks_by_fd = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_socks_by_fd;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((server->socks_by_client = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_socks_by_client;
|
2020-06-18 18:25:11 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((server->socks_local = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_socks_local;
|
2020-06-18 18:25:11 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((server->socks_remote = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_socks_remote;
|
2020-06-16 18:48:29 -04:00
|
|
|
}
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
if ((server->clients = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_clients;
|
|
|
|
}
|
|
|
|
|
2020-06-20 03:01:52 -04:00
|
|
|
if ((server->clients_by_sock = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new_clients_by_sock;
|
|
|
|
}
|
|
|
|
|
2020-06-24 23:56:31 -04:00
|
|
|
return server;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-20 03:01:52 -04:00
|
|
|
error_dict_new_clients_by_sock:
|
2020-06-20 19:37:03 -04:00
|
|
|
patty_dict_destroy(server->clients);
|
|
|
|
|
|
|
|
error_dict_new_clients:
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_dict_destroy(server->socks_remote);
|
2020-06-20 03:01:52 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_new_socks_remote:
|
|
|
|
patty_dict_destroy(server->socks_local);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_new_socks_local:
|
|
|
|
patty_dict_destroy(server->socks_by_client);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_new_socks_by_client:
|
2020-06-18 18:25:11 -04:00
|
|
|
patty_dict_destroy(server->socks_by_fd);
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
error_dict_new_socks_by_fd:
|
2020-06-25 22:20:39 -04:00
|
|
|
patty_ax25_route_table_destroy(server->routes);
|
|
|
|
|
|
|
|
error_route_table_new:
|
2020-06-16 01:59:47 -04:00
|
|
|
patty_list_destroy(server->ifaces);
|
|
|
|
|
|
|
|
error_list_new_ifaces:
|
2020-06-24 23:56:31 -04:00
|
|
|
free(server);
|
|
|
|
|
|
|
|
error_malloc_server:
|
|
|
|
return NULL;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int destroy_if(patty_ax25_if *iface, void *ctx) {
|
|
|
|
patty_ax25_if_destroy(iface);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int destroy_socks_by_client_entry(uint32_t key, void *value, void *ctx) {
|
|
|
|
patty_dict_destroy((patty_dict *)value);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-01 20:34:14 -04:00
|
|
|
void patty_ax25_server_destroy(patty_ax25_server *server) {
|
|
|
|
patty_dict_destroy(server->clients_by_sock);
|
|
|
|
patty_dict_destroy(server->clients);
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_dict_destroy(server->socks_remote);
|
|
|
|
patty_dict_destroy(server->socks_local);
|
|
|
|
patty_dict_each(server->socks_by_client, destroy_socks_by_client_entry, NULL);
|
|
|
|
patty_dict_destroy(server->socks_by_client);
|
2020-07-01 20:34:14 -04:00
|
|
|
patty_dict_destroy(server->socks_by_fd);
|
|
|
|
|
|
|
|
patty_ax25_server_each_if(server, destroy_if, NULL);
|
|
|
|
patty_ax25_route_table_destroy(server->routes);
|
|
|
|
patty_list_destroy(server->ifaces);
|
|
|
|
|
|
|
|
free(server);
|
|
|
|
}
|
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
static inline void fd_watch(patty_ax25_server *server, int fd) {
|
2020-07-01 20:15:46 -04:00
|
|
|
FD_SET(fd, &server->fds_watch);
|
|
|
|
|
|
|
|
if (server->fd_max <= fd) {
|
|
|
|
server->fd_max = fd + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
static inline void fd_clear(patty_ax25_server *server, int fd) {
|
2020-07-01 20:15:46 -04:00
|
|
|
int i;
|
|
|
|
|
|
|
|
FD_CLR(fd, &server->fds_watch);
|
|
|
|
|
2020-07-21 17:44:18 -04:00
|
|
|
if (server->fd_max == fd + 1) {
|
|
|
|
for (i=0; i<8*sizeof(&server->fds_watch); i++) {
|
|
|
|
if (FD_ISSET(i, &server->fds_watch)) {
|
|
|
|
server->fd_max = i;
|
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
}
|
|
|
|
|
2020-07-21 17:44:18 -04:00
|
|
|
server->fd_max++;
|
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
}
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
static patty_ax25_sock *sock_by_fd(patty_dict *dict,
|
|
|
|
int fd) {
|
2020-07-08 17:12:40 -04:00
|
|
|
return patty_dict_get(dict, (uint32_t)fd);
|
2020-06-18 18:25:11 -04:00
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
static patty_ax25_sock *sock_by_addr(patty_dict *dict,
|
|
|
|
patty_ax25_addr *addr) {
|
|
|
|
uint32_t hash;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
patty_hash_init(&hash);
|
|
|
|
patty_ax25_addr_hash(&hash, addr);
|
|
|
|
patty_hash_end(&hash);
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
return patty_dict_get(dict, hash);
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
|
|
|
|
patty_ax25_addr *local,
|
|
|
|
patty_ax25_addr *remote) {
|
2020-06-18 19:59:26 -04:00
|
|
|
uint32_t hash;
|
2020-07-03 19:03:24 -04:00
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
patty_hash_init(&hash);
|
|
|
|
patty_ax25_addr_hash(&hash, local);
|
|
|
|
patty_ax25_addr_hash(&hash, remote);
|
|
|
|
patty_hash_end(&hash);
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
return patty_dict_get(dict, hash);
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
2020-07-22 22:02:26 -04:00
|
|
|
if (patty_dict_set(dict, (uint32_t)sock->fd, sock) == NULL) {
|
2020-06-18 18:25:11 -04:00
|
|
|
goto error_dict_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sock->fd;
|
|
|
|
|
|
|
|
error_dict_set:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
static inline int client_by_sock(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
void *value;
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
if ((value = patty_dict_get(server->clients_by_sock,
|
|
|
|
(uint32_t)sock->fd)) == NULL) {
|
|
|
|
goto error_dict_get;
|
2020-07-03 19:13:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return (int)((int64_t)value);
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
error_dict_get:
|
2020-07-03 19:13:34 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int client_save_by_sock(patty_ax25_server *server,
|
|
|
|
int client,
|
|
|
|
patty_ax25_sock *sock) {
|
2020-07-08 17:12:40 -04:00
|
|
|
if (patty_dict_set(server->clients_by_sock,
|
|
|
|
(uint32_t)sock->fd,
|
|
|
|
NULL + client) == NULL) {
|
|
|
|
goto error_dict_set;
|
2020-07-03 19:13:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
error_dict_set:
|
2020-07-03 19:13:34 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int client_delete_by_sock(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_delete(server->clients_by_sock,
|
|
|
|
(uint32_t)sock->fd);
|
2020-07-03 19:13:34 -04:00
|
|
|
}
|
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
static inline uint32_t hash_addr(patty_ax25_addr *addr) {
|
2020-06-18 18:25:11 -04:00
|
|
|
uint32_t hash;
|
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
patty_hash_init(&hash);
|
|
|
|
patty_ax25_addr_hash(&hash, addr);
|
|
|
|
patty_hash_end(&hash);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32_t hash_addrpair(patty_ax25_addr *local,
|
|
|
|
patty_ax25_addr *remote) {
|
|
|
|
uint32_t hash;
|
|
|
|
|
|
|
|
patty_hash_init(&hash);
|
|
|
|
patty_ax25_addr_hash(&hash, local);
|
|
|
|
patty_ax25_addr_hash(&hash, remote);
|
|
|
|
patty_hash_end(&hash);
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_save_local(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
uint32_t hash = hash_addr(&sock->local);
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_set(server->socks_local, hash, sock) == NULL? -1: 0;
|
|
|
|
}
|
2020-07-03 19:03:24 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_save_remote(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_set(server->socks_remote, hash, sock) == NULL? -1: 0;
|
2020-06-18 18:25:11 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_delete_local(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
uint32_t hash = hash_addr(&sock->local);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_delete(server->socks_local, hash);
|
|
|
|
}
|
2020-07-03 19:03:24 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_delete_remote(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
2020-06-18 18:25:11 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_delete(server->socks_remote, hash);
|
2020-06-18 18:25:11 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_shutdown(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
fd_clear(server, sock->fd);
|
2020-06-28 14:00:50 -04:00
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sock->status = PATTY_AX25_SOCK_PENDING_DISCONNECT;
|
|
|
|
|
|
|
|
return patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL);
|
2020-06-28 14:00:50 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int sock_save(patty_ax25_server *server,
|
|
|
|
int client,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
patty_dict *socks;
|
|
|
|
|
|
|
|
switch (sock->status) {
|
|
|
|
case PATTY_AX25_SOCK_LISTENING:
|
|
|
|
if (sock_save_local(server, sock) < 0) {
|
|
|
|
goto error_sock_save_local;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
if (sock_save_remote(server, sock) < 0) {
|
|
|
|
goto error_sock_save_remote;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
2020-07-22 22:02:26 -04:00
|
|
|
case PATTY_AX25_SOCK_CLOSED:
|
|
|
|
case PATTY_AX25_SOCK_PROMISC:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (client_save_by_sock(server, client, sock) < 0) {
|
|
|
|
goto error_client_save_by_sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
|
|
|
goto error_dict_get_socks_by_client;
|
|
|
|
}
|
2020-06-27 23:54:09 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save_by_fd(socks, sock) < 0) {
|
|
|
|
goto error_sock_save_by_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sock_save_by_fd(server->socks_by_fd, sock);
|
|
|
|
|
|
|
|
error_sock_save_by_fd:
|
|
|
|
error_dict_get_socks_by_client:
|
|
|
|
error_client_save_by_sock:
|
|
|
|
error_sock_save_remote:
|
|
|
|
error_sock_save_local:
|
|
|
|
return -1;
|
2020-06-27 23:54:09 -04:00
|
|
|
}
|
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
static int sock_close(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
2020-07-22 22:02:26 -04:00
|
|
|
int client;
|
|
|
|
patty_dict *socks;
|
2020-06-25 20:37:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
switch (sock->status) {
|
|
|
|
case PATTY_AX25_SOCK_LISTENING:
|
|
|
|
if (sock_delete_local(server, sock) < 0) {
|
|
|
|
goto error_sock_delete_local;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
2020-07-22 22:02:26 -04:00
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
if (sock_delete_remote(server, sock) < 0) {
|
|
|
|
goto error_sock_delete_remote;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_CLOSED:
|
|
|
|
case PATTY_AX25_SOCK_PROMISC:
|
|
|
|
break;
|
2020-06-25 20:37:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((client = client_by_sock(server, sock)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
2020-07-01 20:15:46 -04:00
|
|
|
}
|
2020-06-25 20:37:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
|
|
|
goto error_dict_get_socks_by_client;
|
2020-06-25 20:37:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (patty_dict_delete(socks, (uint32_t)sock->fd) < 0) {
|
2020-07-01 20:15:46 -04:00
|
|
|
goto error_dict_delete_by_fd_socks;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (patty_dict_delete(server->socks_by_fd, (uint32_t)sock->fd) < 0) {
|
|
|
|
goto error_dict_delete_by_fd_socks_by_fd;
|
|
|
|
}
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
(void)client_delete_by_sock(server, sock);
|
2020-06-25 20:37:12 -04:00
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_clear(server, sock->fd);
|
2020-07-01 20:15:46 -04:00
|
|
|
|
|
|
|
patty_ax25_sock_destroy(sock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_delete_by_fd_socks_by_fd:
|
2020-07-01 20:15:46 -04:00
|
|
|
error_dict_delete_by_fd_socks:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_get_socks_by_client:
|
|
|
|
error_client_by_sock:
|
|
|
|
error_sock_delete_remote:
|
|
|
|
error_sock_delete_local:
|
2020-07-01 20:15:46 -04:00
|
|
|
return -1;
|
2020-06-25 20:37:12 -04:00
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
int patty_ax25_server_add_if(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface) {
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_watch(server, fd);
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
if (patty_list_append(server->ifaces, iface) == NULL) {
|
|
|
|
goto error_list_append;
|
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
return 0;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
error_list_append:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
int patty_ax25_server_delete_if(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface) {
|
|
|
|
patty_list_item *item = server->ifaces->first;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
int fd, i = 0;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
while (item) {
|
|
|
|
if (item->value == iface) {
|
|
|
|
if (patty_list_splice(server->ifaces, i) == NULL) {
|
|
|
|
goto error_list_splice;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
item = item->next;
|
|
|
|
i++;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
fd_clear(server, fd);
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
return 0;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
error_list_splice:
|
|
|
|
return -1;
|
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server,
|
|
|
|
const char *name) {
|
2020-07-02 17:13:19 -04:00
|
|
|
patty_list_item *item = server->ifaces->first;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
while (item) {
|
|
|
|
patty_ax25_if *iface = item->value;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
|
|
|
if (strncmp(iface->name, name, sizeof(iface->name)) == 0) {
|
|
|
|
return iface;
|
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
item = item->next;
|
|
|
|
}
|
2020-06-16 18:48:29 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_ax25_server_each_if(patty_ax25_server *server,
|
|
|
|
int (*callback)(patty_ax25_if *, void *),
|
|
|
|
void *ctx) {
|
2020-07-02 17:13:19 -04:00
|
|
|
patty_list_item *item = server->ifaces->first;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
while (item) {
|
|
|
|
patty_ax25_if *iface = item->value;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
if (callback(iface, ctx) < 0) {
|
|
|
|
goto error_callback;
|
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
item = item->next;
|
|
|
|
}
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
return 0;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
error_callback:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-25 23:36:13 -04:00
|
|
|
int patty_ax25_server_add_route(patty_ax25_server *server,
|
|
|
|
patty_ax25_route *route) {
|
|
|
|
return patty_ax25_route_table_add(server->routes, route);
|
|
|
|
}
|
|
|
|
|
2020-07-24 21:35:40 -04:00
|
|
|
static int respond_accept(int client,
|
|
|
|
int ret,
|
|
|
|
int eno,
|
|
|
|
patty_ax25_addr *peer,
|
|
|
|
char *path) {
|
|
|
|
patty_ax25_call_accept_response response;
|
|
|
|
|
|
|
|
memset(&response, '\0', sizeof(response));
|
|
|
|
|
|
|
|
response.ret = ret;
|
|
|
|
response.eno = eno;
|
|
|
|
|
|
|
|
if (peer) {
|
|
|
|
memcpy(&response.peer, peer, sizeof(response.peer));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (path) {
|
|
|
|
strncpy(response.path, path, sizeof(response.path));
|
|
|
|
}
|
|
|
|
|
|
|
|
return write(client, &response, sizeof(response));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int respond_connect(int client, int ret, int eno) {
|
|
|
|
patty_ax25_call_connect_response response = {
|
|
|
|
.ret = ret,
|
|
|
|
.eno = eno
|
|
|
|
};
|
|
|
|
|
|
|
|
return write(client, &response, sizeof(response));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int server_socket(patty_ax25_server *server, int client) {
|
2020-06-16 18:48:29 -04:00
|
|
|
patty_ax25_call_socket_request request;
|
|
|
|
patty_ax25_call_socket_response response;
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
patty_ax25_sock *sock;
|
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_read;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
if ((sock = patty_ax25_sock_new(request.proto, request.type)) == NULL) {
|
2020-06-25 20:37:12 -04:00
|
|
|
goto error_sock_new;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save(server, client, sock) < 0) {
|
|
|
|
goto error_sock_save;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
response.ret = sock->fd;
|
|
|
|
response.eno = 0;
|
|
|
|
|
2020-07-26 18:42:49 -04:00
|
|
|
memcpy(response.path, patty_ax25_sock_pty(sock), sizeof(response.path));
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-03 00:04:46 -04:00
|
|
|
return write(client, &response, sizeof(response));
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save:
|
2020-06-25 20:37:12 -04:00
|
|
|
patty_ax25_sock_destroy(sock);
|
|
|
|
|
|
|
|
error_sock_new:
|
|
|
|
error_read:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
static int server_setsockopt(patty_ax25_server *server,
|
|
|
|
int client) {
|
|
|
|
patty_ax25_call_setsockopt_request request;
|
|
|
|
patty_ax25_call_setsockopt_response response;
|
|
|
|
|
|
|
|
patty_ax25_sock *sock;
|
|
|
|
|
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
|
|
|
|
|
|
|
goto error_sock_by_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (request.opt) {
|
|
|
|
case PATTY_AX25_SOCK_IF: {
|
|
|
|
patty_ax25_call_setsockopt_if data;
|
|
|
|
patty_ax25_if *iface;
|
|
|
|
|
|
|
|
if (sock->type != PATTY_AX25_SOCK_RAW) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EINVAL;
|
|
|
|
|
|
|
|
goto error_invalid_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client, &data, request.len) < 0) {
|
|
|
|
goto error_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = ENODEV;
|
|
|
|
|
|
|
|
goto error_get_if;
|
|
|
|
}
|
|
|
|
|
|
|
|
patty_ax25_sock_bind_if(sock, iface);
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
sock->status = PATTY_AX25_SOCK_PROMISC;
|
2020-07-03 15:21:32 -04:00
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_watch(server, sock->fd);
|
2020-07-03 15:21:32 -04:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EINVAL;
|
|
|
|
|
|
|
|
goto error_invalid_opt;
|
|
|
|
}
|
|
|
|
|
|
|
|
response.ret = 0;
|
|
|
|
response.eno = 0;
|
|
|
|
|
|
|
|
error_sock_by_fd:
|
|
|
|
error_get_if:
|
|
|
|
error_invalid_type:
|
|
|
|
error_invalid_opt:
|
|
|
|
return write(client, &response, sizeof(response));
|
|
|
|
|
|
|
|
error_read:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
static int server_bind(patty_ax25_server *server,
|
2020-06-16 18:48:29 -04:00
|
|
|
int client) {
|
|
|
|
patty_ax25_call_bind_request request;
|
|
|
|
patty_ax25_call_bind_response response;
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
patty_ax25_sock *sock;
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 23:24:32 -04:00
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
2020-06-16 18:48:29 -04:00
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
goto error_sock_by_fd;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
2020-07-23 17:58:29 -04:00
|
|
|
if (sock->local.callsign[0] != '\0') {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EINVAL;
|
|
|
|
|
|
|
|
goto error_bound;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sock_by_addr(server->socks_local, &request.addr) != NULL) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EADDRINUSE;
|
|
|
|
|
|
|
|
goto error_exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&sock->local, &request.addr, sizeof(request.addr));
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-06-18 19:59:26 -04:00
|
|
|
response.ret = 0;
|
|
|
|
response.eno = 0;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-07-23 17:58:29 -04:00
|
|
|
error_exists:
|
|
|
|
error_bound:
|
2020-06-18 19:59:26 -04:00
|
|
|
error_sock_by_fd:
|
2020-07-03 00:04:46 -04:00
|
|
|
return write(client, &response, sizeof(response));
|
2020-06-16 18:48:29 -04:00
|
|
|
|
|
|
|
error_io:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int server_listen(patty_ax25_server *server,
|
2020-06-16 18:48:29 -04:00
|
|
|
int client) {
|
|
|
|
patty_ax25_call_listen_request request;
|
|
|
|
patty_ax25_call_listen_response response;
|
|
|
|
|
2020-06-16 01:59:47 -04:00
|
|
|
patty_ax25_sock *sock;
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 23:24:32 -04:00
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
2020-06-16 18:48:29 -04:00
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
goto error_sock_by_fd;
|
2020-06-16 01:59:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sock->local.callsign[0] == '\0') {
|
2020-06-16 18:48:29 -04:00
|
|
|
response.eno = EINVAL;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
|
|
|
goto error_invalid_fd;
|
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
sock->status = PATTY_AX25_SOCK_LISTENING;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save_local(server, sock) < 0) {
|
|
|
|
goto error_sock_save_local;
|
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
response.ret = 0;
|
|
|
|
response.eno = 0;
|
2020-06-16 01:59:47 -04:00
|
|
|
|
|
|
|
error_invalid_fd:
|
2020-06-18 18:25:11 -04:00
|
|
|
error_sock_by_fd:
|
2020-07-03 00:04:46 -04:00
|
|
|
return write(client, &response, sizeof(response));
|
2020-06-16 18:48:29 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save_local:
|
2020-06-16 18:48:29 -04:00
|
|
|
error_io:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-16 18:48:29 -04:00
|
|
|
static int server_accept(patty_ax25_server *server,
|
|
|
|
int client) {
|
|
|
|
patty_ax25_call_accept_request request;
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_sock *sock;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 23:24:32 -04:00
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
2020-06-18 18:25:11 -04:00
|
|
|
goto error_sock_by_fd;
|
2020-06-16 18:48:29 -04:00
|
|
|
}
|
|
|
|
|
2020-06-18 19:59:26 -04:00
|
|
|
return 0;
|
|
|
|
|
2020-06-18 18:25:11 -04:00
|
|
|
error_sock_by_fd:
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_accept(client, -1, EBADF, NULL, NULL);
|
2020-06-16 18:48:29 -04:00
|
|
|
|
|
|
|
error_io:
|
2020-06-16 01:59:47 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2020-06-18 18:50:24 -04:00
|
|
|
|
|
|
|
static int server_connect(patty_ax25_server *server,
|
|
|
|
int client) {
|
|
|
|
patty_ax25_call_connect_request request;
|
|
|
|
|
|
|
|
patty_ax25_sock *sock;
|
2020-06-26 22:44:19 -04:00
|
|
|
patty_ax25_route *route;
|
|
|
|
patty_ax25_if *iface;
|
2020-06-18 18:50:24 -04:00
|
|
|
|
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 23:24:32 -04:00
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, EBADF);
|
2020-06-18 18:50:24 -04:00
|
|
|
}
|
|
|
|
|
2020-06-18 19:59:26 -04:00
|
|
|
switch (sock->status) {
|
|
|
|
case PATTY_AX25_SOCK_LISTENING:
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, EINVAL);
|
2020-06-18 19:59:26 -04:00
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, EISCONN);
|
2020-06-18 19:59:26 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2020-06-18 18:50:24 -04:00
|
|
|
}
|
|
|
|
|
2020-06-26 22:44:19 -04:00
|
|
|
if (sock->local.callsign[0]) {
|
|
|
|
/*
|
|
|
|
* If there is an address already bound to this socket, locate the
|
|
|
|
* appropriate route.
|
|
|
|
*/
|
|
|
|
route = patty_ax25_route_table_find(server->routes, &sock->local);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Otherwise, locate the default route.
|
|
|
|
*/
|
|
|
|
route = patty_ax25_route_table_default(server->routes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If no route could be found, then assume the network is down or not
|
|
|
|
* configured.
|
|
|
|
*/
|
|
|
|
if (route == NULL) {
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, ENETDOWN);
|
2020-06-26 22:44:19 -04:00
|
|
|
}
|
|
|
|
|
2020-07-19 22:55:42 -04:00
|
|
|
patty_ax25_sock_bind_if(sock, iface = route->iface);
|
2020-06-26 22:44:19 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is no local address bound to this sock, then bind the
|
|
|
|
* address of the default route interface.
|
|
|
|
*/
|
|
|
|
if (sock->local.callsign[0] == '\0') {
|
|
|
|
memcpy(&sock->local, &iface->addr, sizeof(sock->local));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bind the requested remote address to the socket.
|
|
|
|
*/
|
2020-06-18 18:50:24 -04:00
|
|
|
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
|
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save_remote(server, sock) < 0) {
|
|
|
|
goto error_sock_save_remote;
|
2020-06-18 18:50:24 -04:00
|
|
|
}
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
if (client_save_by_sock(server, client, sock) < 0) {
|
|
|
|
goto error_client_save_by_sock;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-06-20 03:01:52 -04:00
|
|
|
/*
|
2020-07-19 23:00:57 -04:00
|
|
|
* Send an XID frame, to attempt to negotiate AX.25 v2.2 and its default
|
|
|
|
* parameters.
|
2020-06-20 03:01:52 -04:00
|
|
|
*/
|
2020-07-21 01:41:32 -04:00
|
|
|
if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) {
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, errno);
|
2020-06-26 22:44:19 -04:00
|
|
|
}
|
2020-06-20 03:01:52 -04:00
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
/*
|
|
|
|
* At this point, we will wait for a DM, FRMR or XID response, which
|
|
|
|
* will help us determine what version of AX.25 to apply for this socket,
|
|
|
|
* or whether the peer is not accepting connections.
|
|
|
|
*/
|
2020-06-30 23:20:12 -04:00
|
|
|
return 0;
|
2020-06-18 19:59:26 -04:00
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
error_client_save_by_sock:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save_remote:
|
2020-06-18 18:50:24 -04:00
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-18 19:59:26 -04:00
|
|
|
static int server_close(patty_ax25_server *server,
|
|
|
|
int client) {
|
|
|
|
patty_ax25_call_close_request request;
|
|
|
|
patty_ax25_call_close_response response;
|
|
|
|
|
|
|
|
patty_ax25_sock *sock;
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_dict *socks;
|
2020-06-18 19:59:26 -04:00
|
|
|
|
|
|
|
if (read(client, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 23:24:32 -04:00
|
|
|
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
|
2020-06-18 19:59:26 -04:00
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
|
|
|
|
|
|
|
goto error_sock_by_fd;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get_socks_by_client;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sock_shutdown(server, sock) < 0) {
|
|
|
|
response.ret = -1;
|
|
|
|
response.eno = errno;
|
|
|
|
|
|
|
|
goto error_sock_shutdown;
|
|
|
|
}
|
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
if (sock_close(server, sock) < 0) {
|
2020-06-18 19:59:26 -04:00
|
|
|
response.ret = -1;
|
|
|
|
response.eno = EBADF;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
goto error_sock_close;
|
2020-06-18 19:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
response.ret = 0;
|
|
|
|
response.eno = 0;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_close:
|
|
|
|
error_sock_shutdown:
|
|
|
|
error_dict_get_socks_by_client:
|
2020-06-18 19:59:26 -04:00
|
|
|
error_sock_by_fd:
|
2020-07-03 00:04:46 -04:00
|
|
|
return write(client, &response, sizeof(response));
|
2020-06-18 19:59:26 -04:00
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = {
|
|
|
|
NULL,
|
|
|
|
server_socket,
|
2020-07-03 15:21:32 -04:00
|
|
|
server_setsockopt,
|
2020-06-20 19:37:03 -04:00
|
|
|
server_bind,
|
|
|
|
server_listen,
|
|
|
|
server_accept,
|
|
|
|
server_connect,
|
|
|
|
server_close,
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static int listen_unix(patty_ax25_server *server, const char *path) {
|
|
|
|
struct sockaddr_un addr;
|
2020-06-25 01:04:04 -04:00
|
|
|
struct stat st;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
if (server->fd) {
|
|
|
|
errno = EBUSY;
|
|
|
|
|
|
|
|
goto error_listening;
|
|
|
|
}
|
|
|
|
|
2020-06-25 01:04:04 -04:00
|
|
|
if (stat(path, &st) >= 0) {
|
|
|
|
unlink(path);
|
|
|
|
}
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
if ((server->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
|
|
goto error_socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&addr, '\0', sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
|
|
|
|
|
|
|
|
if (bind(server->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
goto error_bind;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listen(server->fd, 0) < 0) {
|
|
|
|
goto error_listen;
|
|
|
|
}
|
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_watch(server, server->fd);
|
2020-06-25 01:04:17 -04:00
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_listen:
|
|
|
|
error_bind:
|
|
|
|
close(server->fd);
|
|
|
|
|
|
|
|
error_socket:
|
|
|
|
error_listening:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int accept_client(patty_ax25_server *server) {
|
|
|
|
int fd;
|
|
|
|
struct sockaddr addr;
|
2020-06-25 20:37:12 -04:00
|
|
|
socklen_t addrlen = sizeof(addr);
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_dict *socks;
|
2020-06-25 20:37:12 -04:00
|
|
|
|
|
|
|
memset(&addr, '\0', addrlen);
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
if (!FD_ISSET(server->fd, &server->fds_r)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd = accept(server->fd, &addr, &addrlen)) < 0) {
|
|
|
|
goto error_accept;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((socks = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new;
|
|
|
|
}
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
if (patty_dict_set(server->clients, (uint32_t)fd, NULL + fd) == NULL) {
|
2020-07-22 22:02:26 -04:00
|
|
|
goto error_dict_set_clients;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_dict_set(server->socks_by_client, (uint32_t)fd, socks) == NULL) {
|
|
|
|
goto error_dict_set_socks_by_client;
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_watch(server, fd);
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
done:
|
|
|
|
return 0;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_set_socks_by_client:
|
|
|
|
error_dict_set_clients:
|
|
|
|
patty_dict_destroy(socks);
|
|
|
|
|
|
|
|
error_dict_new:
|
2020-06-20 19:37:03 -04:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
error_accept:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
static int client_sock_close(uint32_t key, void *value, void *ctx) {
|
|
|
|
patty_ax25_server *server = ctx;
|
|
|
|
patty_ax25_sock *sock = value;
|
|
|
|
|
|
|
|
if (sock_shutdown(server, sock) < 0) {
|
|
|
|
goto error_sock_shutdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sock_close(server, sock);
|
|
|
|
|
|
|
|
error_sock_shutdown:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
static int handle_client(uint32_t key,
|
2020-06-20 19:37:03 -04:00
|
|
|
void *value,
|
|
|
|
void *ctx) {
|
|
|
|
patty_ax25_server *server = ctx;
|
2020-07-08 17:12:40 -04:00
|
|
|
int client = (int)key;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
ssize_t readlen;
|
|
|
|
enum patty_ax25_call call;
|
|
|
|
|
|
|
|
if (!FD_ISSET(client, &server->fds_r)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-06-25 20:37:12 -04:00
|
|
|
if ((readlen = read(client, &call, sizeof(call))) < 0) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto error_io;
|
|
|
|
} else if (readlen == 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_dict *socks;
|
|
|
|
|
2020-07-12 19:12:48 -04:00
|
|
|
fd_clear(server, client);
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((socks = patty_dict_get(server->socks_by_client, client)) != NULL) {
|
|
|
|
(void)patty_dict_each(socks, client_sock_close, server);
|
|
|
|
(void)patty_dict_destroy(socks);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_dict_delete(server->socks_by_client, key) < 0) {
|
|
|
|
goto error_dict_delete_socks_by_client;
|
|
|
|
}
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
if (patty_dict_delete(server->clients, key) < 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
goto error_dict_delete_clients;
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (close(client) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (call <= PATTY_AX25_CALL_NONE || call >= PATTY_AX25_CALL_COUNT) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-06-26 22:44:19 -04:00
|
|
|
if (server_calls[call] == NULL) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
|
|
|
|
goto error_not_implemented;
|
|
|
|
}
|
2020-07-03 19:03:24 -04:00
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
return server_calls[call](server, client);
|
|
|
|
|
|
|
|
done:
|
|
|
|
return 0;
|
|
|
|
|
2020-06-26 22:44:19 -04:00
|
|
|
error_not_implemented:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_dict_delete_socks_by_client:
|
|
|
|
error_dict_delete_clients:
|
2020-06-20 19:37:03 -04:00
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_clients(patty_ax25_server *server) {
|
|
|
|
return patty_dict_each(server->clients, handle_client, server);
|
|
|
|
}
|
|
|
|
|
2020-06-28 14:00:50 -04:00
|
|
|
static void save_reply_addr(patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-06-27 23:54:09 -04:00
|
|
|
unsigned int i,
|
2020-06-28 14:00:50 -04:00
|
|
|
hops = frame->hops > PATTY_AX25_MAX_HOPS?
|
2020-06-28 21:33:41 -04:00
|
|
|
PATTY_AX25_MAX_HOPS: sock->hops;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-06-30 23:20:12 -04:00
|
|
|
memcpy(&sock->remote, &frame->src, sizeof(patty_ax25_addr));
|
|
|
|
memcpy(&sock->local, &frame->dest, sizeof(patty_ax25_addr));
|
2020-06-27 23:54:09 -04:00
|
|
|
|
2020-06-28 14:00:50 -04:00
|
|
|
for (i=0; i<hops; i++) {
|
|
|
|
memcpy(&sock->repeaters[i],
|
|
|
|
&frame->repeaters[hops-1-i],
|
|
|
|
sizeof(patty_ax25_addr));
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
2020-06-28 14:00:50 -04:00
|
|
|
|
|
|
|
sock->hops = hops;
|
|
|
|
}
|
|
|
|
|
2020-06-29 00:10:48 -04:00
|
|
|
static int reply_to(patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame,
|
2020-07-10 00:01:50 -04:00
|
|
|
patty_ax25_frame *reply) {
|
2020-06-28 14:00:50 -04:00
|
|
|
ssize_t len;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
frame->cr = PATTY_AX25_FRAME_RESPONSE;
|
|
|
|
|
2020-06-28 14:00:50 -04:00
|
|
|
if ((len = patty_ax25_frame_encode_reply_to(frame,
|
2020-06-29 00:10:48 -04:00
|
|
|
reply,
|
|
|
|
iface->tx_buf,
|
2020-07-17 00:32:04 -04:00
|
|
|
iface->mtu)) < 0) {
|
2020-06-28 14:00:50 -04:00
|
|
|
goto error_toobig;
|
|
|
|
}
|
|
|
|
|
|
|
|
return patty_ax25_if_send(iface, iface->tx_buf, len);
|
|
|
|
|
|
|
|
error_toobig:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-29 00:10:48 -04:00
|
|
|
static int reply_dm(patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame,
|
2020-07-10 00:01:50 -04:00
|
|
|
int flag) {
|
2020-06-29 00:10:48 -04:00
|
|
|
patty_ax25_frame reply = {
|
2020-07-10 00:01:50 -04:00
|
|
|
.control = PATTY_AX25_FRAME_DM | (flag << 4),
|
2020-06-29 00:10:48 -04:00
|
|
|
.proto = PATTY_AX25_PROTO_NONE,
|
|
|
|
.info = NULL,
|
|
|
|
.infolen = 0
|
|
|
|
};
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
return reply_to(iface, frame, &reply);
|
2020-06-28 14:00:50 -04:00
|
|
|
}
|
|
|
|
|
2020-06-29 00:10:48 -04:00
|
|
|
static int reply_ua(patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame,
|
2020-07-10 00:01:50 -04:00
|
|
|
int flag) {
|
2020-06-29 00:10:48 -04:00
|
|
|
patty_ax25_frame reply = {
|
2020-07-10 00:01:50 -04:00
|
|
|
.control = PATTY_AX25_FRAME_UA | (flag << 4),
|
2020-06-29 00:10:48 -04:00
|
|
|
.proto = PATTY_AX25_PROTO_NONE,
|
|
|
|
.info = NULL,
|
|
|
|
.infolen = 0
|
|
|
|
};
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
return reply_to(iface, frame, &reply);
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
static int handle_frmr(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
2020-07-22 22:52:10 -04:00
|
|
|
patty_ax25_sock *sock,
|
2020-07-19 23:00:57 -04:00
|
|
|
patty_ax25_frame *frame) {
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
2020-07-19 23:00:57 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return sock->status == PATTY_AX25_SOCK_PENDING_CONNECT?
|
|
|
|
patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL): 0;
|
2020-07-19 23:00:57 -04:00
|
|
|
}
|
|
|
|
|
2020-06-29 00:29:50 -04:00
|
|
|
static int handle_sabm(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-07-22 22:02:26 -04:00
|
|
|
int client,
|
|
|
|
created = 0;
|
|
|
|
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_sock *local, *remote;
|
2020-06-29 00:29:50 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((local = sock_by_addr(server->socks_local,
|
2020-06-30 23:20:12 -04:00
|
|
|
&frame->dest)) == NULL) {
|
2020-07-06 23:39:22 -04:00
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-06-29 00:29:50 -04:00
|
|
|
}
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
if ((client = client_by_sock(server, local)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
/*
|
|
|
|
* Look to see if there is already a remote socket created based on an XID
|
|
|
|
* packet previously received.
|
|
|
|
*/
|
|
|
|
if ((remote = sock_by_addrpair(server->socks_remote,
|
|
|
|
&frame->dest,
|
|
|
|
&frame->src)) == NULL) {
|
|
|
|
/*
|
|
|
|
* If there is no existing remote socket, we should create one, and
|
|
|
|
* associate it with the client.
|
|
|
|
*/
|
|
|
|
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
|
|
|
goto error_sock_new;
|
|
|
|
}
|
2020-07-14 00:36:05 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
save_reply_addr(remote, frame);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
created = 1;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
remote->status = PATTY_AX25_SOCK_ESTABLISHED;
|
|
|
|
remote->mode = (frame->type == PATTY_AX25_FRAME_SABME)?
|
|
|
|
PATTY_AX25_SOCK_SABME: PATTY_AX25_SOCK_SABM;
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
patty_ax25_sock_bind_if(remote, iface);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (created) {
|
|
|
|
if (sock_save(server, client, remote) < 0) {
|
|
|
|
goto error_sock_save;
|
2020-07-10 17:09:37 -04:00
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
fd_watch(server, remote->fd);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-26 18:42:49 -04:00
|
|
|
if (respond_accept(client, 0, 0, &frame->src, remote->pty) < 0) {
|
2020-07-24 21:35:40 -04:00
|
|
|
goto error_respond_accept;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-24 21:35:40 -04:00
|
|
|
error_respond_accept:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save:
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_sock_destroy(remote);
|
|
|
|
|
|
|
|
error_sock_new:
|
2020-07-03 19:13:34 -04:00
|
|
|
error_client_by_sock:
|
2020-06-30 23:20:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_ua(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
2020-07-22 22:52:10 -04:00
|
|
|
patty_ax25_sock *sock,
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
int client;
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
2020-07-14 17:12:17 -04:00
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
switch (sock->status) {
|
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
|
|
|
break;
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
2020-07-22 22:02:26 -04:00
|
|
|
return sock_close(server, sock);
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
return 0;
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
default:
|
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-06-29 00:29:50 -04:00
|
|
|
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
|
2020-07-19 23:12:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((client = client_by_sock(server, sock)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
2020-07-19 23:12:12 -04:00
|
|
|
}
|
2020-06-29 00:29:50 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save(server, client, sock) < 0) {
|
|
|
|
goto error_sock_save;
|
2020-06-29 00:29:50 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
fd_watch(server, sock->fd);
|
2020-06-29 00:29:50 -04:00
|
|
|
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, 0, 0);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save:
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_sock_destroy(sock);
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
error_client_by_sock:
|
2020-06-30 23:20:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_dm(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
2020-07-22 22:52:10 -04:00
|
|
|
patty_ax25_sock *sock,
|
2020-06-30 23:20:12 -04:00
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
int client;
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL || sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
2020-06-30 23:20:12 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
if ((client = client_by_sock(server, sock)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-26 02:37:17 -04:00
|
|
|
patty_ax25_sock_reset(sock);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-24 21:35:40 -04:00
|
|
|
return respond_connect(client, -1, ECONNREFUSED);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
error_client_by_sock:
|
2020-06-30 23:20:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
static int handle_i(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-07-10 16:56:44 -04:00
|
|
|
if (sock == NULL || sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
|
2020-07-10 17:09:37 -04:00
|
|
|
return frame->pf? reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL): 0;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
if (sock->seq_recv == frame->ns) {
|
2020-07-08 16:25:10 -04:00
|
|
|
patty_ax25_sock_seq_recv_incr(sock);
|
2020-07-06 23:39:22 -04:00
|
|
|
} else {
|
2020-07-14 22:00:31 -04:00
|
|
|
return frame->pf?
|
2020-07-26 02:26:12 -04:00
|
|
|
patty_ax25_sock_send_rej(sock, PATTY_AX25_FRAME_RESPONSE, 0): 0;
|
2020-07-06 23:39:22 -04:00
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-07-10 17:09:37 -04:00
|
|
|
if (write(sock->fd, frame->info, frame->infolen) < 0) {
|
|
|
|
goto error_write;
|
|
|
|
}
|
|
|
|
|
2020-07-14 22:00:31 -04:00
|
|
|
return frame->pf?
|
2020-07-26 02:26:12 -04:00
|
|
|
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0): 0;
|
2020-07-10 17:09:37 -04:00
|
|
|
|
|
|
|
error_write:
|
|
|
|
return -1;
|
2020-06-29 00:29:50 -04:00
|
|
|
}
|
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
static int handle_disc(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
2020-07-22 22:52:10 -04:00
|
|
|
patty_ax25_sock *sock,
|
2020-07-01 20:15:46 -04:00
|
|
|
patty_ax25_frame *frame) {
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
|
|
|
goto reply_dm;
|
2020-07-01 20:15:46 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
switch (sock->status) {
|
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
(void)sock_close(server, sock);
|
2020-07-10 17:09:37 -04:00
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
reply_dm:
|
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
2020-07-01 20:15:46 -04:00
|
|
|
}
|
|
|
|
|
2020-07-16 00:14:21 -04:00
|
|
|
static int handle_rej(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-07-26 01:41:44 -04:00
|
|
|
unsigned int i,
|
|
|
|
end = sock->seq_send;
|
2020-07-16 00:14:21 -04:00
|
|
|
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-26 01:41:44 -04:00
|
|
|
if (frame->nr > end) {
|
|
|
|
end += (sock->mode == PATTY_AX25_SOCK_SABME)? 128: 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=frame->nr; i<end; i++) {
|
2020-07-16 00:14:21 -04:00
|
|
|
if (patty_ax25_sock_resend(sock, i) < 0) {
|
|
|
|
goto error_sock_resend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_sock_resend:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_srej(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-07-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-16 00:14:21 -04:00
|
|
|
/*
|
|
|
|
* TODO: Read the fine print of section 4.3.2.4
|
|
|
|
*/
|
|
|
|
if (patty_ax25_sock_resend(sock, frame->nr) < 0) {
|
|
|
|
goto error_sock_resend;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_sock_resend:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-17 22:57:23 -04:00
|
|
|
static int handle_xid(patty_ax25_server *server,
|
2020-07-19 23:00:57 -04:00
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame,
|
2020-07-17 22:57:23 -04:00
|
|
|
void *buf,
|
|
|
|
size_t offset,
|
|
|
|
size_t len) {
|
|
|
|
patty_ax25_params params;
|
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
patty_ax25_sock *local,
|
|
|
|
*remote;
|
|
|
|
|
2020-07-17 22:57:23 -04:00
|
|
|
if (patty_ax25_frame_decode_xid(¶ms, buf, offset, len) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-07-22 22:02:26 -04:00
|
|
|
* First, check if this XID packet is a response to an XID used to initiate
|
|
|
|
* an outbound connection.
|
2020-07-17 22:57:23 -04:00
|
|
|
*/
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((remote = sock_by_addrpair(server->socks_remote,
|
2020-07-19 23:00:57 -04:00
|
|
|
&frame->dest,
|
|
|
|
&frame->src)) != NULL) {
|
2020-07-22 22:02:26 -04:00
|
|
|
if (remote->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
|
|
|
goto reply_dm;
|
|
|
|
}
|
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
/*
|
|
|
|
* Since we've received an XID packet, we can assume that the remote
|
|
|
|
* station is capable of speaking AX.25 v2.2. Therefore, we should
|
|
|
|
* upgrade the socket defaults accordingly, and negotiate downwards
|
|
|
|
* as necessary.
|
|
|
|
*/
|
2020-07-26 00:55:47 -04:00
|
|
|
if (patty_ax25_sock_upgrade(remote, PATTY_AX25_2_2) < 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
goto error_sock_upgrade;
|
|
|
|
}
|
2020-07-19 23:00:57 -04:00
|
|
|
|
|
|
|
if (patty_ax25_sock_params_set(remote, ¶ms) < 0) {
|
2020-07-24 21:35:40 -04:00
|
|
|
int client;
|
|
|
|
|
|
|
|
if ((client = client_by_sock(server, remote)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
|
|
|
}
|
|
|
|
|
2020-07-26 02:37:17 -04:00
|
|
|
patty_ax25_sock_reset(remote);
|
2020-07-24 21:35:40 -04:00
|
|
|
|
|
|
|
return respond_connect(client, -1, errno);
|
2020-07-19 23:00:57 -04:00
|
|
|
}
|
2020-07-19 01:47:05 -04:00
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
/*
|
|
|
|
* Since this XID frame is for a socket that is awaiting outbound
|
|
|
|
* connection, we can send an SABM or SABME packet, as necessary.
|
|
|
|
*/
|
|
|
|
if (params.hdlc & PATTY_AX25_PARAM_HDLC_MODULO_128) {
|
|
|
|
remote->mode = PATTY_AX25_SOCK_SABME;
|
2020-07-27 00:37:04 -04:00
|
|
|
}
|
2020-07-19 23:00:57 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
|
2020-07-27 00:37:04 -04:00
|
|
|
return patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
|
2020-07-19 01:47:05 -04:00
|
|
|
}
|
2020-07-17 22:57:23 -04:00
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
/*
|
2020-07-22 22:02:26 -04:00
|
|
|
* Second, check if this XID packet is for a listening socket.
|
2020-07-19 23:00:57 -04:00
|
|
|
*/
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((local = sock_by_addr(server->socks_local,
|
2020-07-19 23:00:57 -04:00
|
|
|
&frame->dest)) != NULL) {
|
2020-07-22 22:02:26 -04:00
|
|
|
int client;
|
|
|
|
|
|
|
|
if (local->status != PATTY_AX25_SOCK_LISTENING) {
|
|
|
|
goto reply_dm;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((client = client_by_sock(server, local)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
|
|
|
}
|
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
|
|
|
goto error_sock_new;
|
|
|
|
}
|
|
|
|
|
|
|
|
remote->status = PATTY_AX25_SOCK_PENDING_ACCEPT;
|
|
|
|
|
|
|
|
if (params.hdlc & PATTY_AX25_PARAM_HDLC_MODULO_128) {
|
|
|
|
remote->mode = PATTY_AX25_SOCK_SABME;
|
|
|
|
}
|
|
|
|
|
|
|
|
patty_ax25_sock_bind_if(remote, iface);
|
2020-07-17 22:57:23 -04:00
|
|
|
|
2020-07-26 00:55:47 -04:00
|
|
|
patty_ax25_sock_upgrade(remote, PATTY_AX25_2_2);
|
2020-07-19 23:00:57 -04:00
|
|
|
|
|
|
|
if (patty_ax25_sock_params_set(remote, ¶ms) < 0) {
|
2020-07-24 21:35:40 -04:00
|
|
|
patty_ax25_sock_destroy(remote);
|
|
|
|
|
|
|
|
return respond_accept(client, -1, errno, NULL, NULL);
|
2020-07-19 23:00:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
save_reply_addr(remote, frame);
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if (sock_save(server, client, remote) < 0) {
|
|
|
|
goto error_sock_save;
|
2020-07-19 23:00:57 -04:00
|
|
|
}
|
|
|
|
|
2020-07-21 01:41:32 -04:00
|
|
|
return patty_ax25_sock_send_xid(remote, PATTY_AX25_FRAME_RESPONSE);
|
2020-07-19 23:00:57 -04:00
|
|
|
}
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
reply_dm:
|
2020-07-19 23:00:57 -04:00
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
error_sock_save:
|
2020-07-19 23:00:57 -04:00
|
|
|
error_sock_new:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_client_by_sock:
|
|
|
|
error_sock_upgrade:
|
2020-07-17 22:57:23 -04:00
|
|
|
error_io:
|
|
|
|
return -1;
|
2020-07-16 23:05:31 -04:00
|
|
|
}
|
|
|
|
|
2020-06-28 14:00:50 -04:00
|
|
|
static int handle_frame(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
void *buf,
|
|
|
|
size_t len) {
|
|
|
|
patty_ax25_frame frame;
|
2020-07-10 00:01:50 -04:00
|
|
|
enum patty_ax25_frame_format format = PATTY_AX25_FRAME_NORMAL;
|
|
|
|
|
2020-07-16 23:05:31 -04:00
|
|
|
ssize_t decoded,
|
|
|
|
offset = 0;
|
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
patty_ax25_sock *sock;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
if ((decoded = patty_ax25_frame_decode_address(&frame, buf, len)) < 0) {
|
2020-06-27 23:54:09 -04:00
|
|
|
goto error_io;
|
2020-07-16 23:05:31 -04:00
|
|
|
} else {
|
|
|
|
offset += decoded;
|
2020-06-25 20:37:12 -04:00
|
|
|
}
|
2020-06-26 23:03:00 -04:00
|
|
|
|
2020-07-22 22:02:26 -04:00
|
|
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
2020-07-10 00:01:50 -04:00
|
|
|
&frame.dest,
|
|
|
|
&frame.src)) != NULL) {
|
|
|
|
if (sock->mode == PATTY_AX25_SOCK_SABME) {
|
|
|
|
format = PATTY_AX25_FRAME_EXTENDED;
|
|
|
|
}
|
2020-06-27 23:54:09 -04:00
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-16 23:05:31 -04:00
|
|
|
if ((decoded = patty_ax25_frame_decode_control(&frame, format, buf, offset, len)) < 0) {
|
2020-07-10 00:01:50 -04:00
|
|
|
goto error_io;
|
2020-07-16 23:05:31 -04:00
|
|
|
} else {
|
|
|
|
offset += decoded;
|
2020-07-10 00:01:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (frame.type) {
|
2020-07-16 00:14:21 -04:00
|
|
|
case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame);
|
2020-07-17 22:57:23 -04:00
|
|
|
case PATTY_AX25_FRAME_REJ: return handle_rej(server, sock, &frame);
|
|
|
|
case PATTY_AX25_FRAME_SREJ: return handle_srej(server, sock, &frame);
|
2020-07-19 23:00:57 -04:00
|
|
|
case PATTY_AX25_FRAME_XID: return handle_xid(server, iface, &frame, buf, offset, len);
|
2020-07-22 22:52:10 -04:00
|
|
|
case PATTY_AX25_FRAME_SABM:
|
|
|
|
case PATTY_AX25_FRAME_SABME: return handle_sabm(server, iface, &frame);
|
|
|
|
case PATTY_AX25_FRAME_UA: return handle_ua(server, iface, sock, &frame);
|
|
|
|
case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, sock, &frame);
|
|
|
|
case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, sock, &frame);
|
|
|
|
case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, sock, &frame);
|
2020-07-15 23:13:41 -04:00
|
|
|
|
2020-07-10 00:01:50 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-07-14 17:12:17 -04:00
|
|
|
return 0;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
error_io:
|
2020-07-16 23:05:31 -04:00
|
|
|
iface->stats.dropped++;
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
|
|
|
|
int fd = patty_kiss_tnc_fd(iface->tnc);
|
|
|
|
|
|
|
|
if (!FD_ISSET(fd, &server->fds_r)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-07-12 22:14:58 -04:00
|
|
|
do {
|
2020-07-22 22:02:26 -04:00
|
|
|
void *buf;
|
|
|
|
ssize_t readlen;
|
|
|
|
|
2020-07-12 22:14:58 -04:00
|
|
|
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
} else if (readlen == 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
close(fd);
|
|
|
|
|
2020-07-12 22:14:58 -04:00
|
|
|
fd_clear(server, fd);
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-12 22:14:58 -04:00
|
|
|
goto done;
|
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-12 22:14:58 -04:00
|
|
|
if (handle_frame(server, iface, buf, readlen) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
} while (patty_ax25_if_pending(iface));
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
done:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_ifaces(patty_ax25_server *server) {
|
2020-07-02 17:13:19 -04:00
|
|
|
patty_list_item *item = server->ifaces->first;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
while (item) {
|
|
|
|
patty_ax25_if *iface = item->value;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
if (handle_iface(server, iface) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:13:19 -04:00
|
|
|
item = item->next;
|
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-07-08 17:12:40 -04:00
|
|
|
static int handle_sock(uint32_t key,
|
2020-06-20 19:37:03 -04:00
|
|
|
void *value,
|
|
|
|
void *ctx) {
|
|
|
|
patty_ax25_server *server = ctx;
|
2020-06-21 01:13:33 -04:00
|
|
|
patty_ax25_sock *sock = value;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-06-21 01:13:33 -04:00
|
|
|
ssize_t len;
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
if (!FD_ISSET(sock->fd, &server->fds_r)) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-07-26 01:48:08 -04:00
|
|
|
/*
|
|
|
|
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
|
|
|
|
*/
|
|
|
|
if (sock->seq_recv + sock->n_window_tx == sock->seq_send) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-07-22 19:45:20 -04:00
|
|
|
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
|
2020-07-01 20:15:46 -04:00
|
|
|
if (errno == EIO) {
|
2020-07-22 22:02:26 -04:00
|
|
|
(void)sock_shutdown(server, sock);
|
2020-06-21 01:13:33 -04:00
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
goto done;
|
2020-06-21 01:13:33 -04:00
|
|
|
}
|
|
|
|
|
2020-07-01 20:15:46 -04:00
|
|
|
goto error_io;
|
|
|
|
} else if (len == 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
(void)sock_shutdown(server, sock);
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-06-21 01:13:33 -04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2020-07-22 19:45:20 -04:00
|
|
|
if (patty_ax25_sock_write(sock, sock->rx_buf, len) < 0) {
|
2020-06-30 23:20:12 -04:00
|
|
|
goto error_sock_write;
|
2020-06-21 01:13:33 -04:00
|
|
|
}
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
done:
|
|
|
|
return 0;
|
2020-06-21 01:13:33 -04:00
|
|
|
|
2020-06-30 23:20:12 -04:00
|
|
|
error_sock_write:
|
2020-06-21 01:13:33 -04:00
|
|
|
error_io:
|
|
|
|
return -1;
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_socks(patty_ax25_server *server) {
|
2020-07-22 22:02:26 -04:00
|
|
|
return patty_dict_each(server->socks_by_fd, handle_sock, server);
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int patty_ax25_server_run(patty_ax25_server *server) {
|
2020-06-26 22:44:19 -04:00
|
|
|
if (listen_unix(server, server->path) < 0) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto error_listen_unix;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int nready;
|
|
|
|
|
2020-06-21 22:49:19 -04:00
|
|
|
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
if ((nready = select( server->fd_max,
|
|
|
|
&server->fds_r,
|
2020-06-26 22:44:19 -04:00
|
|
|
NULL,
|
2020-06-20 19:37:03 -04:00
|
|
|
NULL,
|
2020-06-25 01:54:39 -04:00
|
|
|
NULL)) < 0) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_clients(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_ifaces(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_socks(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
|
|
|
|
if (accept_client(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
close(server->fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
close(server->fd);
|
|
|
|
|
|
|
|
error_listen_unix:
|
|
|
|
return -1;
|
|
|
|
}
|