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:
parent
1abf0890d9
commit
ab2c283542
8 changed files with 192 additions and 151 deletions
|
@ -61,7 +61,7 @@ int main(int argc, char **argv) {
|
|||
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",
|
||||
argv[0], "patty_ax25_call_socket()", strerror(errno));
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ int main(int argc, char **argv) {
|
|||
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",
|
||||
argv[0], "patty_ax25_call_socket()", strerror(errno));
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ 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,
|
||||
|
@ -62,13 +63,22 @@ int main(int argc, char **argv) {
|
|||
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",
|
||||
argv[0], "patty_ax25_call_openif()", strerror(errno));
|
||||
argv[0], "patty_ax25_call_socket()", strerror(errno));
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "%s: %s: %s: %s\n",
|
||||
argv[0], path, "open()", strerror(errno));
|
||||
|
@ -107,6 +117,7 @@ error_ax25_frame_decode:
|
|||
error_open_pty:
|
||||
patty_ax25_call_close(fd, sock);
|
||||
|
||||
error_call_setsockopt:
|
||||
error_call_socket:
|
||||
close(fd);
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
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_OPENIF,
|
||||
PATTY_AX25_CALL_CLOSE,
|
||||
PATTY_AX25_CALL_SENDTO,
|
||||
PATTY_AX25_CALL_RECVFROM,
|
||||
|
@ -19,8 +19,8 @@ enum patty_ax25_call {
|
|||
* socket()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_socket_request {
|
||||
int opts;
|
||||
int proto;
|
||||
int type;
|
||||
} patty_ax25_call_socket_request;
|
||||
|
||||
typedef struct _patty_ax25_response_socket {
|
||||
|
@ -30,11 +30,35 @@ typedef struct _patty_ax25_response_socket {
|
|||
} patty_ax25_call_socket_response;
|
||||
|
||||
int patty_ax25_call_socket(int server,
|
||||
int opts,
|
||||
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()
|
||||
*/
|
||||
|
@ -104,24 +128,6 @@ int patty_ax25_call_connect(int server,
|
|||
int fd,
|
||||
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()
|
||||
*/
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
#define PATTY_AX25_SOCK_BUFSZ 4096
|
||||
|
||||
enum patty_ax25_sock_opts {
|
||||
PATTY_AX25_SOCK_NONE,
|
||||
PATTY_AX25_SOCK_PTY = 1 << 0,
|
||||
PATTY_AX25_SOCK_RAW = 1 << 1
|
||||
enum patty_ax25_sock_type {
|
||||
PATTY_AX25_SOCK_STREAM,
|
||||
PATTY_AX25_SOCK_RAW
|
||||
};
|
||||
|
||||
enum patty_ax25_sock_status {
|
||||
|
@ -23,11 +22,15 @@ enum patty_ax25_sock_mode {
|
|||
PATTY_AX25_SOCK_SABME
|
||||
};
|
||||
|
||||
enum patty_ax25_sock_opt {
|
||||
PATTY_AX25_SOCK_IF
|
||||
};
|
||||
|
||||
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_mode mode;
|
||||
enum patty_ax25_proto proto;
|
||||
|
||||
time_t timer_ack,
|
||||
timer_response,
|
||||
|
@ -66,8 +69,8 @@ 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_opts opts,
|
||||
enum patty_ax25_proto proto);
|
||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
|
||||
enum patty_ax25_sock_type type);
|
||||
|
||||
void patty_ax25_sock_reset(patty_ax25_sock *sock);
|
||||
|
||||
|
|
78
src/call.c
78
src/call.c
|
@ -5,14 +5,14 @@
|
|||
#include <patty/ax25.h>
|
||||
|
||||
int patty_ax25_call_socket(int server,
|
||||
int opts,
|
||||
int proto,
|
||||
int type,
|
||||
char *path,
|
||||
size_t len) {
|
||||
enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET;
|
||||
|
||||
patty_ax25_call_socket_request request = {
|
||||
opts, proto
|
||||
proto, type
|
||||
};
|
||||
|
||||
patty_ax25_call_socket_response response;
|
||||
|
@ -41,6 +41,45 @@ 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 *peer) {
|
||||
|
@ -180,41 +219,6 @@ error_io:
|
|||
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 fd) {
|
||||
enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE;
|
||||
|
|
154
src/server.c
154
src/server.c
|
@ -245,10 +245,10 @@ static int sock_save_by_addrpair(patty_dict *dict,
|
|||
uint32_t hash = hash_addrpair(local, remote);
|
||||
|
||||
if (patty_dict_set_with_hash(dict,
|
||||
sock,
|
||||
sizeof(*sock),
|
||||
sock,
|
||||
hash) == NULL) {
|
||||
NULL + sock->fd,
|
||||
sizeof(*sock),
|
||||
sock,
|
||||
hash) == NULL) {
|
||||
goto error_dict_set_with_hash;
|
||||
}
|
||||
|
||||
|
@ -428,7 +428,7 @@ static int server_socket(patty_ax25_server *server,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -463,6 +463,79 @@ error_read:
|
|||
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,
|
||||
int client) {
|
||||
patty_ax25_call_bind_request request;
|
||||
|
@ -701,65 +774,6 @@ error_io:
|
|||
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,
|
||||
int client) {
|
||||
patty_ax25_call_close_request request;
|
||||
|
@ -799,11 +813,11 @@ error_io:
|
|||
static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = {
|
||||
NULL,
|
||||
server_socket,
|
||||
server_setsockopt,
|
||||
server_bind,
|
||||
server_listen,
|
||||
server_accept,
|
||||
server_connect,
|
||||
server_openif,
|
||||
server_close,
|
||||
NULL,
|
||||
NULL
|
||||
|
@ -1042,7 +1056,7 @@ static int handle_sabm(patty_ax25_server *server,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1287,7 @@ static int handle_sock_raw(void *key,
|
|||
patty_ax25_sock *sock = value;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1380,11 +1394,9 @@ static int handle_sock(void *key,
|
|||
patty_ax25_server *server = ctx;
|
||||
patty_ax25_sock *sock = value;
|
||||
|
||||
int fd = (int)(key - NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1415,7 +1427,7 @@ error_io:
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
25
src/sock.c
25
src/sock.c
|
@ -41,8 +41,6 @@ static int bind_pty(patty_ax25_sock *sock) {
|
|||
goto error_tcsetattr;
|
||||
}
|
||||
|
||||
sock->opts |= PATTY_AX25_SOCK_PTY;
|
||||
|
||||
return 0;
|
||||
|
||||
error_tcsetattr:
|
||||
|
@ -56,8 +54,8 @@ error_open:
|
|||
return -1;
|
||||
}
|
||||
|
||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_sock_opts opts,
|
||||
enum patty_ax25_proto proto) {
|
||||
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
|
||||
enum patty_ax25_sock_type type) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
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->proto = proto;
|
||||
sock->type = type;
|
||||
sock->status = PATTY_AX25_SOCK_CLOSED;
|
||||
sock->mode = PATTY_AX25_SOCK_DM;
|
||||
sock->opts = opts;
|
||||
sock->proto = proto;
|
||||
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
|
||||
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
|
||||
|
||||
|
@ -95,9 +93,16 @@ error_malloc_sock:
|
|||
}
|
||||
|
||||
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;
|
||||
sock->status = PATTY_AX25_SOCK_CLOSED;
|
||||
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) {
|
||||
|
@ -225,7 +230,7 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
|
|||
size_t len) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue