From 364a53577eb33f20bed877fc5d4a54de829707d8 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 20 Feb 2015 23:16:38 +0800 Subject: Move generic network routines to netio.c --HG-- branch : fastopen --- netio.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 netio.h (limited to 'netio.h') diff --git a/netio.h b/netio.h new file mode 100644 index 0000000..3c98d6c --- /dev/null +++ b/netio.h @@ -0,0 +1,46 @@ +#ifndef DROPBEAR_NETIO_H +#define DROPBEAR_NETIO_H + +#include "includes.h" +#include "buffer.h" +#include "queue.h" + +enum dropbear_prio { + DROPBEAR_PRIO_DEFAULT = 10, + DROPBEAR_PRIO_LOWDELAY = 11, + DROPBEAR_PRIO_BULK = 12, +}; + +void set_sock_nodelay(int sock); +void set_sock_priority(int sock, enum dropbear_prio prio); + +void get_socket_address(int fd, char **local_host, char **local_port, + char **remote_host, char **remote_port, int host_lookup); +void getaddrstring(struct sockaddr_storage* addr, + char **ret_host, char **ret_port, int host_lookup); +int dropbear_listen(const char* address, const char* port, + int *socks, unsigned int sockcount, char **errstring, int *maxfd); + +struct dropbear_progress_connection; + +/* result is DROPBEAR_SUCCESS or DROPBEAR_FAILURE. +errstring is only set on DROPBEAR_FAILURE, returns failure message for the last attempted socket */ +typedef void(*connect_callback)(int result, int sock, void* data, const char* errstring); + +struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, + connect_callback cb, void *cb_data); + +void set_connect_fds(fd_set *writefd); +void handle_connect_fds(fd_set *writefd); + +/* Doesn't actually stop the connect, but adds a dummy callback instead */ +void cancel_connect(struct dropbear_progress_connection *c); + +void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue); + +/* TODO: writev #ifdef guard */ +struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count); +void packet_queue_consume(struct Queue *queue, ssize_t written); + +#endif + -- cgit v1.2.3 From f04a3a2cfa6a2787e84b07d6d22cb1e9837ff6af Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 20 Feb 2015 23:38:05 +0800 Subject: Fixes for backwards compatibility --HG-- branch : fastopen --- configure.ac | 2 +- dbutil.h | 12 --------- netio.c | 85 +++++++++++++++++++++++++++--------------------------------- netio.h | 12 +++++++++ sysoptions.h | 5 ++++ 5 files changed, 56 insertions(+), 60 deletions(-) (limited to 'netio.h') diff --git a/configure.ac b/configure.ac index b952d7e..b0e85e5 100644 --- a/configure.ac +++ b/configure.ac @@ -632,7 +632,7 @@ fi AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_FUNC_SELECT_ARGTYPES -AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev sendmsg]) +AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev]) AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME)) diff --git a/dbutil.h b/dbutil.h index a7b6897..f5c57b3 100644 --- a/dbutil.h +++ b/dbutil.h @@ -65,18 +65,6 @@ extern int debug_trace; char * stripcontrol(const char * text); -#if defined(__linux__) && HAVE_SENDMSG -#define DROPBEAR_TCP_FAST_OPEN -void set_listen_fast_open(int sock); -/* may be supported by kernel but not libc */ -#ifndef TCP_FASTOPEN -#define TCP_FASTOPEN 23 -#endif -#ifndef MSG_FASTOPEN -#define MSG_FASTOPEN 0x20000000 -#endif -#endif - int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, int *writefd, int *readfd, int *errfd, pid_t *pid); void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell); diff --git a/netio.c b/netio.c index 8dd8060..b86c85b 100644 --- a/netio.c +++ b/netio.c @@ -68,6 +68,11 @@ void cancel_connect(struct dropbear_progress_connection *c) { static void connect_try_next(struct dropbear_progress_connection *c) { struct addrinfo *r; + int res = 0; + int fastopen = 0; +#ifdef DROPBEAR_TCP_FAST_OPEN + struct msghdr message; +#endif if (!c->res_iter) { return; @@ -89,59 +94,45 @@ static void connect_try_next(struct dropbear_progress_connection *c) { set_piggyback_ack(c->sock); #endif -#ifdef PROGRESS_CONNECT_FALLBACK -#if 0 - if (connect(c->sock, r->ai_addr, r->ai_addrlen) < 0) { - if (errno == EINPROGRESS) { - TRACE(("Connect in progress")) - break; - } else { - close(c->sock); - c->sock = -1; - continue; +#ifdef DROPBEAR_TCP_FAST_OPEN + fastopen = (c->writequeue != NULL); + + memset(&message, 0x0, sizeof(message)); + message.msg_name = r->ai_addr; + message.msg_namelen = r->ai_addrlen; + + if (c->writequeue) { + int iovlen; /* Linux msg_iovlen is a size_t */ + message.msg_iov = packet_queue_to_iovec(c->writequeue, &iovlen); + message.msg_iovlen = iovlen; + res = sendmsg(c->sock, &message, MSG_FASTOPEN); + if (res < 0 && errno == EOPNOTSUPP) { + TRACE(("Fastopen not supported")); + /* No kernel MSG_FASTOPEN support. Fall back below */ + fastopen = 0; + /* Set to NULL to avoid trying again */ + c->writequeue = NULL; + } + m_free(message.msg_iov); + if (res > 0) { + packet_queue_consume(c->writequeue, res); } } - - break; /* Success. Treated the same as EINPROGRESS */ #endif -#else - { - struct msghdr message; - int res = 0; - memset(&message, 0x0, sizeof(message)); - message.msg_name = r->ai_addr; - message.msg_namelen = r->ai_addrlen; - - if (c->writequeue) { - int iovlen; /* Linux msg_iovlen is a size_t */ - message.msg_iov = packet_queue_to_iovec(c->writequeue, &iovlen); - message.msg_iovlen = iovlen; - res = sendmsg(c->sock, &message, MSG_FASTOPEN); - if (res < 0 && errno == EOPNOTSUPP) { - TRACE(("Fastopen not supported")); - /* No kernel MSG_FASTOPEN support. Fall back below */ - c->writequeue = NULL; - } - m_free(message.msg_iov); - if (res > 0) { - packet_queue_consume(c->writequeue, res); - } - } - if (!c->writequeue) { - res = connect(c->sock, r->ai_addr, r->ai_addrlen); - } - if (res < 0 && errno != EINPROGRESS) { - close(c->sock); - c->sock = -1; - continue; - } else { - break; - } + /* Normal connect(), used as fallback for TCP fastopen too */ + if (!fastopen) { + res = connect(c->sock, r->ai_addr, r->ai_addrlen); } -#endif - } + if (res < 0 && errno != EINPROGRESS) { + close(c->sock); + c->sock = -1; + continue; + } else { + break; + } + } if (r) { c->res_iter = r->ai_next; diff --git a/netio.h b/netio.h index 3c98d6c..280ccaf 100644 --- a/netio.h +++ b/netio.h @@ -42,5 +42,17 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count); void packet_queue_consume(struct Queue *queue, ssize_t written); +#ifdef DROPBEAR_TCP_FAST_OPEN +/* Try for any Linux builds, will fall back if the kernel doesn't support it */ +void set_listen_fast_open(int sock); +/* Define values which may be supported by the kernel even if the libc is too old */ +#ifndef TCP_FASTOPEN +#define TCP_FASTOPEN 23 +#endif +#ifndef MSG_FASTOPEN +#define MSG_FASTOPEN 0x20000000 +#endif +#endif + #endif diff --git a/sysoptions.h b/sysoptions.h index bec7246..092eb7e 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -259,4 +259,9 @@ /* Use this string since some implementations might special-case it */ #define DROPBEAR_KEEPALIVE_STRING "keepalive@openssh.com" +/* Linux will attempt TCP fast open, falling back if not supported by the kernel */ +#ifdef __linux__ +#define DROPBEAR_TCP_FAST_OPEN 1 +#endif + /* no include guard for this file */ -- cgit v1.2.3 From 89c0b2a6d863e54bd0253355146f09b92edeccda Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sat, 28 Feb 2015 23:15:23 +0800 Subject: Add cleanup --HG-- branch : fastopen --- common-session.c | 2 ++ netio.c | 7 +++++++ netio.h | 4 ++++ 3 files changed, 13 insertions(+) (limited to 'netio.h') diff --git a/common-session.c b/common-session.c index 19247a8..be8f776 100644 --- a/common-session.c +++ b/common-session.c @@ -281,6 +281,8 @@ void session_cleanup() { other session state is freed. */ remove_all_listeners(); + remove_connect_pending(); + while (!isempty(&ses.writequeue)) { buf_free(dequeue(&ses.writequeue)); } diff --git a/netio.c b/netio.c index 9aa7ae5..42d1b32 100644 --- a/netio.c +++ b/netio.c @@ -177,6 +177,13 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons return c; } +void remove_connect_pending() { + while (ses.conn_pending.first) { + struct dropbear_progress_connection *c = ses.conn_pending.first->item; + remove_connect(c, ses.conn_pending.first); + } +} + void set_connect_fds(fd_set *writefd) { m_list_elem *iter; diff --git a/netio.h b/netio.h index 280ccaf..1bf08ce 100644 --- a/netio.h +++ b/netio.h @@ -30,8 +30,12 @@ typedef void(*connect_callback)(int result, int sock, void* data, const char* er struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, connect_callback cb, void *cb_data); +/* Sets up for select() */ void set_connect_fds(fd_set *writefd); +/* Handles ready sockets after select() */ void handle_connect_fds(fd_set *writefd); +/* Cleanup */ +void remove_connect_pending(); /* Doesn't actually stop the connect, but adds a dummy callback instead */ void cancel_connect(struct dropbear_progress_connection *c); -- cgit v1.2.3