Refactor socket(), openif() as setsockopt()

Other changes:

    * Fix blocking on disconnects when a raw socket is bound to an
      interface
This commit is contained in:
XANTRONIX Development 2020-07-03 15:21:32 -04:00 committed by XANTRONIX Industrial
parent 1abf0890d9
commit ab2c283542
8 changed files with 192 additions and 151 deletions

View file

@ -61,7 +61,7 @@ int main(int argc, char **argv) {
goto error_connect; goto error_connect;
} }
if ((sock = patty_ax25_call_socket(fd, 0, PATTY_AX25_PROTO_NONE, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) { if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM, path, PATTY_AX25_SOCK_PATH_SIZE)) < 0) {
fprintf(stderr, "%s: %s: %s\n", fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno)); argv[0], "patty_ax25_call_socket()", strerror(errno));

View file

@ -64,7 +64,7 @@ int main(int argc, char **argv) {
goto error_connect; goto error_connect;
} }
if ((local = patty_ax25_call_socket(fd, 0, PATTY_AX25_PROTO_NONE, NULL, 0)) < 0) { if ((local = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_STREAM, NULL, 0)) < 0) {
fprintf(stderr, "%s: %s: %s\n", fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno)); argv[0], "patty_ax25_call_socket()", strerror(errno));

View file

