Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / mudp.c
blob815ed1c87b56f845469ca0fa8300fd3e2c9ac13a
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-2009 OpenVPN Technologies, Inc. <sales@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 #include "syshead.h"
27 #if P2MP_SERVER
29 #include "multi.h"
30 #include "forward-inline.h"
32 #include "memdbg.h"
35 * Get a client instance based on real address. If
36 * the instance doesn't exist, create it while
37 * maintaining real address hash table atomicity.
40 struct multi_instance *
41 multi_get_create_instance_udp (struct multi_context *m)
43 struct gc_arena gc = gc_new ();
44 struct mroute_addr real;
45 struct multi_instance *mi = NULL;
46 struct hash *hash = m->hash;
48 if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
50 struct hash_element *he;
51 const uint32_t hv = hash_value (hash, &real);
52 struct hash_bucket *bucket = hash_bucket (hash, hv);
54 hash_bucket_lock (bucket);
55 he = hash_lookup_fast (hash, bucket, &real, hv);
57 if (he)
59 mi = (struct multi_instance *) he->value;
61 else
63 if (!m->top.c2.tls_auth_standalone
64 || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
66 if (frequency_limit_event_allowed (m->new_connection_limiter))
68 mi = multi_create_instance (m, &real);
69 if (mi)
71 hash_add_fast (hash, bucket, &mi->real, hv, mi);
72 mi->did_real_hash = true;
75 else
77 msg (D_MULTI_ERRORS,
78 "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
79 mroute_addr_print (&real, &gc));
84 hash_bucket_unlock (bucket);
86 #ifdef ENABLE_DEBUG
87 if (check_debug_level (D_MULTI_DEBUG))
89 const char *status;
91 if (he && mi)
92 status = "[succeeded]";
93 else if (!he && mi)
94 status = "[created]";
95 else
96 status = "[failed]";
98 dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
99 mroute_addr_print (&real, &gc),
100 status);
102 #endif
105 gc_free (&gc);
106 ASSERT (!(mi && mi->halt));
107 return mi;
111 * Send a packet to TCP/UDP socket.
113 static inline void
114 multi_process_outgoing_link (struct multi_context *m, const unsigned int mpp_flags)
116 struct multi_instance *mi = multi_process_outgoing_link_pre (m);
117 if (mi)
118 multi_process_outgoing_link_dowork (m, mi, mpp_flags);
122 * Process an I/O event.
124 static void
125 multi_process_io_udp (struct multi_context *m)
127 const unsigned int status = m->top.c2.event_set_status;
128 const unsigned int mpp_flags = m->top.c2.fast_io
129 ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL)
130 : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL);
132 #ifdef MULTI_DEBUG_EVENT_LOOP
133 char buf[16];
134 buf[0] = 0;
135 if (status & SOCKET_READ)
136 strcat (buf, "SR/");
137 else if (status & SOCKET_WRITE)
138 strcat (buf, "SW/");
139 else if (status & TUN_READ)
140 strcat (buf, "TR/");
141 else if (status & TUN_WRITE)
142 strcat (buf, "TW/");
143 printf ("IO %s\n", buf);
144 #endif
146 #ifdef ENABLE_MANAGEMENT
147 if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE))
149 ASSERT (management);
150 management_io (management);
152 #endif
154 /* UDP port ready to accept write */
155 if (status & SOCKET_WRITE)
157 multi_process_outgoing_link (m, mpp_flags);
159 /* TUN device ready to accept write */
160 else if (status & TUN_WRITE)
162 multi_process_outgoing_tun (m, mpp_flags);
164 /* Incoming data on UDP port */
165 else if (status & SOCKET_READ)
167 read_incoming_link (&m->top);
168 multi_release_io_lock (m);
169 if (!IS_SIG (&m->top))
170 multi_process_incoming_link (m, NULL, mpp_flags);
172 /* Incoming data on TUN device */
173 else if (status & TUN_READ)
175 read_incoming_tun (&m->top);
176 multi_release_io_lock (m);
177 if (!IS_SIG (&m->top))
178 multi_process_incoming_tun (m, mpp_flags);
183 * Return the io_wait() flags appropriate for
184 * a point-to-multipoint tunnel.
186 static inline unsigned int
187 p2mp_iow_flags (const struct multi_context *m)
189 unsigned int flags = IOW_WAIT_SIGNAL;
190 if (m->pending)
192 if (TUN_OUT (&m->pending->context))
193 flags |= IOW_TO_TUN;
194 if (LINK_OUT (&m->pending->context))
195 flags |= IOW_TO_LINK;
197 else if (mbuf_defined (m->mbuf))
198 flags |= IOW_MBUF;
199 else
200 flags |= IOW_READ;
202 return flags;
206 * Top level event loop for single-threaded operation.
207 * UDP mode.
209 static void
210 tunnel_server_udp_single_threaded (struct context *top)
212 struct multi_context multi;
214 top->mode = CM_TOP;
215 context_clear_2 (top);
217 /* initialize top-tunnel instance */
218 init_instance_handle_signals (top, top->es, CC_HARD_USR1_TO_HUP);
219 if (IS_SIG (top))
220 return;
222 /* initialize global multi_context object */
223 multi_init (&multi, top, false, MC_SINGLE_THREADED);
225 /* initialize our cloned top object */
226 multi_top_init (&multi, top, true);
228 /* initialize management interface */
229 init_management_callback_multi (&multi);
231 /* finished with initialization */
232 initialization_sequence_completed (top, ISC_SERVER); /* --mode server --proto udp */
234 /* per-packet event loop */
235 while (true)
237 perf_push (PERF_EVENT_LOOP);
239 /* set up and do the io_wait() */
240 multi_get_timeout (&multi, &multi.top.c2.timeval);
241 io_wait (&multi.top, p2mp_iow_flags (&multi));
242 MULTI_CHECK_SIG (&multi);
244 /* check on status of coarse timers */
245 multi_process_per_second_timers (&multi);
247 /* timeout? */
248 if (multi.top.c2.event_set_status == ES_TIMEOUT)
250 multi_process_timeout (&multi, MPP_PRE_SELECT|MPP_CLOSE_ON_SIGNAL);
252 else
254 /* process I/O */
255 multi_process_io_udp (&multi);
256 MULTI_CHECK_SIG (&multi);
259 perf_pop ();
262 /* shut down management interface */
263 uninit_management_callback_multi (&multi);
265 /* save ifconfig-pool */
266 multi_ifconfig_pool_persist (&multi, true);
268 /* tear down tunnel instance (unless --persist-tun) */
269 multi_uninit (&multi);
270 multi_top_free (&multi);
271 close_instance (top);
274 void
275 tunnel_server_udp (struct context *top)
277 tunnel_server_udp_single_threaded (top);
280 #endif