Send push reply right after async auth complete
PATCH 1/1 Send push reply right after async auth complete
This feature speeds up connection establishment in cases when async authentication result is not ready when first push request arrives. At the moment server sends push reply only when it receives next push request, which comes 5 seconds later.
Implementation overview.
Add new configure option ENABLE_ASYNC_PUSH, which can be enabled if system supports inotify.
Add inotify descriptor to an event loop. Add inotify watch for a authentication control file. Store mapping between watch descriptor and multi_instance in a dictionary. When file is closed, inotify fires an event and we continue with connection establishment - call client- connect etc and send push reply.
Inotify watch descriptor got automatically deleted after file is closed or when file is removed. We catch that event and remove it from the dictionary.
Feature is easily tested with sample "defer" plugin and following settings:
auth-user-pass-optional
setenv test_deferred_auth 3
plugin simple.so
--- configure.ac | 15 ++++++ src/openvpn/forward.c | 8 +++ src/openvpn/mtcp.c | 28 +++++++++++ src/openvpn/mudp.c | 27 ++++++++++ src/openvpn/multi.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/openvpn/multi.h | 10 ++++ src/openvpn/openvpn.h | 9 ++++ src/openvpn/push.c | 67 ++++++++++++++----------- src/openvpn/push.h | 2 + 9 files changed, 270 insertions(+), 31 deletions(-)
configure.ac +15 -0
@@ -264,6 +264,13 @@ AC_ARG_ENABLE( [enable_systemd="no"] ) +AC_ARG_ENABLE( + [async-push], + [AS_HELP_STRING([--enable-async-push], [enable async-push support @<:@default=no@:>@])], + [enable_async_push="yes"], + [enable_async_push="no"] +) + AC_ARG_WITH( [special-build], [AS_HELP_STRING([--with-special-build=STRING], [specify special build string])],
@@ -1168,6 +1175,14 @@ if test "${enable_plugin_auth_pam}" = "yes"; then fi fi +if test "${enable_async_push}" = "yes"; then + AC_CHECK_HEADERS( + [sys/inotify.h], + AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]), + AC_MSG_ERROR([inotify.h not found.]) + ) +fi + CONFIGURE_DEFINES="`set | grep '^enable_.*=' ; set | grep '^with_.*='`" AC_DEFINE_UNQUOTED([CONFIGURE_DEFINES], ["`echo ${CONFIGURE_DEFINES}`"], [Configuration settings])
src/openvpn/forward.c +8 -0
@@ -1378,6 +1378,9 @@ io_wait_dowork (struct context *c, const unsigned int flags)#ifdef ENABLE_MANAGEMENT static int management_shift =6 ;/* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ #endif +#ifdef ENABLE_ASYNC_PUSH +static int file_shift =8 ; +#endif /* * Decide what kind of events we want to wait for.
@@ -1472,6 +1475,11 @@ io_wait_dowork (struct context *c, const unsigned int flags)management_socket_set (management, c->c2.event_set, (void *)&management_shift,NULL );#endif +#ifdef ENABLE_ASYNC_PUSH +/* arm inotify watcher */ +event_ctl (c->c2.event_set, c->c2.inotify_fd,EVENT_READ , (void *)&file_shift); +#endif +/* * Possible scenarios: * (1) tcp/udp port has data available to read
src/openvpn/mtcp.c +28 -0
@@ -62,6 +62,10 @@# define MTCP_MANAGEMENT ((void*)4)#endif +#ifdef ENABLE_ASYNC_PUSH +#define MTCP_FILE_CLOSE_WRITE ((void*)5) +#endif +#define MTCP_N ((void*)16)/* upper bound on MTCP_x */ struct ta_iow_flags
@@ -245,6 +249,12 @@ multi_tcp_wait (const struct context *c,if (management)management_socket_set (management, mtcp->es,MTCP_MANAGEMENT , &mtcp->management_persist_flags);#endif + +#ifdef ENABLE_ASYNC_PUSH +/* arm inotify watcher */ +event_ctl (mtcp->es, c->c2.inotify_fd,EVENT_READ ,MTCP_FILE_CLOSE_WRITE ); +#endif + status =event_wait (mtcp->es, &c->c2.timeval, mtcp->esr, mtcp->maxevents);update_time (); mtcp->n_esr =0 ;
@@ -636,6 +646,12 @@ multi_tcp_process_io (struct multi_context *m) {get_signal (&m->top.sig->signal_received); } +#ifdef ENABLE_ASYNC_PUSH + else if (e->arg == MTCP_FILE_CLOSE_WRITE) + { +multi_process_file_closed (m,MPP_PRE_SELECT |MPP_RECORD_TOUCH ); + } +#endif }if (IS_SIG (&m->top))break ;
@@ -684,6 +700,14 @@ tunnel_server_tcp (struct context *top)/* finished with initialization */ initialization_sequence_completed (top,ISC_SERVER );/* --mode server --proto tcp-server */ +#ifdef ENABLE_ASYNC_PUSH + multi.top.c2.inotify_fd =inotify_init (); +if (multi.top.c2.inotify_fd <0 ) + { +msg (D_MULTI_ERRORS ,"MULTI: inotify_init error: %s" ,strerror (errno)); + } +#endif +/* per-packet event loop */ while (true) {
@@ -712,6 +736,10 @@ tunnel_server_tcp (struct context *top)perf_pop (); } +#ifdef ENABLE_ASYNC_PUSH +close (top->c2.inotify_fd); +#endif +/* shut down management interface */ uninit_management_callback_multi (&multi);
src/openvpn/mudp.c +27 -0
@@ -38,6 +38,10 @@#include "memdbg.h" +#ifdef ENABLE_ASYNC_PUSH +#include <sys/inotify.h> +#endif +/* * Get a client instance based on real address. If * the instance doesn't exist, create it while
@@ -172,6 +176,10 @@ multi_process_io_udp (struct multi_context *m)strcat (buf,"TR/" ); else if (status & TUN_WRITE) strcat (buf, "TW/"); +#ifdef ENABLE_ASYNC_PUSH + else if (status & FILE_CLOSED) + strcat (buf, "FC/"); +#endif printf ("IO %s\n", buf);#endif
@@ -209,6 +217,13 @@ multi_process_io_udp (struct multi_context *m)if (!IS_SIG (&m->top))multi_process_incoming_tun (m, mpp_flags); } +#ifdef ENABLE_ASYNC_PUSH +/* INOTIFY callback */ + else if (status & FILE_CLOSED) + { +multi_process_file_closed (m, mpp_flags); + } +#endif }/*
@@ -271,6 +286,14 @@ tunnel_server_udp_single_threaded (struct context *top)/* finished with initialization */ initialization_sequence_completed (top,ISC_SERVER );/* --mode server --proto udp */ +#ifdef ENABLE_ASYNC_PUSH + multi.top.c2.inotify_fd =inotify_init (); +if (multi.top.c2.inotify_fd <0 ) + { +msg (D_MULTI_ERRORS ,"MULTI: inotify_init error: %s" ,strerror (errno)); + } +#endif +/* per-packet event loop */ while (true) {
@@ -299,6 +322,10 @@ tunnel_server_udp_single_threaded (struct context *top)perf_pop (); } +#ifdef ENABLE_ASYNC_PUSH +close (top->c2.inotify_fd); +#endif +/* shut down management interface */ uninit_management_callback_multi (&multi);
src/openvpn/multi.c +132 -3
199 lines not on this page · raw message
src/openvpn/multi.h +10 -0
@@ -170,6 +170,11 @@ struct multi_context {* Timer object for stale route check */ struct event_timeout stale_routes_check_et; + +#ifdef ENABLE_ASYNC_PUSH +/* mapping between inotify watch descriptors and multi_instances */ +struct hash *inotify_watchers; +#endif };/*
@@ -325,6 +330,11 @@ void multi_close_instance_on_signal (struct multi_context *m, struct multi_instavoid init_management_callback_multi (struct multi_context *m);void uninit_management_callback_multi (struct multi_context *m); + +#ifdef ENABLE_ASYNC_PUSH +void multi_process_file_closed (struct multi_context *m,const unsigned int mpp_flags); +#endif +/* * Return true if our output queue is not full */
src/openvpn/openvpn.h +9 -0
@@ -247,6 +247,9 @@ struct context_2# define MANAGEMENT_READ (1<<6)# define MANAGEMENT_WRITE (1<<7)# endif +#ifdef ENABLE_ASYNC_PUSH +# define FILE_CLOSED (1<<8) +#endif unsigned int event_set_status;
@@ -446,6 +449,7 @@ struct context_2#if P2MP_SERVER /* --ifconfig endpoints to be pushed to client */ bool push_reply_deferred; +bool push_request_received;bool push_ifconfig_defined;time_t sent_push_reply_expiry;in_addr_t push_ifconfig_local;
@@ -491,6 +495,11 @@ struct context_2#ifdef MANAGEMENT_DEF_AUTH struct man_def_auth_context mda_context;#endif + +#ifdef ENABLE_ASYNC_PUSH +/* descriptor for monitoring file changes */ +int inotify_fd; +#endif };
src/openvpn/push.c +39 -28
79 lines not on this page · raw message
src/openvpn/push.h +2 -0
@@ -40,6 +40,8 @@void incoming_push_message (struct context *c,const struct buffer *buffer); +int process_incoming_push_request (struct context *c); + int process_incoming_push_msg (struct context *c, const struct buffer *buffer, bool honor_received_options,
Signature · 1 line
1.9.1