SO BLOODY CLOSE

This commit is contained in:
XANTRONIX Development 2020-06-30 23:20:12 -04:00 committed by XANTRONIX Industrial
parent 94f073c38d
commit 22bf692a61
9 changed files with 594 additions and 241 deletions

View file

@ -18,16 +18,19 @@ enum patty_ax25_call {
* socket()
*/
typedef struct _patty_ax25_call_socket_request {
int type;
int opts;
} patty_ax25_call_socket_request;
typedef struct _patty_ax25_response_socket {
int ret;
int eno;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_ax25_call_socket_response;
int patty_ax25_call_socket(int server,
int type);
int opts,
char *path,
size_t len);
/*
* bind()
@ -71,14 +74,15 @@ typedef struct _patty_ax25_call_accept_request {
typedef struct _patty_ax25_call_accept_response {
int ret;
int eno;
char path[PATTY_AX25_SOCK_PATH_SIZE];
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_ax25_call_accept_response;
int patty_ax25_call_accept(int server,
int socket,
patty_ax25_addr *peer,
char *path);
char *path,
size_t len);
/*
* connect()
@ -91,13 +95,11 @@ typedef struct _patty_ax25_call_connect_request {
typedef struct _patty_ax25_call_connect_response {
int ret;
int eno;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_ax25_call_connect_response;
int patty_ax25_call_connect(int server,
int socket,
patty_ax25_addr *peer,
char *path);
patty_ax25_addr *peer);
/*
* close()

View file

@ -56,7 +56,7 @@
(((c & 0xe0) == 0x00) && ((c & 0x0f) == 0x0f))
#define PATTY_AX25_CONTROL_UNNUMBERED_UA(c) \
(((c & 0xe0) == 0x30) && ((c & 0x0f) == 0x03))
(((c & 0xe0) == 0x60) && ((c & 0x0f) == 0x03))
#define PATTY_AX25_CONTROL_UNNUMBERED_FRMR(c) \
(((c & 0xe0) == 0x40) && ((c & 0x0f) == 0x07))

View file

@ -1,12 +1,13 @@
#ifndef _PATTY_AX25_SOCK_H
#define _PATTY_AX25_SOCK_H
enum patty_ax25_sock_type {
#define PATTY_AX25_SOCK_BUFSZ 4096
enum patty_ax25_sock_opts {
PATTY_AX25_SOCK_NONE,
PATTY_AX25_SOCK_UNIX = 1 << 0,
PATTY_AX25_SOCK_PTY = 1 << 1,
PATTY_AX25_SOCK_RAW = 1 << 2,
PATTY_AX25_SOCK_NONBLOCK = 1 << 3
PATTY_AX25_SOCK_PTY = 1 << 0,
PATTY_AX25_SOCK_RAW = 1 << 1,
PATTY_AX25_SOCK_NONBLOCK = 1 << 2
};
enum patty_ax25_sock_status {
@ -24,7 +25,7 @@ enum patty_ax25_sock_mode {
};
typedef struct _patty_ax25_sock {
enum patty_ax25_sock_type type;
enum patty_ax25_sock_opts opts;
enum patty_ax25_sock_status status;
enum patty_ax25_sock_mode mode;
@ -42,6 +43,9 @@ typedef struct _patty_ax25_sock {
int fd;
char path[PATTY_AX25_SOCK_PATH_SIZE];
void *buf;
size_t bufsz;
patty_ax25_if *iface;
patty_ax25_addr local,
@ -52,7 +56,7 @@ typedef struct _patty_ax25_sock {
} patty_ax25_sock;
#define PATTY_AX25_SOCK_CONTROL_SABM(sock, flag) \
(((sock->seq_recv & 07) << 7) | (flag << 4) | (sock->seq_send & 07))
(((sock->seq_recv & 0x07) << 7) | (flag << 4) | (sock->seq_send & 0x07))
#define PATTY_AX25_SOCK_CONTROL_SABME(sock, flag) \
(((sock->seq_recv & 0x7f) << 15) | (flag << 7) | (sock->seq_send & 0x7f))
@ -62,10 +66,14 @@ typedef struct _patty_ax25_sock {
PATTY_AX25_SOCK_CONTROL_SABME(sock, flag): \
PATTY_AX25_SOCK_CONTROL_SABM(sock, flag))
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type);
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts);
void patty_ax25_sock_reset(patty_ax25_sock *sock);
void patty_ax25_sock_destroy(patty_ax25_sock *sock);
char *patty_ax25_sock_pty(patty_ax25_sock *sock);
ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
uint16_t control,
uint8_t proto,
@ -74,6 +82,10 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int poll);
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int poll);
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll);
ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
uint8_t proto,
void *buf,

View file

@ -14,7 +14,7 @@ HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
OBJS = kiss.o ax25.o if.o call.o frame.o sock.o route.o server.o \
list.o hash.o dict.o
EXAMPLES = decode ptmx testclient testserver
EXAMPLES = decode ptmx testclient-connect testclient-listen testserver
HEADERS_BUILD = $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/, $(HEADERS))

View file

@ -6,11 +6,13 @@
#include <patty/ax25.h>
int patty_ax25_call_socket(int server,
int type) {
int opts,
char *path,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET;
patty_ax25_call_socket_request request = {
type
opts
};
patty_ax25_call_socket_response response;
@ -27,6 +29,10 @@ int patty_ax25_call_socket(int server,
goto error_io;
}
if (path) {
strncpy(path, response.path, len);
}
errno = response.eno;
return response.ret;
@ -101,7 +107,8 @@ error_io:
int patty_ax25_call_accept(int server,
int socket,
patty_ax25_addr *peer,
char *path) {
char *path,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_ACCEPT;
patty_ax25_call_accept_request request = {
@ -110,6 +117,8 @@ int patty_ax25_call_accept(int server,
patty_ax25_call_accept_response response;
memset(&response, '\0', sizeof(response));
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
@ -123,8 +132,11 @@ int patty_ax25_call_accept(int server,
}
if (response.ret >= 0) {
strncpy(path, response.path, PATTY_AX25_SOCK_PATH_SIZE);
memcpy(peer, &response.peer, sizeof(*peer));
if (path) {
strncpy(path, response.path, len);
}
}
errno = response.eno;
@ -137,8 +149,7 @@ error_io:
int patty_ax25_call_connect(int server,
int socket,
patty_ax25_addr *peer,
char *path) {
patty_ax25_addr *peer) {
enum patty_ax25_call call = PATTY_AX25_CALL_CONNECT;
patty_ax25_call_connect_request request = {
@ -161,10 +172,6 @@ int patty_ax25_call_connect(int server,
goto error_io;
}
if (response.ret >= 0) {
strncpy(path, response.path, PATTY_AX25_SOCK_PATH_SIZE);
}
errno = response.eno;
return response.ret;

View file

@ -23,8 +23,6 @@ struct _patty_ax25_server {
struct timeval timeout;
fd_set fds_watch, /* fds to monitor with select() */
fds_socks, /* fds belonging to socks */
fds_clients, /* fds belonging to clients */
fds_r, /* fds select()ed for reading */
fds_w; /* fds select()ed for writing */
@ -126,31 +124,18 @@ static patty_ax25_sock *sock_by_fd(patty_dict *dict,
static patty_ax25_sock *sock_by_addr(patty_dict *dict,
patty_ax25_addr *addr) {
patty_dict_slot *slot;
uint32_t hash;
patty_hash_init(&hash);
patty_ax25_addr_hash(&hash, addr);
patty_hash_end(&hash);
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
errno = EEXIST;
goto error_dict_slot_find;
}
return (patty_ax25_sock *)slot->value;
error_dict_slot_find:
return NULL;
return patty_dict_get_with_hash(dict, hash);
}
static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
patty_ax25_addr *local,
patty_ax25_addr *remote) {
patty_dict_slot *slot;
uint32_t hash;
patty_hash_init(&hash);
@ -158,16 +143,7 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
patty_ax25_addr_hash(&hash, remote);
patty_hash_end(&hash);
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
errno = EEXIST;
goto error_dict_slot_find;
}
return (patty_ax25_sock *)slot->value;
error_dict_slot_find:
return NULL;
return patty_dict_get_with_hash(dict, hash);
}
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
@ -329,26 +305,10 @@ static inline void clear_fd(patty_ax25_server *server, int fd) {
static inline void watch_sock(patty_ax25_server *server, patty_ax25_sock *sock) {
watch_fd(server, sock->fd);
FD_SET(sock->fd, &server->fds_socks);
}
static inline void clear_sock(patty_ax25_server *server, patty_ax25_sock *sock) {
clear_fd(server, sock->fd);
FD_CLR(sock->fd, &server->fds_socks);
}
static inline void watch_client(patty_ax25_server *server, int fd) {
watch_fd(server, fd);
FD_SET(fd, &server->fds_clients);
}
static inline void clear_client(patty_ax25_server *server, int fd) {
clear_fd(server, fd);
FD_CLR(fd, &server->fds_clients);
}
int patty_ax25_server_add_if(patty_ax25_server *server,
@ -469,17 +429,10 @@ static int server_socket(patty_ax25_server *server,
goto error_read;
}
if ((sock = patty_ax25_sock_new(request.type)) == NULL) {
if ((sock = patty_ax25_sock_new(request.opts)) == NULL) {
goto error_sock_new;
}
if ((sock->fd = open("/dev/null", O_RDWR)) < 0) {
goto error_open;
}
response.ret = sock->fd;
response.eno = 0;
if (sock_save_by_fd(server->socks_by_fd, sock) < 0) {
response.ret = -1;
response.eno = errno;
@ -487,17 +440,28 @@ static int server_socket(patty_ax25_server *server,
goto error_sock_save_by_fd;
}
error_sock_save_by_fd:
if (patty_dict_set_with_hash(server->clients_by_sock,
NULL + sock->fd,
sizeof(sock->fd),
NULL + client,
(uint32_t)sock->fd) < 0) {
goto error_dict_set_with_hash;
}
response.ret = sock->fd;
response.eno = 0;
memcpy(response.path, sock->path, sizeof(response.path));
if (write(client, &response, sizeof(response)) < 0) {
goto error_write;
}
return 0;
error_dict_set_with_hash:
error_sock_save_by_fd:
error_write:
close(sock->fd);
error_open:
patty_ax25_sock_destroy(sock);
error_sock_new:
@ -593,132 +557,30 @@ error_io:
return -1;
}
static int server_accept_pty(patty_ax25_server *server,
patty_ax25_call_accept_response *response,
patty_ax25_sock *sock) {
if ((sock->fd = open("/dev/ptmx", O_RDWR)) < 0) {
goto error_open;
}
if (grantpt(sock->fd) < 0) {
goto error_grantpt;
}
if (unlockpt(sock->fd) < 0) {
goto error_unlockpt;
}
if (ptsname_r(sock->fd, response->path, PATTY_AX25_SOCK_PATH_SIZE) < 0) {
goto error_ptsname_r;
}
sock->type |= PATTY_AX25_SOCK_PTY;
response->ret = sock->fd;
response->eno = 0;
return 0;
error_ptsname_r:
error_unlockpt:
error_grantpt:
close(sock->fd);
error_open:
return -1;
}
static int server_accept_unix(patty_ax25_server *server,
patty_ax25_call_accept_response *response,
patty_ax25_sock *sock) {
struct sockaddr_un addr;
struct stat st;
if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
if (snprintf(response->path,
PATTY_AX25_SOCK_PATH_SIZE,
PATTY_AX25_SERVER_CLIENT_PATH_FORMAT,
sock->fd) < 0) {
goto error_snprintf;
}
if (stat(response->path, &st) >= 0) {
unlink(response->path);
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, response->path, sizeof(addr.sun_path));
if (bind(sock->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_bind;
}
sock->type |= PATTY_AX25_SOCK_UNIX;
response->ret = sock->fd;
response->eno = 0;
return 0;
error_bind:
error_snprintf:
close(sock->fd);
error_socket:
return -1;
}
static int server_accept(patty_ax25_server *server,
int client) {
patty_ax25_call_accept_request request;
patty_ax25_call_accept_response response;
patty_ax25_sock *local,
*remote;
patty_ax25_sock *sock;
if (read(client, &request, sizeof(request)) < 0) {
goto error_io;
}
if ((local = sock_by_fd(server->socks_by_fd, request.socket)) == NULL) {
if ((sock = sock_by_fd(server->socks_by_fd, request.socket)) == NULL) {
response.ret = -1;
response.eno = EBADF;
goto error_sock_by_fd;
}
if ((remote = patty_ax25_sock_new(local->type)) == NULL) {
goto error_sock_new_remote;
}
memcpy(&remote->local, &local->local, sizeof(remote->local));
if (local->type & PATTY_AX25_SOCK_PTY) {
if (server_accept_pty(server, &response, remote) < 0) {
goto error_server_accept_pty;
}
} else {
if (server_accept_unix(server, &response, remote) < 0) {
goto error_server_accept_unix;
}
}
remote->status = PATTY_AX25_SOCK_PENDING_ACCEPT;
if (sock_save_by_addr(server->socks_pending_accept,
remote,
&local->local) < 0) {
sock,
&sock->local) < 0) {
goto error_save_by_addr;
}
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
goto error_save_by_fd;
}
return 0;
error_sock_by_fd:
@ -728,13 +590,7 @@ error_sock_by_fd:
return 0;
error_save_by_fd:
error_save_by_addr:
error_server_accept_unix:
error_server_accept_pty:
patty_ax25_sock_destroy(remote);
error_sock_new_remote:
error_io:
return -1;
}
@ -828,6 +684,14 @@ static int server_connect(patty_ax25_server *server,
goto error_sock_save_by_addrpair;
}
if (patty_dict_set_with_hash(server->clients_by_sock,
NULL + sock->fd,
sizeof(sock->fd),
NULL + client,
(uint32_t)client) < 0) {
goto error_dict_set_with_hash;
}
/*
* TODO: Send SABM(E) frame; set timer, and await response from peer.
* We will need to know what client to send a response to when either the
@ -841,7 +705,7 @@ static int server_connect(patty_ax25_server *server,
goto error_sock_send_sabm;
}
return 0;
return 0;
error_sock_send_sabm:
error_network_down:
@ -853,6 +717,7 @@ error_sock_by_fd:
return 0;
error_dict_set_with_hash:
error_sock_save_by_addrpair:
error_io:
return -1;
@ -984,7 +849,7 @@ static int accept_client(patty_ax25_server *server) {
goto error_dict_set;
}
watch_client(server, fd);
watch_fd(server, fd);
done:
return 0;
@ -1013,7 +878,7 @@ static int handle_client(void *key,
if ((readlen = read(client, &call, sizeof(call))) < 0) {
goto error_io;
} else if (readlen == 0) {
clear_client(server, client);
clear_fd(server, client);
if (patty_dict_delete_with_hash(server->clients,
(uint32_t)(key - NULL)) < 0) {
@ -1058,7 +923,8 @@ static void save_reply_addr(patty_ax25_sock *sock,
hops = frame->hops > PATTY_AX25_MAX_HOPS?
PATTY_AX25_MAX_HOPS: sock->hops;
memcpy(&sock->remote, &frame->src, sizeof(patty_ax25_addr));
memcpy(&sock->remote, &frame->src, sizeof(patty_ax25_addr));
memcpy(&sock->local, &frame->dest, sizeof(patty_ax25_addr));
for (i=0; i<hops; i++) {
memcpy(&sock->repeaters[i],
@ -1112,40 +978,228 @@ static int reply_ua(patty_ax25_if *iface,
.infolen = 0
};
char callsign[7];
uint8_t ssid;
patty_ax25_ntop(&frame->dest, callsign, &ssid, sizeof(callsign));
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
}
static int reply_frmr(patty_ax25_if *iface,
patty_ax25_frame *frame,
enum patty_ax25_frame_u_flags flags) {
patty_ax25_frame reply = {
.control = PATTY_AX25_FRAME_U_FRMR | flags,
.proto = PATTY_AX25_PROTO_NONE,
.info = NULL,
.infolen = 0
};
return reply_to(iface, frame, &reply, PATTY_AX25_FRAME_NORMAL);
}
static int handle_sabm(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_frame *frame) {
patty_ax25_sock *sock;
int client;
patty_ax25_sock *local, *remote;
patty_ax25_call_accept_response response;
if ((sock = sock_by_addr(server->socks_pending_accept,
&frame->dest)) == NULL) {
if ((local = sock_by_addr(server->socks_pending_accept,
&frame->dest)) == NULL) {
return reply_dm(iface, frame, PATTY_AX25_FRAME_U_FINAL);
}
if ((client = (int)patty_dict_get_with_hash(server->clients_by_sock,
(uint32_t)local->fd)) == 0) {
goto error_lookup_client;
}
if ((remote = patty_ax25_sock_new(local->opts)) == NULL) {
goto error_sock_new;
}
remote->status = PATTY_AX25_SOCK_ESTABLISHED;
remote->mode = PATTY_AX25_SOCK_SABM;
remote->iface = iface;
save_reply_addr(remote, frame);
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
goto error_sock_save_by_fd;
}
if (sock_save_by_addrpair(server->socks_established,
remote,
&remote->local,
&remote->remote) < 0) {
goto error_sock_save_by_addrpair;
}
if (sock_delete_by_addr(server->socks_pending_accept,
&local->local) < 0) {
goto error_sock_delete_by_addr;
}
if (reply_ua(iface, frame, PATTY_AX25_FRAME_U_FINAL) < 0) {
goto error_reply_ua;
}
memset(&response, '\0', sizeof(response));
response.ret = 0;
response.eno = 0;
memcpy(&response.peer, &frame->src, sizeof(patty_ax25_addr));
memcpy(&response.path, &remote->path, sizeof(response.path));
if (write(client, &response, sizeof(response)) < 0) {
goto error_write;
}
watch_sock(server, remote);
return 0;
error_write:
error_reply_ua:
error_sock_delete_by_addr:
error_sock_save_by_addrpair:
error_sock_save_by_fd:
patty_ax25_sock_destroy(remote);
error_sock_new:
error_lookup_client:
return -1;
}
static int handle_ua(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_frame *frame) {
int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_pending_connect,
&frame->dest,
&frame->src)) == NULL) {
return reply_frmr(iface, frame, PATTY_AX25_FRAME_U_FINAL);
}
if ((client = (int)patty_dict_get_with_hash(server->clients_by_sock,
(uint32_t)sock->fd)) == 0) {
goto error_lookup_client;
}
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
sock->mode = PATTY_AX25_SOCK_SABM;
save_reply_addr(sock, frame);
if (sock_save_by_addrpair(server->socks_established,
sock,
sock,
&sock->local,
&sock->remote) < 0) {
goto error_save_by_addrpair;
}
if (sock_delete_by_addr(server->socks_pending_accept,
&frame->dest) < 0) {
goto error_delete_by_addr;
if (sock_delete_by_addrpair(server->socks_pending_connect,
&sock->local,
&sock->remote) < 0) {
goto error_delete_by_addrpair;
}
return reply_ua(iface, frame, PATTY_AX25_FRAME_U_FINAL);
response.ret = 0;
response.eno = 0;
error_delete_by_addr:
if (write(client, &response, sizeof(response)) < 0) {
goto error_write;
}
watch_sock(server, sock);
return 0;
error_write:
patty_ax25_sock_destroy(sock);
error_delete_by_addrpair:
error_save_by_addrpair:
error_lookup_client:
return -1;
}
static int handle_dm(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_frame *frame) {
int client;
patty_ax25_sock *sock;
patty_ax25_call_connect_response response;
if ((sock = sock_by_addrpair(server->socks_pending_connect,
&frame->dest,
&frame->src)) == NULL) {
return 0;
}
if ((client = (int)patty_dict_get_with_hash(server->clients_by_sock,
(uint32_t)sock->fd)) == 0) {
goto error_lookup_client;
}
if (sock_delete_by_addrpair(server->socks_pending_connect,
&frame->dest,
&frame->src) < 0) {
goto error_delete_by_addrpair;
}
response.ret = -1;
response.eno = ECONNREFUSED;
patty_ax25_sock_reset(sock);
if (write(client, &response, sizeof(response)) < 0) {
goto error_write;
}
return 0;
error_write:
error_delete_by_addrpair:
error_lookup_client:
return -1;
}
static int handle_info(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_frame *frame) {
patty_ax25_sock *sock;
if ((sock = sock_by_addrpair(server->socks_established,
&frame->dest,
&frame->src)) == NULL) {
/*
* TODO: Figure out how to respond to a packet sent outside of an
* active session
*/
goto done;
}
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
/*
* TODO: Figure out how to respond to a packet sent to a socket not
* in an established state
*/
goto done;
}
if (write(sock->fd, frame->info, frame->infolen) < 0) {
goto error_write;
}
done:
return 0;
error_write:
return -1;
}
@ -1166,6 +1220,12 @@ static int handle_frame(patty_ax25_server *server,
if (PATTY_AX25_CONTROL_UNNUMBERED_SABM(frame.control)) {
return handle_sabm(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_UNNUMBERED_UA(frame.control)) {
return handle_ua(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_UNNUMBERED_DM(frame.control)) {
return handle_dm(server, iface, &frame);
} else if (PATTY_AX25_CONTROL_INFO(frame.control)) {
return handle_info(server, iface, &frame);
}
return 0;
@ -1234,18 +1294,16 @@ static int handle_sock(void *key,
void *ctx) {
patty_ax25_server *server = ctx;
patty_ax25_sock *sock = value;
patty_ax25_if *iface = sock->iface;
int fd = (int)(key - NULL),
fd_tnc = patty_kiss_tnc_fd(iface->tnc);
int fd = (int)(key - NULL);
ssize_t len;
if (!FD_ISSET(fd, &server->fds_r) || !FD_ISSET(fd_tnc, &server->fds_w)) {
if (!FD_ISSET(fd, &server->fds_r)) {
goto done;
}
if ((len = read(fd, iface->tx_buf, iface->tx_bufsz)) < 0) {
if ((len = read(sock->fd, sock->buf, sock->bufsz)) < 0) {
goto error_io;
} else if (len == 0) {
clear_sock(server, sock);
@ -1259,26 +1317,21 @@ static int handle_sock(void *key,
goto done;
}
if ((len = patty_ax25_if_send(iface, iface->tx_buf, len)) < 0) {
goto error_io;
if (patty_ax25_sock_write(sock, PATTY_AX25_PROTO_NONE, sock->buf, len) < 0) {
goto error_sock_write;
}
/*
* TODO: Finish this
*/
done:
return 0;
error_sock_write:
error_dict_delete:
error_io:
return -1;
}
static int handle_socks(patty_ax25_server *server) {
return patty_dict_each(server->socks_established,
handle_sock,
server);
return patty_dict_each(server->socks_by_fd, handle_sock, server);
}
int patty_ax25_server_run(patty_ax25_server *server) {
@ -1299,10 +1352,6 @@ int patty_ax25_server_run(patty_ax25_server *server) {
goto error_io;
}
if (accept_client(server) < 0) {
goto error_io;
}
if (handle_clients(server) < 0) {
goto error_io;
}
@ -1314,6 +1363,10 @@ int patty_ax25_server_run(patty_ax25_server *server) {
if (handle_socks(server) < 0) {
goto error_io;
}
if (accept_client(server) < 0) {
goto error_io;
}
}
close(server->fd);

View file

@ -1,10 +1,72 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <patty/ax25.h>
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type) {
static int bind_pty(patty_ax25_sock *sock) {
struct termios t;
int pty;
if ((sock->fd = open("/dev/ptmx", O_RDWR)) < 0) {
goto error_open;
}
if (grantpt(sock->fd) < 0) {
goto error_grantpt;
}
if (unlockpt(sock->fd) < 0) {
goto error_unlockpt;
}
if (ptsname_r(sock->fd, sock->path, sizeof(sock->path)) < 0) {
goto error_ptsname_r;
}
/*if ((pty = open(sock->path, O_RDWR)) < 0) {
goto error_open_pty;
}*/
if (tcgetattr(sock->fd, &t) < 0) {
goto error_tcgetattr;
}
cfmakeraw(&t);
if (tcsetattr(sock->fd, TCSANOW, &t) < 0) {
goto error_tcsetattr;
}
//close(pty);
sock->opts |= PATTY_AX25_SOCK_PTY;
return 0;
error_tcsetattr:
error_tcgetattr:
//close(pty);
error_open_pty:
error_ptsname_r:
error_unlockpt:
error_grantpt:
close(sock->fd);
error_open:
return -1;
}
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts) {
patty_ax25_sock *sock;
if ((sock = malloc(sizeof(*sock))) == NULL) {
@ -13,19 +75,45 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_type type) {
memset(sock, '\0', sizeof(*sock));
if ((sock->buf = malloc(PATTY_AX25_SOCK_BUFSZ)) == NULL) {
goto error_malloc_buf;
}
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
sock->bufsz = PATTY_AX25_SOCK_BUFSZ;
sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM;
sock->type = type;
sock->opts = opts;
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
return sock;
error_bind_pty:
free(sock->buf);
error_malloc_buf:
free(sock);
error_malloc_sock:
return NULL;
}
void patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->opts &= ~PATTY_AX25_SOCK_PTY;
sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM;
}
void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
if (sock->fd) {
close(sock->fd);
}
free(sock->buf);
free(sock);
}
@ -75,7 +163,7 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
uint8_t proto,
void *info,
size_t infolen) {
size_t offset = 0;
size_t offset;
if (toobig(sock, control, infolen)) {
goto error_toobig;
@ -86,8 +174,12 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
if (sock->mode == PATTY_AX25_SOCK_SABME) {
((uint8_t *)sock->iface->tx_buf)[offset++] = (control & 0xff00) >> 8;
((uint8_t *)sock->iface->tx_buf)[offset++] = control & 0x00ff;
sock->seq_send = (sock->seq_send + 1) & 0x07;
} else {
((uint8_t *)sock->iface->tx_buf)[offset++] = control;
sock->seq_send = (sock->seq_send + 1) & 0x7f;
}
if (PATTY_AX25_CONTROL_INFO(control)) {
@ -97,7 +189,7 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
offset += infolen;
}
return offset;
return patty_ax25_if_send(sock->iface, sock->iface->tx_buf, offset);
error_toobig:
return -1;
@ -112,13 +204,46 @@ ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int poll) {
0);
}
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int poll) {
return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_U_SABME
| PATTY_AX25_FRAME_U_POLL,
PATTY_AX25_PROTO_NONE,
NULL,
0);
}
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll) {
return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_U_DISC
| PATTY_AX25_FRAME_U_POLL,
PATTY_AX25_PROTO_NONE,
NULL,
0);
}
ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
uint8_t proto,
void *buf,
size_t len) {
uint16_t control = sock->mode == PATTY_AX25_SOCK_SABME?
PATTY_AX25_SOCK_CONTROL_SABME(sock, 1):
PATTY_AX25_SOCK_CONTROL_SABM(sock, 1);
uint16_t control = 0x0000;
switch (sock->mode) {
case PATTY_AX25_SOCK_DM:
errno = EBADF;
goto error_invalid_mode;
case PATTY_AX25_SOCK_SABM:
control = PATTY_AX25_SOCK_CONTROL_SABM(sock, 1);
break;
case PATTY_AX25_SOCK_SABME:
control = PATTY_AX25_SOCK_CONTROL_SABME(sock, 1);
break;
}
if (patty_ax25_sock_send(sock, control, proto, buf, len) < 0) {
goto error_send;
@ -127,5 +252,6 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
return len;
error_send:
error_invalid_mode:
return -1;
}

View file

@ -29,17 +29,22 @@ static void usage(int argc, char **argv, const char *message, ...) {
int main(int argc, char **argv) {
struct sockaddr_un addr;
int fd,
sock;
sock,
pty;
patty_ax25_addr peer;
char path[256];
char path[PATTY_AX25_SOCK_PATH_SIZE];
uint8_t buf[4096];
ssize_t readlen;
if (argc != 2) {
usage(argc, argv, "No patty socket provided");
}
patty_ax25_pton("GB9BLM", 0, &peer);
patty_ax25_pton("KZ3ROX", 0, &peer);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
@ -56,27 +61,46 @@ int main(int argc, char **argv) {
goto error_connect;
}
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_SOCK_PTY)) < 0) {
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_SOCK_NONE, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
goto error_call_socket;
}
if (patty_ax25_call_connect(fd, sock, &peer, path) < 0) {
if (patty_ax25_call_connect(fd, sock, &peer) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_connect()", strerror(errno));
goto error_call_close;
goto error_call_connect;
}
fprintf(stderr, "connected sock %d\n", sock);
if ((pty = open(path, O_RDWR)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], path, "open()", strerror(errno));
goto error_open_pty;
}
while ((readlen = read(pty, buf, sizeof(buf))) > 0) {
if (write(1, buf, readlen) < 0) {
goto error_write;
}
}
close(pty);
patty_ax25_call_close(fd, sock);
close(fd);
return 0;
error_call_close:
error_write:
error_open_pty:
error_call_connect:
patty_ax25_call_close(fd, sock);
error_call_socket:
close(fd);

