SO BLOODY CLOSE
This commit is contained in:
parent
94f073c38d
commit
22bf692a61
9 changed files with 594 additions and 241 deletions
|
@ -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()
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
27
src/call.c
27
src/call.c
|
@ -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;
|
||||
|
|
451
src/server.c
451
src/server.c
|
@ -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);
|
||||
|
|
140
src/sock.c
140
src/sock.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
129
src/testclient-listen.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue