From b2edf895af82914ab09a842641a45b7a806e9b1e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 25 Nov 2008 23:34:48 +0100 Subject: filter: CIDR-based filtering support This patch adds CIDR-based filtering support. The current implementation is O(n). This patch also introduces the vector data type which is used to store the IP address and the network mask. Signed-off-by: Pablo Neira Ayuso --- src/read_config_yy.y | 86 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 16 deletions(-) (limited to 'src/read_config_yy.y') diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 06ada52..32ddeff 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -26,6 +26,7 @@ #include #include "conntrackd.h" #include "bitops.h" +#include "cidr.h" #include #include #include @@ -780,27 +781,55 @@ filter_address_list : filter_address_item : T_IPV4_ADDR T_IP { union inet_address ip; + char *slash; + unsigned int cidr = 32; memset(&ip, 0, sizeof(union inet_address)); + slash = strchr($2, '/'); + if (slash) { + *slash = '\0'; + cidr = atoi(slash+1); + if (cidr > 32) { + fprintf(stderr, "%s/%d is not a valid network, " + "ignoring\n", $2, cidr); + break; + } + } + if (!inet_aton($2, &ip.ipv4)) { fprintf(stderr, "%s is not a valid IPv4, ignoring", $2); break; } - if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { - if (errno == EEXIST) - fprintf(stderr, "IP %s is repeated " - "in the ignore pool\n", $2); - if (errno == ENOSPC) - fprintf(stderr, "Too many IP in the ignore pool!\n"); + if (slash && cidr < 32) { + /* network byte order */ + struct ct_filter_netmask_ipv4 tmp = { + .ip = ip.ipv4, + .mask = ipv4_cidr2mask_net(cidr) + }; + + if (!ct_filter_add_netmask(STATE(us_filter), &tmp, AF_INET)) { + if (errno == EEXIST) + fprintf(stderr, "Netmask %s is repeated " + "in the ignore pool\n", $2); + } + } else { + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { + if (errno == EEXIST) + fprintf(stderr, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stderr, "Too many IP in the " + "ignore pool!\n"); + } } - __kernel_filter_start(); + /* host byte order */ struct nfct_filter_ipv4 filter_ipv4 = { - .addr = htonl(ip.ipv4), - .mask = 0xffffffff, + .addr = ntohl(ip.ipv4), + .mask = ipv4_cidr2mask_host(cidr), }; nfct_filter_add_attr(STATE(filter), NFCT_FILTER_SRC_IPV4, &filter_ipv4); @@ -810,9 +839,22 @@ filter_address_item : T_IPV4_ADDR T_IP filter_address_item : T_IPV6_ADDR T_IP { union inet_address ip; + char *slash; + int cidr; memset(&ip, 0, sizeof(union inet_address)); + slash = strchr($2, '/'); + if (slash) { + *slash = '\0'; + cidr = atoi(slash+1); + if (cidr > 128) { + fprintf(stderr, "%s/%d is not a valid network, " + "ignoring\n", $2, cidr); + break; + } + } + #ifdef HAVE_INET_PTON_IPV6 if (inet_pton(AF_INET6, $2, &ip.ipv6) <= 0) { fprintf(stderr, "%s is not a valid IPv6, ignoring", $2); @@ -822,13 +864,25 @@ filter_address_item : T_IPV6_ADDR T_IP fprintf(stderr, "Cannot find inet_pton(), IPv6 unsupported!"); break; #endif - - if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { - if (errno == EEXIST) - fprintf(stderr, "IP %s is repeated " - "in the ignore pool\n", $2); - if (errno == ENOSPC) - fprintf(stderr, "Too many IP in the ignore pool!\n"); + if (slash && cidr < 128) { + struct ct_filter_netmask_ipv6 tmp; + + memcpy(tmp.ip, ip.ipv6, sizeof(uint32_t)*4); + ipv6_cidr2mask_net(cidr, tmp.mask); + if (!ct_filter_add_netmask(STATE(us_filter), &tmp, AF_INET6)) { + if (errno == EEXIST) + fprintf(stderr, "Netmask %s is repeated " + "in the ignore pool\n", $2); + } + } else { + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { + if (errno == EEXIST) + fprintf(stderr, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stderr, "Too many IP in the " + "ignore pool!\n"); + } } }; -- cgit v1.2.3