Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ipset: Exceptions support added to hash:*net* types

The "nomatch" keyword and option is added to the hash:*net* types,
by which one can add exception entries to sets. Example:

ipset create test hash:net
ipset add test 192.168.0/24
ipset add test 192.168.0/30 nomatch

In this case the IP addresses from 192.168.0/24 except 192.168.0/30
match the elements of the set.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Jozsef Kadlecsik and committed by
Pablo Neira Ayuso
2a7cef2a 0927a1ac

+399 -116
+4
include/linux/netfilter/ipset/ip_set.h
··· 150 150 IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME), 151 151 IPSET_FLAG_BIT_LIST_HEADER = 2, 152 152 IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER), 153 + IPSET_FLAG_CMD_MAX = 15, /* Lower half */ 153 154 }; 154 155 155 156 /* Flags at CADT attribute level */ ··· 159 158 IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE), 160 159 IPSET_FLAG_BIT_PHYSDEV = 1, 161 160 IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV), 161 + IPSET_FLAG_BIT_NOMATCH = 2, 162 + IPSET_FLAG_NOMATCH = (1 << IPSET_FLAG_BIT_NOMATCH), 163 + IPSET_FLAG_CADT_MAX = 15, /* Upper half */ 162 164 }; 163 165 164 166 /* Commands with settype-specific attributes */
+66 -23
include/linux/netfilter/ipset/ip_set_ahash.h
··· 113 113 } 114 114 115 115 #ifdef IP_SET_HASH_WITH_NETS 116 + #ifdef IP_SET_HASH_WITH_NETS_PACKED 117 + /* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ 118 + #define CIDR(cidr) (cidr + 1) 119 + #else 120 + #define CIDR(cidr) (cidr) 121 + #endif 116 122 117 123 #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) 118 124 ··· 268 262 #define type_pf_data_list TOKEN(TYPE, PF, _data_list) 269 263 #define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) 270 264 #define type_pf_data_next TOKEN(TYPE, PF, _data_next) 265 + #define type_pf_data_flags TOKEN(TYPE, PF, _data_flags) 266 + #ifdef IP_SET_HASH_WITH_NETS 267 + #define type_pf_data_match TOKEN(TYPE, PF, _data_match) 268 + #else 269 + #define type_pf_data_match(d) 1 270 + #endif 271 271 272 272 #define type_pf_elem TOKEN(TYPE, PF, _elem) 273 273 #define type_pf_telem TOKEN(TYPE, PF, _telem) ··· 320 308 * we spare the maintenance of the internal counters. */ 321 309 static int 322 310 type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value, 323 - u8 ahash_max) 311 + u8 ahash_max, u32 cadt_flags) 324 312 { 313 + struct type_pf_elem *data; 314 + 325 315 if (n->pos >= n->size) { 326 316 void *tmp; 327 317 ··· 344 330 n->value = tmp; 345 331 n->size += AHASH_INIT_SIZE; 346 332 } 347 - type_pf_data_copy(ahash_data(n, n->pos++), value); 333 + data = ahash_data(n, n->pos++); 334 + type_pf_data_copy(data, value); 335 + #ifdef IP_SET_HASH_WITH_NETS 336 + /* Resizing won't overwrite stored flags */ 337 + if (cadt_flags) 338 + type_pf_data_flags(data, cadt_flags); 339 + #endif 348 340 return 0; 349 341 } 350 342 ··· 391 371 for (j = 0; j < n->pos; j++) { 392 372 data = ahash_data(n, j); 393 373 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 394 - ret = type_pf_elem_add(m, data, AHASH_MAX(h)); 374 + ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0); 395 375 if (ret < 0) { 396 376 read_unlock_bh(&set->lock); 397 377 ahash_destroy(t); ··· 429 409 struct hbucket *n; 430 410 int i, ret = 0; 431 411 u32 key, multi = 0; 412 + u32 cadt_flags = flags >> 16; 432 413 433 414 if (h->elements >= h->maxelem) { 434 415 if (net_ratelimit()) ··· 444 423 n = hbucket(t, key); 445 424 for (i = 0; i < n->pos; i++) 446 425 if (type_pf_data_equal(ahash_data(n, i), d, &multi)) { 426 + #ifdef IP_SET_HASH_WITH_NETS 427 + if (flags & IPSET_FLAG_EXIST) 428 + /* Support overwriting just the flags */ 429 + type_pf_data_flags(ahash_data(n, i), 430 + cadt_flags); 431 + #endif 447 432 ret = -IPSET_ERR_EXIST; 448 433 goto out; 449 434 } 450 435 TUNE_AHASH_MAX(h, multi); 451 - ret = type_pf_elem_add(n, value, AHASH_MAX(h)); 436 + ret = type_pf_elem_add(n, value, AHASH_MAX(h), cadt_flags); 452 437 if (ret != 0) { 453 438 if (ret == -EAGAIN) 454 439 type_pf_data_next(h, d); ··· 462 435 } 463 436 464 437 #ifdef IP_SET_HASH_WITH_NETS 465 - add_cidr(h, d->cidr, HOST_MASK); 438 + add_cidr(h, CIDR(d->cidr), HOST_MASK); 466 439 #endif 467 440 h->elements++; 468 441 out: ··· 497 470 n->pos--; 498 471 h->elements--; 499 472 #ifdef IP_SET_HASH_WITH_NETS 500 - del_cidr(h, d->cidr, HOST_MASK); 473 + del_cidr(h, CIDR(d->cidr), HOST_MASK); 501 474 #endif 502 475 if (n->pos + AHASH_INIT_SIZE < n->size) { 503 476 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) ··· 540 513 for (i = 0; i < n->pos; i++) { 541 514 data = ahash_data(n, i); 542 515 if (type_pf_data_equal(data, d, &multi)) 543 - return 1; 516 + return type_pf_data_match(data); 544 517 } 545 518 } 546 519 return 0; ··· 562 535 #ifdef IP_SET_HASH_WITH_NETS 563 536 /* If we test an IP address and not a network address, 564 537 * try all possible network sizes */ 565 - if (d->cidr == SET_HOST_MASK(set->family)) 538 + if (CIDR(d->cidr) == SET_HOST_MASK(set->family)) 566 539 return type_pf_test_cidrs(set, d, timeout); 567 540 #endif 568 541 ··· 571 544 for (i = 0; i < n->pos; i++) { 572 545 data = ahash_data(n, i); 573 546 if (type_pf_data_equal(data, d, &multi)) 574 - return 1; 547 + return type_pf_data_match(data); 575 548 } 576 549 return 0; 577 550 } ··· 727 700 728 701 static int 729 702 type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, 730 - u8 ahash_max, u32 timeout) 703 + u8 ahash_max, u32 cadt_flags, u32 timeout) 731 704 { 732 705 struct type_pf_elem *data; 733 706 ··· 754 727 data = ahash_tdata(n, n->pos++); 755 728 type_pf_data_copy(data, value); 756 729 type_pf_data_timeout_set(data, timeout); 730 + #ifdef IP_SET_HASH_WITH_NETS 731 + /* Resizing won't overwrite stored flags */ 732 + if (cadt_flags) 733 + type_pf_data_flags(data, cadt_flags); 734 + #endif 757 735 return 0; 758 736 } 759 737 ··· 779 747 if (type_pf_data_expired(data)) { 780 748 pr_debug("expired %u/%u\n", i, j); 781 749 #ifdef IP_SET_HASH_WITH_NETS 782 - del_cidr(h, data->cidr, HOST_MASK); 750 + del_cidr(h, CIDR(data->cidr), HOST_MASK); 783 751 #endif 784 752 if (j != n->pos - 1) 785 753 /* Not last one */ ··· 847 815 for (j = 0; j < n->pos; j++) { 848 816 data = ahash_tdata(n, j); 849 817 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 850 - ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 818 + ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, 851 819 type_pf_data_timeout(data)); 852 820 if (ret < 0) { 853 821 read_unlock_bh(&set->lock); ··· 881 849 int ret = 0, i, j = AHASH_MAX(h) + 1; 882 850 bool flag_exist = flags & IPSET_FLAG_EXIST; 883 851 u32 key, multi = 0; 852 + u32 cadt_flags = flags >> 16; 884 853 885 854 if (h->elements >= h->maxelem) 886 855 /* FIXME: when set is full, we slow down here */ ··· 901 868 data = ahash_tdata(n, i); 902 869 if (type_pf_data_equal(data, d, &multi)) { 903 870 if (type_pf_data_expired(data) || flag_exist) 871 + /* Just timeout value may be updated */ 904 872 j = i; 905 873 else { 906 874 ret = -IPSET_ERR_EXIST; ··· 914 880 if (j != AHASH_MAX(h) + 1) { 915 881 data = ahash_tdata(n, j); 916 882 #ifdef IP_SET_HASH_WITH_NETS 917 - del_cidr(h, data->cidr, HOST_MASK); 918 - add_cidr(h, d->cidr, HOST_MASK); 883 + del_cidr(h, CIDR(data->cidr), HOST_MASK); 884 + add_cidr(h, CIDR(d->cidr), HOST_MASK); 919 885 #endif 920 886 type_pf_data_copy(data, d); 921 887 type_pf_data_timeout_set(data, timeout); 888 + #ifdef IP_SET_HASH_WITH_NETS 889 + type_pf_data_flags(data, cadt_flags); 890 + #endif 922 891 goto out; 923 892 } 924 893 TUNE_AHASH_MAX(h, multi); 925 - ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout); 894 + ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), cadt_flags, timeout); 926 895 if (ret != 0) { 927 896 if (ret == -EAGAIN) 928 897 type_pf_data_next(h, d); ··· 933 896 } 934 897 935 898 #ifdef IP_SET_HASH_WITH_NETS 936 - add_cidr(h, d->cidr, HOST_MASK); 899 + add_cidr(h, CIDR(d->cidr), HOST_MASK); 937 900 #endif 938 901 h->elements++; 939 902 out: ··· 967 930 n->pos--; 968 931 h->elements--; 969 932 #ifdef IP_SET_HASH_WITH_NETS 970 - del_cidr(h, d->cidr, HOST_MASK); 933 + del_cidr(h, CIDR(d->cidr), HOST_MASK); 971 934 #endif 972 935 if (n->pos + AHASH_INIT_SIZE < n->size) { 973 936 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) ··· 1005 968 n = hbucket(t, key); 1006 969 for (i = 0; i < n->pos; i++) { 1007 970 data = ahash_tdata(n, i); 1008 - if (type_pf_data_equal(data, d, &multi)) 1009 - return !type_pf_data_expired(data); 971 + if (type_pf_data_equal(data, d, &multi) && 972 + !type_pf_data_expired(data)) 973 + return type_pf_data_match(data); 1010 974 } 1011 975 } 1012 976 return 0; ··· 1025 987 u32 key, multi = 0; 1026 988 1027 989 #ifdef IP_SET_HASH_WITH_NETS 1028 - if (d->cidr == SET_HOST_MASK(set->family)) 990 + if (CIDR(d->cidr) == SET_HOST_MASK(set->family)) 1029 991 return type_pf_ttest_cidrs(set, d, timeout); 1030 992 #endif 1031 993 key = HKEY(d, h->initval, t->htable_bits); 1032 994 n = hbucket(t, key); 1033 995 for (i = 0; i < n->pos; i++) { 1034 996 data = ahash_tdata(n, i); 1035 - if (type_pf_data_equal(data, d, &multi)) 1036 - return !type_pf_data_expired(data); 997 + if (type_pf_data_equal(data, d, &multi) && 998 + !type_pf_data_expired(data)) 999 + return type_pf_data_match(data); 1037 1000 } 1038 1001 return 0; 1039 1002 } ··· 1147 1108 #undef type_pf_data_isnull 1148 1109 #undef type_pf_data_copy 1149 1110 #undef type_pf_data_zero_out 1111 + #undef type_pf_data_netmask 1150 1112 #undef type_pf_data_list 1151 1113 #undef type_pf_data_tlist 1114 + #undef type_pf_data_next 1115 + #undef type_pf_data_flags 1116 + #undef type_pf_data_match 1152 1117 1153 1118 #undef type_pf_elem 1154 1119 #undef type_pf_telem 1155 1120 #undef type_pf_data_timeout 1156 1121 #undef type_pf_data_expired 1157 - #undef type_pf_data_netmask 1158 1122 #undef type_pf_data_timeout_set 1159 1123 1160 1124 #undef type_pf_elem_add ··· 1167 1125 #undef type_pf_test 1168 1126 1169 1127 #undef type_pf_elem_tadd 1128 + #undef type_pf_del_telem 1170 1129 #undef type_pf_expire 1171 1130 #undef type_pf_tadd 1172 1131 #undef type_pf_tdel
+100 -35
net/netfilter/ipset/ip_set_hash_ipportnet.c
··· 41 41 42 42 /* The type variant functions: IPv4 */ 43 43 44 + /* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 45 + * However this way we have to store internally cidr - 1, 46 + * dancing back and forth. 47 + */ 48 + #define IP_SET_HASH_WITH_NETS_PACKED 49 + 44 50 /* Member elements without timeout */ 45 51 struct hash_ipportnet4_elem { 46 52 __be32 ip; 47 53 __be32 ip2; 48 54 __be16 port; 49 - u8 cidr; 55 + u8 cidr:7; 56 + u8 nomatch:1; 50 57 u8 proto; 51 58 }; 52 59 ··· 62 55 __be32 ip; 63 56 __be32 ip2; 64 57 __be16 port; 65 - u8 cidr; 58 + u8 cidr:7; 59 + u8 nomatch:1; 66 60 u8 proto; 67 61 unsigned long timeout; 68 62 }; ··· 94 86 } 95 87 96 88 static inline void 89 + hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags) 90 + { 91 + dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 92 + } 93 + 94 + static inline bool 95 + hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) 96 + { 97 + return !elem->nomatch; 98 + } 99 + 100 + static inline void 97 101 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr) 98 102 { 99 103 elem->ip2 &= ip_set_netmask(cidr); 100 - elem->cidr = cidr; 104 + elem->cidr = cidr - 1; 101 105 } 102 106 103 107 static inline void ··· 122 102 hash_ipportnet4_data_list(struct sk_buff *skb, 123 103 const struct hash_ipportnet4_elem *data) 124 104 { 105 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 106 + 125 107 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 126 108 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); 127 109 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 128 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 110 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); 129 111 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 112 + if (flags) 113 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 130 114 return 0; 131 115 132 116 nla_put_failure: ··· 143 119 { 144 120 const struct hash_ipportnet4_telem *tdata = 145 121 (const struct hash_ipportnet4_telem *)data; 122 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 146 123 147 124 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 148 125 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); 149 126 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 150 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 127 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); 151 128 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 152 129 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 153 130 htonl(ip_set_timeout_get(tdata->timeout))); 131 + if (flags) 132 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 154 133 155 134 return 0; 156 135 ··· 185 158 const struct ip_set_hash *h = set->data; 186 159 ipset_adtfn adtfn = set->variant->adt[adt]; 187 160 struct hash_ipportnet4_elem data = { 188 - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 161 + .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 189 162 }; 190 163 191 - if (data.cidr == 0) 192 - return -EINVAL; 193 164 if (adt == IPSET_TEST) 194 - data.cidr = HOST_MASK; 165 + data.cidr = HOST_MASK - 1; 195 166 196 167 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 197 168 &data.port, &data.proto)) ··· 197 172 198 173 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 199 174 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2); 200 - data.ip2 &= ip_set_netmask(data.cidr); 175 + data.ip2 &= ip_set_netmask(data.cidr + 1); 201 176 202 177 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 203 178 } ··· 208 183 { 209 184 const struct ip_set_hash *h = set->data; 210 185 ipset_adtfn adtfn = set->variant->adt[adt]; 211 - struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; 186 + struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 }; 212 187 u32 ip, ip_to = 0, p = 0, port, port_to; 213 188 u32 ip2_from = 0, ip2_to, ip2_last, ip2; 214 189 u32 timeout = h->timeout; 215 190 bool with_ports = false; 191 + u8 cidr; 216 192 int ret; 217 193 218 194 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 219 195 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 220 196 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 221 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 197 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 198 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 222 199 return -IPSET_ERR_PROTOCOL; 223 200 224 201 if (tb[IPSET_ATTR_LINENO]) ··· 235 208 return ret; 236 209 237 210 if (tb[IPSET_ATTR_CIDR2]) { 238 - data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 239 - if (!data.cidr) 211 + cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 212 + if (!cidr || cidr > HOST_MASK) 240 213 return -IPSET_ERR_INVALID_CIDR; 214 + data.cidr = cidr - 1; 241 215 } 242 216 243 217 if (tb[IPSET_ATTR_PORT]) ··· 264 236 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 265 237 } 266 238 239 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 240 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 241 + if (cadt_flags & IPSET_FLAG_NOMATCH) 242 + flags |= (cadt_flags << 16); 243 + } 244 + 267 245 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 268 246 if (adt == IPSET_TEST || 269 247 !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports || 270 248 tb[IPSET_ATTR_IP2_TO])) { 271 249 data.ip = htonl(ip); 272 - data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr)); 250 + data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1)); 273 251 ret = adtfn(set, &data, timeout, flags); 274 252 return ip_set_eexist(ret, flags) ? 0 : ret; 275 253 } ··· 309 275 if (ip2_from + UINT_MAX == ip2_to) 310 276 return -IPSET_ERR_HASH_RANGE; 311 277 } else { 312 - ip_set_mask_from_to(ip2_from, ip2_to, data.cidr); 278 + ip_set_mask_from_to(ip2_from, ip2_to, data.cidr + 1); 313 279 } 314 280 315 281 if (retried) ··· 324 290 while (!after(ip2, ip2_to)) { 325 291 data.ip2 = htonl(ip2); 326 292 ip2_last = ip_set_range_to_cidr(ip2, ip2_to, 327 - &data.cidr); 293 + &cidr); 294 + data.cidr = cidr - 1; 328 295 ret = adtfn(set, &data, timeout, flags); 329 296 330 297 if (ret && !ip_set_eexist(ret, flags)) ··· 356 321 union nf_inet_addr ip; 357 322 union nf_inet_addr ip2; 358 323 __be16 port; 359 - u8 cidr; 324 + u8 cidr:7; 325 + u8 nomatch:1; 360 326 u8 proto; 361 327 }; 362 328 ··· 365 329 union nf_inet_addr ip; 366 330 union nf_inet_addr ip2; 367 331 __be16 port; 368 - u8 cidr; 332 + u8 cidr:7; 333 + u8 nomatch:1; 369 334 u8 proto; 370 335 unsigned long timeout; 371 336 }; ··· 397 360 } 398 361 399 362 static inline void 363 + hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags) 364 + { 365 + dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 366 + } 367 + 368 + static inline bool 369 + hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) 370 + { 371 + return !elem->nomatch; 372 + } 373 + 374 + static inline void 400 375 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem) 401 376 { 402 377 elem->proto = 0; ··· 427 378 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr) 428 379 { 429 380 ip6_netmask(&elem->ip2, cidr); 430 - elem->cidr = cidr; 381 + elem->cidr = cidr - 1; 431 382 } 432 383 433 384 static bool 434 385 hash_ipportnet6_data_list(struct sk_buff *skb, 435 386 const struct hash_ipportnet6_elem *data) 436 387 { 388 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 389 + 437 390 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 438 391 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 439 392 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 440 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 393 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); 441 394 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 395 + if (flags) 396 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 442 397 return 0; 443 398 444 399 nla_put_failure: ··· 455 402 { 456 403 const struct hash_ipportnet6_telem *e = 457 404 (const struct hash_ipportnet6_telem *)data; 405 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 458 406 459 407 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 460 408 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 461 409 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 462 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 410 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1); 463 411 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 464 412 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 465 413 htonl(ip_set_timeout_get(e->timeout))); 414 + if (flags) 415 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 466 416 return 0; 467 417 468 418 nla_put_failure: ··· 494 438 const struct ip_set_hash *h = set->data; 495 439 ipset_adtfn adtfn = set->variant->adt[adt]; 496 440 struct hash_ipportnet6_elem data = { 497 - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 441 + .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 498 442 }; 499 443 500 - if (data.cidr == 0) 501 - return -EINVAL; 502 444 if (adt == IPSET_TEST) 503 - data.cidr = HOST_MASK; 445 + data.cidr = HOST_MASK - 1; 504 446 505 447 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 506 448 &data.port, &data.proto)) ··· 506 452 507 453 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 508 454 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); 509 - ip6_netmask(&data.ip2, data.cidr); 455 + ip6_netmask(&data.ip2, data.cidr + 1); 510 456 511 457 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 512 458 } ··· 517 463 { 518 464 const struct ip_set_hash *h = set->data; 519 465 ipset_adtfn adtfn = set->variant->adt[adt]; 520 - struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; 466 + struct hash_ipportnet6_elem data = { .cidr = HOST_MASK - 1 }; 521 467 u32 port, port_to; 522 468 u32 timeout = h->timeout; 523 469 bool with_ports = false; 470 + u8 cidr; 524 471 int ret; 525 472 526 473 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 527 474 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 528 475 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 529 476 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 477 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 530 478 tb[IPSET_ATTR_IP_TO] || 531 479 tb[IPSET_ATTR_CIDR])) 532 480 return -IPSET_ERR_PROTOCOL; ··· 546 490 if (ret) 547 491 return ret; 548 492 549 - if (tb[IPSET_ATTR_CIDR2]) 550 - data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 493 + if (tb[IPSET_ATTR_CIDR2]) { 494 + cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 495 + if (!cidr || cidr > HOST_MASK) 496 + return -IPSET_ERR_INVALID_CIDR; 497 + data.cidr = cidr - 1; 498 + } 551 499 552 - if (!data.cidr) 553 - return -IPSET_ERR_INVALID_CIDR; 554 - 555 - ip6_netmask(&data.ip2, data.cidr); 500 + ip6_netmask(&data.ip2, data.cidr + 1); 556 501 557 502 if (tb[IPSET_ATTR_PORT]) 558 503 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); ··· 576 519 if (!with_timeout(h->timeout)) 577 520 return -IPSET_ERR_TIMEOUT; 578 521 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 522 + } 523 + 524 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 525 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 526 + if (cadt_flags & IPSET_FLAG_NOMATCH) 527 + flags |= (cadt_flags << 16); 579 528 } 580 529 581 530 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { ··· 687 624 .family = NFPROTO_UNSPEC, 688 625 .revision_min = 0, 689 626 /* 1 SCTP and UDPLITE support added */ 690 - .revision_max = 2, /* Range as input support for IPv4 added */ 627 + /* 2 Range as input support for IPv4 added */ 628 + .revision_max = 3, /* nomatch flag support added */ 691 629 .create = hash_ipportnet_create, 692 630 .create_policy = { 693 631 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, ··· 707 643 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 708 644 [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 709 645 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 646 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 710 647 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 711 648 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 712 649 },
+67 -10
net/netfilter/ipset/ip_set_hash_net.c
··· 43 43 struct hash_net4_elem { 44 44 __be32 ip; 45 45 u16 padding0; 46 - u8 padding1; 46 + u8 nomatch; 47 47 u8 cidr; 48 48 }; 49 49 ··· 51 51 struct hash_net4_telem { 52 52 __be32 ip; 53 53 u16 padding0; 54 - u8 padding1; 54 + u8 nomatch; 55 55 u8 cidr; 56 56 unsigned long timeout; 57 57 }; ··· 61 61 const struct hash_net4_elem *ip2, 62 62 u32 *multi) 63 63 { 64 - return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; 64 + return ip1->ip == ip2->ip && 65 + ip1->cidr == ip2->cidr; 65 66 } 66 67 67 68 static inline bool ··· 77 76 { 78 77 dst->ip = src->ip; 79 78 dst->cidr = src->cidr; 79 + dst->nomatch = src->nomatch; 80 + } 81 + 82 + static inline void 83 + hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) 84 + { 85 + dst->nomatch = flags & IPSET_FLAG_NOMATCH; 86 + } 87 + 88 + static inline bool 89 + hash_net4_data_match(const struct hash_net4_elem *elem) 90 + { 91 + return !elem->nomatch; 80 92 } 81 93 82 94 static inline void ··· 109 95 static bool 110 96 hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) 111 97 { 98 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 99 + 112 100 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 113 101 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 102 + if (flags) 103 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 114 104 return 0; 115 105 116 106 nla_put_failure: ··· 126 108 { 127 109 const struct hash_net4_telem *tdata = 128 110 (const struct hash_net4_telem *)data; 111 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 129 112 130 113 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 131 114 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr); 132 115 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 133 116 htonl(ip_set_timeout_get(tdata->timeout))); 117 + if (flags) 118 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 134 119 135 120 return 0; 136 121 ··· 188 167 int ret; 189 168 190 169 if (unlikely(!tb[IPSET_ATTR_IP] || 191 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 170 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 171 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 192 172 return -IPSET_ERR_PROTOCOL; 193 173 194 174 if (tb[IPSET_ATTR_LINENO]) ··· 201 179 202 180 if (tb[IPSET_ATTR_CIDR]) { 203 181 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 204 - if (!data.cidr) 182 + if (!data.cidr || data.cidr > HOST_MASK) 205 183 return -IPSET_ERR_INVALID_CIDR; 206 184 } 207 185 ··· 209 187 if (!with_timeout(h->timeout)) 210 188 return -IPSET_ERR_TIMEOUT; 211 189 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 190 + } 191 + 192 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 193 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 194 + if (cadt_flags & IPSET_FLAG_NOMATCH) 195 + flags |= (cadt_flags << 16); 212 196 } 213 197 214 198 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { ··· 264 236 struct hash_net6_elem { 265 237 union nf_inet_addr ip; 266 238 u16 padding0; 267 - u8 padding1; 239 + u8 nomatch; 268 240 u8 cidr; 269 241 }; 270 242 271 243 struct hash_net6_telem { 272 244 union nf_inet_addr ip; 273 245 u16 padding0; 274 - u8 padding1; 246 + u8 nomatch; 275 247 u8 cidr; 276 248 unsigned long timeout; 277 249 }; ··· 297 269 { 298 270 dst->ip.in6 = src->ip.in6; 299 271 dst->cidr = src->cidr; 272 + dst->nomatch = src->nomatch; 273 + } 274 + 275 + static inline void 276 + hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags) 277 + { 278 + dst->nomatch = flags & IPSET_FLAG_NOMATCH; 279 + } 280 + 281 + static inline bool 282 + hash_net6_data_match(const struct hash_net6_elem *elem) 283 + { 284 + return !elem->nomatch; 300 285 } 301 286 302 287 static inline void ··· 337 296 static bool 338 297 hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) 339 298 { 299 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 300 + 340 301 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 341 302 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 303 + if (flags) 304 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 342 305 return 0; 343 306 344 307 nla_put_failure: ··· 354 309 { 355 310 const struct hash_net6_telem *e = 356 311 (const struct hash_net6_telem *)data; 312 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 357 313 358 314 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 359 315 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr); 360 316 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 361 317 htonl(ip_set_timeout_get(e->timeout))); 318 + if (flags) 319 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 362 320 return 0; 363 321 364 322 nla_put_failure: ··· 414 366 int ret; 415 367 416 368 if (unlikely(!tb[IPSET_ATTR_IP] || 417 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 369 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 370 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 418 371 return -IPSET_ERR_PROTOCOL; 419 372 if (unlikely(tb[IPSET_ATTR_IP_TO])) 420 373 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; ··· 430 381 if (tb[IPSET_ATTR_CIDR]) 431 382 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 432 383 433 - if (!data.cidr) 384 + if (!data.cidr || data.cidr > HOST_MASK) 434 385 return -IPSET_ERR_INVALID_CIDR; 435 386 436 387 ip6_netmask(&data.ip, data.cidr); ··· 439 390 if (!with_timeout(h->timeout)) 440 391 return -IPSET_ERR_TIMEOUT; 441 392 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 393 + } 394 + 395 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 396 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 397 + if (cadt_flags & IPSET_FLAG_NOMATCH) 398 + flags |= (cadt_flags << 16); 442 399 } 443 400 444 401 ret = adtfn(set, &data, timeout, flags); ··· 529 474 .dimension = IPSET_DIM_ONE, 530 475 .family = NFPROTO_UNSPEC, 531 476 .revision_min = 0, 532 - .revision_max = 1, /* Range as input support for IPv4 added */ 477 + /* = 1 Range as input support for IPv4 added */ 478 + .revision_max = 2, /* nomatch flag support added */ 533 479 .create = hash_net_create, 534 480 .create_policy = { 535 481 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, ··· 544 488 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 545 489 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 546 490 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 491 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 547 492 }, 548 493 .me = THIS_MODULE, 549 494 };
+59 -13
net/netfilter/ipset/ip_set_hash_netiface.c
··· 163 163 __be32 ip; 164 164 u8 physdev; 165 165 u8 cidr; 166 - u16 padding; 166 + u8 nomatch; 167 + u8 padding; 167 168 }; 168 169 169 170 #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) ··· 174 173 __be32 ip; 175 174 u8 physdev; 176 175 u8 cidr; 177 - u16 padding; 176 + u8 nomatch; 177 + u8 padding; 178 178 const char *iface; 179 179 }; 180 180 ··· 184 182 __be32 ip; 185 183 u8 physdev; 186 184 u8 cidr; 187 - u16 padding; 185 + u8 nomatch; 186 + u8 padding; 188 187 const char *iface; 189 188 unsigned long timeout; 190 189 }; ··· 210 207 211 208 static inline void 212 209 hash_netiface4_data_copy(struct hash_netiface4_elem *dst, 213 - const struct hash_netiface4_elem *src) { 210 + const struct hash_netiface4_elem *src) 211 + { 214 212 dst->ip = src->ip; 215 213 dst->cidr = src->cidr; 216 214 dst->physdev = src->physdev; 217 215 dst->iface = src->iface; 216 + dst->nomatch = src->nomatch; 217 + } 218 + 219 + static inline void 220 + hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) 221 + { 222 + dst->nomatch = flags & IPSET_FLAG_NOMATCH; 223 + } 224 + 225 + static inline bool 226 + hash_netiface4_data_match(const struct hash_netiface4_elem *elem) 227 + { 228 + return !elem->nomatch; 218 229 } 219 230 220 231 static inline void ··· 250 233 { 251 234 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 252 235 236 + if (data->nomatch) 237 + flags |= IPSET_FLAG_NOMATCH; 253 238 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 254 239 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 255 240 NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); 256 241 if (flags) 257 - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags); 242 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 258 243 return 0; 259 244 260 245 nla_put_failure: ··· 271 252 (const struct hash_netiface4_telem *)data; 272 253 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 273 254 255 + if (data->nomatch) 256 + flags |= IPSET_FLAG_NOMATCH; 274 257 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 275 258 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 276 259 NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); 277 260 if (flags) 278 - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags); 261 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 279 262 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 280 263 htonl(ip_set_timeout_get(tdata->timeout))); 281 264 ··· 382 361 383 362 if (tb[IPSET_ATTR_CIDR]) { 384 363 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 385 - if (!data.cidr) 364 + if (!data.cidr || data.cidr > HOST_MASK) 386 365 return -IPSET_ERR_INVALID_CIDR; 387 366 } 388 367 ··· 408 387 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 409 388 if (cadt_flags & IPSET_FLAG_PHYSDEV) 410 389 data.physdev = 1; 390 + if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) 391 + flags |= (cadt_flags << 16); 411 392 } 412 393 413 394 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { ··· 463 440 union nf_inet_addr ip; 464 441 u8 physdev; 465 442 u8 cidr; 466 - u16 padding; 443 + u8 nomatch; 444 + u8 padding; 467 445 }; 468 446 469 447 #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) ··· 473 449 union nf_inet_addr ip; 474 450 u8 physdev; 475 451 u8 cidr; 476 - u16 padding; 452 + u8 nomatch; 453 + u8 padding; 477 454 const char *iface; 478 455 }; 479 456 ··· 482 457 union nf_inet_addr ip; 483 458 u8 physdev; 484 459 u8 cidr; 485 - u16 padding; 460 + u8 nomatch; 461 + u8 padding; 486 462 const char *iface; 487 463 unsigned long timeout; 488 464 }; ··· 514 488 } 515 489 516 490 static inline void 491 + hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags) 492 + { 493 + dst->nomatch = flags & IPSET_FLAG_NOMATCH; 494 + } 495 + 496 + static inline bool 497 + hash_netiface6_data_match(const struct hash_netiface6_elem *elem) 498 + { 499 + return !elem->nomatch; 500 + } 501 + 502 + static inline void 517 503 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) 518 504 { 505 + elem->cidr = 0; 519 506 } 520 507 521 508 static inline void ··· 553 514 { 554 515 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 555 516 517 + if (data->nomatch) 518 + flags |= IPSET_FLAG_NOMATCH; 556 519 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 557 520 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 558 521 NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); 559 522 if (flags) 560 - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags); 523 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 561 524 return 0; 562 525 563 526 nla_put_failure: ··· 574 533 (const struct hash_netiface6_telem *)data; 575 534 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 576 535 536 + if (data->nomatch) 537 + flags |= IPSET_FLAG_NOMATCH; 577 538 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 578 539 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 579 540 NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface); 580 541 if (flags) 581 - NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags); 542 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 582 543 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 583 544 htonl(ip_set_timeout_get(e->timeout))); 584 545 return 0; ··· 679 636 680 637 if (tb[IPSET_ATTR_CIDR]) 681 638 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 682 - if (!data.cidr) 639 + if (!data.cidr || data.cidr > HOST_MASK) 683 640 return -IPSET_ERR_INVALID_CIDR; 684 641 ip6_netmask(&data.ip, data.cidr); 685 642 ··· 705 662 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 706 663 if (cadt_flags & IPSET_FLAG_PHYSDEV) 707 664 data.physdev = 1; 665 + if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) 666 + flags |= (cadt_flags << 16); 708 667 } 709 668 710 669 ret = adtfn(set, &data, timeout, flags); ··· 793 748 .dimension = IPSET_DIM_TWO, 794 749 .family = NFPROTO_UNSPEC, 795 750 .revision_min = 0, 751 + .revision_max = 1, /* nomatch flag support added */ 796 752 .create = hash_netiface_create, 797 753 .create_policy = { 798 754 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
+103 -35
net/netfilter/ipset/ip_set_hash_netport.c
··· 40 40 41 41 /* The type variant functions: IPv4 */ 42 42 43 + /* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 44 + * However this way we have to store internally cidr - 1, 45 + * dancing back and forth. 46 + */ 47 + #define IP_SET_HASH_WITH_NETS_PACKED 48 + 43 49 /* Member elements without timeout */ 44 50 struct hash_netport4_elem { 45 51 __be32 ip; 46 52 __be16 port; 47 53 u8 proto; 48 - u8 cidr; 54 + u8 cidr:7; 55 + u8 nomatch:1; 49 56 }; 50 57 51 58 /* Member elements with timeout support */ ··· 60 53 __be32 ip; 61 54 __be16 port; 62 55 u8 proto; 63 - u8 cidr; 56 + u8 cidr:7; 57 + u8 nomatch:1; 64 58 unsigned long timeout; 65 59 }; 66 60 ··· 90 82 dst->port = src->port; 91 83 dst->proto = src->proto; 92 84 dst->cidr = src->cidr; 85 + dst->nomatch = src->nomatch; 86 + } 87 + 88 + static inline void 89 + hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags) 90 + { 91 + dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 92 + } 93 + 94 + static inline bool 95 + hash_netport4_data_match(const struct hash_netport4_elem *elem) 96 + { 97 + return !elem->nomatch; 93 98 } 94 99 95 100 static inline void 96 101 hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr) 97 102 { 98 103 elem->ip &= ip_set_netmask(cidr); 99 - elem->cidr = cidr; 104 + elem->cidr = cidr - 1; 100 105 } 101 106 102 107 static inline void ··· 122 101 hash_netport4_data_list(struct sk_buff *skb, 123 102 const struct hash_netport4_elem *data) 124 103 { 104 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 105 + 125 106 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 126 107 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 127 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 108 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); 128 109 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 110 + if (flags) 111 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 129 112 return 0; 130 113 131 114 nla_put_failure: ··· 142 117 { 143 118 const struct hash_netport4_telem *tdata = 144 119 (const struct hash_netport4_telem *)data; 120 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 145 121 146 122 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 147 123 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 148 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 124 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); 149 125 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 150 126 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 151 127 htonl(ip_set_timeout_get(tdata->timeout))); 128 + if (flags) 129 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 152 130 153 131 return 0; 154 132 ··· 182 154 const struct ip_set_hash *h = set->data; 183 155 ipset_adtfn adtfn = set->variant->adt[adt]; 184 156 struct hash_netport4_elem data = { 185 - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 157 + .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 186 158 }; 187 159 188 - if (data.cidr == 0) 189 - return -EINVAL; 190 160 if (adt == IPSET_TEST) 191 - data.cidr = HOST_MASK; 161 + data.cidr = HOST_MASK - 1; 192 162 193 163 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 194 164 &data.port, &data.proto)) 195 165 return -EINVAL; 196 166 197 167 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 198 - data.ip &= ip_set_netmask(data.cidr); 168 + data.ip &= ip_set_netmask(data.cidr + 1); 199 169 200 170 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 201 171 } ··· 204 178 { 205 179 const struct ip_set_hash *h = set->data; 206 180 ipset_adtfn adtfn = set->variant->adt[adt]; 207 - struct hash_netport4_elem data = { .cidr = HOST_MASK }; 181 + struct hash_netport4_elem data = { .cidr = HOST_MASK - 1 }; 208 182 u32 port, port_to, p = 0, ip = 0, ip_to, last; 209 183 u32 timeout = h->timeout; 210 184 bool with_ports = false; 185 + u8 cidr; 211 186 int ret; 212 187 213 188 if (unlikely(!tb[IPSET_ATTR_IP] || 214 189 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 215 190 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 216 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 191 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 192 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 217 193 return -IPSET_ERR_PROTOCOL; 218 194 219 195 if (tb[IPSET_ATTR_LINENO]) ··· 226 198 return ret; 227 199 228 200 if (tb[IPSET_ATTR_CIDR]) { 229 - data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 230 - if (!data.cidr) 201 + cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 202 + if (!cidr || cidr > HOST_MASK) 231 203 return -IPSET_ERR_INVALID_CIDR; 204 + data.cidr = cidr - 1; 232 205 } 233 206 234 207 if (tb[IPSET_ATTR_PORT]) ··· 256 227 } 257 228 258 229 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 230 + 231 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 232 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 233 + if (cadt_flags & IPSET_FLAG_NOMATCH) 234 + flags |= (cadt_flags << 16); 235 + } 236 + 259 237 if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { 260 - data.ip = htonl(ip & ip_set_hostmask(data.cidr)); 238 + data.ip = htonl(ip & ip_set_hostmask(data.cidr + 1)); 261 239 ret = adtfn(set, &data, timeout, flags); 262 240 return ip_set_eexist(ret, flags) ? 0 : ret; 263 241 } ··· 284 248 if (ip + UINT_MAX == ip_to) 285 249 return -IPSET_ERR_HASH_RANGE; 286 250 } else { 287 - ip_set_mask_from_to(ip, ip_to, data.cidr); 251 + ip_set_mask_from_to(ip, ip_to, data.cidr + 1); 288 252 } 289 253 290 254 if (retried) 291 255 ip = h->next.ip; 292 256 while (!after(ip, ip_to)) { 293 257 data.ip = htonl(ip); 294 - last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); 258 + last = ip_set_range_to_cidr(ip, ip_to, &cidr); 259 + data.cidr = cidr - 1; 295 260 p = retried && ip == h->next.ip ? h->next.port : port; 296 261 for (; p <= port_to; p++) { 297 262 data.port = htons(p); ··· 325 288 union nf_inet_addr ip; 326 289 __be16 port; 327 290 u8 proto; 328 - u8 cidr; 291 + u8 cidr:7; 292 + u8 nomatch:1; 329 293 }; 330 294 331 295 struct hash_netport6_telem { 332 296 union nf_inet_addr ip; 333 297 __be16 port; 334 298 u8 proto; 335 - u8 cidr; 299 + u8 cidr:7; 300 + u8 nomatch:1; 336 301 unsigned long timeout; 337 302 }; 338 303 ··· 363 324 } 364 325 365 326 static inline void 327 + hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags) 328 + { 329 + dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 330 + } 331 + 332 + static inline bool 333 + hash_netport6_data_match(const struct hash_netport6_elem *elem) 334 + { 335 + return !elem->nomatch; 336 + } 337 + 338 + static inline void 366 339 hash_netport6_data_zero_out(struct hash_netport6_elem *elem) 367 340 { 368 341 elem->proto = 0; ··· 393 342 hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr) 394 343 { 395 344 ip6_netmask(&elem->ip, cidr); 396 - elem->cidr = cidr; 345 + elem->cidr = cidr - 1; 397 346 } 398 347 399 348 static bool 400 349 hash_netport6_data_list(struct sk_buff *skb, 401 350 const struct hash_netport6_elem *data) 402 351 { 352 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 353 + 403 354 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 404 355 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 405 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 356 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); 406 357 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 358 + if (flags) 359 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 407 360 return 0; 408 361 409 362 nla_put_failure: ··· 420 365 { 421 366 const struct hash_netport6_telem *e = 422 367 (const struct hash_netport6_telem *)data; 368 + u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 423 369 424 370 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 425 371 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 426 - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 372 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr + 1); 427 373 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 428 374 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 429 375 htonl(ip_set_timeout_get(e->timeout))); 376 + if (flags) 377 + NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)); 430 378 return 0; 431 379 432 380 nla_put_failure: ··· 458 400 const struct ip_set_hash *h = set->data; 459 401 ipset_adtfn adtfn = set->variant->adt[adt]; 460 402 struct hash_netport6_elem data = { 461 - .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 403 + .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1, 462 404 }; 463 405 464 - if (data.cidr == 0) 465 - return -EINVAL; 466 406 if (adt == IPSET_TEST) 467 - data.cidr = HOST_MASK; 407 + data.cidr = HOST_MASK - 1; 468 408 469 409 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 470 410 &data.port, &data.proto)) 471 411 return -EINVAL; 472 412 473 413 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 474 - ip6_netmask(&data.ip, data.cidr); 414 + ip6_netmask(&data.ip, data.cidr + 1); 475 415 476 416 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 477 417 } ··· 480 424 { 481 425 const struct ip_set_hash *h = set->data; 482 426 ipset_adtfn adtfn = set->variant->adt[adt]; 483 - struct hash_netport6_elem data = { .cidr = HOST_MASK }; 427 + struct hash_netport6_elem data = { .cidr = HOST_MASK - 1 }; 484 428 u32 port, port_to; 485 429 u32 timeout = h->timeout; 486 430 bool with_ports = false; 431 + u8 cidr; 487 432 int ret; 488 433 489 434 if (unlikely(!tb[IPSET_ATTR_IP] || 490 435 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 491 436 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 492 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 437 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 438 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 493 439 return -IPSET_ERR_PROTOCOL; 494 440 if (unlikely(tb[IPSET_ATTR_IP_TO])) 495 441 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; ··· 503 445 if (ret) 504 446 return ret; 505 447 506 - if (tb[IPSET_ATTR_CIDR]) 507 - data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 508 - if (!data.cidr) 509 - return -IPSET_ERR_INVALID_CIDR; 510 - ip6_netmask(&data.ip, data.cidr); 448 + if (tb[IPSET_ATTR_CIDR]) { 449 + cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 450 + if (!cidr || cidr > HOST_MASK) 451 + return -IPSET_ERR_INVALID_CIDR; 452 + data.cidr = cidr - 1; 453 + } 454 + ip6_netmask(&data.ip, data.cidr + 1); 511 455 512 456 if (tb[IPSET_ATTR_PORT]) 513 457 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); ··· 532 472 if (!with_timeout(h->timeout)) 533 473 return -IPSET_ERR_TIMEOUT; 534 474 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 475 + } 476 + 477 + if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { 478 + u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 479 + if (cadt_flags & IPSET_FLAG_NOMATCH) 480 + flags |= (cadt_flags << 16); 535 481 } 536 482 537 483 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { ··· 642 576 .family = NFPROTO_UNSPEC, 643 577 .revision_min = 0, 644 578 /* 1 SCTP and UDPLITE support added */ 645 - .revision_max = 2, /* Range as input support for IPv4 added */ 579 + /* 2, Range as input support for IPv4 added */ 580 + .revision_max = 3, /* nomatch flag support added */ 646 581 .create = hash_netport_create, 647 582 .create_policy = { 648 583 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, ··· 662 595 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 663 596 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 664 597 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 598 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 665 599 }, 666 600 .me = THIS_MODULE, 667 601 };