@@ -188,15 +188,14 @@ do_pre_decrypt_check(struct multi_context *m, struct tls_pre_decrypt_state *stat
188188struct multi_instance *
189189handle_connection_attempt (struct multi_context * m ,
190190 struct link_socket * sock ,
191- struct mroute_addr * real ,
192- const uint64_t hv ,
193- struct hash_bucket * bucket )
191+ struct mroute_addr * real )
194192{
195193 struct hash * hash = m -> hash ;
196194 struct tls_pre_decrypt_state state = { 0 };
197195 struct multi_instance * mi = NULL ;
198196 struct gc_arena gc = gc_new ();
199197
198+
200199 if (m -> deferred_shutdown_signal .signal_received )
201200 {
202201 msg (D_MULTI_ERRORS ,
@@ -220,7 +219,10 @@ handle_connection_attempt(struct multi_context *m,
220219 mi = multi_create_instance (m , real , sock );
221220 if (mi )
222221 {
222+ const uint64_t hv = hash_value (hash , real );
223+ struct hash_bucket * bucket = hash_bucket (hash , hv );
223224 hash_add_fast (hash , bucket , & mi -> real , hv , mi );
225+
224226 mi -> did_real_hash = true;
225227 multi_assign_peer_id (m , mi );
226228
@@ -249,88 +251,139 @@ handle_connection_attempt(struct multi_context *m,
249251 return mi ;
250252}
251253
252- /**
253- * Get a client instance based on real address. If
254- * the instance doesn't exist, create it while
255- * maintaining real address hash table atomicity.
256- */
257254struct multi_instance *
258- multi_get_create_instance_udp (struct multi_context * m , bool * floated , struct link_socket * sock )
255+ multi_get_instance_udp_control (struct multi_context * m , struct link_socket * sock )
259256{
260- struct gc_arena gc = gc_new ();
261257 struct mroute_addr real = { 0 };
262- struct multi_instance * mi = NULL ;
263258 struct hash * hash = m -> hash ;
264259 real .proto = sock -> info .proto ;
265- m -> hmac_reply_ls = sock ;
266260
267261 if (mroute_extract_openvpn_sockaddr (& real , & m -> top .c2 .from .dest , true) && m -> top .c2 .buf .len > 0 )
268262 {
269263 struct hash_element * he ;
270264 const uint64_t hv = hash_value (hash , & real );
271265 struct hash_bucket * bucket = hash_bucket (hash , hv );
272- uint8_t * ptr = BPTR (& m -> top .c2 .buf );
273- uint8_t op = ptr [0 ] >> P_OPCODE_SHIFT ;
274- bool v2 = (op == P_DATA_V2 ) && (m -> top .c2 .buf .len >= (1 + 3 ));
275- bool peer_id_disabled = false;
276266
277- /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
278- if (v2 )
267+ he = hash_lookup_fast ( hash , bucket , & real , hv );
268+ if (he )
279269 {
280- uint32_t peer_id = ((uint32_t )ptr [1 ] << 16 ) | ((uint32_t )ptr [2 ] << 8 ) | ((uint32_t )ptr [3 ]);
281- peer_id_disabled = (peer_id == MAX_PEER_ID );
270+ return he -> value ;
271+ }
272+ }
273+
274+ return NULL ;
275+ }
276+
277+ /**
278+ * Get a client instance based on real address. If
279+ * the instance doesn't exist, create it while
280+ * maintaining real address hash table atomicity.
281+ */
282+ struct multi_instance *
283+ multi_get_instance_udp_data (struct multi_context * m , bool * floated , struct mroute_addr * real , struct link_socket * sock )
284+ {
285+ struct multi_instance * mi = NULL ;
286+ struct hash * hash = m -> hash ;
282287
283- if (!peer_id_disabled && (peer_id < m -> max_clients ) && (m -> instances [peer_id ]))
288+ struct hash_element * he ;
289+ const uint64_t hv = hash_value (hash , real );
290+ struct hash_bucket * bucket = hash_bucket (hash , hv );
291+ uint8_t * ptr = BPTR (& m -> top .c2 .buf );
292+ uint8_t op = ptr [0 ] >> P_OPCODE_SHIFT ;
293+ bool v2 = (op == P_DATA_V2 ) && (m -> top .c2 .buf .len >= (1 + 3 ));
294+ bool peer_id_disabled = false;
295+
296+ /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
297+ if (v2 )
298+ {
299+ uint32_t peer_id = ((uint32_t )ptr [1 ] << 16 ) | ((uint32_t )ptr [2 ] << 8 ) | ((uint32_t )ptr [3 ]);
300+ peer_id_disabled = (peer_id == MAX_PEER_ID );
301+
302+ if (!peer_id_disabled && (peer_id < m -> max_clients ) && (m -> instances [peer_id ]))
303+ {
304+ /* Floating on TCP will never be possible, so ensure we only process
305+ * UDP clients */
306+ if (m -> instances [peer_id ]-> context .c2 .link_sockets [0 ]-> info .proto
307+ == sock -> info .proto )
284308 {
285- /* Floating on TCP will never be possible, so ensure we only process
286- * UDP clients */
287- if ( m -> instances [ peer_id ] -> context . c2 . link_sockets [ 0 ] -> info . proto
288- == sock -> info . proto )
309+ mi = m -> instances [ peer_id ];
310+ * floated = ! link_socket_actual_match ( & mi -> context . c2 . from , & m -> top . c2 . from );
311+
312+ if ( * floated )
289313 {
290- mi = m -> instances [peer_id ];
291- * floated = !link_socket_actual_match (& mi -> context .c2 .from , & m -> top .c2 .from );
292-
293- if (* floated )
294- {
295- /* reset prefix, since here we are not sure peer is the one it claims to be
296- */
297- ungenerate_prefix (mi );
298- msg (D_MULTI_MEDIUM , "Float requested for peer %" PRIu32 " to %s" , peer_id ,
299- mroute_addr_print (& real , & gc ));
300- }
314+ /* reset prefix, since here we are not sure peer is the one it claims to be
315+ */
316+ ungenerate_prefix (mi );
317+ struct gc_arena gc = gc_new ();
318+ msg (D_MULTI_MEDIUM , "Float requested for peer %" PRIu32 " to %s" , peer_id ,
319+ mroute_addr_print (real , & gc ));
320+ gc_free (& gc );
301321 }
322+ return mi ;
302323 }
303324 }
304- if (!v2 || peer_id_disabled )
325+ }
326+ if (!v2 || peer_id_disabled )
327+ {
328+ he = hash_lookup_fast (hash , bucket , real , hv );
329+ if (he )
305330 {
306- he = hash_lookup_fast (hash , bucket , & real , hv );
307- if (he )
308- {
309- mi = (struct multi_instance * )he -> value ;
310- }
331+ return he -> value ;
311332 }
333+ }
334+
335+ return NULL ;
336+ }
337+
338+
339+ struct multi_instance *
340+ multi_get_create_instance_udp (struct multi_context * m , bool * floated , struct link_socket * sock )
341+ {
342+ uint8_t * ptr = BPTR (& m -> top .c2 .buf );
343+ uint8_t op = ptr [0 ] >> P_OPCODE_SHIFT ;
344+
345+ struct mroute_addr real = { 0 };
346+ real .proto = sock -> info .proto ;
312347
313- /* we have no existing multi instance for this connection */
348+ if (!mroute_extract_openvpn_sockaddr (& real , & m -> top .c2 .from .dest , true) || m -> top .c2 .buf .len == 0 )
349+ {
350+ return NULL ;
351+ }
352+
353+ struct multi_instance * mi = NULL ;
354+ if (op == P_DATA_V1 || op == P_DATA_V2 )
355+ {
356+ mi = multi_get_instance_udp_data (m , floated , & real , sock );
357+ }
358+ else
359+ {
360+ mi = multi_get_instance_udp_control (m , sock );
361+
362+ /* we have no existing multi instance for this connection, control
363+ * packets can create a session. Data packets cannot */
314364 if (!mi )
315365 {
316- mi = handle_connection_attempt (m , sock , & real , hv , bucket );
366+ m -> hmac_reply_ls = sock ;
367+ mi = handle_connection_attempt (m , sock , & real );
317368 }
369+ }
318370
319371#ifdef ENABLE_DEBUG
320- if (check_debug_level (D_MULTI_DEBUG ))
321- {
322- const char * status = mi ? "[ok]" : "[failed]" ;
372+ if (check_debug_level (D_MULTI_DEBUG ))
373+ {
374+ struct gc_arena gc = gc_new ();
375+ const char * status = mi ? "[ok]" : "[failed]" ;
323376
324- dmsg (D_MULTI_DEBUG , "GET INST BY REAL: %s %s" , mroute_addr_print (& real , & gc ), status );
325- }
326- #endif
377+ dmsg (D_MULTI_DEBUG , "GET INST BY REAL: %s %s" , mroute_addr_print (& real , & gc ), status );
378+ gc_free (& gc );
327379 }
380+ #endif
328381
329- gc_free (& gc );
330382 ASSERT (!(mi && mi -> halt ));
331383 return mi ;
332384}
333385
386+
334387/*
335388 * Send a packet to UDP socket.
336389 */
0 commit comments