129
src/testclient-listen.c Normal file
View file

@ -0,0 +1,129 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <patty/ax25.h>
extern char **environ;
static void usage(int argc, char **argv, const char *message, ...) {
if (message != NULL) {
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
va_end(args);
}
fprintf(stderr, "usage: %s /var/run/patty/patty.sock\n", argv[0]);
exit(1);
}
int main(int argc, char **argv) {
struct sockaddr_un unix_addr;
int fd,
local,
remote,
pty;
patty_ax25_addr addr,
peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
if (argc != 2) {
usage(argc, argv, "No patty socket provided");
}
patty_ax25_pton("KZ3ROX", 0, &addr);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
goto error_socket;
}
memset(&unix_addr, '\0', sizeof(unix_addr));
unix_addr.sun_family = AF_UNIX;
strncpy(unix_addr.sun_path, argv[1], sizeof(unix_addr.sun_path));
if (connect(fd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {
goto error_connect;
}
if ((local = patty_ax25_call_socket(fd, PATTY_AX25_SOCK_NONE, NULL, 0)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
goto error_call_socket;
}
if (patty_ax25_call_bind(fd, local, &addr) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_connect()", strerror(errno));
goto error_call_bind;
}
if (patty_ax25_call_listen(fd, local) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_listen()", strerror(errno));
goto error_call_listen;
}
if ((remote = patty_ax25_call_accept(fd, local, &peer, path, sizeof(path))) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_accept()", strerror(errno));
goto error_call_accept;
}
if ((pty = open(path, O_RDWR)) < 0) {
goto error_open_pty;
}
if (write(pty, "hello world\n", 12) < 0) {
goto error_write;
}
close(pty);
patty_ax25_call_close(fd, remote);
patty_ax25_call_close(fd, local);
close(fd);
return 0;
error_write:
close(pty);
error_open_pty:
patty_ax25_call_close(fd, remote);
error_call_accept:
error_call_listen:
error_call_bind:
patty_ax25_call_close(fd, local);
error_call_socket:
error_connect:
close(fd);
error_socket:
return 1;
}