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-08-10 18:48:14 -04:00
|
|
|
#include <time.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;
|
|
|
|
|
2020-08-10 18:48:14 -04:00
|
|
|
struct timespec elapsed;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
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-08-07 17:59:16 -04:00
|
|
|
strncpy(server->path, path, sizeof(server->path)-1);
|
2020-06-26 22:44:19 -04:00
|
|
|
|
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-08-03 02:44:17 -04:00
|
|
|
if (sock->type != PATTY_AX25_SOCK_STREAM) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
if (sock->state != PATTY_AX25_SOCK_ESTABLISHED) {
|
2020-07-22 22:52:10 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
sock->state = PATTY_AX25_SOCK_PENDING_DISCONNECT;
|
|
|
|
sock->retries = sock->n_retry;
|
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-07 21:48:20 -04:00
|
|
|
|
2020-08-23 22:29:01 -05:00
|
|
|
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;
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-07-22 22:02:26 -04:00
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-07-22 22:02:26 -04:00
|
|
|
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-08-19 22:32:05 -04:00
|
|
|
static inline void sock_flow_stop(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
fd_clear(server, sock->fd);
|
|
|
|
|
|
|
|
sock->flow = PATTY_AX25_SOCK_WAIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void sock_flow_start(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
fd_watch(server, sock->fd);
|
|
|
|
}
|
|
|
|
|
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,
|
2020-08-12 00:19:46 -04:00
|
|
|
int ret,
|
|
|
|
int eno) {
|
|
|
|
patty_client_accept_response response = {
|
|
|
|
.ret = ret,
|
|
|
|
.eno = eno
|
|
|
|
};
|
|
|
|
|
|
|
|
return write(client, &response, sizeof(response));
|
|
|
|
}
|
2020-07-24 21:35:40 -04:00
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
static int notify_accept(int local,
|
|
|
|
int remote,
|
|
|
|
patty_ax25_addr *peer,
|
|
|
|
char *path) {
|
|
|
|
patty_client_accept_message message;
|
2020-07-24 21:35:40 -04:00
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
memset(&message, '\0', sizeof(message));
|
|
|
|
|
|
|
|
message.fd = remote;
|
2020-07-24 21:35:40 -04:00
|
|
|
|
|
|
|
if (peer) {
|
2020-08-12 00:19:46 -04:00
|
|
|
memcpy(&message.peer, peer, sizeof(message.peer));
|
2020-07-24 21:35:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (path) {
|
2020-08-12 00:19:46 -04:00
|
|
|
strncpy(message.path, path, sizeof(message.path)-1);
|
2020-07-24 21:35:40 -04:00
|
|
|
}
|
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
return write(local, &message, sizeof(message));
|
2020-07-24 21:35:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int respond_connect(int client, int ret, int eno) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_connect_response response = {
|
2020-07-24 21:35:40 -04:00
|
|
|
.ret = ret,
|
|
|
|
.eno = eno
|
|
|
|
};
|
|
|
|
|
|
|
|
return write(client, &response, sizeof(response));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int server_socket(patty_ax25_server *server, int client) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_socket_request request;
|
|
|
|
patty_client_socket_response response;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
response.fd = sock->fd;
|
2020-06-30 23:20:12 -04:00
|
|
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_setsockopt_request request;
|
|
|
|
patty_client_setsockopt_response response;
|
2020-07-03 15:21:32 -04:00
|
|
|
|
|
|
|
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) {
|
2020-08-05 22:38:49 -04:00
|
|
|
case PATTY_AX25_SOCK_PARAMS: {
|
|
|
|
patty_client_setsockopt_params data;
|
|
|
|
|
|
|
|
if (read(client, &data, request.len) < 0) {
|
|
|
|
goto error_read;
|
|
|
|
}
|
|
|
|
|
2020-08-12 17:27:11 -04:00
|
|
|
if (data.flags & PATTY_AX25_SOCK_PARAM_MTU)
|
|
|
|
patty_ax25_sock_mtu_set(sock, data.mtu);
|
2020-08-05 22:38:49 -04:00
|
|
|
|
2020-08-12 17:27:11 -04:00
|
|
|
if (data.flags & PATTY_AX25_SOCK_PARAM_WINDOW)
|
|
|
|
patty_ax25_sock_window_set(sock, data.window);
|
|
|
|
|
|
|
|
if (data.flags & PATTY_AX25_SOCK_PARAM_ACK)
|
|
|
|
patty_ax25_sock_ack_set(sock, data.ack);
|
|
|
|
|
|
|
|
if (data.flags & PATTY_AX25_SOCK_PARAM_RETRY)
|
|
|
|
patty_ax25_sock_retry_set(sock, data.retry);
|
|
|
|
|
|
|
|
if (data.flags & (PATTY_AX25_SOCK_PARAM_MTU
|
|
|
|
| PATTY_AX25_SOCK_PARAM_WINDOW)) {
|
2020-08-05 22:53:26 -04:00
|
|
|
if (patty_ax25_sock_realloc_bufs(sock) < 0) {
|
|
|
|
goto error_realloc_bufs;
|
|
|
|
}
|
2020-08-05 22:38:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
case PATTY_AX25_SOCK_IF: {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_setsockopt_if data;
|
2020-07-03 15:21:32 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-08-11 02:00:06 -04:00
|
|
|
if (data.state == PATTY_AX25_SOCK_PROMISC) {
|
|
|
|
sock->state = PATTY_AX25_SOCK_PROMISC;
|
|
|
|
}
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
patty_ax25_sock_bind_if(sock, iface);
|
|
|
|
|
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));
|
|
|
|
|
2020-08-05 22:38:49 -04:00
|
|
|
error_realloc_bufs:
|
2020-07-03 15:21:32 -04:00
|
|
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_bind_request request;
|
|
|
|
patty_client_bind_response response;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_listen_request request;
|
|
|
|
patty_client_listen_response response;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
sock->state = PATTY_AX25_SOCK_LISTENING;
|
2020-06-16 18:48:29 -04:00
|
|
|
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_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-08-12 00:19:46 -04:00
|
|
|
return respond_accept(client, -1, EBADF);
|
2020-06-16 18:48:29 -04:00
|
|
|
}
|
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
if (sock->type != PATTY_AX25_SOCK_STREAM) {
|
|
|
|
return respond_accept(client, -1, EOPNOTSUPP);
|
|
|
|
}
|
2020-06-18 19:59:26 -04:00
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
if (sock->state != PATTY_AX25_SOCK_LISTENING) {
|
|
|
|
return respond_accept(client, -1, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return respond_accept(client, 0, 0);
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_connect_request request;
|
2020-06-18 18:50:24 -04:00
|
|
|
|
|
|
|
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-08-07 18:07:50 -04:00
|
|
|
if (sock->type == PATTY_AX25_SOCK_RAW) {
|
|
|
|
return respond_connect(client, -1, ENOTSUP);
|
|
|
|
}
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-06-18 19:59:26 -04:00
|
|
|
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-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-08-07 18:17:36 -04:00
|
|
|
switch (sock->type) {
|
|
|
|
case PATTY_AX25_SOCK_DGRAM:
|
|
|
|
sock->state = PATTY_AX25_SOCK_ESTABLISHED;
|
2020-06-20 03:01:52 -04:00
|
|
|
|
2020-08-07 18:17:36 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_STREAM:
|
|
|
|
sock->state = PATTY_AX25_SOCK_PENDING_CONNECT;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send an XID frame, to attempt to negotiate AX.25 v2.2 and its
|
|
|
|
* default parameters.
|
|
|
|
*/
|
|
|
|
if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) {
|
|
|
|
return respond_connect(client, -1, errno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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-08-19 22:32:05 -04:00
|
|
|
sock->retries = sock->n_retry;
|
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-07 18:17:36 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-07-27 01:05:43 -04:00
|
|
|
|
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) {
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
patty_client_close_request request;
|
|
|
|
patty_client_close_response response;
|
2020-06-18 19:59:26 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
static patty_ax25_server_call server_calls[PATTY_CLIENT_CALL_COUNT] = {
|
2020-06-20 19:37:03 -04:00
|
|
|
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;
|
2020-08-07 17:59:16 -04:00
|
|
|
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
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;
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
enum patty_client_call call;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
if (call <= PATTY_CLIENT_NONE || call >= PATTY_CLIENT_CALL_COUNT) {
|
2020-06-20 19:37:03 -04:00
|
|
|
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;
|
|
|
|
|
|
|
|
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-08-01 17:13:02 -04:00
|
|
|
static int reply_test(patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
patty_ax25_frame reply = {
|
|
|
|
.control = PATTY_AX25_FRAME_UA | (PATTY_AX25_FRAME_FINAL << 4),
|
|
|
|
.proto = PATTY_AX25_PROTO_NONE,
|
|
|
|
.info = frame->info,
|
|
|
|
.infolen = frame->infolen
|
|
|
|
};
|
|
|
|
|
|
|
|
return reply_to(iface, frame, &reply);
|
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
static int frame_ack(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
sock->rx_pending = 0;
|
|
|
|
|
2020-08-23 17:37:34 -05:00
|
|
|
patty_timer_start(&sock->timer_t3);
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
if (patty_ax25_sock_ack(sock, frame->nr) > 0) {
|
|
|
|
/*
|
|
|
|
* AX.25 v2.2, Section 6.4.6 "Receiving Acknowledgement"
|
|
|
|
*
|
|
|
|
* Whenever an I or S frame is correctly received, even in a busy
|
|
|
|
* condition, the N(R) of the received frame is checked to see if it
|
|
|
|
* includes an acknowledgement of outstanding sent I frames. Timer
|
|
|
|
* T1 is canceled if the received frame actually acknowledges
|
|
|
|
* previously unacknowledged frames. If Timer T1 is canceled and
|
|
|
|
* there are still some frames that have been sent that are not
|
|
|
|
* acknowledged, Timer T1 is started again.
|
|
|
|
*/
|
|
|
|
patty_timer_stop(&sock->timer_t1);
|
2020-08-23 17:37:34 -05:00
|
|
|
|
|
|
|
if (patty_ax25_sock_ack_pending(sock) > 0) {
|
2020-08-23 22:04:58 -05:00
|
|
|
sock->retries = sock->n_retry;
|
|
|
|
|
2020-08-23 17:37:34 -05:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
|
|
|
}
|
2020-08-19 22:32:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (PATTY_AX25_FRAME_CONTROL_S(frame->control) && frame->pf) {
|
|
|
|
/*
|
|
|
|
* AX.25 v2.2, Section 6.4.11 "Waiting Acknowledgement"
|
|
|
|
*
|
|
|
|
* If the TNC correctly receives a supervisory response frame with the
|
|
|
|
* F bit set and an N(R) within the range from the last N(R) received
|
|
|
|
* to the last N(S) sent plus one, the TNC restarts Timer T1 and sets
|
|
|
|
* its send state variable V(S) to the received N(R). It may then
|
|
|
|
* resume with I frame transmission or retransmission, as appropriate.
|
2020-08-23 17:37:34 -05:00
|
|
|
*
|
|
|
|
* Errata: It is not necessary, strictly speaking, to start Timer T1
|
|
|
|
* until the moment there are I frames ready to be sent to the peer.
|
2020-08-19 22:32:05 -04:00
|
|
|
*/
|
|
|
|
int min = sock->va,
|
|
|
|
max = sock->vs;
|
|
|
|
|
|
|
|
if (max < min) {
|
|
|
|
max += sock->mode == PATTY_AX25_SOCK_SABME? 128: 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frame->nr >= min && frame->nr <= max) {
|
2020-08-20 22:01:58 -05:00
|
|
|
sock->vs = frame->nr;
|
|
|
|
sock->retries = sock->n_retry;
|
2020-08-19 22:32:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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-08-20 22:54:12 -05:00
|
|
|
switch (sock->state) {
|
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
|
|
|
if (sock->state == PATTY_AX25_SOCK_PENDING_CONNECT) {
|
|
|
|
sock->retries = sock->n_retry;
|
|
|
|
|
|
|
|
patty_timer_start(&sock->timer_t1);
|
|
|
|
|
|
|
|
return patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
|
|
|
|
}
|
2020-07-27 19:22:40 -04:00
|
|
|
|
2020-08-20 22:54:12 -05:00
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
patty_ax25_sock_reset(sock);
|
2020-08-19 22:32:05 -04:00
|
|
|
|
2020-08-20 22:54:12 -05:00
|
|
|
return 0;
|
2020-07-27 00:52:25 -04:00
|
|
|
|
2020-08-20 22:54:12 -05:00
|
|
|
default:
|
|
|
|
break;
|
2020-07-27 00:52:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 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-08-12 00:19:46 -04:00
|
|
|
&frame->dest)) == NULL
|
|
|
|
|| local->type != PATTY_AX25_SOCK_STREAM
|
|
|
|
|| local->state != PATTY_AX25_SOCK_LISTENING) {
|
|
|
|
goto reply_dm;
|
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-08-20 22:54:12 -05:00
|
|
|
remote->state = PATTY_AX25_SOCK_PENDING_ACCEPT;
|
|
|
|
|
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-08-20 22:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (remote->state) {
|
|
|
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
|
|
|
patty_ax25_sock_reset(remote);
|
|
|
|
|
|
|
|
return frame->pf == 1? reply_ua(iface, frame, 1): 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
goto reply_dm;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
remote->state = PATTY_AX25_SOCK_ESTABLISHED;
|
2020-08-03 02:54:49 -04:00
|
|
|
|
|
|
|
if (frame->type == PATTY_AX25_FRAME_SABME) {
|
|
|
|
patty_ax25_sock_params_upgrade(remote);
|
|
|
|
|
|
|
|
remote->mode = PATTY_AX25_SOCK_SABME;
|
|
|
|
} else {
|
|
|
|
remote->mode = PATTY_AX25_SOCK_SABM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_ax25_sock_realloc_bufs(remote) < 0) {
|
|
|
|
goto error_sock_realloc_bufs;
|
|
|
|
}
|
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-08-12 00:19:46 -04:00
|
|
|
if (notify_accept(local->fd, remote->fd, &remote->remote, remote->pty) < 0) {
|
|
|
|
goto error_notify_accept;
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&remote->timer_t3);
|
2020-08-01 16:41:57 -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-08-12 00:19:46 -04:00
|
|
|
reply_dm:
|
|
|
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
|
|
|
|
|
|
|
error_notify_accept:
|
2020-08-03 02:54:49 -04:00
|
|
|
error_sock_realloc_bufs:
|
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;
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:13:02 -04:00
|
|
|
static int handle_test(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-08-22 15:33:12 -05:00
|
|
|
if (!patty_ax25_if_addr_match(iface, &frame->dest)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-01 17:13:02 -04:00
|
|
|
return reply_test(iface, frame);
|
|
|
|
}
|
|
|
|
|
2020-06-30 23:20:12 -04:00
|
|
|
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-08-22 15:33:12 -05:00
|
|
|
if (!patty_ax25_if_addr_match(iface, &frame->dest)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-07-22 22:02:26 -04:00
|
|
|
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-08-03 02:54:49 -04:00
|
|
|
if (patty_ax25_sock_realloc_bufs(sock) < 0) {
|
|
|
|
goto error_sock_realloc_bufs;
|
|
|
|
}
|
|
|
|
|
2020-08-01 16:37:39 -04:00
|
|
|
patty_timer_stop(&sock->timer_t1);
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t3);
|
2020-08-01 16:41:57 -04:00
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
sock->state = 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-08-03 02:54:49 -04:00
|
|
|
error_sock_realloc_bufs:
|
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) {
|
2020-08-07 21:50:01 -04:00
|
|
|
if (sock == NULL) {
|
2020-06-30 23:20:12 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 21:50:01 -04:00
|
|
|
switch (sock->state) {
|
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT: {
|
|
|
|
int client;
|
|
|
|
|
|
|
|
if ((client = client_by_sock(server, sock)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-08-07 21:50:01 -04:00
|
|
|
patty_ax25_sock_reset(sock);
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-08-07 21:50:01 -04:00
|
|
|
return respond_connect(client, -1, ECONNREFUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
|
|
|
patty_timer_stop(&sock->timer_t1);
|
|
|
|
|
|
|
|
return sock_close(server, sock);
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-08-12 15:06:45 -04:00
|
|
|
return 0;
|
|
|
|
|
2020-07-03 19:13:34 -04:00
|
|
|
error_client_by_sock:
|
2020-06-30 23:20:12 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-08-14 22:24:17 -04:00
|
|
|
static int handle_segment(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
uint8_t *info = (uint8_t *)frame->info;
|
|
|
|
|
|
|
|
uint8_t first,
|
|
|
|
remaining;
|
|
|
|
|
|
|
|
if (frame->infolen < 2) {
|
|
|
|
goto reply_rej;
|
|
|
|
}
|
|
|
|
|
|
|
|
first = info[0] & 0x80;
|
|
|
|
remaining = info[0] & 0x7f;
|
|
|
|
|
|
|
|
if (first) {
|
|
|
|
if (remaining == 0) {
|
|
|
|
goto reply_rej;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_ax25_sock_assembler_init(sock, remaining + 1) < 0) {
|
|
|
|
goto error_sock_assembler_init;
|
|
|
|
}
|
|
|
|
} else if (remaining > 0) {
|
|
|
|
if (frame->infolen != sock->n_maxlen_rx) {
|
|
|
|
goto reply_rej;
|
|
|
|
}
|
|
|
|
} else if (remaining == 0) {
|
|
|
|
if (frame->infolen > sock->n_maxlen_rx) {
|
|
|
|
goto reply_rej;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!patty_ax25_sock_assembler_ready(sock, remaining)) {
|
|
|
|
patty_ax25_sock_assembler_stop(sock);
|
|
|
|
|
|
|
|
goto reply_rej;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_ax25_sock_assembler_save(sock,
|
|
|
|
info + 1,
|
|
|
|
frame->infolen - 1) < 0) {
|
|
|
|
goto error_sock_assembler_save;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remaining == 0) {
|
|
|
|
size_t len;
|
|
|
|
void *buf;
|
|
|
|
|
|
|
|
if ((buf = patty_ax25_sock_assembler_read(sock, NULL, &len)) == NULL) {
|
|
|
|
goto error_sock_assembler_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(sock->fd, buf, len) < 0) {
|
|
|
|
goto error_write;
|
|
|
|
}
|
|
|
|
|
|
|
|
patty_ax25_sock_assembler_stop(sock);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
reply_rej:
|
2020-08-17 21:31:28 -05:00
|
|
|
return patty_ax25_sock_send_srej(sock, PATTY_AX25_FRAME_RESPONSE);
|
2020-08-14 22:24:17 -04:00
|
|
|
|
|
|
|
error_write:
|
|
|
|
error_sock_assembler_read:
|
|
|
|
error_sock_assembler_save:
|
|
|
|
error_sock_assembler_init:
|
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
if (sock == NULL || sock->state != 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-08-19 22:32:05 -04:00
|
|
|
frame_ack(server, sock, frame);
|
2020-08-18 19:07:43 -05:00
|
|
|
|
2020-08-17 21:31:28 -05:00
|
|
|
if (frame->ns == sock->vr) {
|
2020-08-03 18:47:48 -04:00
|
|
|
patty_ax25_sock_vr_incr(sock);
|
2020-08-17 21:31:28 -05:00
|
|
|
} else if (frame->ns == sock->vr + 1) {
|
|
|
|
return patty_ax25_sock_send_srej(sock, PATTY_AX25_FRAME_RESPONSE);
|
|
|
|
} else if (frame->ns > sock->vr + 1) {
|
|
|
|
return patty_ax25_sock_send_rej(sock, PATTY_AX25_FRAME_RESPONSE, 1);
|
2020-07-06 23:39:22 -04:00
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-08-14 22:24:17 -04:00
|
|
|
if (frame->proto == PATTY_AX25_PROTO_FRAGMENT) {
|
|
|
|
if (handle_segment(server, iface, sock, frame) < 0) {
|
|
|
|
goto error_handle_segment;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (write(sock->fd, frame->info, frame->infolen) < 0) {
|
|
|
|
goto error_write;
|
|
|
|
}
|
2020-07-10 17:09:37 -04:00
|
|
|
}
|
|
|
|
|
2020-08-22 22:57:35 -05:00
|
|
|
if (frame->pf || ++sock->rx_pending == sock->n_window_rx / 2) {
|
|
|
|
/*
|
|
|
|
* AX.25 v2.2 Section 6.7.1.2 "Response Delay Timer T2"
|
|
|
|
*
|
|
|
|
* Timer T2, the Response Delay Timer, may optionally be implemented
|
|
|
|
* by the TNC to specify a maximum amount of delay to be introduced
|
|
|
|
* between the time an I frame is received and the time the resulting
|
|
|
|
* response frame is sent. This delay is introduced to allow a
|
|
|
|
* receiving TNC to wait a short period of time to determine if more
|
|
|
|
* than one frame is being sent to it. If more frames are received,
|
|
|
|
* the TNC can acknowledge them at once (up to seven),
|
|
|
|
* rather than acknowledging each individual frame. The use of Timer
|
|
|
|
* T2 is not required; it is simply recommended to improve channel
|
|
|
|
* efficiency. Note that to achieve maximum throughput on full-duplex
|
|
|
|
* channels, acknowledgements should not be delayed beyond k/2
|
|
|
|
* frames. The k parameter is defined in Section 6.8.2.3.
|
|
|
|
*/
|
2020-08-19 22:09:56 -04:00
|
|
|
sock->rx_pending = 0;
|
2020-08-07 22:11:03 -04:00
|
|
|
|
2020-08-01 16:37:39 -04:00
|
|
|
patty_timer_stop(&sock->timer_t2);
|
2020-07-31 01:14:11 -04:00
|
|
|
|
2020-08-22 22:57:35 -05:00
|
|
|
/*
|
|
|
|
* AX.25 v2.2 Section 6.2 "Poll/Final (P/F) Bit Procedures"
|
|
|
|
*/
|
2020-08-22 21:48:23 -05:00
|
|
|
return frame->pf?
|
|
|
|
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1): 0;
|
2020-07-31 01:14:11 -04:00
|
|
|
}
|
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t2);
|
|
|
|
patty_timer_start(&sock->timer_t3);
|
2020-08-01 16:41:57 -04:00
|
|
|
|
2020-07-31 01:14:11 -04:00
|
|
|
return 0;
|
2020-07-10 17:09:37 -04:00
|
|
|
|
2020-08-14 22:24:17 -04:00
|
|
|
error_handle_segment:
|
2020-07-10 17:09:37 -04:00
|
|
|
error_write:
|
|
|
|
return -1;
|
2020-06-29 00:29:50 -04:00
|
|
|
}
|
|
|
|
|
2020-08-07 18:17:36 -04:00
|
|
|
static int handle_ui(patty_ax25_server *server,
|
|
|
|
patty_ax25_if *iface,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
if (sock == NULL || sock->type != PATTY_AX25_SOCK_DGRAM) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-14 22:24:17 -04:00
|
|
|
if (frame->proto == PATTY_AX25_PROTO_FRAGMENT) {
|
|
|
|
return handle_segment(server, iface, sock, frame);
|
|
|
|
}
|
|
|
|
|
2020-08-07 18:17:36 -04:00
|
|
|
return write(sock->fd, frame->info, frame->infolen);
|
|
|
|
}
|
|
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-07-22 22:52:10 -04:00
|
|
|
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-08-01 16:41:57 -04:00
|
|
|
static int handle_rr(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
2020-08-04 23:33:18 -04:00
|
|
|
if (sock == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
frame_ack(server, sock, frame);
|
2020-08-04 23:33:18 -04:00
|
|
|
|
|
|
|
switch (frame->cr) {
|
|
|
|
case PATTY_AX25_FRAME_COMMAND:
|
2020-08-22 22:54:11 -05:00
|
|
|
return frame->pf?
|
|
|
|
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1): 0;
|
2020-08-04 23:33:18 -04:00
|
|
|
|
|
|
|
case PATTY_AX25_FRAME_RESPONSE:
|
2020-08-19 22:32:05 -04:00
|
|
|
sock_flow_start(server, sock);
|
2020-08-04 23:33:18 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_rnr(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock,
|
|
|
|
patty_ax25_frame *frame) {
|
|
|
|
if (sock == NULL) {
|
2020-08-01 16:41:57 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
frame_ack(server, sock, frame);
|
2020-08-18 19:07:43 -05:00
|
|
|
|
2020-08-01 16:41:57 -04:00
|
|
|
switch (frame->cr) {
|
|
|
|
case PATTY_AX25_FRAME_COMMAND:
|
2020-08-22 22:54:11 -05:00
|
|
|
return frame->pf?
|
|
|
|
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1): 0;
|
2020-08-04 23:33:18 -04:00
|
|
|
|
2020-08-01 16:41:57 -04:00
|
|
|
case PATTY_AX25_FRAME_RESPONSE:
|
2020-08-19 22:32:05 -04:00
|
|
|
sock_flow_stop(server, sock);
|
2020-08-01 16:41:57 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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-22 22:52:10 -04:00
|
|
|
if (sock == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
frame_ack(server, sock, frame);
|
2020-08-16 18:15:11 -05:00
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
switch (frame->cr) {
|
|
|
|
case PATTY_AX25_FRAME_COMMAND:
|
2020-08-22 22:54:11 -05:00
|
|
|
return frame->pf?
|
|
|
|
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1): 0;
|
2020-08-06 00:35:11 -04:00
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
case PATTY_AX25_FRAME_RESPONSE:
|
|
|
|
sock_flow_start(server, sock);
|
2020-07-26 01:41:44 -04:00
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
default:
|
|
|
|
break;
|
2020-07-16 00:14:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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-08-19 22:32:05 -04:00
|
|
|
frame_ack(server, sock, frame);
|
2020-08-16 18:15:11 -05:00
|
|
|
|
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-27 19:22:40 -04:00
|
|
|
int ret;
|
|
|
|
|
2020-08-22 15:33:12 -05:00
|
|
|
if (!patty_ax25_if_addr_match(iface, &frame->dest)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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-08-07 17:58:13 -04:00
|
|
|
if (remote->state != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
2020-07-22 22:02:26 -04:00
|
|
|
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-08-03 02:54:49 -04:00
|
|
|
if (patty_ax25_sock_params_negotiate(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-08-03 02:54:49 -04:00
|
|
|
patty_ax25_sock_init(remote);
|
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-27 19:22:40 -04:00
|
|
|
ret = patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
|
2020-07-22 22:02:26 -04:00
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&remote->timer_t1);
|
2020-07-27 19:22:40 -04:00
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
remote->retries = remote->n_retry;
|
|
|
|
|
2020-07-27 19:22:40 -04:00
|
|
|
return ret;
|
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-08-12 22:57:34 -04:00
|
|
|
int ret,
|
|
|
|
client;
|
2020-07-22 22:02:26 -04:00
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
if (local->state != PATTY_AX25_SOCK_LISTENING) {
|
2020-07-22 22:02:26 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
remote->state = PATTY_AX25_SOCK_PENDING_ACCEPT;
|
2020-07-19 23:00:57 -04:00
|
|
|
|
|
|
|
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-08-03 02:54:49 -04:00
|
|
|
patty_ax25_sock_params_max(remote);
|
2020-07-19 23:00:57 -04:00
|
|
|
|
2020-08-03 02:54:49 -04:00
|
|
|
if (patty_ax25_sock_params_negotiate(remote, ¶ms) < 0) {
|
2020-08-12 00:19:46 -04:00
|
|
|
goto error_sock_params_negotiate;
|
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-08-12 22:57:34 -04:00
|
|
|
ret = patty_ax25_sock_send_xid(remote, PATTY_AX25_FRAME_RESPONSE);
|
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&remote->timer_t1);
|
2020-08-12 22:57:34 -04:00
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
remote->retries = remote->n_retry;
|
|
|
|
|
2020-08-12 22:57:34 -04:00
|
|
|
return ret;
|
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-08-12 00:19:46 -04:00
|
|
|
error_sock_params_negotiate:
|
|
|
|
patty_ax25_sock_destroy(remote);
|
|
|
|
|
2020-07-19 23:00:57 -04:00
|
|
|
error_sock_new:
|
2020-07-22 22:02:26 -04:00
|
|
|
error_client_by_sock:
|
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-08-09 13:16:21 -04:00
|
|
|
goto error_decode;
|
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-08-09 13:16:21 -04:00
|
|
|
goto error_decode;
|
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-08-07 18:17:36 -04:00
|
|
|
case PATTY_AX25_FRAME_UI: return handle_ui(server, iface, sock, &frame);
|
2020-08-01 16:41:57 -04:00
|
|
|
case PATTY_AX25_FRAME_RR: return handle_rr(server, sock, &frame);
|
2020-08-04 23:33:18 -04:00
|
|
|
case PATTY_AX25_FRAME_RNR: return handle_rnr(server, 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);
|
2020-08-01 17:13:02 -04:00
|
|
|
case PATTY_AX25_FRAME_TEST: return handle_test(server, iface, &frame);
|
2020-07-22 22:52:10 -04:00
|
|
|
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-10 00:01:50 -04:00
|
|
|
}
|
|
|
|
|
2020-07-14 17:12:17 -04:00
|
|
|
return 0;
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-08-09 13:16:21 -04:00
|
|
|
error_decode:
|
2020-07-16 23:05:31 -04:00
|
|
|
iface->stats.dropped++;
|
|
|
|
|
2020-08-09 13:16:21 -04:00
|
|
|
return 0;
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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-08-07 22:06:22 -04:00
|
|
|
static int handle_sock_dgram(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
ssize_t len;
|
|
|
|
|
|
|
|
if (!FD_ISSET(sock->fd, &server->fds_r)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-23 21:01:07 -05:00
|
|
|
if ((len = read(sock->fd, sock->io_buf, sock->n_maxlen_tx)) < 0) {
|
2020-08-07 22:06:22 -04:00
|
|
|
if (errno == EIO) {
|
|
|
|
(void)sock_close(server, sock);
|
|
|
|
} else {
|
|
|
|
goto error_unknown;
|
|
|
|
}
|
|
|
|
} else if (len == 0) {
|
|
|
|
(void)sock_close(server, sock);
|
|
|
|
} else if (len > 0) {
|
2020-08-23 21:01:07 -05:00
|
|
|
if (patty_ax25_sock_write(sock, sock->io_buf, len) < 0) {
|
2020-08-07 22:06:22 -04:00
|
|
|
goto error_sock_write;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_sock_write:
|
|
|
|
error_unknown:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-08-05 02:05:15 -04:00
|
|
|
static int handle_sock_raw(patty_ax25_server *server,
|
|
|
|
patty_ax25_sock *sock) {
|
|
|
|
if (!FD_ISSET(sock->fd, &server->fds_r) || sock->iface == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-05 21:47:08 -04:00
|
|
|
do {
|
|
|
|
ssize_t len;
|
2020-08-05 02:05:15 -04:00
|
|
|
|
2020-08-05 21:47:08 -04:00
|
|
|
if ((len = patty_ax25_sock_recv(sock,
|
|
|
|
sock->iface->tx_buf,
|
|
|
|
sock->iface->mtu)) < 0) {
|
2020-08-11 02:03:23 -04:00
|
|
|
if (errno == EIO) {
|
|
|
|
(void)sock_close(server, sock);
|
|
|
|
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
} else if (len == 0) {
|
|
|
|
(void)sock_close(server, sock);
|
|
|
|
|
|
|
|
break;
|
2020-08-05 21:47:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_ax25_sock_send(sock, sock->iface->tx_buf, len) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
} while (patty_ax25_sock_recv_pending(sock));
|
2020-08-05 02:05:15 -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-08-07 22:06:22 -04:00
|
|
|
switch (sock->type) {
|
|
|
|
case PATTY_AX25_SOCK_DGRAM:
|
|
|
|
return handle_sock_dgram(server, sock);
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_RAW:
|
|
|
|
return handle_sock_raw(server, sock);
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_STREAM:
|
|
|
|
break;
|
2020-08-05 02:05:15 -04:00
|
|
|
}
|
|
|
|
|
2020-08-07 22:06:22 -04:00
|
|
|
patty_timer_tick(&sock->timer_t1, &server->elapsed);
|
|
|
|
patty_timer_tick(&sock->timer_t2, &server->elapsed);
|
|
|
|
patty_timer_tick(&sock->timer_t3, &server->elapsed);
|
|
|
|
|
2020-08-07 17:58:13 -04:00
|
|
|
switch (sock->state) {
|
2020-08-12 22:57:34 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
|
|
|
if (patty_timer_expired(&sock->timer_t1)) {
|
2020-08-23 20:35:10 -05:00
|
|
|
if (sock->retries--) {
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-12 22:57:34 -04:00
|
|
|
|
2020-08-23 20:35:10 -05:00
|
|
|
return patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_RESPONSE);
|
2020-08-12 22:57:34 -04:00
|
|
|
} else {
|
|
|
|
(void)sock_close(server, sock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2020-07-31 01:14:11 -04:00
|
|
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
|
|
|
if (patty_timer_expired(&sock->timer_t1)) {
|
2020-08-23 20:35:10 -05:00
|
|
|
if (sock->retries--) {
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-07-27 00:52:25 -04:00
|
|
|
|
2020-08-23 20:35:10 -05:00
|
|
|
return patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
|
2020-07-31 01:14:11 -04:00
|
|
|
} else {
|
2020-08-03 02:54:49 -04:00
|
|
|
int client;
|
|
|
|
|
|
|
|
if ((client = client_by_sock(server, sock)) < 0) {
|
|
|
|
goto error_client_by_sock;
|
|
|
|
}
|
|
|
|
|
2020-07-31 01:14:11 -04:00
|
|
|
(void)sock_shutdown(server, sock);
|
2020-08-03 02:54:49 -04:00
|
|
|
(void)sock_close(server, sock);
|
2020-07-31 01:14:11 -04:00
|
|
|
|
2020-08-03 02:54:49 -04:00
|
|
|
return respond_connect(client, -1, ETIMEDOUT);
|
2020-07-31 01:14:11 -04:00
|
|
|
}
|
2020-07-27 00:52:25 -04:00
|
|
|
}
|
|
|
|
|
2020-08-07 22:06:22 -04:00
|
|
|
return 0;
|
2020-07-31 01:14:11 -04:00
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
2020-08-01 16:41:57 -04:00
|
|
|
if (patty_timer_expired(&sock->timer_t1)) {
|
2020-08-23 20:35:10 -05:00
|
|
|
if (sock->retries--) {
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-23 20:35:10 -05:00
|
|
|
|
2020-08-23 21:03:03 -05:00
|
|
|
return patty_ax25_sock_resend_pending(sock)
|
|
|
|
|| patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1);
|
2020-08-01 16:41:57 -04:00
|
|
|
} else {
|
|
|
|
(void)sock_shutdown(server, sock);
|
|
|
|
|
|
|
|
return sock_close(server, sock);
|
|
|
|
}
|
|
|
|
}
|
2020-07-31 01:14:11 -04:00
|
|
|
|
|
|
|
if (patty_timer_expired(&sock->timer_t2)) {
|
2020-08-01 16:41:57 -04:00
|
|
|
patty_timer_stop(&sock->timer_t2);
|
|
|
|
|
2020-08-19 22:09:56 -04:00
|
|
|
if (sock->rx_pending) {
|
|
|
|
sock->rx_pending = 0;
|
2020-07-31 01:14:11 -04:00
|
|
|
|
2020-08-22 21:48:56 -05:00
|
|
|
return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1);
|
2020-07-31 01:14:11 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 16:41:57 -04:00
|
|
|
if (patty_timer_expired(&sock->timer_t3)) {
|
|
|
|
/*
|
2020-08-19 22:32:05 -04:00
|
|
|
* AX.25 v.2.2 Section 6.7.1.3 "Inactive Link Timer T3"
|
2020-08-01 16:41:57 -04:00
|
|
|
*/
|
2020-08-19 22:32:05 -04:00
|
|
|
sock->retries = sock->n_retry;
|
|
|
|
|
2020-08-01 16:41:57 -04:00
|
|
|
patty_timer_stop(&sock->timer_t3);
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-01 16:41:57 -04:00
|
|
|
|
2020-08-22 21:49:15 -05:00
|
|
|
return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1);
|
2020-08-01 16:41:57 -04:00
|
|
|
}
|
|
|
|
|
2020-08-23 22:29:11 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PATTY_AX25_SOCK_PENDING_DISCONNECT:
|
|
|
|
if (patty_timer_expired(&sock->timer_t1)) {
|
|
|
|
if (sock->retries--) {
|
|
|
|
patty_timer_start(&sock->timer_t1);
|
|
|
|
|
|
|
|
return patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL);
|
|
|
|
} else {
|
|
|
|
return sock_close(server, sock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-31 01:14:11 -04:00
|
|
|
default:
|
|
|
|
break;
|
2020-07-27 00:52:25 -04:00
|
|
|
}
|
|
|
|
|
2020-07-03 15:21:32 -04:00
|
|
|
if (!FD_ISSET(sock->fd, &server->fds_r)) {
|
2020-08-07 22:06:22 -04:00
|
|
|
return 0;
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
2020-08-16 18:15:11 -05:00
|
|
|
if (sock->flow == PATTY_AX25_SOCK_WAIT) {
|
|
|
|
sock->flow = PATTY_AX25_SOCK_READY;
|
2020-08-23 00:39:39 -05:00
|
|
|
}
|
2020-08-17 18:53:55 -04:00
|
|
|
|
2020-08-23 00:39:39 -05:00
|
|
|
/*
|
|
|
|
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
|
|
|
|
*/
|
|
|
|
if (patty_ax25_sock_flow_left(sock) == 1) {
|
2020-08-19 22:32:05 -04:00
|
|
|
sock_flow_stop(server, sock);
|
2020-07-26 01:48:08 -04:00
|
|
|
}
|
|
|
|
|
2020-08-19 22:32:05 -04:00
|
|
|
/*
|
|
|
|
* Check to see if any frames are pending resend. If so, return, allowing
|
|
|
|
* service to another socket rather than sending another frame to the
|
|
|
|
* current peer.
|
|
|
|
*/
|
|
|
|
if ((len = patty_ax25_sock_resend_pending(sock)) < 0) {
|
|
|
|
goto error_sock_resend_pending;
|
|
|
|
} else if (len > 0) {
|
|
|
|
patty_timer_start(&sock->timer_t1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-23 21:01:07 -05:00
|
|
|
if ((len = read(sock->fd, sock->io_buf, sock->n_maxlen_tx)) < 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-08-07 22:06:22 -04:00
|
|
|
} else {
|
|
|
|
goto error_unknown;
|
2020-06-21 01:13:33 -04:00
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
} else if (len == 0) {
|
2020-07-22 22:02:26 -04:00
|
|
|
(void)sock_shutdown(server, sock);
|
2020-08-07 22:06:22 -04:00
|
|
|
} else if (len > 0) {
|
2020-08-23 21:01:07 -05:00
|
|
|
if (patty_ax25_sock_write(sock, sock->io_buf, len) < 0) {
|
2020-08-07 22:06:22 -04:00
|
|
|
goto error_sock_write;
|
|
|
|
}
|
2020-07-01 20:15:46 -04:00
|
|
|
|
2020-08-19 22:06:39 -04:00
|
|
|
patty_timer_start(&sock->timer_t1);
|
2020-08-23 00:57:16 -05:00
|
|
|
patty_timer_stop(&sock->timer_t3);
|
2020-06-21 01:13:33 -04:00
|
|
|
}
|
|
|
|
|
2020-06-20 19:37:03 -04:00
|
|
|
return 0;
|
2020-06-21 01:13:33 -04:00
|
|
|
|
2020-08-03 02:54:49 -04:00
|
|
|
error_client_by_sock:
|
2020-06-30 23:20:12 -04:00
|
|
|
error_sock_write:
|
2020-08-19 22:32:05 -04:00
|
|
|
error_sock_resend_pending:
|
2020-08-07 22:06:22 -04:00
|
|
|
error_unknown:
|
2020-06-21 01:13:33 -04:00
|
|
|
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-08-10 18:48:14 -04:00
|
|
|
struct timeval timeout = { 1, 0 };
|
|
|
|
|
|
|
|
struct timespec before,
|
|
|
|
after;
|
2020-07-27 00:52:25 -04:00
|
|
|
|
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
|
|
|
|
2020-08-10 18:48:14 -04:00
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) {
|
|
|
|
goto error_clock_gettime;
|
2020-08-07 21:44:24 -04:00
|
|
|
}
|
|
|
|
|
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-08-07 21:44:24 -04:00
|
|
|
&timeout)) < 0) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-08-10 18:48:14 -04:00
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) {
|
|
|
|
goto error_clock_gettime;
|
2020-08-07 21:44:24 -04:00
|
|
|
}
|
|
|
|
|
2020-08-10 18:48:14 -04:00
|
|
|
patty_timer_sub(&after, &before, &server->elapsed);
|
2020-07-27 00:52:25 -04:00
|
|
|
|
2020-08-07 21:46:22 -04:00
|
|
|
if (handle_socks(server) < 0) {
|
2020-06-20 19:37:03 -04:00
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-08-07 21:46:22 -04:00
|
|
|
if (nready > 0) {
|
|
|
|
if (handle_clients(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
|
2020-08-07 21:46:22 -04:00
|
|
|
if (handle_ifaces(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
|
2020-08-07 21:46:22 -04:00
|
|
|
if (accept_client(server) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2020-06-30 23:20:12 -04:00
|
|
|
}
|
2020-06-20 19:37:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
close(server->fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2020-08-10 18:48:14 -04:00
|
|
|
error_clock_gettime:
|
2020-06-20 19:37:03 -04:00
|
|
|
error_io:
|
|
|
|
close(server->fd);
|
|
|
|
|
|
|
|
error_listen_unix:
|
|
|
|
return -1;
|
|
|
|
}
|