MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
/*
* MAP management functions .
*
* Copyright 2000 - 2013 Willy Tarreau < w @ 1 wt . eu >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*
*/
# include <stdio.h>
2021-04-30 08:57:03 -04:00
# include <syslog.h>
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
2020-05-27 06:58:42 -04:00
# include <haproxy/api.h>
2022-05-03 05:54:47 -04:00
# include <haproxy/applet.h>
2020-06-09 03:07:15 -04:00
# include <haproxy/arg.h>
2020-06-04 14:19:54 -04:00
# include <haproxy/cli.h>
2020-06-04 09:10:43 -04:00
# include <haproxy/map.h>
2020-06-04 09:06:28 -04:00
# include <haproxy/pattern.h>
2020-06-02 11:32:26 -04:00
# include <haproxy/regex.h>
2020-06-09 03:07:15 -04:00
# include <haproxy/sample.h>
2022-05-27 03:25:10 -04:00
# include <haproxy/sc_strm.h>
2020-06-04 13:58:55 -04:00
# include <haproxy/stats-t.h>
2022-05-27 03:47:12 -04:00
# include <haproxy/stconn.h>
2020-06-03 12:09:46 -04:00
# include <haproxy/tools.h>
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
2015-08-04 13:35:46 -04:00
/* Parse an IPv4 or IPv6 address and store it into the sample.
* The output type is IPv4 or IPv6 .
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
*/
2015-08-19 02:35:43 -04:00
int map_parse_ip ( const char * text , struct sample_data * data )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
2015-08-04 13:35:46 -04:00
int len = strlen ( text ) ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
2015-08-04 13:35:46 -04:00
if ( buf2ip ( text , len , & data - > u . ipv4 ) ) {
data - > type = SMP_T_IPV4 ;
return 1 ;
}
if ( buf2ip6 ( text , len , & data - > u . ipv6 ) ) {
data - > type = SMP_T_IPV6 ;
return 1 ;
}
return 0 ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
}
/* Parse a string and store a pointer to it into the sample. The original
* string must be left in memory because we return a direct memory reference .
2013-12-16 18:20:33 -05:00
* The output type is SMP_T_STR . There is no risk that the data will be
* overwritten because sample_conv_map ( ) makes a const sample with this
* output .
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
*/
2015-08-19 02:35:43 -04:00
int map_parse_str ( const char * text , struct sample_data * data )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
2018-07-13 04:54:26 -04:00
data - > u . str . area = ( char * ) text ;
data - > u . str . data = strlen ( text ) ;
data - > u . str . size = data - > u . str . data + 1 ;
2015-08-19 02:35:43 -04:00
data - > type = SMP_T_STR ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
return 1 ;
}
/* Parse an integer and convert it to a sample. The output type is SINT if the
* number is negative , or UINT if it is positive or null . The function returns
* zero ( error ) if the number is too large .
*/
2015-08-19 02:35:43 -04:00
int map_parse_int ( const char * text , struct sample_data * data )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
2015-08-19 02:35:43 -04:00
data - > type = SMP_T_SINT ;
2015-08-19 03:07:19 -04:00
data - > u . sint = read_int64 ( & text , text + strlen ( text ) ) ;
2015-07-06 17:43:03 -04:00
if ( * text ! = ' \0 ' )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
return 0 ;
return 1 ;
}
/* This crete and initialize map descriptor.
* Return NULL if out of memory error
*/
2014-02-11 05:31:40 -05:00
static struct map_descriptor * map_create_descriptor ( struct sample_conv * conv )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
struct map_descriptor * desc ;
desc = calloc ( 1 , sizeof ( * desc ) ) ;
if ( ! desc )
return NULL ;
desc - > conv = conv ;
return desc ;
}
/* This function load the map file according with data type declared into
* the " struct sample_conv " .
*
* This function choose the indexation type ( ebtree or list ) according with
* the type of match needed .
*/
2015-04-07 05:27:54 -04:00
int sample_load_map ( struct arg * arg , struct sample_conv * conv ,
const char * file , int line , char * * err )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
struct map_descriptor * desc ;
2020-08-05 17:23:37 -04:00
if ( ! ( global . mode & MODE_STARTING ) ) {
memprintf ( err , " map: cannot load map at runtime " ) ;
return 0 ;
}
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
/* create new map descriptor */
2014-02-11 05:31:40 -05:00
desc = map_create_descriptor ( conv ) ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
if ( ! desc ) {
memprintf ( err , " out of memory " ) ;
return 0 ;
}
2014-02-11 05:31:40 -05:00
/* Initialize pattern */
pattern_init_head ( & desc - > pat ) ;
/* This is original pattern, must free */
desc - > do_free = 1 ;
/* Set the match method. */
2014-12-15 10:18:39 -05:00
desc - > pat . match = pat_match_fcts [ ( long ) conv - > private ] ;
desc - > pat . parse = pat_parse_fcts [ ( long ) conv - > private ] ;
desc - > pat . index = pat_index_fcts [ ( long ) conv - > private ] ;
desc - > pat . prune = pat_prune_fcts [ ( long ) conv - > private ] ;
desc - > pat . expect_type = pat_match_types [ ( long ) conv - > private ] ;
2014-02-11 05:31:40 -05:00
/* Set the output parse method. */
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
switch ( desc - > conv - > out_type ) {
2014-02-11 05:31:40 -05:00
case SMP_T_STR : desc - > pat . parse_smp = map_parse_str ; break ;
2015-07-06 17:43:03 -04:00
case SMP_T_SINT : desc - > pat . parse_smp = map_parse_int ; break ;
2015-08-04 13:35:46 -04:00
case SMP_T_ADDR : desc - > pat . parse_smp = map_parse_ip ; break ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
default :
memprintf ( err , " map: internal haproxy error: no default parse case for the input type <%d>. " ,
conv - > out_type ) ;
2016-03-03 14:32:23 -05:00
free ( desc ) ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
return 0 ;
}
2014-01-29 07:29:45 -05:00
/* Load map. */
2018-07-13 04:54:26 -04:00
if ( ! pattern_read_from_file ( & desc - > pat , PAT_REF_MAP , arg [ 0 ] . data . str . area , PAT_MF_NO_DNS ,
2014-02-11 08:36:45 -05:00
1 , err , file , line ) )
2014-02-11 05:31:40 -05:00
return 0 ;
2013-12-05 08:40:25 -05:00
2019-04-19 05:35:22 -04:00
/* the maps of type IP support a string as default value. This
* string can be an ipv4 or an ipv6 , we must convert it .
2015-08-04 13:35:46 -04:00
*/
2019-04-19 05:35:22 -04:00
if ( arg [ 1 ] . type ! = ARGT_STOP & & desc - > conv - > out_type = = SMP_T_ADDR ) {
2015-08-04 13:35:46 -04:00
struct sample_data data ;
2018-07-13 04:54:26 -04:00
if ( ! map_parse_ip ( arg [ 1 ] . data . str . area , & data ) ) {
memprintf ( err , " map: cannot parse default ip <%s>. " ,
arg [ 1 ] . data . str . area ) ;
2015-08-04 13:35:46 -04:00
return 0 ;
}
2020-08-07 05:45:18 -04:00
chunk_destroy ( & arg [ 1 ] . data . str ) ;
2015-08-04 13:35:46 -04:00
if ( data . type = = SMP_T_IPV4 ) {
arg [ 1 ] . type = ARGT_IPV4 ;
arg [ 1 ] . data . ipv4 = data . u . ipv4 ;
} else {
arg [ 1 ] . type = ARGT_IPV6 ;
arg [ 1 ] . data . ipv6 = data . u . ipv6 ;
}
}
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
/* replace the first argument by this definition */
2020-08-07 05:45:18 -04:00
chunk_destroy ( & arg [ 0 ] . data . str ) ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
arg [ 0 ] . type = ARGT_MAP ;
arg [ 0 ] . data . map = desc ;
return 1 ;
}
2015-05-11 09:20:49 -04:00
static int sample_conv_map ( const struct arg * arg_p , struct sample * smp , void * private )
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{
struct map_descriptor * desc ;
2014-01-17 09:25:13 -05:00
struct pattern * pat ;
2018-07-13 05:56:34 -04:00
struct buffer * str ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
/* get config */
desc = arg_p [ 0 ] . data . map ;
/* Execute the match function. */
2014-02-11 05:31:40 -05:00
pat = pattern_exec_match ( & desc - > pat , smp , 1 ) ;
2014-01-17 09:25:13 -05:00
/* Match case. */
if ( pat ) {
2015-08-19 02:35:43 -04:00
if ( pat - > data ) {
2016-02-10 16:55:20 -05:00
/* In the regm case, merge the sample with the input. */
if ( ( long ) private = = PAT_MATCH_REGM ) {
2018-07-17 09:47:07 -04:00
struct buffer * tmptrash ;
2018-08-21 22:55:43 -04:00
int len ;
2018-07-17 09:47:07 -04:00
/* Copy the content of the sample because it could
be scratched by incoming get_trash_chunk */
tmptrash = alloc_trash_chunk ( ) ;
if ( ! tmptrash )
return 0 ;
tmptrash - > data = smp - > data . u . str . data ;
if ( tmptrash - > data > ( tmptrash - > size - 1 ) )
tmptrash - > data = tmptrash - > size - 1 ;
memcpy ( tmptrash - > area , smp - > data . u . str . area , tmptrash - > data ) ;
tmptrash - > area [ tmptrash - > data ] = 0 ;
2016-02-10 16:55:20 -05:00
str = get_trash_chunk ( ) ;
2018-08-21 22:55:43 -04:00
len = exp_replace ( str - > area , str - > size ,
tmptrash - > area ,
pat - > data - > u . str . area ,
( regmatch_t * ) smp - > ctx . a [ 0 ] ) ;
2019-04-12 16:54:28 -04:00
free_trash_chunk ( tmptrash ) ;
2018-08-21 22:55:43 -04:00
if ( len = = - 1 )
2016-02-10 16:55:20 -05:00
return 0 ;
2018-08-21 22:55:43 -04:00
str - > data = len ;
2016-02-10 16:55:20 -05:00
smp - > data . u . str = * str ;
return 1 ;
}
/* Copy sample. */
2015-08-19 03:02:36 -04:00
smp - > data = * pat - > data ;
2014-01-17 09:25:13 -05:00
smp - > flags | = SMP_F_CONST ;
return 1 ;
}
/* Return just int sample containing 1. */
2015-08-19 03:00:18 -04:00
smp - > data . type = SMP_T_SINT ;
2015-08-19 03:07:19 -04:00
smp - > data . u . sint = 1 ;
2014-01-17 09:25:13 -05:00
return 1 ;
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
}
2018-11-25 14:48:18 -05:00
/* If no default value available, the converter fails. */
2015-03-12 19:10:16 -04:00
if ( arg_p [ 1 ] . type = = ARGT_STOP )
2014-01-17 09:25:13 -05:00
return 0 ;
/* Return the default value. */
2015-03-12 19:10:16 -04:00
switch ( desc - > conv - > out_type ) {
case SMP_T_STR :
2015-08-19 03:00:18 -04:00
smp - > data . type = SMP_T_STR ;
2015-03-12 19:10:16 -04:00
smp - > flags | = SMP_F_CONST ;
2015-08-19 03:07:19 -04:00
smp - > data . u . str = arg_p [ 1 ] . data . str ;
2015-03-12 19:10:16 -04:00
break ;
2015-07-06 17:43:03 -04:00
case SMP_T_SINT :
2015-08-19 03:00:18 -04:00
smp - > data . type = SMP_T_SINT ;
2015-08-19 03:07:19 -04:00
smp - > data . u . sint = arg_p [ 1 ] . data . sint ;
2015-03-12 19:10:16 -04:00
break ;
2015-08-04 13:35:46 -04:00
case SMP_T_ADDR :
if ( arg_p [ 1 ] . type = = ARGT_IPV4 ) {
smp - > data . type = SMP_T_IPV4 ;
smp - > data . u . ipv4 = arg_p [ 1 ] . data . ipv4 ;
} else {
smp - > data . type = SMP_T_IPV6 ;
smp - > data . u . ipv6 = arg_p [ 1 ] . data . ipv6 ;
}
2015-03-12 19:10:16 -04:00
break ;
}
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
return 1 ;
}
2016-11-18 13:26:17 -05:00
/* This function is used with map and acl management. It permits to browse
* each reference . The variable < getnext > must contain the current node ,
* < end > point to the root node and the < flags > permit to filter required
* nodes .
*/
static inline
struct pat_ref * pat_list_get_next ( struct pat_ref * getnext , struct list * end ,
unsigned int flags )
{
struct pat_ref * ref = getnext ;
while ( 1 ) {
/* Get next list entry. */
ref = LIST_NEXT ( & ref - > list , struct pat_ref * , list ) ;
/* If the entry is the last of the list, return NULL. */
if ( & ref - > list = = end )
return NULL ;
/* If the entry match the flag, return it. */
if ( ref - > flags & flags )
return ref ;
}
}
static inline
struct pat_ref * pat_ref_lookup_ref ( const char * reference )
{
int id ;
char * error ;
/* If the reference starts by a '#', this is numeric id. */
if ( reference [ 0 ] = = ' # ' ) {
/* Try to convert the numeric id. If the conversion fails, the lookup fails. */
id = strtol ( reference + 1 , & error , 10 ) ;
if ( * error ! = ' \0 ' )
return NULL ;
/* Perform the unique id lookup. */
return pat_ref_lookupid ( id ) ;
}
/* Perform the string lookup. */
return pat_ref_lookup ( reference ) ;
}
/* This function is used with map and acl management. It permits to browse
* each reference .
*/
static inline
struct pattern_expr * pat_expr_get_next ( struct pattern_expr * getnext , struct list * end )
{
struct pattern_expr * expr ;
expr = LIST_NEXT ( & getnext - > list , struct pattern_expr * , list ) ;
if ( & expr - > list = = end )
return NULL ;
return expr ;
}
2022-05-03 05:54:47 -04:00
/* appctx context for the "{show|get|add|del|*} {map|acl}" commands. This is
* used even by commands that only have a parser and no I / O handler because
* it provides a unified way to manipulate some fields and will allow to
* expand some of them more easily later if needed .
*/
struct show_map_ctx {
struct pat_ref * ref ;
struct bref bref ; /* back-reference from the pat_ref_elt being dumped */
struct pattern_expr * expr ;
struct buffer chunk ;
unsigned int display_flags ;
2022-05-03 08:12:56 -04:00
unsigned int curr_gen ; /* current/latest generation, for show/clear */
unsigned int prev_gen ; /* prev generation, for clear */
2022-05-03 09:12:21 -04:00
enum {
STATE_INIT = 0 , /* initialize list and backrefs */
STATE_LIST , /* list entries */
STATE_DONE , /* finished */
} state ; /* state of the dump */
2022-05-03 05:54:47 -04:00
} ;
2022-05-03 08:12:56 -04:00
/* expects the current generation ID in ctx->curr_gen */
2016-11-18 13:26:17 -05:00
static int cli_io_handler_pat_list ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
2022-05-27 05:08:15 -04:00
struct stconn * sc = appctx_sc ( appctx ) ;
2017-06-29 09:40:33 -04:00
struct pat_ref_elt * elt ;
2022-05-27 04:26:46 -04:00
if ( unlikely ( sc_ic ( sc ) - > flags & ( CF_WRITE_ERROR | CF_SHUTW ) ) ) {
2017-06-29 09:40:33 -04:00
/* If we're forced to shut down, we might have to remove our
* reference to the last ref_elt being dumped .
*/
2022-05-03 09:42:07 -04:00
if ( ! LIST_ISEMPTY ( & ctx - > bref . users ) ) {
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2022-05-03 09:42:07 -04:00
LIST_DEL_INIT ( & ctx - > bref . users ) ;
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2017-06-29 09:40:33 -04:00
}
return 1 ;
}
2016-11-18 13:26:17 -05:00
2022-05-03 09:12:21 -04:00
switch ( ctx - > state ) {
case STATE_INIT :
ctx - > state = STATE_LIST ;
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
2022-05-03 09:12:21 -04:00
case STATE_LIST :
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2017-07-03 05:34:05 -04:00
2022-05-03 05:54:47 -04:00
if ( ! LIST_ISEMPTY ( & ctx - > bref . users ) ) {
LIST_DELETE ( & ctx - > bref . users ) ;
LIST_INIT ( & ctx - > bref . users ) ;
2022-05-03 09:26:27 -04:00
} else {
2022-05-03 05:54:47 -04:00
ctx - > bref . ref = ctx - > ref - > head . n ;
2017-06-29 09:40:33 -04:00
}
2022-05-03 05:54:47 -04:00
while ( ctx - > bref . ref ! = & ctx - > ref - > head ) {
2016-11-18 13:26:17 -05:00
chunk_reset ( & trash ) ;
2022-05-03 05:54:47 -04:00
elt = LIST_ELEM ( ctx - > bref . ref , struct pat_ref_elt * , list ) ;
2017-06-29 09:40:33 -04:00
2022-05-03 08:12:56 -04:00
if ( elt - > gen_id ! = ctx - > curr_gen )
2020-10-29 04:41:34 -04:00
goto skip ;
2016-11-18 13:26:17 -05:00
/* build messages */
2017-06-29 09:40:33 -04:00
if ( elt - > sample )
2016-11-18 13:26:17 -05:00
chunk_appendf ( & trash , " %p %s %s \n " ,
2017-06-29 09:40:33 -04:00
elt , elt - > pattern ,
elt - > sample ) ;
2016-11-18 13:26:17 -05:00
else
chunk_appendf ( & trash , " %p %s \n " ,
2017-06-29 09:40:33 -04:00
elt , elt - > pattern ) ;
2016-11-18 13:26:17 -05:00
2022-05-18 09:07:19 -04:00
if ( applet_putchk ( appctx , & trash ) = = - 1 ) {
2016-11-18 13:26:17 -05:00
/* let's try again later from this stream. We add ourselves into
* this stream ' s users so that it can remove us upon termination .
*/
2022-05-03 05:54:47 -04:00
LIST_APPEND ( & elt - > back_refs , & ctx - > bref . users ) ;
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
return 0 ;
}
2020-10-29 04:41:34 -04:00
skip :
2016-11-18 13:26:17 -05:00
/* get next list entry and check the end of the list */
2022-05-03 05:54:47 -04:00
ctx - > bref . ref = elt - > list . n ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
default :
2022-05-03 09:12:21 -04:00
ctx - > state = STATE_DONE ;
2016-11-18 13:26:17 -05:00
return 1 ;
}
}
static int cli_io_handler_pats_list ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
2016-11-18 13:26:17 -05:00
2022-05-03 09:12:21 -04:00
switch ( ctx - > state ) {
case STATE_INIT :
2016-11-18 13:26:17 -05:00
/* Display the column headers. If the message cannot be sent,
2018-11-25 14:48:18 -05:00
* quit the function with returning 0. The function is called
2022-05-03 09:12:21 -04:00
* later and restarted at the state " STATE_INIT " .
2016-11-18 13:26:17 -05:00
*/
chunk_reset ( & trash ) ;
chunk_appendf ( & trash , " # id (file) description \n " ) ;
2022-05-18 09:07:19 -04:00
if ( applet_putchk ( appctx , & trash ) = = - 1 )
2016-11-18 13:26:17 -05:00
return 0 ;
/* Now, we start the browsing of the references lists.
2018-11-25 14:48:18 -05:00
* Note that the following call to LIST_ELEM returns a bad pointer . The only
2016-11-18 13:26:17 -05:00
* available field of this pointer is < list > . It is used with the function
2018-11-25 14:48:18 -05:00
* pat_list_get_next ( ) for returning the first available entry
2016-11-18 13:26:17 -05:00
*/
2022-05-03 05:54:47 -04:00
ctx - > ref = LIST_ELEM ( & pattern_reference , struct pat_ref * , list ) ;
ctx - > ref = pat_list_get_next ( ctx - > ref , & pattern_reference ,
ctx - > display_flags ) ;
2022-05-03 09:12:21 -04:00
ctx - > state = STATE_LIST ;
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
2022-05-03 09:12:21 -04:00
case STATE_LIST :
2022-05-03 05:54:47 -04:00
while ( ctx - > ref ) {
2016-11-18 13:26:17 -05:00
chunk_reset ( & trash ) ;
/* Build messages. If the reference is used by another category than
2018-11-25 14:48:18 -05:00
* the listed categories , display the information in the message .
2016-11-18 13:26:17 -05:00
*/
2022-05-03 05:54:47 -04:00
chunk_appendf ( & trash , " %d (%s) %s. curr_ver=%u next_ver=%u entry_cnt=%llu \n " , ctx - > ref - > unique_id ,
ctx - > ref - > reference ? ctx - > ref - > reference : " " ,
ctx - > ref - > display , ctx - > ref - > curr_gen , ctx - > ref - > next_gen ,
ctx - > ref - > entry_cnt ) ;
2016-11-18 13:26:17 -05:00
2022-05-18 09:07:19 -04:00
if ( applet_putchk ( appctx , & trash ) = = - 1 ) {
2016-11-18 13:26:17 -05:00
/* let's try again later from this stream. We add ourselves into
* this stream ' s users so that it can remove us upon termination .
*/
return 0 ;
}
/* get next list entry and check the end of the list */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_list_get_next ( ctx - > ref , & pattern_reference ,
ctx - > display_flags ) ;
2016-11-18 13:26:17 -05:00
}
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
default :
2022-05-03 09:12:21 -04:00
ctx - > state = STATE_DONE ;
2016-11-18 13:26:17 -05:00
return 1 ;
}
return 0 ;
}
static int cli_io_handler_map_lookup ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
2016-11-18 13:26:17 -05:00
struct sample sample ;
struct pattern * pat ;
int match_method ;
2022-05-03 09:12:21 -04:00
switch ( ctx - > state ) {
case STATE_INIT :
2016-11-18 13:26:17 -05:00
/* Init to the first entry. The list cannot be change */
2022-05-03 05:54:47 -04:00
ctx - > expr = LIST_ELEM ( & ctx - > ref - > pat , struct pattern_expr * , list ) ;
ctx - > expr = pat_expr_get_next ( ctx - > expr , & ctx - > ref - > pat ) ;
2022-05-03 09:12:21 -04:00
ctx - > state = STATE_LIST ;
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
2022-05-03 09:12:21 -04:00
case STATE_LIST :
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
/* for each lookup type */
2022-05-03 05:54:47 -04:00
while ( ctx - > expr ) {
2016-11-18 13:26:17 -05:00
/* initialise chunk to build new message */
chunk_reset ( & trash ) ;
/* execute pattern matching */
sample . data . type = SMP_T_STR ;
sample . flags = SMP_F_CONST ;
2022-05-03 05:54:47 -04:00
sample . data . u . str . data = ctx - > chunk . data ;
sample . data . u . str . area = ctx - > chunk . area ;
2017-07-03 05:34:05 -04:00
2022-05-03 05:54:47 -04:00
if ( ctx - > expr - > pat_head - > match & &
sample_convert ( & sample , ctx - > expr - > pat_head - > expect_type ) )
pat = ctx - > expr - > pat_head - > match ( & sample , ctx - > expr , 1 ) ;
2016-11-18 13:26:17 -05:00
else
pat = NULL ;
/* build return message: set type of match */
for ( match_method = 0 ; match_method < PAT_MATCH_NUM ; match_method + + )
2022-05-03 05:54:47 -04:00
if ( ctx - > expr - > pat_head - > match = = pat_match_fcts [ match_method ] )
2016-11-18 13:26:17 -05:00
break ;
if ( match_method > = PAT_MATCH_NUM )
2022-05-03 05:54:47 -04:00
chunk_appendf ( & trash , " type=unknown(%p) " , ctx - > expr - > pat_head - > match ) ;
2016-11-18 13:26:17 -05:00
else
chunk_appendf ( & trash , " type=%s " , pat_match_names [ match_method ] ) ;
/* case sensitive */
2022-05-03 05:54:47 -04:00
if ( ctx - > expr - > mflags & PAT_MF_IGNORE_CASE )
2016-11-18 13:26:17 -05:00
chunk_appendf ( & trash , " , case=insensitive " ) ;
else
chunk_appendf ( & trash , " , case=sensitive " ) ;
/* Display no match, and set default value */
if ( ! pat ) {
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2016-11-18 13:26:17 -05:00
chunk_appendf ( & trash , " , found=no " ) ;
else
chunk_appendf ( & trash , " , match=no " ) ;
}
/* Display match and match info */
else {
/* display match */
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2016-11-18 13:26:17 -05:00
chunk_appendf ( & trash , " , found=yes " ) ;
else
chunk_appendf ( & trash , " , match=yes " ) ;
/* display index mode */
if ( pat - > sflags & PAT_SF_TREE )
chunk_appendf ( & trash , " , idx=tree " ) ;
else
chunk_appendf ( & trash , " , idx=list " ) ;
/* display pattern */
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP ) {
2016-11-18 13:26:17 -05:00
if ( pat - > ref & & pat - > ref - > pattern )
chunk_appendf ( & trash , " , key= \" %s \" " , pat - > ref - > pattern ) ;
else
chunk_appendf ( & trash , " , key=unknown " ) ;
}
else {
if ( pat - > ref & & pat - > ref - > pattern )
chunk_appendf ( & trash , " , pattern= \" %s \" " , pat - > ref - > pattern ) ;
else
chunk_appendf ( & trash , " , pattern=unknown " ) ;
}
/* display return value */
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP ) {
2016-11-18 13:26:17 -05:00
if ( pat - > data & & pat - > ref & & pat - > ref - > sample )
chunk_appendf ( & trash , " , value= \" %s \" , type= \" %s \" " , pat - > ref - > sample ,
smp_to_type [ pat - > data - > type ] ) ;
else
chunk_appendf ( & trash , " , value=none " ) ;
}
}
chunk_appendf ( & trash , " \n " ) ;
/* display response */
2022-05-18 09:07:19 -04:00
if ( applet_putchk ( appctx , & trash ) = = - 1 ) {
2016-11-18 13:26:17 -05:00
/* let's try again later from this stream. We add ourselves into
* this stream ' s users so that it can remove us upon termination .
*/
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
return 0 ;
}
/* get next entry */
2022-05-03 05:54:47 -04:00
ctx - > expr = pat_expr_get_next ( ctx - > expr ,
& ctx - > ref - > pat ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2022-11-14 01:35:24 -05:00
__fallthrough ;
2016-11-18 13:26:17 -05:00
default :
2022-05-03 09:12:21 -04:00
ctx - > state = STATE_DONE ;
2016-11-18 13:26:17 -05:00
return 1 ;
}
}
static void cli_release_mlook ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
ha_free ( & ctx - > chunk . area ) ;
2016-11-18 13:26:17 -05:00
}
2018-04-18 07:26:46 -04:00
static int cli_parse_get_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | | strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
/* Set flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2016-11-18 13:26:17 -05:00
/* No parameter. */
if ( ! * args [ 2 ] | | ! * args [ 3 ] ) {
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Missing map identifier and/or key. \n " ) ;
else
return cli_err ( appctx , " Missing ACL identifier and/or key. \n " ) ;
2016-11-18 13:26:17 -05:00
}
/* lookup into the maps */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
}
/* copy input string. The string must be allocated because
* it may be used over multiple iterations . It ' s released
* at the end and upon abort anyway .
*/
2022-05-03 05:54:47 -04:00
ctx - > chunk . data = strlen ( args [ 3 ] ) ;
ctx - > chunk . size = ctx - > chunk . data + 1 ;
ctx - > chunk . area = strdup ( args [ 3 ] ) ;
if ( ! ctx - > chunk . area )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Out of memory error. \n " ) ;
2016-11-18 13:26:17 -05:00
return 0 ;
}
return 1 ;
}
2021-04-30 08:57:03 -04:00
static int cli_parse_prepare_map ( char * * args , char * payload , struct appctx * appctx , void * private )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2021-04-30 08:57:03 -04:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | |
strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
uint next_gen ;
char * msg = NULL ;
/* Set ACL or MAP flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2021-04-30 08:57:03 -04:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2021-04-30 08:57:03 -04:00
/* lookup into the refs and check the map flag */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref | |
! ( ctx - > ref - > flags & ctx - > display_flags ) ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2021-04-30 08:57:03 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
}
2022-05-03 05:54:47 -04:00
next_gen = pat_ref_newgen ( ctx - > ref ) ;
2021-04-30 08:57:03 -04:00
return cli_dynmsg ( appctx , LOG_INFO , memprintf ( & msg , " New version created: %u \n " , next_gen ) ) ;
}
return 0 ;
}
2017-06-29 09:40:33 -04:00
static void cli_release_show_map ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
2022-05-03 09:42:07 -04:00
if ( ! LIST_ISEMPTY ( & ctx - > bref . users ) ) {
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2022-05-03 09:42:07 -04:00
LIST_DEL_INIT ( & ctx - > bref . users ) ;
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2017-06-29 09:40:33 -04:00
}
}
2018-04-18 07:26:46 -04:00
static int cli_parse_show_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | |
strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
2021-04-30 06:09:54 -04:00
const char * gen = NULL ;
2016-11-18 13:26:17 -05:00
/* Set ACL or MAP flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2016-11-18 13:26:17 -05:00
/* no parameter: display all map available */
if ( ! * args [ 2 ] ) {
appctx - > io_handler = cli_io_handler_pats_list ;
return 0 ;
}
2021-04-30 06:09:54 -04:00
/* For both "map" and "acl" we may have an optional generation
* number specified using a " @ " character before the pattern
* file name .
*/
if ( * args [ 2 ] = = ' @ ' ) {
gen = args [ 2 ] + 1 ;
args + + ;
}
2016-11-18 13:26:17 -05:00
/* lookup into the refs and check the map flag */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref | |
! ( ctx - > ref - > flags & ctx - > display_flags ) ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2021-04-30 06:09:54 -04:00
2022-05-03 08:12:56 -04:00
/* set the desired generation id in curr_gen */
2021-04-30 06:09:54 -04:00
if ( gen )
2022-05-03 08:12:56 -04:00
ctx - > curr_gen = str2uic ( gen ) ;
2021-04-30 06:09:54 -04:00
else
2022-05-03 08:12:56 -04:00
ctx - > curr_gen = ctx - > ref - > curr_gen ;
2021-04-30 06:09:54 -04:00
2022-05-03 05:54:47 -04:00
LIST_INIT ( & ctx - > bref . users ) ;
2016-11-18 13:26:17 -05:00
appctx - > io_handler = cli_io_handler_pat_list ;
2017-06-29 09:40:33 -04:00
appctx - > io_release = cli_release_show_map ;
2016-11-18 13:26:17 -05:00
return 0 ;
}
return 0 ;
}
2018-04-18 07:26:46 -04:00
static int cli_parse_set_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 ) {
char * err ;
/* Set flags. */
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
/* Expect three parameters: map name, key and new value. */
2019-08-09 05:21:01 -04:00
if ( ! * args [ 2 ] | | ! * args [ 3 ] | | ! * args [ 4 ] )
return cli_err ( appctx , " 'set map' expects three parameters: map identifier, key and value. \n " ) ;
2016-11-18 13:26:17 -05:00
/* Lookup the reference in the maps. */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
/* If the entry identifier start with a '#', it is considered as
* pointer id
*/
if ( args [ 3 ] [ 0 ] = = ' # ' & & args [ 3 ] [ 1 ] = = ' 0 ' & & args [ 3 ] [ 2 ] = = ' x ' ) {
struct pat_ref_elt * ref ;
long long int conv ;
char * error ;
/* Convert argument to integer value. */
conv = strtoll ( & args [ 3 ] [ 1 ] , & error , 16 ) ;
2019-08-09 05:21:01 -04:00
if ( * error ! = ' \0 ' )
return cli_err ( appctx , " Malformed identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
/* Convert and check integer to pointer. */
ref = ( struct pat_ref_elt * ) ( long ) conv ;
2019-08-09 05:21:01 -04:00
if ( ( long long int ) ( long ) ref ! = conv )
return cli_err ( appctx , " Malformed identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
2018-04-16 13:02:42 -04:00
/* Try to modify the entry. */
2016-11-18 13:26:17 -05:00
err = NULL ;
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
if ( ! pat_ref_set_by_id ( ctx - > ref , ref , args [ 4 ] , & err ) ) {
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2019-08-09 05:21:01 -04:00
if ( err )
return cli_dynerr ( appctx , memprintf ( & err , " %s. \n " , err ) ) ;
else
return cli_err ( appctx , " Failed to update an entry. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
}
else {
/* Else, use the entry identifier as pattern
* string , and update the value .
*/
err = NULL ;
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
if ( ! pat_ref_set ( ctx - > ref , args [ 3 ] , args [ 4 ] , & err ) ) {
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2019-08-09 05:21:01 -04:00
if ( err )
return cli_dynerr ( appctx , memprintf ( & err , " %s. \n " , err ) ) ;
else
return cli_err ( appctx , " Failed to update an entry. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
}
/* The set is done, send message. */
2016-11-24 09:53:53 -05:00
appctx - > st0 = CLI_ST_PROMPT ;
2016-11-18 13:26:17 -05:00
return 0 ;
}
return 1 ;
}
2018-04-18 07:26:46 -04:00
static int cli_parse_add_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | |
strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
2021-04-30 09:23:36 -04:00
const char * gen = NULL ;
uint genid = 0 ;
2016-11-18 13:26:17 -05:00
int ret ;
char * err ;
/* Set flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2016-11-18 13:26:17 -05:00
2021-04-30 09:23:36 -04:00
/* For both "map" and "acl" we may have an optional generation
* number specified using a " @ " character before the pattern
* file name .
*/
if ( * args [ 2 ] = = ' @ ' ) {
gen = args [ 2 ] + 1 ;
args + + ;
}
2018-04-18 08:04:47 -04:00
/* If the keyword is "map", we expect:
* - three parameters if there is no payload
* - one parameter if there is a payload
* If it is " acl " , we expect only two parameters
2016-11-18 13:26:17 -05:00
*/
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP ) {
2018-04-18 08:04:47 -04:00
if ( ( ! payload & & ( ! * args [ 2 ] | | ! * args [ 3 ] | | ! * args [ 4 ] ) ) | |
2019-08-09 05:21:01 -04:00
( payload & & ! * args [ 2 ] ) )
return cli_err ( appctx ,
" 'add map' expects three parameters (map identifier, key and value) "
" or one parameter (map identifier) and a payload \n " ) ;
2016-11-18 13:26:17 -05:00
}
2019-08-09 05:21:01 -04:00
else if ( ! * args [ 2 ] | | ! * args [ 3 ] )
return cli_err ( appctx , " 'add acl' expects two parameters: ACL identifier and pattern. \n " ) ;
2016-11-18 13:26:17 -05:00
/* Lookup for the reference. */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2021-04-30 09:23:36 -04:00
if ( gen ) {
genid = str2uic ( gen ) ;
2022-05-03 05:54:47 -04:00
if ( ( int ) ( genid - ctx - > ref - > next_gen ) > 0 ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2021-04-30 09:23:36 -04:00
return cli_err ( appctx , " Version number in the future, please use 'prepare map' before. \n " ) ;
else
return cli_err ( appctx , " Version number in the future, please use 'prepare acl' before. \n " ) ;
}
}
2016-11-18 13:26:17 -05:00
/* The command "add acl" is prohibited if the reference
* use samples .
*/
2022-05-03 05:54:47 -04:00
if ( ( ctx - > display_flags & PAT_REF_ACL ) & &
( ctx - > ref - > flags & PAT_REF_SMP ) ) {
2019-08-09 05:21:01 -04:00
return cli_err ( appctx ,
" This ACL is shared with a map containing samples. "
" You must use the command 'add map' to add values. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2021-04-29 10:02:48 -04:00
/* Add value(s). If no payload is used, key and value are read
* from the command line and only one key is set . If a payload
* is passed , one key / value pair is read per line till the end
* of the payload is reached .
*/
2016-11-18 13:26:17 -05:00
err = NULL ;
2018-04-18 08:04:47 -04:00
2021-04-29 10:02:48 -04:00
do {
char * key = args [ 3 ] ;
char * value = args [ 4 ] ;
size_t l ;
if ( payload ) {
/* key and value passed as payload, one pair per line */
if ( ! * payload )
break ;
2018-04-18 08:04:47 -04:00
key = payload ;
l = strcspn ( key , " \t " ) ;
payload + = l ;
2022-05-03 05:54:47 -04:00
if ( ! * payload & & ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_dynerr ( appctx , memprintf ( & err , " Missing value for key '%s'. \n " , key ) ) ;
2018-04-18 08:04:47 -04:00
key [ l ] = 0 ;
payload + + ;
/* value */
payload + = strspn ( payload , " \t " ) ;
value = payload ;
l = strcspn ( value , " \n " ) ;
payload + = l ;
if ( * payload )
payload + + ;
value [ l ] = 0 ;
2021-04-29 10:02:48 -04:00
}
2018-04-18 08:04:47 -04:00
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags ! = PAT_REF_MAP )
2021-04-29 10:55:17 -04:00
value = NULL ;
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
ret = ! ! pat_ref_load ( ctx - > ref , gen ? genid : ctx - > ref - > curr_gen , key , value , - 1 , & err ) ;
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2021-04-29 10:55:17 -04:00
2021-04-29 10:02:48 -04:00
if ( ! ret ) {
if ( err )
return cli_dynerr ( appctx , memprintf ( & err , " %s. \n " , err ) ) ;
else
return cli_err ( appctx , " Failed to add a key. \n " ) ;
2018-04-16 13:02:42 -04:00
}
2021-04-29 10:02:48 -04:00
} while ( payload & & * payload ) ;
2016-11-18 13:26:17 -05:00
/* The add is done, send message. */
2016-11-24 09:53:53 -05:00
appctx - > st0 = CLI_ST_PROMPT ;
2016-11-18 13:26:17 -05:00
return 1 ;
}
return 0 ;
}
2018-04-18 07:26:46 -04:00
static int cli_parse_del_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2016-11-18 13:26:17 -05:00
/* Expect two parameters: map name and key. */
2019-08-09 05:21:01 -04:00
if ( ! * args [ 2 ] | | ! * args [ 3 ] ) {
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " This command expects two parameters: map identifier and key. \n " ) ;
else
return cli_err ( appctx , " This command expects two parameters: ACL identifier and key. \n " ) ;
2016-11-18 13:26:17 -05:00
}
/* Lookup the reference in the maps. */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref | |
! ( ctx - > ref - > flags & ctx - > display_flags ) )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
/* If the entry identifier start with a '#', it is considered as
* pointer id
*/
if ( args [ 3 ] [ 0 ] = = ' # ' & & args [ 3 ] [ 1 ] = = ' 0 ' & & args [ 3 ] [ 2 ] = = ' x ' ) {
struct pat_ref_elt * ref ;
long long int conv ;
char * error ;
/* Convert argument to integer value. */
conv = strtoll ( & args [ 3 ] [ 1 ] , & error , 16 ) ;
2019-08-09 05:21:01 -04:00
if ( * error ! = ' \0 ' )
return cli_err ( appctx , " Malformed identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
/* Convert and check integer to pointer. */
ref = ( struct pat_ref_elt * ) ( long ) conv ;
2019-08-09 05:21:01 -04:00
if ( ( long long int ) ( long ) ref ! = conv )
return cli_err ( appctx , " Malformed identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
/* Try to delete the entry. */
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
if ( ! pat_ref_delete_by_id ( ctx - > ref , ref ) ) {
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
/* The entry is not found, send message. */
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Key not found. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
}
else {
/* Else, use the entry identifier as pattern
* string and try to delete the entry .
*/
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
if ( ! pat_ref_delete ( ctx - > ref , args [ 3 ] ) ) {
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
/* The entry is not found, send message. */
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Key not found. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2016-11-18 13:26:17 -05:00
}
/* The deletion is done, send message. */
2016-11-24 09:53:53 -05:00
appctx - > st0 = CLI_ST_PROMPT ;
2016-11-18 13:26:17 -05:00
return 1 ;
}
2021-04-30 07:31:43 -04:00
/* continue to clear a map which was started in the parser. The range of
2022-05-03 08:12:56 -04:00
* generations this applies to is taken from ctx - > curr_gen for the oldest
* and ctx - > prev_gen for the latest .
2021-04-30 07:31:43 -04:00
*/
2019-12-20 12:22:02 -05:00
static int cli_io_handler_clear_map ( struct appctx * appctx )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = appctx - > svcctx ;
2019-12-20 12:22:02 -05:00
int finished ;
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2022-05-03 08:12:56 -04:00
finished = pat_ref_purge_range ( ctx - > ref , ctx - > curr_gen , ctx - > prev_gen , 100 ) ;
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2019-12-20 12:22:02 -05:00
if ( ! finished ) {
/* let's come back later */
2022-05-25 09:42:03 -04:00
applet_have_more_data ( appctx ) ;
2019-12-20 12:22:02 -05:00
return 0 ;
}
return 1 ;
}
2022-05-03 08:12:56 -04:00
/* note: sets ctx->curr_gen and ctx->prev_gen to the oldest and
2021-04-30 07:31:43 -04:00
* latest generations to clear , respectively , and will call the clear_map
* handler .
*/
2018-04-18 07:26:46 -04:00
static int cli_parse_clear_map ( char * * args , char * payload , struct appctx * appctx , void * private )
2016-11-18 13:26:17 -05:00
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2016-11-18 13:26:17 -05:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | | strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
2021-04-30 07:31:43 -04:00
const char * gen = NULL ;
2016-11-18 13:26:17 -05:00
/* Set ACL or MAP flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2016-11-18 13:26:17 -05:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2016-11-18 13:26:17 -05:00
2021-04-30 07:31:43 -04:00
/* For both "map" and "acl" we may have an optional generation
* number specified using a " @ " character before the pattern
* file name .
*/
if ( * args [ 2 ] = = ' @ ' ) {
gen = args [ 2 ] + 1 ;
args + + ;
}
2016-11-18 13:26:17 -05:00
/* no parameter */
if ( ! * args [ 2 ] ) {
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Missing map identifier. \n " ) ;
else
return cli_err ( appctx , " Missing ACL identifier. \n " ) ;
2016-11-18 13:26:17 -05:00
}
/* lookup into the refs and check the map flag */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 2 ] ) ;
if ( ! ctx - > ref | |
! ( ctx - > ref - > flags & ctx - > display_flags ) ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2019-08-09 05:21:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 08:12:56 -04:00
/* set the desired generation id in curr_gen/prev_gen */
2021-04-30 07:31:43 -04:00
if ( gen )
2022-05-03 08:12:56 -04:00
ctx - > prev_gen = ctx - > curr_gen = str2uic ( gen ) ;
2021-04-30 07:31:43 -04:00
else
2022-05-03 08:12:56 -04:00
ctx - > prev_gen = ctx - > curr_gen = ctx - > ref - > curr_gen ;
2021-04-30 07:31:43 -04:00
2019-12-20 12:22:02 -05:00
/* delegate the clearing to the I/O handler which can yield */
return 0 ;
2016-11-18 13:26:17 -05:00
}
2019-12-20 12:22:02 -05:00
return 1 ;
2016-11-18 13:26:17 -05:00
}
2022-05-03 08:12:56 -04:00
/* note: sets ctx->curr_gen and ctx->prev_gen to the oldest and
2021-04-30 09:10:01 -04:00
* latest generations to clear , respectively , and will call the clear_map
* handler .
*/
static int cli_parse_commit_map ( char * * args , char * payload , struct appctx * appctx , void * private )
{
2022-05-03 05:54:47 -04:00
struct show_map_ctx * ctx = applet_reserve_svcctx ( appctx , sizeof ( * ctx ) ) ;
2021-04-30 09:10:01 -04:00
if ( strcmp ( args [ 1 ] , " map " ) = = 0 | | strcmp ( args [ 1 ] , " acl " ) = = 0 ) {
const char * gen = NULL ;
uint genid ;
uint ret ;
/* Set ACL or MAP flags. */
if ( args [ 1 ] [ 0 ] = = ' m ' )
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_MAP ;
2021-04-30 09:10:01 -04:00
else
2022-05-03 05:54:47 -04:00
ctx - > display_flags = PAT_REF_ACL ;
2021-04-30 09:10:01 -04:00
if ( * args [ 2 ] ! = ' @ ' )
return cli_err ( appctx , " Missing version number. \n " ) ;
/* The generation number is mandatory for a commit. The range
* of generations that get trashed by a commit starts from the
* opposite of the current one and ends at the previous one .
*/
gen = args [ 2 ] + 1 ;
genid = str2uic ( gen ) ;
2022-05-03 08:12:56 -04:00
ctx - > prev_gen = genid - 1 ;
ctx - > curr_gen = ctx - > prev_gen - ( ( ~ 0U ) > > 1 ) ;
2021-04-30 09:10:01 -04:00
/* no parameter */
if ( ! * args [ 3 ] ) {
2022-05-03 05:54:47 -04:00
if ( ctx - > display_flags = = PAT_REF_MAP )
2021-04-30 09:10:01 -04:00
return cli_err ( appctx , " Missing map identifier. \n " ) ;
else
return cli_err ( appctx , " Missing ACL identifier. \n " ) ;
}
/* lookup into the refs and check the map flag */
2022-05-03 05:54:47 -04:00
ctx - > ref = pat_ref_lookup_ref ( args [ 3 ] ) ;
if ( ! ctx - > ref | |
! ( ctx - > ref - > flags & ctx - > display_flags ) ) {
if ( ctx - > display_flags = = PAT_REF_MAP )
2021-04-30 09:10:01 -04:00
return cli_err ( appctx , " Unknown map identifier. Please use #<id> or <file>. \n " ) ;
else
return cli_err ( appctx , " Unknown ACL identifier. Please use #<id> or <file>. \n " ) ;
}
2022-05-03 05:54:47 -04:00
HA_SPIN_LOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
if ( genid - ( ctx - > ref - > curr_gen + 1 ) <
ctx - > ref - > next_gen - ctx - > ref - > curr_gen )
ret = pat_ref_commit ( ctx - > ref , genid ) ;
2021-04-30 09:10:01 -04:00
else
ret = 1 ;
2022-05-03 05:54:47 -04:00
HA_SPIN_UNLOCK ( PATREF_LOCK , & ctx - > ref - > lock ) ;
2021-04-30 09:10:01 -04:00
if ( ret ! = 0 )
return cli_err ( appctx , " Version number out of range. \n " ) ;
/* delegate the clearing to the I/O handler which can yield */
return 0 ;
}
return 1 ;
}
2016-11-18 13:26:17 -05:00
/* register cli keywords */
static struct cli_kw_list cli_kws = { { } , {
2021-05-07 05:38:37 -04:00
{ { " add " , " acl " , NULL } , " add acl [@<ver>] <acl> <pattern> : add an acl entry " , cli_parse_add_map , NULL } ,
{ { " clear " , " acl " , NULL } , " clear acl [@<ver>] <acl> : clear the contents of this acl " , cli_parse_clear_map , cli_io_handler_clear_map , NULL } ,
{ { " commit " , " acl " , NULL } , " commit acl @<ver> <acl> : commit the ACL at this version " , cli_parse_commit_map , cli_io_handler_clear_map , NULL } ,
{ { " del " , " acl " , NULL } , " del acl <acl> [<key>|#<ref>] : delete acl entries matching <key> " , cli_parse_del_map , NULL } ,
{ { " get " , " acl " , NULL } , " get acl <acl> <value> : report the patterns matching a sample for an ACL " , cli_parse_get_map , cli_io_handler_map_lookup , cli_release_mlook } ,
{ { " prepare " , " acl " , NULL } , " prepare acl <acl> : prepare a new version for atomic ACL replacement " , cli_parse_prepare_map , NULL } ,
{ { " show " , " acl " , NULL } , " show acl [@<ver>] <acl>] : report available acls or dump an acl's contents " , cli_parse_show_map , NULL } ,
{ { " add " , " map " , NULL } , " add map [@<ver>] <map> <key> <val> : add a map entry (payload supported instead of key/val) " , cli_parse_add_map , NULL } ,
{ { " clear " , " map " , NULL } , " clear map [@<ver>] <map> : clear the contents of this map " , cli_parse_clear_map , cli_io_handler_clear_map , NULL } ,
{ { " commit " , " map " , NULL } , " commit map @<ver> <map> : commit the map at this version " , cli_parse_commit_map , cli_io_handler_clear_map , NULL } ,
{ { " del " , " map " , NULL } , " del map <map> [<key>|#<ref>] : delete map entries matching <key> " , cli_parse_del_map , NULL } ,
{ { " get " , " map " , NULL } , " get map <acl> <value> : report the keys and values matching a sample for a map " , cli_parse_get_map , cli_io_handler_map_lookup , cli_release_mlook } ,
{ { " prepare " , " map " , NULL } , " prepare map <acl> : prepare a new version for atomic map replacement " , cli_parse_prepare_map , NULL } ,
{ { " set " , " map " , NULL } , " set map <map> [<key>|#<ref>] <value> : modify a map entry " , cli_parse_set_map , NULL } ,
{ { " show " , " map " , NULL } , " show map [@ver] [map] : report available maps or dump a map's contents " , cli_parse_show_map , NULL } ,
2016-11-18 13:26:17 -05:00
{ { NULL } , NULL , NULL , NULL }
} } ;
2018-11-25 13:14:37 -05:00
INITCALL1 ( STG_REGISTER , cli_register_kw , & cli_kws ) ;
2016-11-18 13:26:17 -05:00
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
/* Note: must not be declared <const> as its list will be overwritten
*
* For the map_ * _int keywords , the output is declared as SMP_T_UINT , but the converter function
* can provide SMP_T_UINT , SMP_T_SINT or SMP_T_BOOL depending on how the patterns found in the
* file can be parsed .
*
* For the map_ * _ip keyword , the output is declared as SMP_T_IPV4 , but the converter function
* can provide SMP_T_IPV4 or SMP_T_IPV6 depending on the patterns found in the file .
*
* The map_ * keywords only emit strings .
*
* The output type is only used during the configuration parsing . It is used for detecting
* compatibility problems .
*
* The arguments are : < file > [ , < default value > ]
*/
static struct sample_conv_kw_list sample_conv_kws = { ILH , {
2014-12-15 10:18:39 -05:00
{ " map " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_STR } ,
{ " map_str " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_STR } ,
{ " map_beg " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_BEG } ,
{ " map_sub " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_SUB } ,
{ " map_dir " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_DIR } ,
{ " map_dom " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_DOM } ,
{ " map_end " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_END } ,
{ " map_reg " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_REG } ,
2016-02-10 16:55:20 -05:00
{ " map_regm " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_STR , ( void * ) PAT_MATCH_REGM } ,
2015-07-06 17:43:03 -04:00
{ " map_int " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_SINT , SMP_T_STR , ( void * ) PAT_MATCH_INT } ,
2014-12-15 10:18:39 -05:00
{ " map_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_ADDR , SMP_T_STR , ( void * ) PAT_MATCH_IP } ,
2015-07-20 11:45:02 -04:00
{ " map_str_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_STR } ,
{ " map_beg_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_BEG } ,
{ " map_sub_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_SUB } ,
{ " map_dir_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_DIR } ,
{ " map_dom_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_DOM } ,
{ " map_end_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_END } ,
{ " map_reg_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_STR , SMP_T_SINT , ( void * ) PAT_MATCH_REG } ,
{ " map_int_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_SINT , SMP_T_SINT , ( void * ) PAT_MATCH_INT } ,
{ " map_ip_int " , sample_conv_map , ARG2 ( 1 , STR , SINT ) , sample_load_map , SMP_T_ADDR , SMP_T_SINT , ( void * ) PAT_MATCH_IP } ,
2015-03-12 19:10:16 -04:00
2015-08-04 13:35:46 -04:00
{ " map_str_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_STR } ,
{ " map_beg_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_BEG } ,
{ " map_sub_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_SUB } ,
{ " map_dir_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_DIR } ,
{ " map_dom_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_DOM } ,
{ " map_end_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_END } ,
{ " map_reg_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_STR , SMP_T_ADDR , ( void * ) PAT_MATCH_REG } ,
{ " map_int_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_SINT , SMP_T_ADDR , ( void * ) PAT_MATCH_INT } ,
{ " map_ip_ip " , sample_conv_map , ARG2 ( 1 , STR , STR ) , sample_load_map , SMP_T_ADDR , SMP_T_ADDR , ( void * ) PAT_MATCH_IP } ,
MEDIUM: sample: add the "map" converter
Add a new converter with the following prototype :
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>])
map_<match_type>_<output_type>(<map_file>[,<default_value>])
It searches the for input value from <map_file> using the <match_type>
matching method, and return the associated value converted to the type
<output_type>. If the input value cannot be found in the <map_file>,
the converter returns the <default_value>. If the <default_value> is
not set, the converter fails and acts as if no input value could be
fetched. If the <match_type> is not set, it defaults to "str".
Likewise, if the <output_type> is not set, it defaults to "str". For
convenience, the "map" keyword is an alias for "map_str" and maps a
string to another string. The following array contains contains the
list of all the map* converters.
+----+----------+---------+-------------+------------+
| `-_ out | | | |
| input `-_ | str | int | ip |
| / match `-_ | | | |
+---------------+---------+-------------+------------+
| str / str | map_str | map_str_int | map_str_ip |
| str / sub | map_sub | map_sub_int | map_sub_ip |
| str / dir | map_dir | map_dir_int | map_dir_ip |
| str / dom | map_dom | map_dom_int | map_dom_ip |
| str / end | map_end | map_end_int | map_end_ip |
| str / reg | map_reg | map_reg_int | map_reg_ip |
| int / int | map_int | map_int_int | map_int_ip |
| ip / ip | map_ip | map_ip_int | map_ip_ip |
+---------------+---------+-------------+------------+
The names are intentionally chosen to reflect the same match methods
as ACLs use.
2013-11-26 05:52:33 -05:00
{ /* END */ } ,
} } ;
2018-11-25 13:14:37 -05:00
INITCALL1 ( STG_REGISTER , sample_register_convs , & sample_conv_kws ) ;