svn cleanup
[anytun.git] / openvpn / mudp.c
blob750dc8f871494b9fed2fa459e001deea1f2650eb
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef WIN32
26 #include "config-win32.h"
27 #else
28 #include "config.h"
29 #endif
31 #include "syshead.h"
33 #if P2MP_SERVER
35 #include "multi.h"
36 #include "forward-inline.h"
38 #include "memdbg.h"
41 * Get a client instance based on real address. If
42 * the instance doesn't exist, create it while
43 * maintaining real address hash table atomicity.
46 struct multi_instance *
47 multi_get_create_instance_udp (struct multi_context *m)
49 struct gc_arena gc = gc_new ();
50 struct mroute_addr real;
51 struct multi_instance *mi = NULL;
52 struct hash *hash = m->hash;
54 if (mroute_extract_sockaddr_in (&real, &m->top.c2.from, true))
56 struct hash_element *he;
57 const uint32_t hv = hash_value (hash, &real);
58 struct hash_bucket *bucket = hash_bucket (hash, hv);
60 hash_bucket_lock (bucket);
61 he = hash_lookup_fast (hash, bucket, &real, hv);
63 if (he)
65 mi = (struct multi_instance *) he->value;
67 else
69 if (!m->top.c2.tls_auth_standalone
70 || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
72 if (frequency_limit_event_allowed (m->new_connection_limiter))
74 mi = multi_create_instance (m, &real);
75 if (mi)
77 hash_add_fast (hash, bucket, &mi->real, hv, mi);
78 mi->did_real_hash = true;
81 else
83 msg (D_MULTI_ERRORS,
84 "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
85 mroute_addr_print (&real, &gc));
90 hash_bucket_unlock (bucket);
92 #ifdef ENABLE_DEBUG
93 if (check_debug_level (D_MULTI_DEBUG))
95 const char *status;
97 if (he && mi)
98 status = "[succeeded]";
99 else if (!he && mi)
100 status = "[created]";
101 else
102 status = "[failed]";
104 dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
105 mroute_addr_print (&real, &gc),
106 status);
108 #endif
111 gc_free (&gc);
112 ASSERT (!(mi && mi->halt));
113 return mi;
117 * Send a packet to TCP/UDP socket.
119 static inline void
120 multi_process_outgoing_link (struct multi_context *m, const unsigned int mpp_flags)
122 struct multi_instance *mi = multi_process_outgoing_link_pre (m);
123 if (mi)
124 multi_process_outgoing_link_dowork (m, mi, mpp_flags);
128 * Process an I/O event.
130 static void
131 multi_process_io_udp (struct multi_context *m)
133 const unsigned int status = m->top.c2.event_set_status;
134 const unsigned int mpp_flags = m->top.c2.fast_io
135 ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL)
136 : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL);
138 #ifdef MULTI_DEBUG_EVENT_LOOP
139 char buf[16];
140 buf[0] = 0;
141 if (status & SOCKET_READ)
142 strcat (buf, "SR/");
143 else if (status & SOCKET_WRITE)
144 strcat (buf, "SW/");
145 else if (status & TUN_READ)
146 strcat (buf, "TR/");
147 else if (status & TUN_WRITE)
148 strcat (buf, "TW/");
149 printf ("IO %s\n", buf);
150 #endif
152 #ifdef ENABLE_MANAGEMENT
153 if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE))
155 ASSERT (management);
156 management_io (management);
158 #endif
160 /* UDP port ready to accept write */
161 if (status & SOCKET_WRITE)
163 multi_process_outgoing_link (m, mpp_flags);
165 /* TUN device ready to accept write */
166 else if (status & TUN_WRITE)
168 multi_process_outgoing_tun (m, mpp_flags);
170 /* Incoming data on UDP port */
171 else if (status & SOCKET_READ)
173 read_incoming_link (&m->top);
174 multi_release_io_lock (m);
175 if (!IS_SIG (&m->top))
176 multi_process_incoming_link (m, NULL, mpp_flags);
178 /* Incoming data on TUN device */
179 else if (status & TUN_READ)
181 read_incoming_tun (&m->top);
182 multi_release_io_lock (m);
183 if (!IS_SIG (&m->top))
184 multi_process_incoming_tun (m, mpp_flags);
189 * Return the io_wait() flags appropriate for
190 * a point-to-multipoint tunnel.
192 static inline unsigned int
193 p2mp_iow_flags (const struct multi_context *m)
195 unsigned int flags = IOW_WAIT_SIGNAL;
196 if (m->pending)
198 if (TUN_OUT (&m->pending->context))
199 flags |= IOW_TO_TUN;
200 if (LINK_OUT (&m->pending->context))
201 flags |= IOW_TO_LINK;
203 else if (mbuf_defined (m->mbuf))
204 flags |= IOW_MBUF;
205 else
206 flags |= IOW_READ;
208 return flags;
212 * Top level event loop for single-threaded operation.
213 * UDP mode.
215 static void
216 tunnel_server_udp_single_threaded (struct context *top)
218 struct multi_context multi;
220 top->mode = CM_TOP;
221 context_clear_2 (top);
223 /* initialize top-tunnel instance */
224 init_instance_handle_signals (top, top->es, CC_HARD_USR1_TO_HUP);
225 if (IS_SIG (top))
226 return;
228 /* initialize global multi_context object */
229 multi_init (&multi, top, false, MC_SINGLE_THREADED);
231 /* initialize our cloned top object */
232 multi_top_init (&multi, top, true);
234 /* initialize management interface */
235 init_management_callback_multi (&multi);
237 /* finished with initialization */
238 initialization_sequence_completed (top, ISC_SERVER); /* --mode server --proto udp */
240 /* per-packet event loop */
241 while (true)
243 perf_push (PERF_EVENT_LOOP);
245 /* set up and do the io_wait() */
246 multi_get_timeout (&multi, &multi.top.c2.timeval);
247 io_wait (&multi.top, p2mp_iow_flags (&multi));
248 MULTI_CHECK_SIG (&multi);
250 /* check on status of coarse timers */
251 multi_process_per_second_timers (&multi);
253 /* timeout? */
254 if (multi.top.c2.event_set_status == ES_TIMEOUT)
256 multi_process_timeout (&multi, MPP_PRE_SELECT|MPP_CLOSE_ON_SIGNAL);
258 else
260 /* process I/O */
261 multi_process_io_udp (&multi);
262 MULTI_CHECK_SIG (&multi);
265 perf_pop ();
268 /* shut down management interface */
269 uninit_management_callback_multi (&multi);
271 /* save ifconfig-pool */
272 multi_ifconfig_pool_persist (&multi, true);
274 /* tear down tunnel instance (unless --persist-tun) */
275 multi_uninit (&multi);
276 multi_top_free (&multi);
277 close_instance (top);
280 void
281 tunnel_server_udp (struct context *top)
283 tunnel_server_udp_single_threaded (top);
286 #endif