@@ -1896,6 +1896,140 @@ static liAction* core_map(liServer *srv, liWorker *wrk, liPlugin* p, liValue *va
18961896 return li_action_new_function (core_handle_map , NULL , core_map_free , md );
18971897}
18981898
1899+ typedef struct core_map_cidr_data core_map_cidr_data ;
1900+ struct core_map_cidr_data {
1901+ GPtrArray * actions ;
1902+ liRadixTree * ipv4 ; /* map to index in actions */
1903+ liRadixTree * ipv6 ; /* map to index in actions */
1904+ gint default_action ;
1905+ };
1906+ static void core_map_cidr_free (liServer * srv , gpointer param ) {
1907+ core_map_cidr_data * md = param ;
1908+
1909+ UNUSED (srv );
1910+
1911+ for (gsize i = 0 ; i < md -> actions -> len ; i ++ ) {
1912+ li_action_release (srv , g_ptr_array_index (md -> actions , i ));
1913+ }
1914+
1915+ g_ptr_array_free (md -> actions , TRUE);
1916+ li_radixtree_free (md -> ipv4 , NULL , NULL );
1917+ li_radixtree_free (md -> ipv6 , NULL , NULL );
1918+
1919+ g_slice_free (core_map_cidr_data , md );
1920+ }
1921+
1922+ static liHandlerResult core_handle_map_cidr (liVRequest * vr , gpointer param , gpointer * context ) {
1923+ core_map_cidr_data * md = param ;
1924+ gpointer action_ndx_ptr = NULL ;
1925+ gint action_ndx = md -> default_action ;
1926+ liSockAddrPtr addr_up = vr -> coninfo -> remote_addr .addr_up ;
1927+ UNUSED (context );
1928+
1929+ if (addr_up .plain -> sa_family == AF_INET ) {
1930+ action_ndx_ptr = li_radixtree_lookup (md -> ipv4 , & addr_up .ipv4 -> sin_addr .s_addr , 32 );
1931+ #ifdef HAVE_IPV6
1932+ } else if (addr_up .plain -> sa_family == AF_INET6 ) {
1933+ action_ndx_ptr = li_radixtree_lookup (md -> ipv6 , & addr_up .ipv6 -> sin6_addr .s6_addr , 128 );
1934+ #endif
1935+ }
1936+
1937+ if (NULL != action_ndx_ptr ) {
1938+ action_ndx = GPOINTER_TO_INT (action_ndx_ptr );
1939+ }
1940+
1941+ if (action_ndx >= 0 ) {
1942+ li_action_enter (vr , g_ptr_array_index (md -> actions , action_ndx ));
1943+ }
1944+
1945+ return LI_HANDLER_GO_ON ;
1946+ }
1947+
1948+ static liAction * core_map_cidr (liServer * srv , liWorker * wrk , liPlugin * p , liValue * val , gpointer userdata ) {
1949+ core_map_cidr_data * md ;
1950+ liValue * cidr_list , * action ;
1951+ UNUSED (wrk ); UNUSED (p ); UNUSED (userdata );
1952+
1953+ md = g_slice_new (core_map_cidr_data );
1954+ md -> actions = g_ptr_array_new ();
1955+ md -> ipv4 = li_radixtree_new ();
1956+ md -> ipv6 = li_radixtree_new ();
1957+ md -> default_action = -1 ;
1958+
1959+ /* can't store anything at index 0 */
1960+ g_ptr_array_add (md -> actions , NULL );
1961+
1962+ val = li_value_get_single_argument (val );
1963+
1964+ LI_VALUE_FOREACH (map_entry , val )
1965+ gint action_ndx ;
1966+
1967+ if (!li_value_list_has_len (map_entry , 2 )) {
1968+ ERROR (srv , "%s" , "'map_cidr' action expects list of (key => action) pairs as parameter" );
1969+ core_map_cidr_free (srv , md );
1970+ return NULL ;
1971+ }
1972+
1973+ cidr_list = li_value_list_at (map_entry , 0 );
1974+ action = li_value_list_at (map_entry , 1 );
1975+
1976+ if (LI_VALUE_ACTION != li_value_type (action )) {
1977+ ERROR (
1978+ srv ,
1979+ "'map_cidr' action expects list of (key => action) pairs as parameter, expected action, got %s" ,
1980+ li_value_type_string (action )
1981+ );
1982+ core_map_cidr_free (srv , md );
1983+ return NULL ;
1984+ }
1985+
1986+ action_ndx = md -> actions -> len ;
1987+ g_ptr_array_add (md -> actions , li_value_extract_action (action ));
1988+
1989+ if (LI_VALUE_NONE == li_value_type (cidr_list )) {
1990+ md -> default_action = action_ndx ;
1991+ continue ;
1992+ }
1993+
1994+ if (LI_VALUE_LIST != li_value_type (cidr_list )) li_value_wrap_in_list (cidr_list );
1995+
1996+ LI_VALUE_FOREACH (cidr_entry , cidr_list )
1997+ guint32 ipv4 , netmaskv4 ;
1998+ guint8 ipv6_addr [16 ];
1999+ guint ipv6_network ;
2000+
2001+ if (LI_VALUE_NONE == li_value_type (cidr_entry )) {
2002+ md -> default_action = action_ndx ;
2003+ continue ;
2004+ }
2005+
2006+ if (LI_VALUE_STRING != li_value_type (cidr_entry )) {
2007+ ERROR (srv , "%s" , "map_cidr: expect strings as keys in 'map_cidr'" );
2008+ core_map_cidr_free (srv , md );
2009+ return NULL ;
2010+ }
2011+
2012+ if (g_str_equal (cidr_entry -> data .string -> str , "all" )) {
2013+ md -> default_action = action_ndx ;
2014+ } else if (li_parse_ipv4 (cidr_entry -> data .string -> str , & ipv4 , & netmaskv4 , NULL )) {
2015+ gint prefixlen ;
2016+ netmaskv4 = ntohl (netmaskv4 );
2017+ prefixlen = 32 - g_bit_nth_lsf (netmaskv4 , -1 );
2018+ if (prefixlen < 0 || prefixlen > 32 ) prefixlen = 0 ;
2019+ li_radixtree_insert (md -> ipv4 , & ipv4 , prefixlen , GINT_TO_POINTER (action_ndx ));
2020+ } else if (li_parse_ipv6 (cidr_entry -> data .string -> str , ipv6_addr , & ipv6_network , NULL )) {
2021+ li_radixtree_insert (md -> ipv6 , ipv6_addr , ipv6_network , GINT_TO_POINTER (action_ndx ));
2022+ } else {
2023+ ERROR (srv , "map_cidr: error parsing IP cidr: %s" , cidr_entry -> data .string -> str );
2024+ core_map_cidr_free (srv , md );
2025+ return NULL ;
2026+ }
2027+ LI_VALUE_END_FOREACH ()
2028+ LI_VALUE_END_FOREACH ()
2029+
2030+ return li_action_new_function (core_handle_map_cidr , NULL , core_map_cidr_free , md );
2031+ }
2032+
18992033static void fetch_files_static_lookup (liFetchDatabase * db , gpointer data , liFetchEntry * entry ) {
19002034 GHashTable * stringdb = (GHashTable * ) data ;
19012035 UNUSED (db );
@@ -2134,6 +2268,7 @@ static const liPluginAction actions[] = {
21342268 { "io.buffer_in" , core_buffer_in , NULL },
21352269
21362270 { "map" , core_map , NULL },
2271+ { "map_cidr" , core_map_cidr , NULL },
21372272
21382273 { NULL , NULL , NULL }
21392274};
0 commit comments