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
This commit is contained in:
XANTRONIX Development 2020-08-01 20:21:01 -04:00 committed by XANTRONIX Industrial
parent 81d063cb68
commit 1f4ffc98ac
12 changed files with 745 additions and 589 deletions

View file

@ -29,20 +29,18 @@ static void usage(int argc, char **argv, const char *message, ...) {
}
int main(int argc, char **argv) {
struct sockaddr_un addr;
patty_ax25_call_setsockopt_if ifreq;
int fd,
sock;
patty_client *client;
patty_client_setsockopt_if ifreq;
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
uint8_t buf[4096];
ssize_t readlen;
patty_kiss_tnc *raw;
int fd;
if (argc < 2) {
usage(argc, argv, "No patty socket provided");
} else if (argc < 3) {
@ -53,42 +51,34 @@ int main(int argc, char **argv) {
patty_ax25_pton(argv[2], 0, &peer);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
if ((client = patty_client_new(argv[1])) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
argv[0], "patty_client_new()", argv[1], strerror(errno));
goto error_socket;
goto error_client_new;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path));
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW, path, sizeof(path))) < 0) {
if ((fd = patty_client_socket(client, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
argv[0], "patty_client_socket()", strerror(errno));
goto error_call_socket;
goto error_client_socket;
}
strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
if (patty_ax25_call_setsockopt(fd, sock, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
if (patty_client_setsockopt(client, fd, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_setsockopt()", strerror(errno));
argv[0], "patty_client_setsockopt()", strerror(errno));
goto error_call_setsockopt;
goto error_client_setsockopt;
}
if ((raw = patty_kiss_tnc_new(path)) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], path, "patty_kiss_tnc_new()", strerror(errno));
if ((raw = patty_kiss_tnc_new_fd(fd)) == NULL) {
fprintf(stderr, "%s: fd %d: %s: %s\n",
argv[0], fd, "patty_kiss_tnc_new_fd()", strerror(errno));
goto error_kiss_tnc_new;
goto error_kiss_tnc_new_fd;
}
while ((readlen = patty_kiss_tnc_recv(raw, buf, sizeof(buf), NULL)) > 0) {
@ -151,23 +141,20 @@ error_ax25_frame_decode_address:
patty_kiss_tnc_destroy(raw);
patty_ax25_call_close(fd, sock);
patty_client_close(client, fd);
close(fd);
patty_client_destroy(client);
return 0;
error_io:
patty_kiss_tnc_destroy(raw);
error_kiss_tnc_new:
patty_ax25_call_close(fd, sock);
error_kiss_tnc_new_fd:
error_client_setsockopt:
error_client_socket:
(void)patty_client_close(client, fd);
error_call_setsockopt:
error_call_socket:
close(fd);
error_connect:
error_socket:
error_client_new:
return 1;
}

View file

@ -28,14 +28,10 @@ static void usage(int argc, char **argv, const char *message, ...) {
}
int main(int argc, char **argv) {
struct sockaddr_un addr;
int fd,
sock,
pty;
patty_client *client;
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
int fd;
uint8_t buf[4096];
ssize_t readlen;
@ -50,65 +46,46 @@ int main(int argc, char **argv) {
patty_ax25_pton(argv[2], 0, &peer);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
if ((client = patty_client_new(argv[1])) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
argv[0], "patty_client_new()", argv[1], strerror(errno));
goto error_socket;
goto error_client_new;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path));
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) {
if ((fd = patty_client_socket(client, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
argv[0], "patty_client_socket()", strerror(errno));
goto error_call_socket;
goto error_client_socket;
}
if (patty_ax25_call_connect(fd, sock, &peer) < 0) {
if (patty_client_connect(client, fd, &peer) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_connect()", strerror(errno));
argv[0], "patty_client_connect()", strerror(errno));
goto error_call_connect;
goto error_client_connect;
}
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) {
while ((readlen = read(fd, buf, sizeof(buf))) > 0) {
if (write(1, buf, readlen) < 0) {
goto error_write;
}
}
close(pty);
patty_client_close(client, fd);
patty_ax25_call_close(fd, sock);
close(fd);
patty_client_destroy(client);
return 0;
error_write:
error_open_pty:
error_call_connect:
patty_ax25_call_close(fd, sock);
error_client_connect:
patty_client_close(client, fd);
error_call_socket:
close(fd);
error_client_socket:
patty_client_destroy(client);
error_connect:
error_socket:
error_client_new:
return 1;
}

View file

@ -31,17 +31,13 @@ static void usage(int argc, char **argv, const char *message, ...) {
}
int main(int argc, char **argv) {
struct sockaddr_un unix_addr;
int fd,
local,
remote,
pty;
patty_client *client;
patty_ax25_addr addr,
peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
int local,
remote;
if (argc < 2) {
usage(argc, argv, "No patty socket provided");
@ -53,81 +49,63 @@ int main(int argc, char **argv) {
patty_ax25_pton(argv[2], 0, &addr);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
if ((client = patty_client_new(argv[1])) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
argv[0], "patty_client_new()", argv[1], strerror(errno));
goto error_socket;
goto error_client_new;
}
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_PROTO_NONE, PATTY_AX25_SOCK_STREAM, NULL, 0)) < 0) {
if ((local = patty_client_socket(client, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
argv[0], "patty_client_socket()", strerror(errno));
goto error_call_socket;
goto error_client_socket;
}
if (patty_ax25_call_bind(fd, local, &addr) < 0) {
if (patty_client_bind(client, local, &addr) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_connect()", strerror(errno));
argv[0], "patty_client_bind()", strerror(errno));
goto error_call_bind;
goto error_client_bind;
}
if (patty_ax25_call_listen(fd, local) < 0) {
if (patty_client_listen(client, local) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_listen()", strerror(errno));
argv[0], "patty_client_listen()", strerror(errno));
goto error_call_listen;
goto error_client_listen;
}
if ((remote = patty_ax25_call_accept(fd, local, &peer, path, sizeof(path))) < 0) {
if ((remote = patty_client_accept(client, local, &peer)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_accept()", strerror(errno));
argv[0], "patty_client_accept()", strerror(errno));
goto error_call_accept;
goto error_client_accept;
}
if ((pty = open(path, O_RDWR)) < 0) {
goto error_open_pty;
}
if (write(pty, "hello world\n", 12) < 0) {
if (write(remote, "hello world\n", 12) < 0) {
goto error_write;
}
close(pty);
patty_client_close(client, remote);
patty_client_close(client, local);
patty_ax25_call_close(fd, remote);
patty_ax25_call_close(fd, local);
close(fd);
patty_client_destroy(client);
return 0;
error_write:
close(pty);
(void)patty_client_close(client, remote);
error_open_pty:
patty_ax25_call_close(fd, remote);
error_client_accept:
error_client_listen:
error_client_bind:
(void)patty_client_close(client, local);
error_call_accept:
error_call_listen:
error_call_bind:
patty_ax25_call_close(fd, local);
error_client_socket:
patty_client_destroy(client);
error_call_socket:
error_connect:
close(fd);
error_socket:
error_client_new:
return 1;
}

View file

@ -92,8 +92,8 @@ typedef struct _patty_ax25_params {
typedef struct _patty_ax25_if patty_ax25_if;
#include <patty/client.h>
#include <patty/ax25/frame.h>
#include <patty/ax25/call.h>
#include <patty/ax25/if.h>
#include <patty/ax25/route.h>
#include <patty/ax25/sock.h>

View file

@ -1,164 +0,0 @@
#ifndef _PATTY_AX25_CALL_H
#define _PATTY_AX25_CALL_H
enum patty_ax25_call {
PATTY_AX25_CALL_NONE,
PATTY_AX25_CALL_SOCKET,
PATTY_AX25_CALL_SETSOCKOPT,
PATTY_AX25_CALL_BIND,
PATTY_AX25_CALL_LISTEN,
PATTY_AX25_CALL_ACCEPT,
PATTY_AX25_CALL_CONNECT,
PATTY_AX25_CALL_CLOSE,
PATTY_AX25_CALL_SENDTO,
PATTY_AX25_CALL_RECVFROM,
PATTY_AX25_CALL_COUNT
};
/*
* socket()
*/
typedef struct _patty_ax25_call_socket_request {
int proto;
int type;
} 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 proto,
int type,
char *path,
size_t len);
/*
* setsockopt()
*/
typedef struct _patty_ax25_call_setsockopt_request {
int fd;
int opt;
size_t len;
} patty_ax25_call_setsockopt_request;
typedef struct _patty_ax25_call_setsockopt_if {
char name[8];
} patty_ax25_call_setsockopt_if;
typedef struct _patty_ax25_call_setsockopt_response {
int ret;
int eno;
} patty_ax25_call_setsockopt_response;
int patty_ax25_call_setsockopt(int server,
int fd,
int opt,
void *data,
size_t len);
/*
* bind()
*/
typedef struct _patty_ax25_call_bind_request {
int fd;
patty_ax25_addr addr;
} patty_ax25_call_bind_request;
typedef struct _patty_ax25_call_bind_response {
int ret;
int eno;
} patty_ax25_call_bind_response;
int patty_ax25_call_bind(int server,
int fd,
patty_ax25_addr *addr);
/*
* listen()
*/
typedef struct _patty_ax25_call_listen_request {
int fd;
} patty_ax25_call_listen_request;
typedef struct _patty_ax25_call_listen_response {
int ret;
int eno;
} patty_ax25_call_listen_response;
int patty_ax25_call_listen(int server,
int fd);
/*
* accept()
*/
typedef struct _patty_ax25_call_accept_request {
int fd;
} patty_ax25_call_accept_request;
typedef struct _patty_ax25_call_accept_response {
int ret;
int eno;
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_ax25_call_accept_response;
int patty_ax25_call_accept(int server,
int fd,
patty_ax25_addr *peer,
char *path,
size_t len);
/*
* connect()
*/
typedef struct _patty_ax25_call_connect_request {
int fd;
patty_ax25_addr peer;
} patty_ax25_call_connect_request;
typedef struct _patty_ax25_call_connect_response {
int ret;
int eno;
} patty_ax25_call_connect_response;
int patty_ax25_call_connect(int server,
int fd,
patty_ax25_addr *peer);
/*
* close()
*/
typedef struct _patty_ax25_call_close_request {
int fd;
} patty_ax25_call_close_request;
typedef struct _patty_ax25_call_close_response {
int ret;
int eno;
} patty_ax25_call_close_response;
int patty_ax25_call_close(int server,
int fd);
/*
* sendto()
*/
ssize_t patty_ax25_call_sendto(int server,
int fd,
const void *buf,
size_t len,
patty_ax25_addr *addr);
/*
* recvfrom()
*/
int patty_ax25_call_recvfrom(int server,
int fd,
void *buf,
size_t len,
patty_ax25_addr *addr);
#endif /* _PATTY_AX25_CALL_H */

174
include/patty/client.h Normal file
View file

@ -0,0 +1,174 @@
#ifndef _PATTY_CLIENT_H
#define _PATTY_CLIENT_H
enum patty_client_call {
PATTY_CLIENT_NONE,
PATTY_CLIENT_SOCKET,
PATTY_CLIENT_SETSOCKOPT,
PATTY_CLIENT_BIND,
PATTY_CLIENT_LISTEN,
PATTY_CLIENT_ACCEPT,
PATTY_CLIENT_CONNECT,
PATTY_CLIENT_CLOSE,
PATTY_CLIENT_SENDTO,
PATTY_CLIENT_RECVFROM,
PATTY_CLIENT_CALL_COUNT
};
typedef struct _patty_client_sock {
int fd;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_client_sock;
typedef struct _patty_client {
int fd;
patty_dict *socks;
} patty_client;
patty_client *patty_client_new(const char *path);
void patty_client_destroy(patty_client *client);
/*
* socket()
*/
typedef struct _patty_client_socket_request {
int proto;
int type;
} patty_client_socket_request;
typedef struct _patty_ax25_response_socket_response {
int fd;
int eno;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_client_socket_response;
int patty_client_socket(patty_client *client,
int proto,
int type);
/*
* setsockopt()
*/
typedef struct _patty_client_setsockopt_request {
int fd;
int opt;
size_t len;
} patty_client_setsockopt_request;
typedef struct _patty_client_setsockopt_if {
char name[8];
} patty_client_setsockopt_if;
typedef struct _patty_client_setsockopt_response {
int ret;
int eno;
} patty_client_setsockopt_response;
int patty_client_setsockopt(patty_client *client,
int fd,
int opt,
void *data,
size_t len);
/*
* bind()
*/
typedef struct _patty_client_bind_request {
int fd;
patty_ax25_addr addr;
} patty_client_bind_request;
typedef struct _patty_client_bind_response {
int ret;
int eno;
} patty_client_bind_response;
int patty_client_bind(patty_client *client,
int fd,
patty_ax25_addr *addr);
/*
* listen()
*/
typedef struct _patty_client_listen_request {
int fd;
} patty_client_listen_request;
typedef struct _patty_client_listen_response {
int ret;
int eno;
} patty_client_listen_response;
int patty_client_listen(patty_client *client,
int fd);
/*
* accept()
*/
typedef struct _patty_client_accept_request {
int fd;
} patty_client_accept_request;
typedef struct _patty_client_accept_response {
int fd;
int eno;
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_client_accept_response;
int patty_client_accept(patty_client *client,
int fd,
patty_ax25_addr *peer);
/*
* connect()
*/
typedef struct _patty_client_connect_request {
int fd;
patty_ax25_addr peer;
} patty_client_connect_request;
typedef struct _patty_client_connect_response {
int ret;
int eno;
} patty_client_connect_response;
int patty_client_connect(patty_client *client,
int fd,
patty_ax25_addr *peer);
/*
* close()
*/
typedef struct _patty_client_close_request {
int fd;
} patty_client_close_request;
typedef struct _patty_client_close_response {
int ret;
int eno;
} patty_client_close_response;
int patty_client_close(patty_client *client,
int fd);
/*
* sendto()
*/
ssize_t patty_client_sendto(patty_client *client,
int fd,
const void *buf,
size_t len,
patty_ax25_addr *addr);
/*
* recvfrom()
*/
int patty_client_recvfrom(patty_client *client,
int fd,
void *buf,
size_t len,
patty_ax25_addr *addr);
#endif /* _PATTY_CLIENT_H */

View file

@ -7,13 +7,13 @@ CC = $(CROSS)cc
CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
LDFLAGS =
HEADERS = kiss.h ax25.h ax25/if.h ax25/call.h ax25/frame.h ax25/sock.h \
ax25/route.h ax25/server.h list.h hash.h dict.h timer.h \
print.h
HEADERS = kiss.h ax25.h client.h ax25/if.h ax25/frame.h \
ax25/sock.h ax25/route.h ax25/server.h list.h hash.h dict.h \
timer.h print.h
OBJS = kiss.o ax25.o if.o call.o frame.o sock.o \
route.o server.o list.o hash.o dict.o timer.o \
print.o
OBJS = kiss.o ax25.o client.o if.o frame.o \
sock.o route.o server.o list.o hash.o dict.o \
timer.o print.o
VERSION_MAJOR = 0
VERSION_MINOR = 0.1

View file

@ -1,250 +0,0 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <patty/ax25.h>
int patty_ax25_call_socket(int server,
int proto,
int type,
char *path,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET;
patty_ax25_call_socket_request request = {
proto, type
};
patty_ax25_call_socket_response response;
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
if (path) {
strncpy(path, response.path, len);
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_setsockopt(int server,
int fd,
int opt,
void *data,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_SETSOCKOPT;
patty_ax25_call_setsockopt_request request = {
.fd = fd,
.opt = opt,
.len = len
};
patty_ax25_call_setsockopt_response response;
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (write(server, data, len) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_bind(int server,
int fd,
patty_ax25_addr *addr) {
enum patty_ax25_call call = PATTY_AX25_CALL_BIND;
patty_ax25_call_bind_request request = {
fd
};
patty_ax25_call_bind_response response;
memcpy(&request.addr, addr, sizeof(*addr));
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_listen(int server,
int fd) {
enum patty_ax25_call call = PATTY_AX25_CALL_LISTEN;
patty_ax25_call_listen_request request = {
fd
};
patty_ax25_call_listen_response response;
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_accept(int server,
int fd,
patty_ax25_addr *peer,
char *path,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_ACCEPT;
patty_ax25_call_accept_request request = {
fd
};
patty_ax25_call_accept_response response;
memset(&response, '\0', sizeof(response));
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
if (response.ret >= 0) {
memcpy(peer, &response.peer, sizeof(*peer));
if (path) {
strncpy(path, response.path, len);
}
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_connect(int server,
int fd,
patty_ax25_addr *peer) {
enum patty_ax25_call call = PATTY_AX25_CALL_CONNECT;
patty_ax25_call_connect_request request = {
fd
};
patty_ax25_call_connect_response response;
memcpy(&request.peer, peer, sizeof(*peer));
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
int patty_ax25_call_close(int server,
int fd) {
enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE;
patty_ax25_call_close_request request = {
fd
};
patty_ax25_call_close_response response;
if (write(server, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(server, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(server, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}

467
src/client.c Normal file
View file

@ -0,0 +1,467 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <patty/ax25.h>
patty_client *patty_client_new(const char *path) {
patty_client *client;
struct sockaddr_un addr;
if ((client = malloc(sizeof(*client))) == NULL) {
goto error_malloc_client;
}
if ((client->socks = patty_dict_new()) == NULL) {
goto error_dict_new;
}
if ((client->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
if (connect(client->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
return client;
error_connect:
close(client->fd);
error_socket:
patty_dict_destroy(client->socks);
error_dict_new:
free(client);
error_malloc_client:
return NULL;
}
static int request_close(patty_client *client,
int fd) {
enum patty_client_call call = PATTY_CLIENT_CLOSE;
patty_client_close_request request = { fd };
patty_client_close_response response;
size_t len;
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if ((len = read(client->fd, &response, sizeof(response))) < 0) {
goto error_io;
} else if (len != sizeof(response)) {
errno = EIO;
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
return -1;
}
static int destroy_sock(uint32_t key, void *value, void *ctx) {
patty_client *client = ctx;
patty_client_sock *sock = value;
(void)request_close(client, sock->fd);
free(sock);
return 0;
}
void patty_client_destroy(patty_client *client) {
close(client->fd);
(void)patty_dict_each(client->socks, destroy_sock, client);
patty_dict_destroy(client->socks);
free(client);
}
int patty_client_socket(patty_client *client,
int proto,
int type) {
enum patty_client_call call = PATTY_CLIENT_SOCKET;
patty_client_socket_request request = {
proto, type
};
patty_client_socket_response response;
patty_client_sock *sock;
int fd;
struct termios t;
if ((sock = malloc(sizeof(*sock))) == NULL) {
goto error_malloc_sock;
}
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
sock->fd = response.fd;
strncpy(sock->path, response.path, sizeof(sock->path));
if ((fd = open(sock->path, O_RDWR)) < 0) {
goto error_open;
}
if (tcgetattr(fd, &t) < 0) {
goto error_tcgetattr;
}
cfmakeraw(&t);
if (tcsetattr(fd, TCSANOW, &t) < 0) {
goto error_tcsetattr;
}
if (patty_dict_set(client->socks,
(uint32_t)fd,
sock) == NULL) {
goto error_dict_set;
}
errno = response.eno;
return fd;
error_dict_set:
error_tcsetattr:
error_tcgetattr:
(void)close(fd);
error_open:
(void)request_close(client, sock->fd);
error_io:
free(sock);
error_malloc_sock:
return -1;
}
int patty_client_setsockopt(patty_client *client,
int fd,
int opt,
void *data,
size_t len) {
enum patty_client_call call = PATTY_CLIENT_SETSOCKOPT;
patty_client_setsockopt_request request = {
.opt = opt,
.len = len
};
patty_client_setsockopt_response response;
patty_client_sock *sock;
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
request.fd = sock->fd;
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (write(client->fd, data, len) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
error_dict_get:
return -1;
}
int patty_client_bind(patty_client *client,
int fd,
patty_ax25_addr *addr) {
enum patty_client_call call = PATTY_CLIENT_BIND;
patty_client_bind_request request;
patty_client_bind_response response;
patty_client_sock *sock;
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
memset(&request, '\0', sizeof(request));
request.fd = sock->fd;
memcpy(&request.addr, addr, sizeof(*addr));
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
error_dict_get:
return -1;
}
int patty_client_listen(patty_client *client,
int fd) {
enum patty_client_call call = PATTY_CLIENT_LISTEN;
patty_client_listen_request request;
patty_client_listen_response response;
patty_client_sock *sock;
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
request.fd = sock->fd;
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
error_dict_get:
return -1;
}
int patty_client_accept(patty_client *client,
int fd,
patty_ax25_addr *peer) {
enum patty_client_call call = PATTY_CLIENT_ACCEPT;
patty_client_accept_request request;
patty_client_accept_response response;
patty_client_sock *local,
*remote;
int pty;
struct termios t;
if ((local = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
if ((remote = malloc(sizeof(*remote))) == NULL) {
goto error_malloc_remote;
}
request.fd = local->fd;
memset(&response, '\0', sizeof(response));
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
if (response.fd >= 0) {
memcpy(peer, &response.peer, sizeof(*peer));
remote->fd = response.fd;
strncpy(remote->path, response.path, sizeof(remote->path));
}
if ((pty = open(remote->path, O_RDWR)) < 0) {
goto error_open;
}
if (tcgetattr(pty, &t) < 0) {
goto error_tcgetattr;
}
cfmakeraw(&t);
if (tcsetattr(pty, TCSANOW, &t) < 0) {
goto error_tcsetattr;
}
if (patty_dict_set(client->socks,
(uint32_t)pty,
remote) == NULL) {
goto error_dict_set;
}
errno = response.eno;
return pty;
error_tcsetattr:
error_tcgetattr:
error_dict_set:
(void)close(pty);
error_open:
(void)request_close(client, remote->fd);
error_io:
free(remote);
error_malloc_remote:
error_dict_get:
return -1;
}
int patty_client_connect(patty_client *client,
int fd,
patty_ax25_addr *peer) {
enum patty_client_call call = PATTY_CLIENT_CONNECT;
patty_client_connect_request request;
patty_client_connect_response response;
patty_client_sock *sock;
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
memset(&request, '\0', sizeof(request));
request.fd = sock->fd;
memcpy(&request.peer, peer, sizeof(*peer));
if (write(client->fd, &call, sizeof(call)) < 0) {
goto error_io;
}
if (write(client->fd, &request, sizeof(request)) < 0) {
goto error_io;
}
if (read(client->fd, &response, sizeof(response)) < 0) {
goto error_io;
}
errno = response.eno;
return response.ret;
error_io:
error_dict_get:
return -1;
}
int patty_client_close(patty_client *client,
int fd) {
patty_client_sock *sock;
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
errno = EBADF;
goto error_dict_get;
}
if (request_close(client, sock->fd) < 0) {
goto error_request_close;
}
if (close(fd) < 0) {
goto error_close;
}
patty_dict_delete(client->socks, (uint32_t)fd);
free(sock);
return 0;
error_close:
error_request_close:
error_dict_get:
return -1;
}

View file

@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

View file

@ -503,15 +503,15 @@ int patty_ax25_server_add_route(patty_ax25_server *server,
}
static int respond_accept(int client,
int ret,
int fd,
int eno,
patty_ax25_addr *peer,
char *path) {
patty_ax25_call_accept_response response;
patty_client_accept_response response;
memset(&response, '\0', sizeof(response));
response.ret = ret;
response.fd = fd;
response.eno = eno;
if (peer) {
@ -526,7 +526,7 @@ static int respond_accept(int client,
}
static int respond_connect(int client, int ret, int eno) {
patty_ax25_call_connect_response response = {
patty_client_connect_response response = {
.ret = ret,
.eno = eno
};
@ -535,8 +535,8 @@ static int respond_connect(int client, int ret, int eno) {
}
static int server_socket(patty_ax25_server *server, int client) {
patty_ax25_call_socket_request request;
patty_ax25_call_socket_response response;
patty_client_socket_request request;
patty_client_socket_response response;
patty_ax25_sock *sock;
@ -552,7 +552,7 @@ static int server_socket(patty_ax25_server *server, int client) {
goto error_sock_save;
}
response.ret = sock->fd;
response.fd = sock->fd;
response.eno = 0;
memcpy(response.path, patty_ax25_sock_pty(sock), sizeof(response.path));
@ -569,8 +569,8 @@ error_read:
static int server_setsockopt(patty_ax25_server *server,
int client) {
patty_ax25_call_setsockopt_request request;
patty_ax25_call_setsockopt_response response;
patty_client_setsockopt_request request;
patty_client_setsockopt_response response;
patty_ax25_sock *sock;
@ -587,7 +587,7 @@ static int server_setsockopt(patty_ax25_server *server,
switch (request.opt) {
case PATTY_AX25_SOCK_IF: {
patty_ax25_call_setsockopt_if data;
patty_client_setsockopt_if data;
patty_ax25_if *iface;
if (sock->type != PATTY_AX25_SOCK_RAW) {
@ -639,8 +639,8 @@ error_read:
static int server_bind(patty_ax25_server *server,
int client) {
patty_ax25_call_bind_request request;
patty_ax25_call_bind_response response;
patty_client_bind_request request;
patty_client_bind_response response;
patty_ax25_sock *sock;
@ -685,8 +685,8 @@ error_io:
static int server_listen(patty_ax25_server *server,
int client) {
patty_ax25_call_listen_request request;
patty_ax25_call_listen_response response;
patty_client_listen_request request;
patty_client_listen_response response;
patty_ax25_sock *sock;
@ -727,7 +727,7 @@ error_io:
static int server_accept(patty_ax25_server *server,
int client) {
patty_ax25_call_accept_request request;
patty_client_accept_request request;
patty_ax25_sock *sock;
if (read(client, &request, sizeof(request)) < 0) {
@ -749,7 +749,7 @@ error_io:
static int server_connect(patty_ax25_server *server,
int client) {
patty_ax25_call_connect_request request;
patty_client_connect_request request;
patty_ax25_sock *sock;
patty_ax25_route *route;
@ -845,8 +845,8 @@ error_io:
static int server_close(patty_ax25_server *server,
int client) {
patty_ax25_call_close_request request;
patty_ax25_call_close_response response;
patty_client_close_request request;
patty_client_close_response response;
patty_ax25_sock *sock;
patty_dict *socks;
@ -896,7 +896,7 @@ error_io:
return -1;
}
static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = {
static patty_ax25_server_call server_calls[PATTY_CLIENT_CALL_COUNT] = {
NULL,
server_socket,
server_setsockopt,
@ -1017,7 +1017,7 @@ static int handle_client(uint32_t key,
int client = (int)key;
ssize_t readlen;
enum patty_ax25_call call;
enum patty_client_call call;
if (!FD_ISSET(client, &server->fds_r)) {
goto done;
@ -1050,7 +1050,7 @@ static int handle_client(uint32_t key,
goto done;
}
if (call <= PATTY_AX25_CALL_NONE || call >= PATTY_AX25_CALL_COUNT) {
if (call <= PATTY_CLIENT_NONE || call >= PATTY_CLIENT_CALL_COUNT) {
goto error_io;
}
@ -1222,7 +1222,7 @@ static int handle_sabm(patty_ax25_server *server,
fd_watch(server, remote->fd);
if (respond_accept(client, 0, 0, &frame->src, remote->pty) < 0) {
if (respond_accept(client, remote->fd, 0, &frame->src, remote->pty) < 0) {
goto error_respond_accept;
}

View file

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
@ -13,7 +12,6 @@
#include <patty/ax25.h>
static int bind_pty(patty_ax25_sock *sock) {
struct termios t;
char *pty;
if ((sock->fd = open("/dev/ptmx", O_RDWR)) < 0) {
@ -34,20 +32,8 @@ static int bind_pty(patty_ax25_sock *sock) {
(void)strncpy(sock->pty, pty, sizeof(sock->pty));
if (tcgetattr(sock->fd, &t) < 0) {
goto error_tcgetattr;
}
cfmakeraw(&t);
if (tcsetattr(sock->fd, TCSANOW, &t) < 0) {
goto error_tcsetattr;
}
return 0;
error_tcsetattr:
error_tcgetattr:
error_ptsname:
error_unlockpt:
error_grantpt: