Message ID | 1490120944-1770-3-git-send-email-johunt@akamai.com |
---|---|
State | Changes Requested |
Delegated to: | Jozsef Kadlecsik |
Headers | show |
Hi Josh, [auto build test ERROR on nf-next/master] [also build test ERROR on v4.11-rc3 next-20170324] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Josh-Hunt/netfilter-ipset-Extend-netmask-support-for-kernel/20170324-170517 base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master config: x86_64-rhel (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Note: the linux-review/Josh-Hunt/netfilter-ipset-Extend-netmask-support-for-kernel/20170324-170517 HEAD 1311d08039e3713214109b1d179d4aab64c4ceed builds fine. It only hurts bisectibility. All errors (new ones prefixed by >>): net/netfilter/ipset/ip_set_hash_ip.c: In function 'hash_ip4_kadt': >> net/netfilter/ipset/ip_set_hash_ip.c:92:23: error: incompatible type for argument 1 of 'ip_set_netmask' ip &= ip_set_netmask(h->netmask); ^ In file included from net/netfilter/ipset/ip_set_hash_ip.c:22:0: include/linux/netfilter/ipset/pfxlen.h:13:1: note: expected 'u8 {aka unsigned char}' but argument is of type 'const struct ipset_netmask' ip_set_netmask(u8 pfxlen) ^~~~~~~~~~~~~~ net/netfilter/ipset/ip_set_hash_ip.c: In function 'hash_ip4_uadt': >> net/netfilter/ipset/ip_set_hash_ip.c:125:24: error: incompatible type for argument 1 of 'ip_set_hostmask' ip &= ip_set_hostmask(h->netmask); ^ In file included from net/netfilter/ipset/ip_set_hash_ip.c:22:0: include/linux/netfilter/ipset/pfxlen.h:25:1: note: expected 'u8 {aka unsigned char}' but argument is of type 'const struct ipset_netmask' ip_set_hostmask(u8 pfxlen) ^~~~~~~~~~~~~~~ >> net/netfilter/ipset/ip_set_hash_ip.c:149:21: error: invalid operands to binary == (have 'const struct ipset_netmask' and 'int') hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); ~~~~~~~~~~ ^~ >> net/netfilter/ipset/ip_set_hash_ip.c:149:42: error: invalid operands to binary - (have 'int' and 'const struct ipset_netmask') hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); ^ ~~~~~~~~~~ net/netfilter/ipset/ip_set_hash_ip.c: In function 'hash_ip6_kadt': >> net/netfilter/ipset/ip_set_hash_ip.c:226:26: error: incompatible type for argument 2 of 'hash_ip6_netmask' hash_ip6_netmask(&e.ip, h->netmask); ^ net/netfilter/ipset/ip_set_hash_ip.c:185:1: note: expected 'u8 {aka unsigned char}' but argument is of type 'const struct ipset_netmask' hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) ^~~~~~~~~~~~~~~~ net/netfilter/ipset/ip_set_hash_ip.c: In function 'hash_ip6_uadt': net/netfilter/ipset/ip_set_hash_ip.c:265:26: error: incompatible type for argument 2 of 'hash_ip6_netmask' hash_ip6_netmask(&e.ip, h->netmask); ^ net/netfilter/ipset/ip_set_hash_ip.c:185:1: note: expected 'u8 {aka unsigned char}' but argument is of type 'const struct ipset_netmask' hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) ^~~~~~~~~~~~~~~~ vim +149 net/netfilter/ipset/ip_set_hash_ip.c 6c0278896 Jozsef Kadlecsik 2011-02-01 16 #include <net/ip.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 17 #include <net/ipv6.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 18 #include <net/netlink.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 19 #include <net/tcp.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 20 6c0278896 Jozsef Kadlecsik 2011-02-01 21 #include <linux/netfilter.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 @22 #include <linux/netfilter/ipset/pfxlen.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 23 #include <linux/netfilter/ipset/ip_set.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 24 #include <linux/netfilter/ipset/ip_set_hash.h> 6c0278896 Jozsef Kadlecsik 2011-02-01 25 35b8dcf8c Jozsef Kadlecsik 2013-04-30 26 #define IPSET_TYPE_REV_MIN 0 fda75c6d9 Oliver Smith 2013-09-22 27 /* 1 Counters support */ 07cf8f5ae Josh Hunt 2014-02-28 28 /* 2 Comments support */ af331419d Anton Danilov 2014-08-28 29 /* 3 Forceadd support */ af331419d Anton Danilov 2014-08-28 30 #define IPSET_TYPE_REV_MAX 4 /* skbinfo support */ 10111a6ef Jozsef Kadlecsik 2012-09-21 31 6c0278896 Jozsef Kadlecsik 2011-02-01 32 MODULE_LICENSE("GPL"); 6c0278896 Jozsef Kadlecsik 2011-02-01 33 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 35b8dcf8c Jozsef Kadlecsik 2013-04-30 34 IP_SET_MODULE_DESC("hash:ip", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 6c0278896 Jozsef Kadlecsik 2011-02-01 35 MODULE_ALIAS("ip_set_hash:ip"); 6c0278896 Jozsef Kadlecsik 2011-02-01 36 6c0278896 Jozsef Kadlecsik 2011-02-01 37 /* Type specific function prefix */ 5d50e1d88 Jozsef Kadlecsik 2013-04-08 38 #define HTYPE hash_ip 5d50e1d88 Jozsef Kadlecsik 2013-04-08 39 #define IP_SET_HASH_WITH_NETMASK 6c0278896 Jozsef Kadlecsik 2011-02-01 40 03c8b234e Jozsef Kadlecsik 2013-09-07 41 /* IPv4 variant */ 6c0278896 Jozsef Kadlecsik 2011-02-01 42 5d50e1d88 Jozsef Kadlecsik 2013-04-08 43 /* Member elements */ 6c0278896 Jozsef Kadlecsik 2011-02-01 44 struct hash_ip4_elem { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 45 /* Zero valued IP addresses cannot be stored */ 6c0278896 Jozsef Kadlecsik 2011-02-01 46 __be32 ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 47 }; 6c0278896 Jozsef Kadlecsik 2011-02-01 48 5d50e1d88 Jozsef Kadlecsik 2013-04-08 49 /* Common functions */ 6c0278896 Jozsef Kadlecsik 2011-02-01 50 6c0278896 Jozsef Kadlecsik 2011-02-01 51 static inline bool 5d50e1d88 Jozsef Kadlecsik 2013-04-08 52 hash_ip4_data_equal(const struct hash_ip4_elem *e1, 5d50e1d88 Jozsef Kadlecsik 2013-04-08 53 const struct hash_ip4_elem *e2, 5d50e1d88 Jozsef Kadlecsik 2013-04-08 54 u32 *multi) 6c0278896 Jozsef Kadlecsik 2011-02-01 55 { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 56 return e1->ip == e2->ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 57 } 6c0278896 Jozsef Kadlecsik 2011-02-01 58 728a7e690 Sergey Popovich 2015-05-02 59 static bool 5d50e1d88 Jozsef Kadlecsik 2013-04-08 60 hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *e) 6c0278896 Jozsef Kadlecsik 2011-02-01 61 { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 62 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, e->ip)) 7cf7899d9 David S. Miller 2012-04-01 63 goto nla_put_failure; 728a7e690 Sergey Popovich 2015-05-02 64 return false; 6c0278896 Jozsef Kadlecsik 2011-02-01 65 6c0278896 Jozsef Kadlecsik 2011-02-01 66 nla_put_failure: 728a7e690 Sergey Popovich 2015-05-02 67 return true; 6c0278896 Jozsef Kadlecsik 2011-02-01 68 } 6c0278896 Jozsef Kadlecsik 2011-02-01 69 5d50e1d88 Jozsef Kadlecsik 2013-04-08 70 static inline void 5d50e1d88 Jozsef Kadlecsik 2013-04-08 71 hash_ip4_data_next(struct hash_ip4_elem *next, const struct hash_ip4_elem *e) 6c0278896 Jozsef Kadlecsik 2011-02-01 72 { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 73 next->ip = e->ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 74 } 6c0278896 Jozsef Kadlecsik 2011-02-01 75 5d50e1d88 Jozsef Kadlecsik 2013-04-08 76 #define MTYPE hash_ip4 6c0278896 Jozsef Kadlecsik 2011-02-01 77 #define HOST_MASK 32 5d50e1d88 Jozsef Kadlecsik 2013-04-08 78 #include "ip_set_hash_gen.h" 3d14b171f Jozsef Kadlecsik 2011-06-16 79 6c0278896 Jozsef Kadlecsik 2011-02-01 80 static int 6c0278896 Jozsef Kadlecsik 2011-02-01 81 hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, b66554cf0 Jozsef Kadlecsik 2011-06-16 82 const struct xt_action_param *par, 5d50e1d88 Jozsef Kadlecsik 2013-04-08 83 enum ipset_adt adt, struct ip_set_adt_opt *opt) 6c0278896 Jozsef Kadlecsik 2011-02-01 84 { 21956ab29 Jozsef Kadlecsik 2015-06-26 85 const struct hash_ip4 *h = set->data; 6c0278896 Jozsef Kadlecsik 2011-02-01 86 ipset_adtfn adtfn = set->variant->adt[adt]; 94729f8a1 Mark Rustad 2014-08-05 87 struct hash_ip4_elem e = { 0 }; ca134ce86 Jozsef Kadlecsik 2013-09-07 88 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 6c0278896 Jozsef Kadlecsik 2011-02-01 89 __be32 ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 90 ac8cc925d Jozsef Kadlecsik 2011-06-16 91 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip); 6c0278896 Jozsef Kadlecsik 2011-02-01 @92 ip &= ip_set_netmask(h->netmask); 6c0278896 Jozsef Kadlecsik 2011-02-01 93 if (ip == 0) 6c0278896 Jozsef Kadlecsik 2011-02-01 94 return -EINVAL; 6c0278896 Jozsef Kadlecsik 2011-02-01 95 5d50e1d88 Jozsef Kadlecsik 2013-04-08 96 e.ip = ip; 5d50e1d88 Jozsef Kadlecsik 2013-04-08 97 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 6c0278896 Jozsef Kadlecsik 2011-02-01 98 } 6c0278896 Jozsef Kadlecsik 2011-02-01 99 6c0278896 Jozsef Kadlecsik 2011-02-01 100 static int 6c0278896 Jozsef Kadlecsik 2011-02-01 101 hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], 3d14b171f Jozsef Kadlecsik 2011-06-16 102 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 6c0278896 Jozsef Kadlecsik 2011-02-01 103 { 21956ab29 Jozsef Kadlecsik 2015-06-26 104 const struct hash_ip4 *h = set->data; 6c0278896 Jozsef Kadlecsik 2011-02-01 105 ipset_adtfn adtfn = set->variant->adt[adt]; 94729f8a1 Mark Rustad 2014-08-05 106 struct hash_ip4_elem e = { 0 }; ca134ce86 Jozsef Kadlecsik 2013-09-07 107 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 20b2fab48 Jozsef Kadlecsik 2013-05-01 108 u32 ip = 0, ip_to = 0, hosts; 6c0278896 Jozsef Kadlecsik 2011-02-01 109 int ret = 0; 6c0278896 Jozsef Kadlecsik 2011-02-01 110 6c0278896 Jozsef Kadlecsik 2011-02-01 111 if (tb[IPSET_ATTR_LINENO]) 6c0278896 Jozsef Kadlecsik 2011-02-01 112 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 6c0278896 Jozsef Kadlecsik 2011-02-01 113 a212e08e8 Sergey Popovich 2015-06-12 114 if (unlikely(!tb[IPSET_ATTR_IP])) a212e08e8 Sergey Popovich 2015-06-12 115 return -IPSET_ERR_PROTOCOL; a212e08e8 Sergey Popovich 2015-06-12 116 8e55d2e59 Sergey Popovich 2015-05-02 117 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 8e55d2e59 Sergey Popovich 2015-05-02 118 if (ret) 8e55d2e59 Sergey Popovich 2015-05-02 119 return ret; 8e55d2e59 Sergey Popovich 2015-05-02 120 8e55d2e59 Sergey Popovich 2015-05-02 121 ret = ip_set_get_extensions(set, tb, &ext); 6c0278896 Jozsef Kadlecsik 2011-02-01 122 if (ret) 6c0278896 Jozsef Kadlecsik 2011-02-01 123 return ret; 6c0278896 Jozsef Kadlecsik 2011-02-01 124 6c0278896 Jozsef Kadlecsik 2011-02-01 @125 ip &= ip_set_hostmask(h->netmask); 6c0278896 Jozsef Kadlecsik 2011-02-01 126 6c0278896 Jozsef Kadlecsik 2011-02-01 127 if (adt == IPSET_TEST) { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 128 e.ip = htonl(ip); 5d50e1d88 Jozsef Kadlecsik 2013-04-08 129 if (e.ip == 0) 6c0278896 Jozsef Kadlecsik 2011-02-01 130 return -IPSET_ERR_HASH_ELEM; 5d50e1d88 Jozsef Kadlecsik 2013-04-08 131 return adtfn(set, &e, &ext, &ext, flags); 6c0278896 Jozsef Kadlecsik 2011-02-01 132 } 6c0278896 Jozsef Kadlecsik 2011-02-01 133 4fe198e6b Jozsef Kadlecsik 2012-11-19 134 ip_to = ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 135 if (tb[IPSET_ATTR_IP_TO]) { 6c0278896 Jozsef Kadlecsik 2011-02-01 136 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 6c0278896 Jozsef Kadlecsik 2011-02-01 137 if (ret) 6c0278896 Jozsef Kadlecsik 2011-02-01 138 return ret; 6c0278896 Jozsef Kadlecsik 2011-02-01 139 if (ip > ip_to) 6c0278896 Jozsef Kadlecsik 2011-02-01 140 swap(ip, ip_to); 6c0278896 Jozsef Kadlecsik 2011-02-01 141 } else if (tb[IPSET_ATTR_CIDR]) { 6c0278896 Jozsef Kadlecsik 2011-02-01 142 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 6c0278896 Jozsef Kadlecsik 2011-02-01 143 cabfd139a Sergey Popovich 2015-05-02 144 if (!cidr || cidr > HOST_MASK) 6c0278896 Jozsef Kadlecsik 2011-02-01 145 return -IPSET_ERR_INVALID_CIDR; e6146e868 Jozsef Kadlecsik 2011-06-16 146 ip_set_mask_from_to(ip, ip_to, cidr); 4fe198e6b Jozsef Kadlecsik 2012-11-19 147 } 6c0278896 Jozsef Kadlecsik 2011-02-01 148 6c0278896 Jozsef Kadlecsik 2011-02-01 @149 hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); 6c0278896 Jozsef Kadlecsik 2011-02-01 150 3d14b171f Jozsef Kadlecsik 2011-06-16 151 if (retried) 6e27c9b4e Jozsef Kadlecsik 2012-09-21 152 ip = ntohl(h->next.ip); 6c0278896 Jozsef Kadlecsik 2011-02-01 153 for (; !before(ip_to, ip); ip += hosts) { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 154 e.ip = htonl(ip); 5d50e1d88 Jozsef Kadlecsik 2013-04-08 155 if (e.ip == 0) 6c0278896 Jozsef Kadlecsik 2011-02-01 156 return -IPSET_ERR_HASH_ELEM; 5d50e1d88 Jozsef Kadlecsik 2013-04-08 157 ret = adtfn(set, &e, &ext, &ext, flags); 6c0278896 Jozsef Kadlecsik 2011-02-01 158 6c0278896 Jozsef Kadlecsik 2011-02-01 159 if (ret && !ip_set_eexist(ret, flags)) 6c0278896 Jozsef Kadlecsik 2011-02-01 160 return ret; ca0f6a5cd Jozsef Kadlecsik 2015-06-13 161 6c0278896 Jozsef Kadlecsik 2011-02-01 162 ret = 0; 6c0278896 Jozsef Kadlecsik 2011-02-01 163 } 6c0278896 Jozsef Kadlecsik 2011-02-01 164 return ret; 6c0278896 Jozsef Kadlecsik 2011-02-01 165 } 6c0278896 Jozsef Kadlecsik 2011-02-01 166 03c8b234e Jozsef Kadlecsik 2013-09-07 167 /* IPv6 variant */ 6c0278896 Jozsef Kadlecsik 2011-02-01 168 5d50e1d88 Jozsef Kadlecsik 2013-04-08 169 /* Member elements */ 6c0278896 Jozsef Kadlecsik 2011-02-01 170 struct hash_ip6_elem { 6c0278896 Jozsef Kadlecsik 2011-02-01 171 union nf_inet_addr ip; 6c0278896 Jozsef Kadlecsik 2011-02-01 172 }; 6c0278896 Jozsef Kadlecsik 2011-02-01 173 5d50e1d88 Jozsef Kadlecsik 2013-04-08 174 /* Common functions */ 5d50e1d88 Jozsef Kadlecsik 2013-04-08 175 6c0278896 Jozsef Kadlecsik 2011-02-01 176 static inline bool 6c0278896 Jozsef Kadlecsik 2011-02-01 177 hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 89dc79b78 Jozsef Kadlecsik 2011-07-21 178 const struct hash_ip6_elem *ip2, 89dc79b78 Jozsef Kadlecsik 2011-07-21 179 u32 *multi) 6c0278896 Jozsef Kadlecsik 2011-02-01 180 { 29e3b1608 YOSHIFUJI Hideaki / 吉藤英明 2013-01-29 181 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6); 6c0278896 Jozsef Kadlecsik 2011-02-01 182 } 6c0278896 Jozsef Kadlecsik 2011-02-01 183 6c0278896 Jozsef Kadlecsik 2011-02-01 184 static inline void 5d50e1d88 Jozsef Kadlecsik 2013-04-08 185 hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) 6c0278896 Jozsef Kadlecsik 2011-02-01 186 { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 187 ip6_netmask(ip, prefix); 6c0278896 Jozsef Kadlecsik 2011-02-01 188 } 6c0278896 Jozsef Kadlecsik 2011-02-01 189 6c0278896 Jozsef Kadlecsik 2011-02-01 190 static bool 5d50e1d88 Jozsef Kadlecsik 2013-04-08 191 hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e) 6c0278896 Jozsef Kadlecsik 2011-02-01 192 { 5d50e1d88 Jozsef Kadlecsik 2013-04-08 193 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6)) 7cf7899d9 David S. Miller 2012-04-01 194 goto nla_put_failure; 728a7e690 Sergey Popovich 2015-05-02 195 return false; 6c0278896 Jozsef Kadlecsik 2011-02-01 196 6c0278896 Jozsef Kadlecsik 2011-02-01 197 nla_put_failure: 728a7e690 Sergey Popovich 2015-05-02 198 return true; 6c0278896 Jozsef Kadlecsik 2011-02-01 199 } 6c0278896 Jozsef Kadlecsik 2011-02-01 200 5d50e1d88 Jozsef Kadlecsik 2013-04-08 201 static inline void 21956ab29 Jozsef Kadlecsik 2015-06-26 202 hash_ip6_data_next(struct hash_ip6_elem *next, const struct hash_ip6_elem *e) 6c0278896 Jozsef Kadlecsik 2011-02-01 203 { 6c0278896 Jozsef Kadlecsik 2011-02-01 204 } 6c0278896 Jozsef Kadlecsik 2011-02-01 205 5d50e1d88 Jozsef Kadlecsik 2013-04-08 206 #undef MTYPE 6c0278896 Jozsef Kadlecsik 2011-02-01 207 #undef HOST_MASK 6c0278896 Jozsef Kadlecsik 2011-02-01 208 5d50e1d88 Jozsef Kadlecsik 2013-04-08 209 #define MTYPE hash_ip6 6c0278896 Jozsef Kadlecsik 2011-02-01 210 #define HOST_MASK 128 6c0278896 Jozsef Kadlecsik 2011-02-01 211 5d50e1d88 Jozsef Kadlecsik 2013-04-08 212 #define IP_SET_EMIT_CREATE 5d50e1d88 Jozsef Kadlecsik 2013-04-08 213 #include "ip_set_hash_gen.h" 3d14b171f Jozsef Kadlecsik 2011-06-16 214 6c0278896 Jozsef Kadlecsik 2011-02-01 215 static int 6c0278896 Jozsef Kadlecsik 2011-02-01 216 hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, b66554cf0 Jozsef Kadlecsik 2011-06-16 217 const struct xt_action_param *par, 5d50e1d88 Jozsef Kadlecsik 2013-04-08 218 enum ipset_adt adt, struct ip_set_adt_opt *opt) 6c0278896 Jozsef Kadlecsik 2011-02-01 219 { 21956ab29 Jozsef Kadlecsik 2015-06-26 220 const struct hash_ip6 *h = set->data; 6c0278896 Jozsef Kadlecsik 2011-02-01 221 ipset_adtfn adtfn = set->variant->adt[adt]; 94729f8a1 Mark Rustad 2014-08-05 222 struct hash_ip6_elem e = { { .all = { 0 } } }; ca134ce86 Jozsef Kadlecsik 2013-09-07 223 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 6c0278896 Jozsef Kadlecsik 2011-02-01 224 5d50e1d88 Jozsef Kadlecsik 2013-04-08 225 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 5d50e1d88 Jozsef Kadlecsik 2013-04-08 @226 hash_ip6_netmask(&e.ip, h->netmask); 5d50e1d88 Jozsef Kadlecsik 2013-04-08 227 if (ipv6_addr_any(&e.ip.in6)) 6c0278896 Jozsef Kadlecsik 2011-02-01 228 return -EINVAL; 6c0278896 Jozsef Kadlecsik 2011-02-01 229 :::::: The code at line 149 was first introduced by commit :::::: 6c027889696a7a694b0e2f6e3cabadefec7553b6 netfilter: ipset: hash:ip set type support :::::: TO: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> :::::: CC: Patrick McHardy <kaber@trash.net> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Josh, Overall, I like the feature and the patches. After reviewing I comment only the parts where I believe some modifications are needed. On Tue, 21 Mar 2017, Josh Hunt wrote: > Extends ipset netmask support to handle both cidr values and full > netmasks. As part of that it now supports wildcard masks allowing the > user to mask out any bits of an address. This commit provides the > infrastructure to specify netmasks of these types for hash sets of > both v4 and v6 addressees. > > Follow on commits will add support for this type of netmasking to various > hash set types. > > Signed-off-by: Josh Hunt <johunt@akamai.com> > --- > include/linux/netfilter/ipset/ip_set.h | 3 + > include/uapi/linux/netfilter/ipset/ip_set.h | 5 ++ > net/netfilter/ipset/ip_set_core.c | 2 + > net/netfilter/ipset/ip_set_hash_gen.h | 91 +++++++++++++++++++++++++---- > 4 files changed, 89 insertions(+), 12 deletions(-) > > diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h > index 8e42253..0153cd3 100644 > --- a/include/linux/netfilter/ipset/ip_set.h > +++ b/include/linux/netfilter/ipset/ip_set.h > @@ -69,6 +69,7 @@ enum ip_set_extension { > #define SET_WITH_COMMENT(s) ((s)->extensions & IPSET_EXT_COMMENT) > #define SET_WITH_SKBINFO(s) ((s)->extensions & IPSET_EXT_SKBINFO) > #define SET_WITH_FORCEADD(s) ((s)->flags & IPSET_CREATE_FLAG_FORCEADD) > +#define SET_WITH_NETMASK(s) ((s)->flags & IPSET_CREATE_FLAG_NETMASK) > > /* Extension id, in size order */ > enum ip_set_ext_id { > @@ -292,6 +293,8 @@ struct ip_set { > cadt_flags |= IPSET_FLAG_WITH_SKBINFO; > if (SET_WITH_FORCEADD(set)) > cadt_flags |= IPSET_FLAG_WITH_FORCEADD; > + if (SET_WITH_NETMASK(set)) > + cadt_flags |= IPSET_FLAG_WITH_NETMASK; > > if (!cadt_flags) > return 0; > diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h > index ebb5154..2193908 100644 > --- a/include/uapi/linux/netfilter/ipset/ip_set.h > +++ b/include/uapi/linux/netfilter/ipset/ip_set.h > @@ -84,6 +84,7 @@ enum { > IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ > IPSET_ATTR_MARK, /* 10 */ > IPSET_ATTR_MARKMASK, /* 11 */ > + IPSET_ATTR_NETMASK_MASK,/* 12 */ > /* Reserve empty slots */ > IPSET_ATTR_CADT_MAX = 16, > /* Create-only specific attributes */ > @@ -200,6 +201,8 @@ enum ipset_cadt_flags { > IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD), > IPSET_FLAG_BIT_WITH_SKBINFO = 6, > IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO), > + IPSET_FLAG_BIT_WITH_NETMASK = 7, > + IPSET_FLAG_WITH_NETMASK = (1 << IPSET_FLAG_BIT_WITH_NETMASK), > IPSET_FLAG_CADT_MAX = 15, > }; > > @@ -207,6 +210,8 @@ enum ipset_cadt_flags { > enum ipset_create_flags { > IPSET_CREATE_FLAG_BIT_FORCEADD = 0, > IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD), > + IPSET_CREATE_FLAG_BIT_NETMASK = 1, > + IPSET_CREATE_FLAG_NETMASK = (1 << IPSET_CREATE_FLAG_BIT_NETMASK), > IPSET_CREATE_FLAG_BIT_MAX = 7, > }; > > diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c > index c296f9b..e2ce7ab 100644 > --- a/net/netfilter/ipset/ip_set_core.c > +++ b/net/netfilter/ipset/ip_set_core.c > @@ -374,6 +374,8 @@ static inline struct ip_set_net *ip_set_pernet(struct net *net) > cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); > if (cadt_flags & IPSET_FLAG_WITH_FORCEADD) > set->flags |= IPSET_CREATE_FLAG_FORCEADD; > + if (cadt_flags & IPSET_FLAG_WITH_NETMASK) > + set->flags |= IPSET_CREATE_FLAG_NETMASK; > if (!align) > align = 1; > for (id = 0; id < IPSET_EXT_ID_MAX; id++) { > diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h > index f236c0b..a407f85 100644 > --- a/net/netfilter/ipset/ip_set_hash_gen.h > +++ b/net/netfilter/ipset/ip_set_hash_gen.h > @@ -166,6 +166,41 @@ struct net_prefixes { > #define NLEN 0 > #endif /* IP_SET_HASH_WITH_NETS */ > > +#ifdef IP_SET_HASH_WITH_NETMASK > +const static union nf_inet_addr onesmask = { > + .all[0] = 0xffffffff, > + .all[1] = 0xffffffff, > + .all[2] = 0xffffffff, > + .all[3] = 0xffffffff > +}; > +const static union nf_inet_addr zeromask; > + > +struct ipset_netmask { > + u8 cidr; > + union nf_inet_addr mask; > +}; > + > +static void > +ip_set_cidr_to_mask(union nf_inet_addr *addr, uint8_t cidr, uint8_t family) > +{ > + uint8_t i; > + uint8_t addrsize = (family == NFPROTO_IPV4) ? 1 : 4; > + > + for (i=0; i < addrsize; i++) { > + if (!cidr) { > + addr->all[i] = 0; > + } else if (cidr >= 32) { > + addr->all[i] = 0xffffffff; > + cidr -= 32; > + } else { > + addr->all[i] = htonl(~((1 << (32 - cidr)) - 1)); > + break; > + } > + } > +} > + > +#endif > + > #endif /* _IP_SET_HASH_GEN_H */ > > #ifndef MTYPE > @@ -289,7 +324,7 @@ struct htype { > u8 ahash_max; /* max elements in an array block */ > #endif > #ifdef IP_SET_HASH_WITH_NETMASK > - u8 netmask; /* netmask value for subnets to store */ > + struct ipset_netmask netmask; > #endif > struct mtype_elem next; /* temporary storage for uadd */ > #ifdef IP_SET_HASH_WITH_NETS > @@ -449,7 +484,8 @@ struct htype { > return x->maxelem == y->maxelem && > a->timeout == b->timeout && > #ifdef IP_SET_HASH_WITH_NETMASK > - x->netmask == y->netmask && > + nf_inet_addr_cmp(&x->netmask.mask, &y->netmask.mask) && > + x->netmask.cidr == y->netmask.cidr && > #endif > #ifdef IP_SET_HASH_WITH_MARKMASK > x->markmask == y->markmask && > @@ -1061,9 +1097,20 @@ struct htype { > nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem))) > goto nla_put_failure; > #ifdef IP_SET_HASH_WITH_NETMASK > - if (h->netmask != HOST_MASK && > - nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) > - goto nla_put_failure; > + if (!nf_inet_addr_cmp(&onesmask, &h->netmask.mask)) { > + if (SET_WITH_NETMASK(set)) { > + if (set->family == NFPROTO_IPV4) { > + if (nla_put_ipaddr4(skb, IPSET_ATTR_NETMASK_MASK, h->netmask.mask.ip)) > + goto nla_put_failure; > + } else if (set->family == NFPROTO_IPV6) { > + if (nla_put_ipaddr6(skb, IPSET_ATTR_NETMASK_MASK, &h->netmask.mask.in6)) > + goto nla_put_failure; > + } > + } > + > + if (nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask.cidr)) > + goto nla_put_failure; > + } Please do not pass (and do not process) both IPSET_ATTR_NETMASK and IPSET_ATTR_NETMASK_MASK. If it'd be allowed, which one should be used? So instead of "if ..." it should be "else if" above. > #endif > #ifdef IP_SET_HASH_WITH_MARKMASK > if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask)) > @@ -1220,7 +1267,9 @@ struct htype { > #endif > u8 hbits; > #ifdef IP_SET_HASH_WITH_NETMASK > - u8 netmask; > + union nf_inet_addr netmask = onesmask; > + int ret = 0; > + u8 cidr = 0; > #endif > size_t hsize; > struct htype *h; > @@ -1254,15 +1303,32 @@ struct htype { > #endif > > #ifdef IP_SET_HASH_WITH_NETMASK > - netmask = set->family == NFPROTO_IPV4 ? 32 : 128; > if (tb[IPSET_ATTR_NETMASK]) { > - netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); > + cidr = nla_get_u8(tb[IPSET_ATTR_NETMASK]); > + if ((set->family == NFPROTO_IPV4 && cidr > 32) || > + (set->family == NFPROTO_IPV6 && cidr > 128)) > + return -IPSET_ERR_INVALID_NETMASK; > > - if ((set->family == NFPROTO_IPV4 && netmask > 32) || > - (set->family == NFPROTO_IPV6 && netmask > 128) || > - netmask == 0) > + } > + if (tb[IPSET_ATTR_NETMASK_MASK]) { > + if (set->family == NFPROTO_IPV4) { > + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_NETMASK_MASK], &netmask.ip); > + if (ret || !netmask.ip) > + return -IPSET_ERR_INVALID_NETMASK; > + } else if (set->family == NFPROTO_IPV6) { > + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_NETMASK_MASK], &netmask); > + if (ret || ipv6_addr_any(&netmask.in6)) > + return -IPSET_ERR_INVALID_NETMASK; > + } > + if (nf_inet_addr_cmp(&netmask, &zeromask)) > return -IPSET_ERR_INVALID_NETMASK; > } Do not trust the netlink messages and if both IPSET_ATTR_NETMASK and IPSET_ATTR_NETMASK_MASK attributes are present, simply reject it. > + > + /* For backwards compatibility, we'll convert the cidr to a mask if > + * userspace didn't give us one. > + */ > + if (cidr && nf_inet_addr_cmp(&netmask, &onesmask)) > + ip_set_cidr_to_mask(&netmask, cidr, set->family); > #endif > > if (tb[IPSET_ATTR_HASHSIZE]) { > @@ -1292,7 +1358,8 @@ struct htype { > } > h->maxelem = maxelem; > #ifdef IP_SET_HASH_WITH_NETMASK > - h->netmask = netmask; > + h->netmask.mask = netmask; > + h->netmask.cidr = cidr; > #endif > #ifdef IP_SET_HASH_WITH_MARKMASK > h->markmask = markmask; > -- > 1.9.1 Best regards, Jozsef - E-mail : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences H-1525 Budapest 114, POB. 49, Hungary -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/27/2017 02:21 PM, Jozsef Kadlecsik wrote: > Hi Josh, > > Overall, I like the feature and the patches. After reviewing I comment > only the parts where I believe some modifications are needed. > Jozsef Thanks for the review. I'll go through this and send a v2 in the next few days. Josh -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Josh, On Tue, 28 Mar 2017, Josh Hunt wrote: > > Overall, I like the feature and the patches. After reviewing I comment > > only the parts where I believe some modifications are needed. > > Thanks for the review. I'll go through this and send a v2 in the next > few days. Thinking over it I understand better your approach: replace IPSET_ATTR_NETMASK with IPSET_ATTR_NETMASK_MASK completely and keeping the former for backward compatibility reasons only. What I propose is able to maintain syntax-compatibility in the sense that what is passed to the kernel as cidr/netmask can be saved from there in the same syntax. The exemption from adding multiple entries from a range in the case of non-cidr value netmask must also be documented in the manpage. Maybe it'd be even better additionally to return an explicit error in such cases: thus it cannot lead to a misunderstanding from user point of view. Best regards, Jozsef - E-mail : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences H-1525 Budapest 114, POB. 49, Hungary -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/28/2017 01:28 PM, Jozsef Kadlecsik wrote: > Hi Josh, > > On Tue, 28 Mar 2017, Josh Hunt wrote: > >>> Overall, I like the feature and the patches. After reviewing I comment >>> only the parts where I believe some modifications are needed. >> >> Thanks for the review. I'll go through this and send a v2 in the next >> few days. > > Thinking over it I understand better your approach: replace > IPSET_ATTR_NETMASK with IPSET_ATTR_NETMASK_MASK completely and keeping the > former for backward compatibility reasons only. What I propose is able to > maintain syntax-compatibility in the sense that what is passed to the > kernel as cidr/netmask can be saved from there in the same syntax. I have not gone through all of your comments yet, but my intention was to make sure that if cidrs are used they are presented the same way they are today (prior to my patches.) If a user uses the new full netmask support then that is what is shown. This way we stay consistent with whatever the user inputs at create time. Examples of both: # ipset create foo hash:ip netmask 24 # ipset list -t foo Name: foo Type: hash:ip Revision: 5 Header: family inet hashsize 1024 maxelem 65536 netmask 24 Size in memory: 104 References: 0 Number of entries: 0 # ipset create foo hash:ip netmask 255.255.255.0 # ipset list -t foo Name: foo Type: hash:ip Revision: 5 Header: family inet hashsize 1024 maxelem 65536 netmask 255.255.255.0 Size in memory: 104 References: 0 Number of entries: 0 Internally they both resolve to the same mask, but we present them consistently based on how they were input at create time. This way if a user uses cidrs today nothing changes from their perspective. > > The exemption from adding multiple entries from a range in the case of > non-cidr value netmask must also be documented in the manpage. Maybe it'd > be even better additionally to return an explicit error in such cases: > thus it cannot lead to a misunderstanding from user point of view. I haven't gone through this yet, but will take a look and let you know if I have any questions. Josh -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, 28 Mar 2017, Josh Hunt wrote: > > Thinking over it I understand better your approach: replace > > IPSET_ATTR_NETMASK with IPSET_ATTR_NETMASK_MASK completely and keeping > > the former for backward compatibility reasons only. What I propose is > > able to maintain syntax-compatibility in the sense that what is passed > > to the kernel as cidr/netmask can be saved from there in the same > > syntax. > > I have not gone through all of your comments yet, but my intention was > to make sure that if cidrs are used they are presented the same way they > are today (prior to my patches.) If a user uses the new full netmask > support then that is what is shown. This way we stay consistent with > whatever the user inputs at create time. Yes, you are right, some conversion confused me. Best regards, Jozsef - E-mail : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences H-1525 Budapest 114, POB. 49, Hungary -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 8e42253..0153cd3 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -69,6 +69,7 @@ enum ip_set_extension { #define SET_WITH_COMMENT(s) ((s)->extensions & IPSET_EXT_COMMENT) #define SET_WITH_SKBINFO(s) ((s)->extensions & IPSET_EXT_SKBINFO) #define SET_WITH_FORCEADD(s) ((s)->flags & IPSET_CREATE_FLAG_FORCEADD) +#define SET_WITH_NETMASK(s) ((s)->flags & IPSET_CREATE_FLAG_NETMASK) /* Extension id, in size order */ enum ip_set_ext_id { @@ -292,6 +293,8 @@ struct ip_set { cadt_flags |= IPSET_FLAG_WITH_SKBINFO; if (SET_WITH_FORCEADD(set)) cadt_flags |= IPSET_FLAG_WITH_FORCEADD; + if (SET_WITH_NETMASK(set)) + cadt_flags |= IPSET_FLAG_WITH_NETMASK; if (!cadt_flags) return 0; diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h index ebb5154..2193908 100644 --- a/include/uapi/linux/netfilter/ipset/ip_set.h +++ b/include/uapi/linux/netfilter/ipset/ip_set.h @@ -84,6 +84,7 @@ enum { IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ IPSET_ATTR_MARK, /* 10 */ IPSET_ATTR_MARKMASK, /* 11 */ + IPSET_ATTR_NETMASK_MASK,/* 12 */ /* Reserve empty slots */ IPSET_ATTR_CADT_MAX = 16, /* Create-only specific attributes */ @@ -200,6 +201,8 @@ enum ipset_cadt_flags { IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD), IPSET_FLAG_BIT_WITH_SKBINFO = 6, IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO), + IPSET_FLAG_BIT_WITH_NETMASK = 7, + IPSET_FLAG_WITH_NETMASK = (1 << IPSET_FLAG_BIT_WITH_NETMASK), IPSET_FLAG_CADT_MAX = 15, }; @@ -207,6 +210,8 @@ enum ipset_cadt_flags { enum ipset_create_flags { IPSET_CREATE_FLAG_BIT_FORCEADD = 0, IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD), + IPSET_CREATE_FLAG_BIT_NETMASK = 1, + IPSET_CREATE_FLAG_NETMASK = (1 << IPSET_CREATE_FLAG_BIT_NETMASK), IPSET_CREATE_FLAG_BIT_MAX = 7, }; diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index c296f9b..e2ce7ab 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -374,6 +374,8 @@ static inline struct ip_set_net *ip_set_pernet(struct net *net) cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); if (cadt_flags & IPSET_FLAG_WITH_FORCEADD) set->flags |= IPSET_CREATE_FLAG_FORCEADD; + if (cadt_flags & IPSET_FLAG_WITH_NETMASK) + set->flags |= IPSET_CREATE_FLAG_NETMASK; if (!align) align = 1; for (id = 0; id < IPSET_EXT_ID_MAX; id++) { diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index f236c0b..a407f85 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -166,6 +166,41 @@ struct net_prefixes { #define NLEN 0 #endif /* IP_SET_HASH_WITH_NETS */ +#ifdef IP_SET_HASH_WITH_NETMASK +const static union nf_inet_addr onesmask = { + .all[0] = 0xffffffff, + .all[1] = 0xffffffff, + .all[2] = 0xffffffff, + .all[3] = 0xffffffff +}; +const static union nf_inet_addr zeromask; + +struct ipset_netmask { + u8 cidr; + union nf_inet_addr mask; +}; + +static void +ip_set_cidr_to_mask(union nf_inet_addr *addr, uint8_t cidr, uint8_t family) +{ + uint8_t i; + uint8_t addrsize = (family == NFPROTO_IPV4) ? 1 : 4; + + for (i=0; i < addrsize; i++) { + if (!cidr) { + addr->all[i] = 0; + } else if (cidr >= 32) { + addr->all[i] = 0xffffffff; + cidr -= 32; + } else { + addr->all[i] = htonl(~((1 << (32 - cidr)) - 1)); + break; + } + } +} + +#endif + #endif /* _IP_SET_HASH_GEN_H */ #ifndef MTYPE @@ -289,7 +324,7 @@ struct htype { u8 ahash_max; /* max elements in an array block */ #endif #ifdef IP_SET_HASH_WITH_NETMASK - u8 netmask; /* netmask value for subnets to store */ + struct ipset_netmask netmask; #endif struct mtype_elem next; /* temporary storage for uadd */ #ifdef IP_SET_HASH_WITH_NETS @@ -449,7 +484,8 @@ struct htype { return x->maxelem == y->maxelem && a->timeout == b->timeout && #ifdef IP_SET_HASH_WITH_NETMASK - x->netmask == y->netmask && + nf_inet_addr_cmp(&x->netmask.mask, &y->netmask.mask) && + x->netmask.cidr == y->netmask.cidr && #endif #ifdef IP_SET_HASH_WITH_MARKMASK x->markmask == y->markmask && @@ -1061,9 +1097,20 @@ struct htype { nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem))) goto nla_put_failure; #ifdef IP_SET_HASH_WITH_NETMASK - if (h->netmask != HOST_MASK && - nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) - goto nla_put_failure; + if (!nf_inet_addr_cmp(&onesmask, &h->netmask.mask)) { + if (SET_WITH_NETMASK(set)) { + if (set->family == NFPROTO_IPV4) { + if (nla_put_ipaddr4(skb, IPSET_ATTR_NETMASK_MASK, h->netmask.mask.ip)) + goto nla_put_failure; + } else if (set->family == NFPROTO_IPV6) { + if (nla_put_ipaddr6(skb, IPSET_ATTR_NETMASK_MASK, &h->netmask.mask.in6)) + goto nla_put_failure; + } + } + + if (nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask.cidr)) + goto nla_put_failure; + } #endif #ifdef IP_SET_HASH_WITH_MARKMASK if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask)) @@ -1220,7 +1267,9 @@ struct htype { #endif u8 hbits; #ifdef IP_SET_HASH_WITH_NETMASK - u8 netmask; + union nf_inet_addr netmask = onesmask; + int ret = 0; + u8 cidr = 0; #endif size_t hsize; struct htype *h; @@ -1254,15 +1303,32 @@ struct htype { #endif #ifdef IP_SET_HASH_WITH_NETMASK - netmask = set->family == NFPROTO_IPV4 ? 32 : 128; if (tb[IPSET_ATTR_NETMASK]) { - netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); + cidr = nla_get_u8(tb[IPSET_ATTR_NETMASK]); + if ((set->family == NFPROTO_IPV4 && cidr > 32) || + (set->family == NFPROTO_IPV6 && cidr > 128)) + return -IPSET_ERR_INVALID_NETMASK; - if ((set->family == NFPROTO_IPV4 && netmask > 32) || - (set->family == NFPROTO_IPV6 && netmask > 128) || - netmask == 0) + } + if (tb[IPSET_ATTR_NETMASK_MASK]) { + if (set->family == NFPROTO_IPV4) { + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_NETMASK_MASK], &netmask.ip); + if (ret || !netmask.ip) + return -IPSET_ERR_INVALID_NETMASK; + } else if (set->family == NFPROTO_IPV6) { + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_NETMASK_MASK], &netmask); + if (ret || ipv6_addr_any(&netmask.in6)) + return -IPSET_ERR_INVALID_NETMASK; + } + if (nf_inet_addr_cmp(&netmask, &zeromask)) return -IPSET_ERR_INVALID_NETMASK; } + + /* For backwards compatibility, we'll convert the cidr to a mask if + * userspace didn't give us one. + */ + if (cidr && nf_inet_addr_cmp(&netmask, &onesmask)) + ip_set_cidr_to_mask(&netmask, cidr, set->family); #endif if (tb[IPSET_ATTR_HASHSIZE]) { @@ -1292,7 +1358,8 @@ struct htype { } h->maxelem = maxelem; #ifdef IP_SET_HASH_WITH_NETMASK - h->netmask = netmask; + h->netmask.mask = netmask; + h->netmask.cidr = cidr; #endif #ifdef IP_SET_HASH_WITH_MARKMASK h->markmask = markmask;
Extends ipset netmask support to handle both cidr values and full netmasks. As part of that it now supports wildcard masks allowing the user to mask out any bits of an address. This commit provides the infrastructure to specify netmasks of these types for hash sets of both v4 and v6 addressees. Follow on commits will add support for this type of netmasking to various hash set types. Signed-off-by: Josh Hunt <johunt@akamai.com> --- include/linux/netfilter/ipset/ip_set.h | 3 + include/uapi/linux/netfilter/ipset/ip_set.h | 5 ++ net/netfilter/ipset/ip_set_core.c | 2 + net/netfilter/ipset/ip_set_hash_gen.h | 91 +++++++++++++++++++++++++---- 4 files changed, 89 insertions(+), 12 deletions(-)