23
23
#include < violite.h>
24
24
#include < proxy_protocol.h>
25
25
#include < log.h>
26
+ #include < my_pthread.h>
26
27
27
28
#define PROXY_PROTOCOL_V1_SIGNATURE " PROXY"
28
29
#define PROXY_PROTOCOL_V2_SIGNATURE " \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A "
29
30
#define MAX_PROXY_HEADER_LEN 256
30
31
32
+ static mysql_rwlock_t lock;
33
+
31
34
/*
32
35
Parse proxy protocol version 1 header (text)
33
36
*/
@@ -341,31 +344,41 @@ static int parse_subnet(char *addr_str, struct subnet *subnet)
341
344
342
345
@param[in] subnets_str : networks in CIDR format,
343
346
separated by comma and/or space
347
+ @param[out] out_subnets : parsed subnets;
348
+ @param[out] out_count : number of parsed subnets
344
349
345
350
@return 0 if success, otherwise -1
346
351
*/
347
- int set_proxy_protocol_networks (const char *subnets_str)
352
+ static int parse_networks (const char *subnets_str, subnet **out_subnets, size_t *out_count )
348
353
{
354
+ int ret= -1 ;
355
+ subnet *subnets= 0 ;
356
+ size_t count= 0 ;
357
+ const char *p= subnets_str;
358
+ size_t max_subnets;
359
+
349
360
if (!subnets_str || !*subnets_str)
350
- return 0 ;
361
+ {
362
+ ret= 0 ;
363
+ goto end;
364
+ }
351
365
352
- size_t max_subnets= MY_MAX (3 ,strlen (subnets_str)/2 );
353
- proxy_protocol_subnets = (subnet *)my_malloc (max_subnets * sizeof (subnet),MY_ZEROFILL);
366
+ max_subnets= MY_MAX (3 ,strlen (subnets_str)/2 );
367
+ subnets = (subnet *)my_malloc (max_subnets * sizeof (subnet),MY_ZEROFILL);
354
368
355
369
/* Check for special case '*'. */
356
370
if (strcmp (subnets_str, " *" ) == 0 )
357
371
{
358
-
359
- proxy_protocol_subnets[ 0 ].family = AF_INET ;
360
- proxy_protocol_subnets[ 1 ].family = AF_INET6 ;
361
- proxy_protocol_subnets[ 2 ]. family = AF_UNIX ;
362
- proxy_protocol_subnet_count= 3 ;
363
- return 0 ;
372
+ subnets[ 0 ]. family = AF_INET;
373
+ subnets[ 1 ].family = AF_INET6 ;
374
+ subnets[ 2 ].family = AF_UNIX ;
375
+ count= 3 ;
376
+ ret= 0 ;
377
+ goto end ;
364
378
}
365
379
366
380
char token[256 ];
367
- const char *p= subnets_str;
368
- for (proxy_protocol_subnet_count= 0 ;; proxy_protocol_subnet_count++)
381
+ for (count= 0 ;; count++)
369
382
{
370
383
while (*p && (*p ==' ,' || *p == ' ' ))
371
384
p++;
@@ -377,18 +390,75 @@ int set_proxy_protocol_networks(const char *subnets_str)
377
390
token[cnt++]= *p++;
378
391
379
392
token[cnt++]=0 ;
380
- if (cnt == sizeof (token))
381
- return - 1 ;
393
+ if (cnt == sizeof (token))
394
+ goto end ;
382
395
383
- if (parse_subnet (token, &proxy_protocol_subnets[proxy_protocol_subnet_count ]))
396
+ if (parse_subnet (token, &subnets[count ]))
384
397
{
385
- sql_print_error ( " Error parsing proxy_protocol_networks parameter, near '%s'" ,token);
386
- return - 1 ;
398
+ my_printf_error (ER_PARSE_ERROR, " Error parsing proxy_protocol_networks parameter, near '%s'" , MYF ( 0 ) ,token);
399
+ goto end ;
387
400
}
388
401
}
402
+
403
+ ret = 0 ;
404
+
405
+ end:
406
+ if (ret)
407
+ {
408
+ my_free (subnets);
409
+ *out_subnets= NULL ;
410
+ *out_count= 0 ;
411
+ return ret;
412
+ }
413
+ *out_subnets = subnets;
414
+ *out_count= count;
389
415
return 0 ;
390
416
}
391
417
418
+ /* *
419
+ Check validity of proxy_protocol_networks parameter
420
+ @param[in] in - input string
421
+ @return : true, if input is list of CIDR-style networks
422
+ separated by command or space
423
+ */
424
+ bool proxy_protocol_networks_valid (const char *in)
425
+ {
426
+ subnet *new_subnets;
427
+ size_t new_count;
428
+ int ret= parse_networks (in, &new_subnets, &new_count);
429
+ my_free (new_subnets);
430
+ return !ret;
431
+ }
432
+
433
+
434
+ /* *
435
+ Set 'proxy_protocol_networks' parameter.
436
+
437
+ @param[in] spec : networks in CIDR format,
438
+ separated by comma and/or space
439
+
440
+ @return 0 if success, otherwise -1
441
+ */
442
+ int set_proxy_protocol_networks (const char *spec)
443
+ {
444
+ subnet *new_subnets;
445
+ subnet *old_subnet = 0 ;
446
+ size_t new_count;
447
+
448
+ int ret= parse_networks (spec, &new_subnets, &new_count);
449
+ if (ret)
450
+ return ret;
451
+
452
+ mysql_rwlock_wrlock (&lock);
453
+ old_subnet = proxy_protocol_subnets;
454
+ proxy_protocol_subnets = new_subnets;
455
+ proxy_protocol_subnet_count = new_count;
456
+ mysql_rwlock_unlock (&lock);
457
+ my_free (old_subnet);
458
+ return ret;
459
+ }
460
+
461
+
392
462
/* *
393
463
Compare memory areas, in memcmp().similar fashion.
394
464
The difference to memcmp() is that size parameter is the
@@ -475,20 +545,39 @@ bool is_proxy_protocol_allowed(const sockaddr *addr)
475
545
break ;
476
546
default :
477
547
DBUG_ASSERT (0 );
478
- }
548
+ }
479
549
550
+ bool ret= false ;
551
+ mysql_rwlock_rdlock (&lock);
480
552
for (size_t i= 0 ; i < proxy_protocol_subnet_count; i++)
553
+ {
481
554
if (addr_matches_subnet (normalized_addr, &proxy_protocol_subnets[i]))
482
- return true ;
555
+ {
556
+ ret= true ;
557
+ break ;
558
+ }
559
+ }
560
+ mysql_rwlock_unlock (&lock);
483
561
484
- return false ;
562
+ return ret ;
485
563
}
486
564
487
565
488
- void cleanup_proxy_protocol_networks ( )
566
+ int init_proxy_protocol_networks ( const char *spec )
489
567
{
490
- my_free (proxy_protocol_subnets);
491
- proxy_protocol_subnets= 0 ;
492
- proxy_protocol_subnet_count= 0 ;
568
+ #ifdef HAVE_PSI_INTERFACE
569
+ static PSI_rwlock_key psi_rwlock_key;
570
+ static PSI_rwlock_info psi_rwlock_info={ &psi_rwlock_key, " rwlock" , 0 };
571
+ mysql_rwlock_register (" proxy_protocol" , &psi_rwlock_info, 1 );
572
+ #endif
573
+
574
+ mysql_rwlock_init (psi_rwlock_key, &lock);
575
+ return set_proxy_protocol_networks (spec);
493
576
}
494
577
578
+
579
+ void destroy_proxy_protocol_networks ()
580
+ {
581
+ my_free (proxy_protocol_subnets);
582
+ mysql_rwlock_destroy (&lock);
583
+ }
0 commit comments