diff --git a/include/patty/client.h b/include/patty/client.h index dc463ae..331f3c0 100644 --- a/include/patty/client.h +++ b/include/patty/client.h @@ -120,11 +120,15 @@ typedef struct _patty_client_accept_request { } patty_client_accept_request; typedef struct _patty_client_accept_response { - int fd; + int ret; int eno; +} patty_client_accept_response; + +typedef struct _patty_client_accept_message { + int fd; patty_ax25_addr peer; char path[PATTY_AX25_SOCK_PATH_SIZE]; -} patty_client_accept_response; +} patty_client_accept_message; int patty_client_accept(patty_client *client, int fd, diff --git a/src/client.c b/src/client.c index f1c69e5..f71c322 100644 --- a/src/client.c +++ b/src/client.c @@ -312,6 +312,7 @@ int patty_client_accept(patty_client *client, patty_client_accept_request request; patty_client_accept_response response; + patty_client_accept_message message; patty_client_sock *local, *remote; @@ -341,18 +342,33 @@ int patty_client_accept(patty_client *client, goto error_io; } + /* + * First, the server will tell us if the fd specified in accept() is indeed + * accepting connections. + */ if (read(client->fd, &response, sizeof(response)) < 0) { goto error_io; } - if (response.fd >= 0) { - memcpy(peer, &response.peer, sizeof(*peer)); + if (response.ret < 0) { + errno = response.eno; - remote->fd = response.fd; - - strncpy(remote->path, response.path, sizeof(remote->path)); + return response.ret; } + /* + * Next, we will wait for the server to receive a SABM or SABME frame, and + * notify us via the listening socket that a connection has been accepted. + */ + if (read(fd, &message, sizeof(message)) < 0) { + goto error_io; + } + + remote->fd = message.fd; + + memcpy(peer, &message.peer, sizeof(*peer)); + strncpy(remote->path, message.path, sizeof(remote->path)); + if ((pty = open(remote->path, O_RDWR)) < 0) { goto error_open; } diff --git a/src/server.c b/src/server.c index ef62c64..7b2ae0c 100644 --- a/src/server.c +++ b/src/server.c @@ -514,26 +514,35 @@ int patty_ax25_server_add_route(patty_ax25_server *server, } static int respond_accept(int client, - int fd, - int eno, - patty_ax25_addr *peer, - char *path) { - patty_client_accept_response response; + int ret, + int eno) { + patty_client_accept_response response = { + .ret = ret, + .eno = eno + }; - memset(&response, '\0', sizeof(response)); + return write(client, &response, sizeof(response)); +} - response.fd = fd; - response.eno = eno; +static int notify_accept(int local, + int remote, + patty_ax25_addr *peer, + char *path) { + patty_client_accept_message message; + + memset(&message, '\0', sizeof(message)); + + message.fd = remote; if (peer) { - memcpy(&response.peer, peer, sizeof(response.peer)); + memcpy(&message.peer, peer, sizeof(message.peer)); } if (path) { - strncpy(response.path, path, sizeof(response.path)-1); + strncpy(message.path, path, sizeof(message.path)-1); } - return write(client, &response, sizeof(response)); + return write(local, &message, sizeof(message)); } static int respond_connect(int client, int ret, int eno) { @@ -770,13 +779,18 @@ static int server_accept(patty_ax25_server *server, } if ((sock = sock_by_fd(server->socks_by_fd, request.fd)) == NULL) { - goto error_sock_by_fd; + return respond_accept(client, -1, EBADF); } - return 0; + if (sock->type != PATTY_AX25_SOCK_STREAM) { + return respond_accept(client, -1, EOPNOTSUPP); + } -error_sock_by_fd: - return respond_accept(client, -1, EBADF, NULL, NULL); + if (sock->state != PATTY_AX25_SOCK_LISTENING) { + return respond_accept(client, -1, EINVAL); + } + + return respond_accept(client, 0, 0); error_io: return -1; @@ -1228,8 +1242,10 @@ static int handle_sabm(patty_ax25_server *server, patty_ax25_sock *local, *remote; if ((local = sock_by_addr(server->socks_local, - &frame->dest)) == NULL) { - return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); + &frame->dest)) == NULL + || local->type != PATTY_AX25_SOCK_STREAM + || local->state != PATTY_AX25_SOCK_LISTENING) { + goto reply_dm; } if ((client = client_by_sock(server, local)) < 0) { @@ -1254,6 +1270,8 @@ static int handle_sabm(patty_ax25_server *server, save_reply_addr(remote, frame); created = 1; + } else if (remote->state != PATTY_AX25_SOCK_PENDING_ACCEPT) { + goto reply_dm; } remote->state = PATTY_AX25_SOCK_ESTABLISHED; @@ -1280,15 +1298,18 @@ static int handle_sabm(patty_ax25_server *server, fd_watch(server, remote->fd); - if (respond_accept(client, remote->fd, 0, &frame->src, remote->pty) < 0) { - goto error_respond_accept; + if (notify_accept(local->fd, remote->fd, &remote->remote, remote->pty) < 0) { + goto error_notify_accept; } patty_timer_start(&remote->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL); -error_respond_accept: +reply_dm: + return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); + +error_notify_accept: error_sock_realloc_bufs: error_sock_save: patty_ax25_sock_destroy(remote); @@ -1673,9 +1694,7 @@ static int handle_xid(patty_ax25_server *server, patty_ax25_sock_params_max(remote); if (patty_ax25_sock_params_negotiate(remote, ¶ms) < 0) { - patty_ax25_sock_destroy(remote); - - return respond_accept(client, -1, errno, NULL, NULL); + goto error_sock_params_negotiate; } save_reply_addr(remote, frame); @@ -1691,6 +1710,9 @@ reply_dm: return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); error_sock_save: +error_sock_params_negotiate: + patty_ax25_sock_destroy(remote); + error_sock_new: error_client_by_sock: error_io: