diff --git a/src/openvpn/event.h b/src/openvpn/event.h index 856551ad..844ea7b3 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -126,6 +126,20 @@ struct event_set struct event_set_functions func; }; +typedef enum { + EVENT_ARG_MULTI_INSTANCE = 0, + EVENT_ARG_LINK_SOCKET, +} event_arg_t; + +/* generic event argument object to pass to event_ctl() */ +struct event_arg +{ + event_arg_t type; + union { + struct multi_instance *mi; /* if type = EVENT_ARG_MULTI_INSTANCE */ + } u; +}; + /* * maxevents on input: desired max number of event_t descriptors * simultaneously set with event_ctl diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 3ae8be73..67e3e8e2 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -54,7 +54,6 @@ /* * Special tags passed to event.[ch] functions */ -#define MTCP_SOCKET ((void *)1) #define MTCP_TUN ((void *)2) #define MTCP_SIG ((void *)3) /* Only on Windows */ #define MTCP_MANAGEMENT ((void *)4) @@ -245,7 +244,7 @@ multi_tcp_set_global_rw_flags(struct multi_context *m, struct multi_instance *mi socket_set(mi->context.c2.link_socket, m->mtcp->es, mbuf_defined(mi->tcp_link_out_deferred) ? EVENT_WRITE : EVENT_READ, - mi, + &mi->ev_arg, &mi->tcp_rwflags); } } @@ -255,8 +254,8 @@ multi_tcp_wait(const struct context *c, struct multi_tcp *mtcp) { int status; - unsigned int *persistent = &mtcp->tun_rwflags; - socket_set_listen_persistent(c->c2.link_socket, mtcp->es, MTCP_SOCKET); + socket_set_listen_persistent(c->c2.link_socket, mtcp->es, + &c->c2.link_socket->ev_arg); #ifdef _WIN32 if (tuntap_is_wintun(c->c1.tuntap)) @@ -272,7 +271,7 @@ multi_tcp_wait(const struct context *c, persistent = NULL; } #endif - tun_set(c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, persistent); + tun_set(c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, &mtcp->tun_rwflags); #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) dco_event_set(&c->c1.tuntap->dco, mtcp->es, MTCP_DCO); #endif @@ -685,20 +684,43 @@ multi_tcp_process_io(struct multi_context *m) { struct event_set_return *e = &mtcp->esr[i]; - /* incoming data for instance? */ + /* incoming data for instance or listening socket? */ if (e->arg >= MTCP_N) { - struct multi_instance *mi = (struct multi_instance *) e->arg; - if (mi) + struct event_arg *ev_arg = (struct event_arg *)e->arg; + switch (ev_arg->type) { - if (e->rwflags & EVENT_WRITE) - { - multi_tcp_action(m, mi, TA_SOCKET_WRITE_READY, false); - } - else if (e->rwflags & EVENT_READ) - { - multi_tcp_action(m, mi, TA_SOCKET_READ, false); - } + struct multi_instance *mi; + + /* react to event on child instance */ + case EVENT_ARG_MULTI_INSTANCE: + if (!ev_arg->u.mi) + { + msg(D_MULTI_ERRORS, "MULTI: mtcp_proc_io: null minstance"); + break; + } + + mi = ev_arg->u.mi; + if (e->rwflags & EVENT_WRITE) + { + multi_tcp_action(m, mi, TA_SOCKET_WRITE_READY, false); + } + else if (e->rwflags & EVENT_READ) + { + multi_tcp_action(m, mi, TA_SOCKET_READ, false); + } + break; + + /* new incoming TCP client attempting to connect? */ + case EVENT_ARG_LINK_SOCKET: + ASSERT(m->top.c2.link_socket); + socket_reset_listen_persistent(m->top.c2.link_socket); + mi = multi_create_instance_tcp(m); + if (mi) + { + multi_tcp_action(m, mi, TA_INITIAL, false); + } + break; } } else @@ -723,18 +745,6 @@ multi_tcp_process_io(struct multi_context *m) multi_tcp_action(m, NULL, TA_TUN_READ, false); } } - /* new incoming TCP client attempting to connect? */ - else if (e->arg == MTCP_SOCKET) - { - struct multi_instance *mi; - ASSERT(m->top.c2.link_socket); - socket_reset_listen_persistent(m->top.c2.link_socket); - mi = multi_create_instance_tcp(m); - if (mi) - { - multi_tcp_action(m, mi, TA_INITIAL, false); - } - } #if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD)) /* incoming data on DCO? */ else if (e->arg == MTCP_DCO) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 0509911d..45b3cfa2 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -823,6 +823,9 @@ multi_create_instance(struct multi_context *m, const struct mroute_addr *real) goto err; } + mi->ev_arg.type = EVENT_ARG_MULTI_INSTANCE; + mi->ev_arg.u.mi = mi; + perf_pop(); gc_free(&gc); return mi; diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 7167639e..1b99ef70 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -102,6 +102,12 @@ struct multi_instance { struct schedule_entry se; /* this must be the first element of the structure, * We cast between this and schedule_entry so the * beginning of the struct must be identical */ + + struct event_arg ev_arg; /**< this struct will store a pointer to either mi or + * link_socket, depending on the event type, to keep + * it accessible it's placed within the same struct + * it points to. */ + struct gc_arena gc; bool halt; int refcount; diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 7b1e6038..cf04090c 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -1830,6 +1830,8 @@ link_socket_new(void) ALLOC_OBJ_CLEAR(sock, struct link_socket); sock->sd = SOCKET_UNDEFINED; sock->ctrl_sd = SOCKET_UNDEFINED; + sock->ev_arg.type = EVENT_ARG_LINK_SOCKET; + return sock; } diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 04eb8a42..27caab4d 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -178,6 +178,11 @@ struct link_socket { struct link_socket_info info; + struct event_arg ev_arg; /**< this struct will store a pointer to either mi or + * link_socket, depending on the event type, to keep + * it accessible it's placed within the same struct + * it points to. */ + socket_descriptor_t sd; socket_descriptor_t ctrl_sd; /* only used for UDP over Socks */