diff options
-rw-r--r-- | src/async.c | 8 | ||||
-rw-r--r-- | src/fastd.c | 8 | ||||
-rw-r--r-- | src/fastd.h | 10 | ||||
-rw-r--r-- | src/peer.c | 12 | ||||
-rw-r--r-- | src/poll.c | 260 | ||||
-rw-r--r-- | src/poll.h | 25 | ||||
-rw-r--r-- | src/receive.c | 2 | ||||
-rw-r--r-- | src/send.c | 4 | ||||
-rw-r--r-- | src/socket.c | 24 | ||||
-rw-r--r-- | src/status.c | 16 | ||||
-rw-r--r-- | src/tuntap.c | 46 | ||||
-rw-r--r-- | src/types.h | 10 |
12 files changed, 185 insertions, 240 deletions
diff --git a/src/async.c b/src/async.c index d05b8c5..50efeac 100644 --- a/src/async.c +++ b/src/async.c @@ -56,8 +56,10 @@ void fastd_async_init(void) { fastd_setnonblock(fds[1]); #endif - ctx.async_rfd = fds[0]; + ctx.async_rfd = FASTD_POLL_FD(POLL_TYPE_ASYNC, fds[0]); ctx.async_wfd = fds[1]; + + fastd_poll_fd_register(&ctx.async_rfd); } /** Handles a DNS resolver response */ @@ -104,7 +106,7 @@ void fastd_async_handle(void) { .msg_iovlen = 1, }; - if (recvmsg(ctx.async_rfd, &msg, MSG_PEEK) < 0) + if (recvmsg(ctx.async_rfd.fd, &msg, MSG_PEEK) < 0) exit_errno("fastd_async_handle: recvmsg"); uint8_t buf[header.len] __attribute__((aligned(8))); @@ -112,7 +114,7 @@ void fastd_async_handle(void) { vec[1].iov_len = sizeof(buf); msg.msg_iovlen = 2; - if (recvmsg(ctx.async_rfd, &msg, 0) < 0) + if (recvmsg(ctx.async_rfd.fd, &msg, 0) < 0) exit_errno("fastd_async_handle: recvmsg"); switch (header.type) { diff --git a/src/fastd.c b/src/fastd.c index 4ac0e8e..52bbf9c 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -178,7 +178,7 @@ static void init_sockets(void) { fastd_bind_address_t *addr = conf.bind_addrs; for (i = 0; i < conf.n_bind_addrs; i++) { if (get_bind_port(addr)) { - ctx.socks[i] = (fastd_socket_t){ .fd = -2, .addr = addr }; + ctx.socks[i] = (fastd_socket_t){ .fd = FASTD_POLL_FD(POLL_TYPE_SOCKET, -2), .addr = addr }; if (addr == conf.bind_addr_default_v4) ctx.sock_default_v4 = &ctx.socks[i]; @@ -187,7 +187,7 @@ static void init_sockets(void) { ctx.sock_default_v6 = &ctx.socks[i]; } else { - ctx.socks[i] = (fastd_socket_t){ .fd = -1, .addr = NULL }; + ctx.socks[i] = (fastd_socket_t){ .fd = FASTD_POLL_FD(POLL_TYPE_SOCKET, -1), .addr = NULL }; } addr = addr->next; @@ -508,10 +508,12 @@ static inline void init(int argc, char *argv[]) { fastd_cap_init(); + fastd_poll_init(); + init_sockets(); + fastd_status_init(); fastd_async_init(); - fastd_poll_init(); if (!fastd_socket_handle_binds()) exit_error("unable to bind default socket"); diff --git a/src/fastd.h b/src/fastd.h index f1b2f93..ba6acfb 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -39,6 +39,7 @@ #include "dlist.h" #include "buffer.h" #include "log.h" +#include "poll.h" #include "sem.h" #include "shell.h" #include "util.h" @@ -147,7 +148,7 @@ struct fastd_bind_address { /** A socket descriptor */ struct fastd_socket { - int fd; /**< The file descriptor for the socket */ + fastd_poll_fd_t fd; /**< The file descriptor for the socket */ const fastd_bind_address_t *addr; /**< The address this socket is supposed to be bound to (or NULL) */ fastd_peer_address_t *bound_addr; /**< The actual address that was bound to (may differ from addr when addr has a random port) */ fastd_peer_t *peer; /**< If the socket belongs to a single peer (as it was create dynamically when sending a handshake), contains that peer */ @@ -280,11 +281,12 @@ struct fastd_context { #ifdef USE_EPOLL int epoll_fd; /**< The file descriptor for the epoll facility */ #else + VECTOR(fastd_poll_fd_t *) fds; /**< Vector of file descriptors to poll on, indexed by the FD itself */ VECTOR(struct pollfd) pollfds; /**< The vector of pollfds for all file descriptors */ #endif #ifdef WITH_STATUS_SOCKET - int status_fd; /**< The file descriptor of the status socket */ + fastd_poll_fd_t status_fd; /**< The file descriptor of the status socket */ #endif bool has_floating; /**< Specifies if any of the configured peers have floating remotes */ @@ -298,12 +300,12 @@ struct fastd_context { fastd_timeout_t next_maintenance; /**< The time of the next maintenance call */ VECTOR(pid_t) async_pids; /**< PIDs of asynchronously executed commands which still have to be reaped */ - int async_rfd; /**< The read side of the pipe used to send data from other threads to the main thread */ + fastd_poll_fd_t async_rfd; /**< The read side of the pipe used to send data from other threads to the main thread */ int async_wfd; /**< The write side of the pipe used to send data from other threads to the main thread */ pthread_attr_t detached_thread; /**< pthread_attr_t for creating detached threads */ - int tunfd; /**< The file descriptor of the tunnel interface */ + fastd_poll_fd_t tunfd; /**< The file descriptor of the tunnel interface */ #ifdef __ANDROID__ int android_ctrl_sock_fd; /**< The unix domain socket for communicating with Android GUI */ @@ -183,13 +183,9 @@ static void free_socket_by_id(size_t i) { fastd_socket_close(peer->sock); free(peer->sock); - - peer->sock = NULL; - fastd_poll_set_fd_peer(i); - } - else { - peer->sock = NULL; } + + peer->sock = NULL; } /** Closes and frees a peer's dynamic socket */ @@ -245,8 +241,6 @@ void fastd_peer_reset_socket(fastd_peer_t *peer) { if (!peer->sock || !fastd_peer_is_socket_dynamic(peer)) return; - - fastd_poll_set_fd_peer(i); } /** @@ -446,7 +440,6 @@ static void delete_peer(fastd_peer_t *peer) { size_t i = peer_index(peer); VECTOR_DELETE(ctx.peers, i); - fastd_poll_delete_peer(i); conf.protocol->free_peer_state(peer); @@ -741,7 +734,6 @@ bool fastd_peer_add(fastd_peer_t *peer) { peer->id = ctx.next_peer_id++; VECTOR_ADD(ctx.peers, peer); - fastd_poll_add_peer(); conf.protocol->init_peer_state(peer); @@ -66,6 +66,47 @@ static inline int handshake_timeout(void) { } +/** Handles a file descriptor that was selected on */ +static inline void handle_fd(fastd_poll_fd_t *fd, bool input, bool error) { + switch (fd->type) { + case POLL_TYPE_ASYNC: + if (input) + fastd_async_handle(); + break; + +#ifdef WITH_STATUS_SOCKET + case POLL_TYPE_STATUS: + if (input) + fastd_status_handle(); + break; +#endif + + case POLL_TYPE_IFACE: + if (input) + fastd_tuntap_handle(); + break; + + case POLL_TYPE_SOCKET: + { + fastd_socket_t *sock = container_of(fd, fastd_socket_t, fd); + if (error) { + if (sock->peer) + fastd_peer_reset_socket(sock->peer); + else + fastd_socket_error(sock); + } + else if (input) { + fastd_receive(sock); + } + } + break; + + default: + exit_bug("unknown FD type"); + } +} + + #ifdef USE_EPOLL @@ -84,25 +125,6 @@ void fastd_poll_init(void) { ctx.epoll_fd = epoll_create(1); if (ctx.epoll_fd < 0) exit_errno("epoll_create1"); - - struct epoll_event event_async = { - .events = EPOLLIN, - .data.ptr = &ctx.async_rfd, - }; - if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.async_rfd, &event_async) < 0) - exit_errno("epoll_ctl"); - -#ifdef WITH_STATUS_SOCKET - if (ctx.status_fd >= 0) { - struct epoll_event event_status = { - .events = EPOLLIN, - .data.ptr = &ctx.status_fd, - }; - - if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.status_fd, &event_status) < 0) - exit_errno("epoll_ctl"); - } -#endif } void fastd_poll_free(void) { @@ -110,42 +132,25 @@ void fastd_poll_free(void) { pr_warn_errno("closing EPOLL: close"); } -void fastd_poll_set_fd_tuntap(void) { - struct epoll_event event = { - .events = EPOLLIN, - .data.ptr = &ctx.tunfd, - }; - if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.tunfd, &event) < 0) - exit_errno("epoll_ctl"); -} - -void fastd_poll_set_fd_sock(size_t i) { - struct epoll_event event = { - .events = EPOLLIN, - .data.ptr = &ctx.socks[i], - }; - if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.socks[i].fd, &event) < 0) - exit_errno("epoll_ctl"); -} - -void fastd_poll_set_fd_peer(size_t i) { - fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i); - if (!peer->sock || !fastd_peer_is_socket_dynamic(peer)) - return; +void fastd_poll_fd_register(fastd_poll_fd_t *fd) { + if (fd->fd < 0) + exit_bug("fastd_poll_fd_register: invalid FD"); struct epoll_event event = { .events = EPOLLIN, - .data.ptr = peer->sock, + .data.ptr = fd, }; - if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, peer->sock->fd, &event) < 0) + + if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, fd->fd, &event) < 0) exit_errno("epoll_ctl"); } -void fastd_poll_add_peer(void) { -} +bool fastd_poll_fd_close(fastd_poll_fd_t *fd) { + if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL) < 0) + exit_errno("epoll_ctl"); -void fastd_poll_delete_peer(UNUSED size_t i) { + return (close(fd->fd) == 0); } @@ -170,115 +175,44 @@ void fastd_poll_handle(void) { return; size_t i; - for (i = 0; i < (size_t)ret; i++) { - if (events[i].data.ptr == &ctx.tunfd) { - if (events[i].events & EPOLLIN) - fastd_tuntap_handle(); - } - else if (events[i].data.ptr == &ctx.async_rfd) { - if (events[i].events & EPOLLIN) - fastd_async_handle(); - } -#ifdef WITH_STATUS_SOCKET - else if (events[i].data.ptr == &ctx.status_fd) { - if (events[i].events & EPOLLIN) - fastd_status_handle(); - } -#endif - else { - fastd_socket_t *sock = events[i].data.ptr; - - if (events[i].events & (EPOLLERR|EPOLLHUP)) { - if (sock->peer) - fastd_peer_reset_socket(sock->peer); - else - fastd_socket_error(sock); - } - else if (events[i].events & EPOLLIN) { - fastd_receive(sock); - } - } - } + for (i = 0; i < (size_t)ret; i++) + handle_fd(events[i].data.ptr, + events[i].events & EPOLLIN, + events[i].events & (EPOLLERR|EPOLLHUP)); } #else void fastd_poll_init(void) { - VECTOR_RESIZE(ctx.pollfds, 3 + ctx.n_socks + VECTOR_LEN(ctx.peers)); - - VECTOR_INDEX(ctx.pollfds, 0) = (struct pollfd) { - .fd = -1, - .events = POLLIN, - .revents = 0, - }; - - VECTOR_INDEX(ctx.pollfds, 1) = (struct pollfd) { - .fd = ctx.async_rfd, - .events = POLLIN, - .revents = 0, - }; - - VECTOR_INDEX(ctx.pollfds, 2) = (struct pollfd) { -#ifdef WITH_STATUS_SOCKET - .fd = ctx.status_fd, -#else - .fd = -1, -#endif - .events = POLLIN, - .revents = 0, - }; - - size_t i; - for (i = 0; i < ctx.n_socks + VECTOR_LEN(ctx.peers); i++) { - VECTOR_INDEX(ctx.pollfds, 3+i) = (struct pollfd) { - .fd = -1, - .events = POLLIN, - .revents = 0, - }; - } } void fastd_poll_free(void) { + VECTOR_FREE(ctx.fds); VECTOR_FREE(ctx.pollfds); } -void fastd_poll_set_fd_tuntap(void) { - VECTOR_INDEX(ctx.pollfds, 0).fd = ctx.tunfd; -} - -void fastd_poll_set_fd_sock(size_t i) { - VECTOR_INDEX(ctx.pollfds, 3+i).fd = ctx.socks[i].fd; -} +void fastd_poll_fd_register(fastd_poll_fd_t *fd) { + if (fd->fd < 0) + exit_bug("fastd_poll_fd_register: invalid FD"); -void fastd_poll_set_fd_peer(size_t i) { - if (!VECTOR_LEN(ctx.pollfds)) - exit_bug("fastd_poll_set_fd_peer: polling not initialized yet"); + while (VECTOR_LEN(ctx.fds) <= (size_t)fd->fd) + VECTOR_ADD(ctx.fds, NULL); - fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i); + VECTOR_INDEX(ctx.fds, fd->fd) = fd; - if (!peer->sock || !fastd_peer_is_socket_dynamic(peer)) - VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).fd = -1; - else - VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).fd = peer->sock->fd; + VECTOR_RESIZE(ctx.pollfds, 0); } -void fastd_poll_add_peer(void) { - if (!VECTOR_LEN(ctx.pollfds)) - /* Polling is not initialized yet */ - return; +bool fastd_poll_fd_close(fastd_poll_fd_t *fd) { + if (fd->fd < 0 || (size_t)fd->fd >= VECTOR_LEN(ctx.fds)) + exit_bug("fastd_poll_fd_close: invalid FD"); - struct pollfd pollfd = { - .fd = -1, - .events = POLLIN, - .revents = 0, - }; + VECTOR_INDEX(ctx.fds, fd->fd) = NULL; - VECTOR_ADD(ctx.pollfds, pollfd); -} + VECTOR_RESIZE(ctx.pollfds, 0); -void fastd_poll_delete_peer(size_t i) { - VECTOR_DELETE(ctx.pollfds, 3+ctx.n_socks+i); + return (close(fd->fd) == 0); } @@ -294,8 +228,20 @@ void fastd_poll_handle(void) { if (timeout < 0 || timeout > maintenance_timeout) timeout = maintenance_timeout; - if (VECTOR_LEN(ctx.pollfds) != 3 + ctx.n_socks + VECTOR_LEN(ctx.peers)) - exit_bug("fd count mismatch"); + if (!VECTOR_LEN(ctx.pollfds)) { + for (i = 0; i < VECTOR_LEN(ctx.fds); i++) { + fastd_poll_fd_t *fd = VECTOR_INDEX(ctx.fds, i); + if (!fd) + continue; + + struct pollfd pollfd = { + .fd = fd->fd, + .events = POLLIN, + .revents = 0, + }; + VECTOR_ADD(ctx.pollfds, pollfd); + } + } sigset_t set, oldset; sigemptyset(&set); @@ -334,6 +280,8 @@ void fastd_poll_handle(void) { } if (ret > 0) { + ret = 0; + for (i = 0; i < VECTOR_LEN(ctx.pollfds); i++) { struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i); pollfd->revents = 0; @@ -345,6 +293,9 @@ void fastd_poll_handle(void) { pollfd->revents |= POLLIN; if (FD_ISSET(pollfd->fd, &errfds)) pollfd->revents |= POLLERR; + + if (pollfd->revents) + ret++; } } @@ -360,39 +311,14 @@ void fastd_poll_handle(void) { if (ret <= 0) return; - if (VECTOR_INDEX(ctx.pollfds, 0).revents & POLLIN) - fastd_tuntap_handle(); - if (VECTOR_INDEX(ctx.pollfds, 1).revents & POLLIN) - fastd_async_handle(); - -#ifdef WITH_STATUS_SOCKET - if (VECTOR_INDEX(ctx.pollfds, 2).revents & POLLIN) - fastd_status_handle(); -#endif - - for (i = 0; i < ctx.n_socks; i++) { - if (VECTOR_INDEX(ctx.pollfds, 3+i).revents & (POLLERR|POLLHUP|POLLNVAL)) { - fastd_socket_error(&ctx.socks[i]); - VECTOR_INDEX(ctx.pollfds, 3+i).fd = -1; - } - else if (VECTOR_INDEX(ctx.pollfds, 3+i).revents & POLLIN) { - fastd_receive(&ctx.socks[i]); - } - } + for (i = 0; i < VECTOR_LEN(ctx.pollfds) && ret > 0; i++) { + struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i); - for (i = 0; i < VECTOR_LEN(ctx.peers); i++) { - fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i); + if (pollfd->revents) + ret--; - if (VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).revents & (POLLERR|POLLHUP|POLLNVAL)) { - fastd_peer_reset_socket(peer); - } - else if (VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).revents & POLLIN) { - fastd_receive(peer->sock); - } + handle_fd(VECTOR_INDEX(ctx.fds, pollfd->fd), pollfd->revents & POLLIN, pollfd->revents & (POLLERR|POLLHUP|POLLNVAL)); } - - if (VECTOR_LEN(ctx.pollfds) != 3 + ctx.n_socks + VECTOR_LEN(ctx.peers)) - exit_bug("fd count mismatch"); } #endif @@ -36,22 +36,25 @@ #include "types.h" +/** A file descriptor to poll on */ +struct fastd_poll_fd { + fastd_poll_type_t type; /**< What the file descriptor is used for */ + int fd; /**< The file descriptor itself */ +}; + + /** Initializes the poll interface */ void fastd_poll_init(void); /** Frees the poll interface */ void fastd_poll_free(void); -/** Updates the file descriptor of the TUN/TAP interface from \e ctx.tunfd */ -void fastd_poll_set_fd_tuntap(void); -/** Updates the file descriptor of the socket \e ctx.socks[i] */ -void fastd_poll_set_fd_sock(size_t i); -/** Updates the file descriptor of the dynamic socket for the peer with index \e i in \e ctx.peers */ -void fastd_poll_set_fd_peer(size_t i); - -/** Must be called when a peer is added at the end of the peer list */ -void fastd_poll_add_peer(void); -/** Must be called then the peer with the index \e i is deleted */ -void fastd_poll_delete_peer(size_t i); +/** Returns a fastd_poll_fd_t structure */ +#define FASTD_POLL_FD(type, fd) ((fastd_poll_fd_t){type, fd}) + +/** Registers a new file descriptor to poll on */ +void fastd_poll_fd_register(fastd_poll_fd_t *fd); +/** Unregisters and closes a file descriptor */ +bool fastd_poll_fd_close(fastd_poll_fd_t *fd); /** Waits for the next input event */ void fastd_poll_handle(void); diff --git a/src/receive.c b/src/receive.c index 2ee402a..8bb926c 100644 --- a/src/receive.c +++ b/src/receive.c @@ -260,7 +260,7 @@ void fastd_receive(fastd_socket_t *sock) { .msg_controllen = sizeof(cbuf), }; - ssize_t len = recvmsg(sock->fd, &message, 0); + ssize_t len = recvmsg(sock->fd.fd, &message, 0); if (len <= 0) { if (len < 0) pr_warn_errno("recvmsg"); @@ -131,7 +131,7 @@ static void send_type(const fastd_socket_t *sock, const fastd_peer_address_t *lo if (!msg.msg_controllen) msg.msg_control = NULL; - int ret = sendmsg(sock->fd, &msg, 0); + int ret = sendmsg(sock->fd.fd, &msg, 0); if (ret < 0 && errno == EINVAL && msg.msg_controllen) { pr_debug2("sendmsg failed, trying again without pktinfo"); @@ -142,7 +142,7 @@ static void send_type(const fastd_socket_t *sock, const fastd_peer_address_t *lo msg.msg_control = NULL; msg.msg_controllen = 0; - ret = sendmsg(sock->fd, &msg, 0); + ret = sendmsg(sock->fd.fd, &msg, 0); } if (ret < 0) { diff --git a/src/socket.c b/src/socket.c index e932148..325ff30 100644 --- a/src/socket.c +++ b/src/socket.c @@ -180,7 +180,7 @@ static bool set_bound_address(fastd_socket_t *sock) { fastd_peer_address_t addr = {}; socklen_t len = sizeof(addr); - if (getsockname(sock->fd, &addr.sa, &len) < 0) { + if (getsockname(sock->fd.fd, &addr.sa, &len) < 0) { pr_error_errno("getsockname"); return false; } @@ -201,22 +201,20 @@ bool fastd_socket_handle_binds(void) { size_t i; for (i = 0; i < ctx.n_socks; i++) { - if (ctx.socks[i].fd >= 0) + if (ctx.socks[i].fd.fd >= 0) continue; if (!ctx.socks[i].addr) continue; - ctx.socks[i].fd = bind_socket(ctx.socks[i].addr, ctx.socks[i].fd < -1); + ctx.socks[i].fd = FASTD_POLL_FD(POLL_TYPE_SOCKET, bind_socket(ctx.socks[i].addr, ctx.socks[i].fd.fd < -1)); - if (ctx.socks[i].fd >= 0) { + if (ctx.socks[i].fd.fd >= 0) { if (!set_bound_address(&ctx.socks[i])) { fastd_socket_close(&ctx.socks[i]); continue; } - fastd_poll_set_fd_sock(i); - fastd_peer_address_t bound_addr = *ctx.socks[i].bound_addr; if (!ctx.socks[i].addr->addr.sa.sa_family) bound_addr.sa.sa_family = AF_UNSPEC; @@ -225,10 +223,12 @@ bool fastd_socket_handle_binds(void) { pr_info("successfully bound to %B on `%s'", &bound_addr, ctx.socks[i].addr->bindtodev); else pr_info("successfully bound to %B", &bound_addr); + + fastd_poll_fd_register(&ctx.socks[i].fd); } } - if ((ctx.sock_default_v4 && ctx.sock_default_v4->fd < 0) || (ctx.sock_default_v6 && ctx.sock_default_v6->fd < 0)) + if ((ctx.sock_default_v4 && ctx.sock_default_v4->fd.fd < 0) || (ctx.sock_default_v6 && ctx.sock_default_v6->fd.fd < 0)) return false; return true; @@ -260,7 +260,7 @@ fastd_socket_t * fastd_socket_open(fastd_peer_t *peer, int af) { fastd_socket_t *sock = fastd_new(fastd_socket_t); - sock->fd = fd; + sock->fd = FASTD_POLL_FD(POLL_TYPE_SOCKET, fd); sock->addr = NULL; sock->bound_addr = NULL; sock->peer = peer; @@ -271,16 +271,18 @@ fastd_socket_t * fastd_socket_open(fastd_peer_t *peer, int af) { return NULL; } + fastd_poll_fd_register(&sock->fd); + return sock; } /** Closes a socket */ void fastd_socket_close(fastd_socket_t *sock) { - if (sock->fd >= 0) { - if(close(sock->fd)) + if (sock->fd.fd >= 0) { + if (!fastd_poll_fd_close(&sock->fd)) pr_error_errno("closing socket: close"); - sock->fd = -2; + sock->fd.fd = -2; } if (sock->bound_addr) { diff --git a/src/status.c b/src/status.c index f079938..181ab11 100644 --- a/src/status.c +++ b/src/status.c @@ -199,7 +199,7 @@ static void dump_status(int fd) { /** Initialized the status socket */ void fastd_status_init(void) { if (!conf.status_socket) { - ctx.status_fd = -1; + ctx.status_fd.fd = -1; return; } @@ -215,8 +215,8 @@ void fastd_status_init(void) { } #endif - ctx.status_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (ctx.status_fd < 0) + ctx.status_fd = FASTD_POLL_FD(POLL_TYPE_STATUS, socket(AF_UNIX, SOCK_STREAM, 0)); + if (ctx.status_fd.fd < 0) exit_errno("fastd_status_init: socket"); @@ -230,7 +230,7 @@ void fastd_status_init(void) { sa->sun_family = AF_UNIX; memcpy(sa->sun_path, conf.status_socket, status_socket_len+1); - if (bind(ctx.status_fd, (struct sockaddr*)sa, len)) { + if (bind(ctx.status_fd.fd, (struct sockaddr*)sa, len)) { switch (errno) { case EADDRINUSE: exit_error("unable to create status socket: the path `%s' already exists", conf.status_socket); @@ -240,7 +240,7 @@ void fastd_status_init(void) { } } - if (listen(ctx.status_fd, 4)) + if (listen(ctx.status_fd.fd, 4)) exit_errno("fastd_status_init: listen"); @@ -250,6 +250,8 @@ void fastd_status_init(void) { if (setegid(gid) < 0) pr_debug_errno("setegid"); #endif + + fastd_poll_fd_register(&ctx.status_fd); } /** Closes the status socket */ @@ -257,7 +259,7 @@ void fastd_status_close(void) { if (!conf.status_socket) return; - if (close(ctx.status_fd)) + if (!fastd_poll_fd_close(&ctx.status_fd)) pr_warn_errno("fastd_status_cleanup: close"); if (unlink(conf.status_socket)) @@ -266,7 +268,7 @@ void fastd_status_close(void) { /** Handles a single connection on the status socket */ void fastd_status_handle(void) { - int fd = accept(ctx.status_fd, NULL, NULL); + int fd = accept(ctx.status_fd.fd, NULL, NULL); if (fd < 0) { pr_warn_errno("fastd_status_handle: accept"); diff --git a/src/tuntap.c b/src/tuntap.c index 98a0983..e9e0cb4 100644 --- a/src/tuntap.c +++ b/src/tuntap.c @@ -71,7 +71,8 @@ static void tuntap_open_linux(const char * dev_name) { struct ifreq ifr = {}; - if ((ctx.tunfd = open(dev_name, O_RDWR|O_NONBLOCK)) < 0) + ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(dev_name, O_RDWR|O_NONBLOCK)); + if (ctx.tunfd.fd < 0) exit_errno("could not open tun/tap device file"); if (conf.ifname) @@ -91,7 +92,7 @@ static void tuntap_open_linux(const char * dev_name) { } ifr.ifr_flags |= IFF_NO_PI; - if (ioctl(ctx.tunfd, TUNSETIFF, &ifr) < 0) + if (ioctl(ctx.tunfd.fd, TUNSETIFF, &ifr) < 0) exit_errno("TUNSETIFF ioctl failed"); ctx.ifname = fastd_strndup(ifr.ifr_name, IFNAMSIZ-1); @@ -112,7 +113,7 @@ static void tuntap_open_linux(const char * dev_name) { if (close(ctl_sock)) pr_error_errno("close"); - fastd_poll_set_fd_tuntap(); + fastd_poll_fd_register(&ctx.tunfd); pr_debug("tun/tap device initialized."); } @@ -131,11 +132,11 @@ void fastd_tuntap_open(void) { } pr_debug("using android TUN fd"); - ctx.tunfd = fastd_android_receive_tunfd(); + ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE(fastd_android_receive_tunfd())); fastd_android_send_pid(); - fastd_poll_set_fd_tuntap(); + fastd_poll_fd_register(&ctx.tunfd); pr_debug("tun device initialized."); } else { @@ -157,12 +158,12 @@ void fastd_tuntap_open(void) { static void set_tun_mtu(void) { struct tuninfo tuninfo; - if (ioctl(ctx.tunfd, TUNGIFINFO, &tuninfo) < 0) + if (ioctl(ctx.tunfd.fd, TUNGIFINFO, &tuninfo) < 0) exit_errno("TUNGIFINFO ioctl failed"); tuninfo.mtu = conf.mtu; - if (ioctl(ctx.tunfd, TUNSIFINFO, &tuninfo) < 0) + if (ioctl(ctx.tunfd.fd, TUNSIFINFO, &tuninfo) < 0) exit_errno("TUNSIFINFO ioctl failed"); } @@ -173,19 +174,19 @@ static void set_tun_mtu(void) { static void set_tap_mtu(void) { struct tapinfo tapinfo; - if (ioctl(ctx.tunfd, TAPGIFINFO, &tapinfo) < 0) + if (ioctl(ctx.tunfd.fd, TAPGIFINFO, &tapinfo) < 0) exit_errno("TAPGIFINFO ioctl failed"); tapinfo.mtu = conf.mtu; - if (ioctl(ctx.tunfd, TAPSIFINFO, &tapinfo) < 0) + if (ioctl(ctx.tunfd.fd, TAPSIFINFO, &tapinfo) < 0) exit_errno("TAPSIFINFO ioctl failed"); } /** Sets up the TUN device */ static void setup_tun(void) { int one = 1; - if (ioctl(ctx.tunfd, TUNSIFHEAD, &one) < 0) + if (ioctl(ctx.tunfd.fd, TUNSIFHEAD, &one) < 0) exit_errno("TUNSIFHEAD ioctl failed"); set_tun_mtu(); @@ -195,7 +196,7 @@ static void setup_tun(void) { static void setup_tap(void) { struct ifreq ifr = {}; - if (ioctl(ctx.tunfd, TAPGIFNAME, &ifr) < 0) + if (ioctl(ctx.tunfd.fd, TAPGIFNAME, &ifr) < 0) exit_errno("TAPGIFNAME ioctl failed"); free(ctx.ifname); @@ -234,10 +235,11 @@ void fastd_tuntap_open(void) { strncat(ifname, type, IFNAMSIZ-1); } - if ((ctx.tunfd = open(ifname, O_RDWR|O_NONBLOCK)) < 0) + ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK)); + if (ctx.tunfd.fd < 0) exit_errno("could not open tun/tap device file"); - if (!(ctx.ifname = fdevname_r(ctx.tunfd, fastd_alloc(IFNAMSIZ), IFNAMSIZ))) + if (!(ctx.ifname = fdevname_r(ctx.tunfd.fd, fastd_alloc(IFNAMSIZ), IFNAMSIZ))) exit_errno("could not get tun/tap interface name"); switch (conf.mode) { @@ -253,7 +255,7 @@ void fastd_tuntap_open(void) { exit_bug("invalid mode"); } - fastd_poll_set_fd_tuntap(); + fastd_poll_fd_register(&ctx.tunfd); pr_debug("tun/tap device initialized."); } @@ -307,7 +309,8 @@ void fastd_tuntap_open(void) { pr_debug("initializing tun device..."); - if ((ctx.tunfd = open(ifname, O_RDWR|O_NONBLOCK)) < 0) + ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK)); + if (ctx.tunfd.fd < 0) exit_errno("could not open tun device file"); ctx.ifname = fastd_strndup(conf.ifname, IFNAMSIZ-1); @@ -325,7 +328,7 @@ void fastd_tuntap_open(void) { exit_bug("invalid mode"); } - fastd_poll_set_fd_tuntap(); + fastd_poll_fd_register(&ctx.tunfd); pr_debug("tun device initialized."); } @@ -360,7 +363,8 @@ void fastd_tuntap_open(void) { pr_debug("initializing tun device..."); - if ((ctx.tunfd = open(ifname, O_RDWR|O_NONBLOCK)) < 0) + ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK)); + if (ctx.tunfd.fd < 0) exit_errno("could not open tun device file"); ctx.ifname = fastd_strndup(conf.ifname, IFNAMSIZ-1); @@ -378,7 +382,7 @@ void fastd_tuntap_open(void) { if (close(ctl_sock)) pr_error_errno("close"); - fastd_poll_set_fd_tuntap(); + fastd_poll_fd_register(&ctx.tunfd); pr_debug("tun device initialized."); } @@ -400,7 +404,7 @@ void fastd_tuntap_handle(void) { else buffer = fastd_buffer_alloc(max_len, conf.min_encrypt_head_space, conf.min_encrypt_tail_space); - ssize_t len = read(ctx.tunfd, buffer.data, max_len); + ssize_t len = read(ctx.tunfd.fd, buffer.data, max_len); if (len < 0) exit_errno("read"); @@ -436,12 +440,12 @@ void fastd_tuntap_write(fastd_buffer_t buffer) { memcpy(buffer.data, &af, 4); } - if (write(ctx.tunfd, buffer.data, buffer.len) < 0) + if (write(ctx.tunfd.fd, buffer.data, buffer.len) < 0) pr_debug2_errno("write"); } /** Closes the TUN/TAP device */ void fastd_tuntap_close(void) { - if (close(ctx.tunfd)) + if (!fastd_poll_fd_close(&ctx.tunfd)) pr_warn_errno("closing tun/tap: close"); } diff --git a/src/types.h b/src/types.h index f380541..2a854c2 100644 --- a/src/types.h +++ b/src/types.h @@ -75,12 +75,22 @@ typedef enum fastd_drop_caps { DROP_CAPS_EARLY, /**< The capabilities are dropped before executing the on-up command */ } fastd_drop_caps_t; +/** Types of file descriptors to poll on */ +typedef enum fastd_poll_type { + POLL_TYPE_UNSPEC = 0, + POLL_TYPE_ASYNC, + POLL_TYPE_STATUS, + POLL_TYPE_IFACE, + POLL_TYPE_SOCKET, +} fastd_poll_type_t; + /** A timestamp used as a timeout */ typedef int64_t fastd_timeout_t; typedef struct fastd_buffer fastd_buffer_t; +typedef struct fastd_poll_fd fastd_poll_fd_t; typedef union fastd_peer_address fastd_peer_address_t; typedef struct fastd_bind_address fastd_bind_address_t; |