@ -30,6 +30,7 @@ static void usage(int argc, char **argv, const char *message, ...) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct sockaddr_un addr; struct sockaddr_un addr;
patty_ax25_call_setsockopt_if ifreq;
int fd, int fd,
sock, sock,
@ -62,13 +63,22 @@ int main(int argc, char **argv) {
goto error_connect; goto error_connect;
} }
if ((sock = patty_ax25_call_openif(fd, "kiss0", path, sizeof(path))) < 0) { if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW, path, sizeof(path))) < 0) {
fprintf(stderr, "%s: %s: %s\n", fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_openif()", strerror(errno)); argv[0], "patty_ax25_call_socket()", strerror(errno));
goto error_call_socket; goto error_call_socket;
} }
strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
if (patty_ax25_call_setsockopt(fd, sock, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_setsockopt()", strerror(errno));
goto error_call_setsockopt;
}
if ((pty = open(path, O_RDWR)) < 0) { if ((pty = open(path, O_RDWR)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n", fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], path, "open()", strerror(errno)); argv[0], path, "open()", strerror(errno));
@ -107,6 +117,7 @@ error_ax25_frame_decode:
error_open_pty: error_open_pty:
patty_ax25_call_close(fd, sock); patty_ax25_call_close(fd, sock);
error_call_setsockopt:
error_call_socket: error_call_socket:
close(fd); close(fd);

View file

@ -4,11 +4,11 @@
enum patty_ax25_call { enum patty_ax25_call {
PATTY_AX25_CALL_NONE, PATTY_AX25_CALL_NONE,
PATTY_AX25_CALL_SOCKET, PATTY_AX25_CALL_SOCKET,
PATTY_AX25_CALL_SETSOCKOPT,
PATTY_AX25_CALL_BIND, PATTY_AX25_CALL_BIND,
PATTY_AX25_CALL_LISTEN, PATTY_AX25_CALL_LISTEN,
PATTY_AX25_CALL_ACCEPT, PATTY_AX25_CALL_ACCEPT,
PATTY_AX25_CALL_CONNECT, PATTY_AX25_CALL_CONNECT,
PATTY_AX25_CALL_OPENIF,
PATTY_AX25_CALL_CLOSE, PATTY_AX25_CALL_CLOSE,
PATTY_AX25_CALL_SENDTO, PATTY_AX25_CALL_SENDTO,
PATTY_AX25_CALL_RECVFROM, PATTY_AX25_CALL_RECVFROM,
@ -19,8 +19,8 @@ enum patty_ax25_call {
* socket() * socket()
*/ */
typedef struct _patty_ax25_call_socket_request { typedef struct _patty_ax25_call_socket_request {
int opts;
int proto; int proto;
int type;
} patty_ax25_call_socket_request; } patty_ax25_call_socket_request;
typedef struct _patty_ax25_response_socket { typedef struct _patty_ax25_response_socket {
@ -30,11 +30,35 @@ typedef struct _patty_ax25_response_socket {
} patty_ax25_call_socket_response; } patty_ax25_call_socket_response;
int patty_ax25_call_socket(int server, int patty_ax25_call_socket(int server,
int opts,
int proto, int proto,
int type,
char *path, char *path,
size_t len); 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() * bind()
*/ */
@ -104,24 +128,6 @@ int patty_ax25_call_connect(int server,
int fd, int fd,
patty_ax25_addr *peer); patty_ax25_addr *peer);
/*
* openif()
*/
typedef struct _patty_ax25_call_openif_request {
char name[8];
} patty_ax25_call_openif_request;
typedef struct _patty_ax25_call_openif_response {
int fd;
int eno;
char path[PATTY_AX25_SOCK_PATH_SIZE];
} patty_ax25_call_openif_response;
int patty_ax25_call_openif(int server,
char *name,
char *path,
size_t len);
/* /*
* close() * close()
*/ */

View file

@ -3,10 +3,9 @@
#define PATTY_AX25_SOCK_BUFSZ 4096 #define PATTY_AX25_SOCK_BUFSZ 4096
enum patty_ax25_sock_opts { enum patty_ax25_sock_type {
PATTY_AX25_SOCK_NONE, PATTY_AX25_SOCK_STREAM,
PATTY_AX25_SOCK_PTY = 1 << 0, PATTY_AX25_SOCK_RAW
PATTY_AX25_SOCK_RAW = 1 << 1
}; };
enum patty_ax25_sock_status { enum patty_ax25_sock_status {
@ -23,11 +22,15 @@ enum patty_ax25_sock_mode {
PATTY_AX25_SOCK_SABME PATTY_AX25_SOCK_SABME
}; };
enum patty_ax25_sock_opt {
PATTY_AX25_SOCK_IF
};
typedef struct _patty_ax25_sock { typedef struct _patty_ax25_sock {
enum patty_ax25_sock_opts opts; enum patty_ax25_proto proto;
enum patty_ax25_sock_type type;
enum patty_ax25_sock_status status; enum patty_ax25_sock_status status;
enum patty_ax25_sock_mode mode; enum patty_ax25_sock_mode mode;
enum patty_ax25_proto proto;
time_t timer_ack, time_t timer_ack,
timer_response, timer_response,
@ -66,8 +69,8 @@ typedef struct _patty_ax25_sock {
PATTY_AX25_SOCK_CONTROL_SABME(sock, flag): \ PATTY_AX25_SOCK_CONTROL_SABME(sock, flag): \
PATTY_AX25_SOCK_CONTROL_SABM(sock, flag)) PATTY_AX25_SOCK_CONTROL_SABM(sock, flag))
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts, patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
enum patty_ax25_proto proto); enum patty_ax25_sock_type type);
void patty_ax25_sock_reset(patty_ax25_sock *sock); void patty_ax25_sock_reset(patty_ax25_sock *sock);

View file

@ -5,14 +5,14 @@
#include <patty/ax25.h> #include <patty/ax25.h>
int patty_ax25_call_socket(int server, int patty_ax25_call_socket(int server,
int opts,
int proto, int proto,
int type,
char *path, char *path,
size_t len) { size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET; enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET;
patty_ax25_call_socket_request request = { patty_ax25_call_socket_request request = {
opts, proto proto, type
}; };
patty_ax25_call_socket_response response; patty_ax25_call_socket_response response;
@ -41,6 +41,45 @@ error_io:
return -1; 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 patty_ax25_call_bind(int server,
int fd, int fd,
patty_ax25_addr *peer) { patty_ax25_addr *peer) {
@ -180,41 +219,6 @@ error_io:
return -1; return -1;
} }
int patty_ax25_call_openif(int server,
char *name,
char *path,
size_t len) {
enum patty_ax25_call call = PATTY_AX25_CALL_OPENIF;
patty_ax25_call_openif_request request;
patty_ax25_call_openif_response response;
memcpy(request.name, name, sizeof(request.name));
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.fd;
error_io:
return -1;
}
int patty_ax25_call_close(int server, int patty_ax25_call_close(int server,
int fd) { int fd) {
enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE; enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE;

View file

@ -245,10 +245,10 @@ static int sock_save_by_addrpair(patty_dict *dict,
uint32_t hash = hash_addrpair(local, remote); uint32_t hash = hash_addrpair(local, remote);
if (patty_dict_set_with_hash(dict, if (patty_dict_set_with_hash(dict,
sock, NULL + sock->fd,
sizeof(*sock), sizeof(*sock),
sock, sock,
hash) == NULL) { hash) == NULL) {
goto error_dict_set_with_hash; goto error_dict_set_with_hash;
} }
@ -428,7 +428,7 @@ static int server_socket(patty_ax25_server *server,
goto error_read; goto error_read;
} }
if ((sock = patty_ax25_sock_new(request.opts, request.proto)) == NULL) { if ((sock = patty_ax25_sock_new(request.proto, request.type)) == NULL) {
goto error_sock_new; goto error_sock_new;
} }
@ -463,6 +463,79 @@ error_read:
return -1; return -1;
} }
static int server_setsockopt(patty_ax25_server *server,
int client) {
patty_ax25_call_setsockopt_request request;
patty_ax25_call_setsockopt_response response;
patty_ax25_sock *sock;
if (read(client, &request, sizeof(request)) < 0) {
goto error_read;
}
if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) {
response.ret = -1;
response.eno = EBADF;
goto error_sock_by_fd;
}
switch (request.opt) {
case PATTY_AX25_SOCK_IF: {
patty_ax25_call_setsockopt_if data;
patty_ax25_if *iface;
if (sock->type != PATTY_AX25_SOCK_RAW) {
response.ret = -1;
response.eno = EINVAL;
goto error_invalid_type;
}
if (read(client, &data, request.len) < 0) {
goto error_read;
}
if ((iface = patty_ax25_server_get_if(server, data.name)) == NULL) {
response.ret = -1;
response.eno = ENODEV;
goto error_get_if;
}
patty_ax25_sock_bind_if(sock, iface);
if (sock_save_by_fd(server->socks_established, sock) < 0) {
goto error_sock_save_by_fd;
}
watch_fd(server, sock->fd);
break;
}
default:
response.ret = -1;
response.eno = EINVAL;
goto error_invalid_opt;
}
response.ret = 0;
response.eno = 0;
error_sock_by_fd:
error_get_if:
error_invalid_type:
error_invalid_opt:
return write(client, &response, sizeof(response));
error_sock_save_by_fd:
error_read:
return -1;
}
static int server_bind(patty_ax25_server *server, static int server_bind(patty_ax25_server *server,
int client) { int client) {
patty_ax25_call_bind_request request; patty_ax25_call_bind_request request;
@ -701,65 +774,6 @@ error_io:
return -1; return -1;
} }
static int server_openif(patty_ax25_server *server,
int client) {
patty_ax25_call_openif_request request;
patty_ax25_call_openif_response response;
patty_ax25_sock *sock;
patty_ax25_if *iface;
if (read(client, &request, sizeof(request)) < 0) {
goto error_io;
}
if ((sock = patty_ax25_sock_new(PATTY_AX25_SOCK_RAW,
PATTY_AX25_PROTO_NONE)) == NULL) {
response.fd = -1;
response.eno = errno;
goto error_sock_new;
}
if ((iface = patty_ax25_server_get_if(server, request.name)) == NULL) {
response.fd = -1;
response.eno = ENODEV;
goto error_get_if;
}
patty_ax25_sock_bind_if(sock, iface);
watch_fd(server, sock->fd);
if (sock_save_by_fd(server->socks_by_fd, sock) < 0) {
response.fd = -1;
response.eno = errno;
goto error_sock_save_by_fd;
}
if (sock_save_by_fd(server->socks_established, sock) < 0) {
response.fd = -1;
response.eno = errno;
goto error_sock_save_by_fd;
}
response.fd = sock->fd;
response.eno = 0;
strncpy(response.path, sock->path, sizeof(response.path));
error_get_if:
error_sock_new:
return write(client, &response, sizeof(response));
error_sock_save_by_fd:
error_io:
return -1;
}
static int server_close(patty_ax25_server *server, static int server_close(patty_ax25_server *server,
int client) { int client) {
patty_ax25_call_close_request request; patty_ax25_call_close_request request;
@ -799,11 +813,11 @@ error_io:
static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = { static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = {
NULL, NULL,
server_socket, server_socket,
server_setsockopt,
server_bind, server_bind,
server_listen, server_listen,
server_accept, server_accept,
server_connect, server_connect,
server_openif,
server_close, server_close,
NULL, NULL,
NULL NULL
@ -1042,7 +1056,7 @@ static int handle_sabm(patty_ax25_server *server,
goto error_lookup_client; goto error_lookup_client;
} }
if ((remote = patty_ax25_sock_new(local->opts, local->proto)) == NULL) { if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
goto error_sock_new; goto error_sock_new;
} }
@ -1273,7 +1287,7 @@ static int handle_sock_raw(void *key,
patty_ax25_sock *sock = value; patty_ax25_sock *sock = value;
struct sock_raw_frame *raw_frame = ctx; struct sock_raw_frame *raw_frame = ctx;
if (raw_frame->iface != sock->iface || !(sock->opts & PATTY_AX25_SOCK_RAW)) { if (sock->type != PATTY_AX25_SOCK_RAW || raw_frame->iface != sock->iface) {
return 0; return 0;
} }
@ -1380,11 +1394,9 @@ static int handle_sock(void *key,
patty_ax25_server *server = ctx; patty_ax25_server *server = ctx;
patty_ax25_sock *sock = value; patty_ax25_sock *sock = value;
int fd = (int)(key - NULL);
ssize_t len; ssize_t len;
if (!FD_ISSET(fd, &server->fds_r) || sock->opts & PATTY_AX25_SOCK_RAW) { if (!FD_ISSET(sock->fd, &server->fds_r)) {
goto done; goto done;
} }
@ -1415,7 +1427,7 @@ error_io:
} }
static int handle_socks(patty_ax25_server *server) { static int handle_socks(patty_ax25_server *server) {
return patty_dict_each(server->socks_by_fd, handle_sock, server); return patty_dict_each(server->socks_established, handle_sock, server);
} }
int patty_ax25_server_run(patty_ax25_server *server) { int patty_ax25_server_run(patty_ax25_server *server) {

View file

@ -41,8 +41,6 @@ static int bind_pty(patty_ax25_sock *sock) {
goto error_tcsetattr; goto error_tcsetattr;
} }
sock->opts |= PATTY_AX25_SOCK_PTY;
return 0; return 0;
error_tcsetattr: error_tcsetattr:
@ -56,8 +54,8 @@ error_open:
return -1; return -1;
} }
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts, patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
enum patty_ax25_proto proto) { enum patty_ax25_sock_type type) {
patty_ax25_sock *sock; patty_ax25_sock *sock;
if ((sock = malloc(sizeof(*sock))) == NULL) { if ((sock = malloc(sizeof(*sock))) == NULL) {
@ -75,10 +73,10 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts,
} }
sock->bufsz = PATTY_AX25_SOCK_BUFSZ; sock->bufsz = PATTY_AX25_SOCK_BUFSZ;
sock->proto = proto;
sock->type = type;
sock->status = PATTY_AX25_SOCK_CLOSED; sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM; sock->mode = PATTY_AX25_SOCK_DM;
sock->opts = opts;
sock->proto = proto;
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN; sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW; sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
@ -95,9 +93,16 @@ error_malloc_sock:
} }
void patty_ax25_sock_reset(patty_ax25_sock *sock) { void patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->opts &= ~PATTY_AX25_SOCK_PTY; sock->status = PATTY_AX25_SOCK_CLOSED;
sock->status = PATTY_AX25_SOCK_CLOSED; sock->mode = PATTY_AX25_SOCK_DM;
sock->mode = PATTY_AX25_SOCK_DM; sock->timer_ack = 0;
sock->timer_response = 0;
sock->timer_keepalive = 0;
sock->n_maxlen = 0;
sock->n_retry = 0;
sock->n_window = 0;
sock->seq_send = 0;
sock->seq_recv = 0;
} }
void patty_ax25_sock_destroy(patty_ax25_sock *sock) { void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
@ -225,7 +230,7 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
size_t len) { size_t len) {
uint16_t control = 0x0000; uint16_t control = 0x0000;
if (sock->opts & PATTY_AX25_SOCK_RAW) { if (sock->type == PATTY_AX25_SOCK_RAW) {
return patty_ax25_if_send(sock->iface, buf, len); return patty_ax25_if_send(sock->iface, buf, len);
} }