diff options
| author | David S. Miller <davem@davemloft.net> | 2012-09-24 15:36:53 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-09-24 15:42:04 -0400 |
| commit | ae4735166ee31e29fbf8615949dac9e56299b1fd (patch) | |
| tree | ee39087a83e0e6d6aaab87e905ce6d170185e32d | |
| parent | 2ddc7fe1cd1b2e0502f12b89c60b6e1ca66837dd (diff) | |
| parent | 6ee584be3ee30f72dec8a8ca87bc10824e27a631 (diff) | |
Merge branch 'master' of git://1984.lsi.us.es/nf-next
Pablo Neira Ayuso says:
====================
This patchset contains updates for your net-next tree, they are:
* Mostly fixes for the recently pushed IPv6 NAT support:
- Fix crash while removing nf_nat modules from Patrick McHardy.
- Fix unbalanced rcu_read_unlock from Ulrich Weber.
- Merge NETMAP and REDIRECT into one single xt_target module, from
Jan Engelhardt.
- Fix Kconfig for IPv6 NAT, which allows inconsistent configurations,
from myself.
* Updates for ipset, all of the from Jozsef Kadlecsik:
- Add the new "nomatch" option to obtain reverse set matching.
- Support for /0 CIDR in hash:net,iface set type.
- One non-critical fix for a rare crash due to pass really
wrong configuration parameters.
- Coding style cleanups.
- Sparse fixes.
- Add set revision supported via modinfo.i
* One extension for the xt_time match, to support matching during
the transition between two days with one single rule, from
Florian Westphal.
* Fix maximum packet length supported by nfnetlink_queue and add
NFQA_CAP_LEN attribute, from myself.
You can notice that this batch contains a couple of fixes that may
go to 3.6-rc but I don't consider them critical to push them:
* The ipset fix for the /0 cidr case, which is triggered with one
inconsistent command line invocation of ipset.
* The nfnetlink_queue maximum packet length supported since it requires
the new NFQA_CAP_LEN attribute to provide a full workaround for the
described problem.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
37 files changed, 773 insertions, 670 deletions
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index 2edc64cab739..528697b3c152 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h | |||
| @@ -190,6 +190,7 @@ enum ip_set_dim { | |||
| 190 | * If changed, new revision of iptables match/target is required. | 190 | * If changed, new revision of iptables match/target is required. |
| 191 | */ | 191 | */ |
| 192 | IPSET_DIM_MAX = 6, | 192 | IPSET_DIM_MAX = 6, |
| 193 | IPSET_BIT_RETURN_NOMATCH = 7, | ||
| 193 | }; | 194 | }; |
| 194 | 195 | ||
| 195 | /* Option flags for kernel operations */ | 196 | /* Option flags for kernel operations */ |
| @@ -198,6 +199,7 @@ enum ip_set_kopt { | |||
| 198 | IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), | 199 | IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), |
| 199 | IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), | 200 | IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), |
| 200 | IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), | 201 | IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), |
| 202 | IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH), | ||
| 201 | }; | 203 | }; |
| 202 | 204 | ||
| 203 | #ifdef __KERNEL__ | 205 | #ifdef __KERNEL__ |
| @@ -206,9 +208,15 @@ enum ip_set_kopt { | |||
| 206 | #include <linux/netlink.h> | 208 | #include <linux/netlink.h> |
| 207 | #include <linux/netfilter.h> | 209 | #include <linux/netfilter.h> |
| 208 | #include <linux/netfilter/x_tables.h> | 210 | #include <linux/netfilter/x_tables.h> |
| 211 | #include <linux/stringify.h> | ||
| 209 | #include <linux/vmalloc.h> | 212 | #include <linux/vmalloc.h> |
| 210 | #include <net/netlink.h> | 213 | #include <net/netlink.h> |
| 211 | 214 | ||
| 215 | #define _IP_SET_MODULE_DESC(a, b, c) \ | ||
| 216 | MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c) | ||
| 217 | #define IP_SET_MODULE_DESC(a, b, c) \ | ||
| 218 | _IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c)) | ||
| 219 | |||
| 212 | /* Set features */ | 220 | /* Set features */ |
| 213 | enum ip_set_feature { | 221 | enum ip_set_feature { |
| 214 | IPSET_TYPE_IP_FLAG = 0, | 222 | IPSET_TYPE_IP_FLAG = 0, |
| @@ -223,6 +231,8 @@ enum ip_set_feature { | |||
| 223 | IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), | 231 | IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), |
| 224 | IPSET_TYPE_IFACE_FLAG = 5, | 232 | IPSET_TYPE_IFACE_FLAG = 5, |
| 225 | IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG), | 233 | IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG), |
| 234 | IPSET_TYPE_NOMATCH_FLAG = 6, | ||
| 235 | IPSET_TYPE_NOMATCH = (1 << IPSET_TYPE_NOMATCH_FLAG), | ||
| 226 | /* Strictly speaking not a feature, but a flag for dumping: | 236 | /* Strictly speaking not a feature, but a flag for dumping: |
| 227 | * this settype must be dumped last */ | 237 | * this settype must be dumped last */ |
| 228 | IPSET_DUMP_LAST_FLAG = 7, | 238 | IPSET_DUMP_LAST_FLAG = 7, |
| @@ -249,7 +259,7 @@ struct ip_set_type_variant { | |||
| 249 | * returns negative error code, | 259 | * returns negative error code, |
| 250 | * zero for no match/success to add/delete | 260 | * zero for no match/success to add/delete |
| 251 | * positive for matching element */ | 261 | * positive for matching element */ |
| 252 | int (*kadt)(struct ip_set *set, const struct sk_buff * skb, | 262 | int (*kadt)(struct ip_set *set, const struct sk_buff *skb, |
| 253 | const struct xt_action_param *par, | 263 | const struct xt_action_param *par, |
| 254 | enum ipset_adt adt, const struct ip_set_adt_opt *opt); | 264 | enum ipset_adt adt, const struct ip_set_adt_opt *opt); |
| 255 | 265 | ||
| @@ -424,7 +434,8 @@ static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr) | |||
| 424 | return ret; | 434 | return ret; |
| 425 | } | 435 | } |
| 426 | 436 | ||
| 427 | static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, const struct in6_addr *ipaddrptr) | 437 | static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, |
| 438 | const struct in6_addr *ipaddrptr) | ||
| 428 | { | 439 | { |
| 429 | struct nlattr *__nested = ipset_nest_start(skb, type); | 440 | struct nlattr *__nested = ipset_nest_start(skb, type); |
| 430 | int ret; | 441 | int ret; |
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h index b114d35aea5e..ef9acd3c8450 100644 --- a/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/include/linux/netfilter/ipset/ip_set_ahash.h | |||
| @@ -137,50 +137,59 @@ htable_bits(u32 hashsize) | |||
| 137 | #endif | 137 | #endif |
| 138 | 138 | ||
| 139 | #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) | 139 | #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) |
| 140 | #ifdef IP_SET_HASH_WITH_MULTI | ||
| 141 | #define NETS_LENGTH(family) (SET_HOST_MASK(family) + 1) | ||
| 142 | #else | ||
| 143 | #define NETS_LENGTH(family) SET_HOST_MASK(family) | ||
| 144 | #endif | ||
| 140 | 145 | ||
| 141 | /* Network cidr size book keeping when the hash stores different | 146 | /* Network cidr size book keeping when the hash stores different |
| 142 | * sized networks */ | 147 | * sized networks */ |
| 143 | static void | 148 | static void |
| 144 | add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) | 149 | add_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length) |
| 145 | { | 150 | { |
| 146 | u8 i; | 151 | int i, j; |
| 147 | |||
| 148 | ++h->nets[cidr-1].nets; | ||
| 149 | |||
| 150 | pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets); | ||
| 151 | 152 | ||
| 152 | if (h->nets[cidr-1].nets > 1) | 153 | /* Add in increasing prefix order, so larger cidr first */ |
| 153 | return; | 154 | for (i = 0, j = -1; i < nets_length && h->nets[i].nets; i++) { |
| 154 | 155 | if (j != -1) | |
| 155 | /* New cidr size */ | 156 | continue; |
| 156 | for (i = 0; i < host_mask && h->nets[i].cidr; i++) { | 157 | else if (h->nets[i].cidr < cidr) |
| 157 | /* Add in increasing prefix order, so larger cidr first */ | 158 | j = i; |
| 158 | if (h->nets[i].cidr < cidr) | 159 | else if (h->nets[i].cidr == cidr) { |
| 159 | swap(h->nets[i].cidr, cidr); | 160 | h->nets[i].nets++; |
| 161 | return; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | if (j != -1) { | ||
| 165 | for (; i > j; i--) { | ||
| 166 | h->nets[i].cidr = h->nets[i - 1].cidr; | ||
| 167 | h->nets[i].nets = h->nets[i - 1].nets; | ||
| 168 | } | ||
| 160 | } | 169 | } |
| 161 | if (i < host_mask) | 170 | h->nets[i].cidr = cidr; |
| 162 | h->nets[i].cidr = cidr; | 171 | h->nets[i].nets = 1; |
| 163 | } | 172 | } |
| 164 | 173 | ||
| 165 | static void | 174 | static void |
| 166 | del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) | 175 | del_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length) |
| 167 | { | 176 | { |
| 168 | u8 i; | 177 | u8 i, j; |
| 169 | |||
| 170 | --h->nets[cidr-1].nets; | ||
| 171 | 178 | ||
| 172 | pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets); | 179 | for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++) |
| 180 | ; | ||
| 181 | h->nets[i].nets--; | ||
| 173 | 182 | ||
| 174 | if (h->nets[cidr-1].nets != 0) | 183 | if (h->nets[i].nets != 0) |
| 175 | return; | 184 | return; |
| 176 | 185 | ||
| 177 | /* All entries with this cidr size deleted, so cleanup h->cidr[] */ | 186 | for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) { |
| 178 | for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) { | 187 | h->nets[j].cidr = h->nets[j + 1].cidr; |
| 179 | if (h->nets[i].cidr == cidr) | 188 | h->nets[j].nets = h->nets[j + 1].nets; |
| 180 | h->nets[i].cidr = cidr = h->nets[i+1].cidr; | ||
| 181 | } | 189 | } |
| 182 | h->nets[i - 1].cidr = 0; | ||
| 183 | } | 190 | } |
| 191 | #else | ||
| 192 | #define NETS_LENGTH(family) 0 | ||
| 184 | #endif | 193 | #endif |
| 185 | 194 | ||
| 186 | /* Destroy the hashtable part of the set */ | 195 | /* Destroy the hashtable part of the set */ |
| @@ -202,14 +211,14 @@ ahash_destroy(struct htable *t) | |||
| 202 | 211 | ||
| 203 | /* Calculate the actual memory size of the set data */ | 212 | /* Calculate the actual memory size of the set data */ |
| 204 | static size_t | 213 | static size_t |
| 205 | ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask) | 214 | ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 nets_length) |
| 206 | { | 215 | { |
| 207 | u32 i; | 216 | u32 i; |
| 208 | struct htable *t = h->table; | 217 | struct htable *t = h->table; |
| 209 | size_t memsize = sizeof(*h) | 218 | size_t memsize = sizeof(*h) |
| 210 | + sizeof(*t) | 219 | + sizeof(*t) |
| 211 | #ifdef IP_SET_HASH_WITH_NETS | 220 | #ifdef IP_SET_HASH_WITH_NETS |
| 212 | + sizeof(struct ip_set_hash_nets) * host_mask | 221 | + sizeof(struct ip_set_hash_nets) * nets_length |
| 213 | #endif | 222 | #endif |
| 214 | + jhash_size(t->htable_bits) * sizeof(struct hbucket); | 223 | + jhash_size(t->htable_bits) * sizeof(struct hbucket); |
| 215 | 224 | ||
| @@ -238,7 +247,7 @@ ip_set_hash_flush(struct ip_set *set) | |||
| 238 | } | 247 | } |
| 239 | #ifdef IP_SET_HASH_WITH_NETS | 248 | #ifdef IP_SET_HASH_WITH_NETS |
| 240 | memset(h->nets, 0, sizeof(struct ip_set_hash_nets) | 249 | memset(h->nets, 0, sizeof(struct ip_set_hash_nets) |
| 241 | * SET_HOST_MASK(set->family)); | 250 | * NETS_LENGTH(set->family)); |
| 242 | #endif | 251 | #endif |
| 243 | h->elements = 0; | 252 | h->elements = 0; |
| 244 | } | 253 | } |
| @@ -271,9 +280,6 @@ ip_set_hash_destroy(struct ip_set *set) | |||
| 271 | (jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \ | 280 | (jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \ |
| 272 | & jhash_mask(htable_bits)) | 281 | & jhash_mask(htable_bits)) |
| 273 | 282 | ||
| 274 | #define CONCAT(a, b, c) a##b##c | ||
| 275 | #define TOKEN(a, b, c) CONCAT(a, b, c) | ||
| 276 | |||
| 277 | /* Type/family dependent function prototypes */ | 283 | /* Type/family dependent function prototypes */ |
| 278 | 284 | ||
| 279 | #define type_pf_data_equal TOKEN(TYPE, PF, _data_equal) | 285 | #define type_pf_data_equal TOKEN(TYPE, PF, _data_equal) |
| @@ -478,7 +484,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 478 | } | 484 | } |
| 479 | 485 | ||
| 480 | #ifdef IP_SET_HASH_WITH_NETS | 486 | #ifdef IP_SET_HASH_WITH_NETS |
| 481 | add_cidr(h, CIDR(d->cidr), HOST_MASK); | 487 | add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); |
| 482 | #endif | 488 | #endif |
| 483 | h->elements++; | 489 | h->elements++; |
| 484 | out: | 490 | out: |
| @@ -513,7 +519,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 513 | n->pos--; | 519 | n->pos--; |
| 514 | h->elements--; | 520 | h->elements--; |
| 515 | #ifdef IP_SET_HASH_WITH_NETS | 521 | #ifdef IP_SET_HASH_WITH_NETS |
| 516 | del_cidr(h, CIDR(d->cidr), HOST_MASK); | 522 | del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); |
| 517 | #endif | 523 | #endif |
| 518 | if (n->pos + AHASH_INIT_SIZE < n->size) { | 524 | if (n->pos + AHASH_INIT_SIZE < n->size) { |
| 519 | void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) | 525 | void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) |
| @@ -546,10 +552,10 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) | |||
| 546 | const struct type_pf_elem *data; | 552 | const struct type_pf_elem *data; |
| 547 | int i, j = 0; | 553 | int i, j = 0; |
| 548 | u32 key, multi = 0; | 554 | u32 key, multi = 0; |
| 549 | u8 host_mask = SET_HOST_MASK(set->family); | 555 | u8 nets_length = NETS_LENGTH(set->family); |
| 550 | 556 | ||
| 551 | pr_debug("test by nets\n"); | 557 | pr_debug("test by nets\n"); |
| 552 | for (; j < host_mask && h->nets[j].cidr && !multi; j++) { | 558 | for (; j < nets_length && h->nets[j].nets && !multi; j++) { |
| 553 | type_pf_data_netmask(d, h->nets[j].cidr); | 559 | type_pf_data_netmask(d, h->nets[j].cidr); |
| 554 | key = HKEY(d, h->initval, t->htable_bits); | 560 | key = HKEY(d, h->initval, t->htable_bits); |
| 555 | n = hbucket(t, key); | 561 | n = hbucket(t, key); |
| @@ -604,7 +610,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb) | |||
| 604 | memsize = ahash_memsize(h, with_timeout(h->timeout) | 610 | memsize = ahash_memsize(h, with_timeout(h->timeout) |
| 605 | ? sizeof(struct type_pf_telem) | 611 | ? sizeof(struct type_pf_telem) |
| 606 | : sizeof(struct type_pf_elem), | 612 | : sizeof(struct type_pf_elem), |
| 607 | set->family == AF_INET ? 32 : 128); | 613 | NETS_LENGTH(set->family)); |
| 608 | read_unlock_bh(&set->lock); | 614 | read_unlock_bh(&set->lock); |
| 609 | 615 | ||
| 610 | nested = ipset_nest_start(skb, IPSET_ATTR_DATA); | 616 | nested = ipset_nest_start(skb, IPSET_ATTR_DATA); |
| @@ -690,7 +696,7 @@ nla_put_failure: | |||
| 690 | } | 696 | } |
| 691 | 697 | ||
| 692 | static int | 698 | static int |
| 693 | type_pf_kadt(struct ip_set *set, const struct sk_buff * skb, | 699 | type_pf_kadt(struct ip_set *set, const struct sk_buff *skb, |
| 694 | const struct xt_action_param *par, | 700 | const struct xt_action_param *par, |
| 695 | enum ipset_adt adt, const struct ip_set_adt_opt *opt); | 701 | enum ipset_adt adt, const struct ip_set_adt_opt *opt); |
| 696 | static int | 702 | static int |
| @@ -783,7 +789,7 @@ type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, | |||
| 783 | 789 | ||
| 784 | /* Delete expired elements from the hashtable */ | 790 | /* Delete expired elements from the hashtable */ |
| 785 | static void | 791 | static void |
| 786 | type_pf_expire(struct ip_set_hash *h) | 792 | type_pf_expire(struct ip_set_hash *h, u8 nets_length) |
| 787 | { | 793 | { |
| 788 | struct htable *t = h->table; | 794 | struct htable *t = h->table; |
| 789 | struct hbucket *n; | 795 | struct hbucket *n; |
| @@ -798,7 +804,7 @@ type_pf_expire(struct ip_set_hash *h) | |||
| 798 | if (type_pf_data_expired(data)) { | 804 | if (type_pf_data_expired(data)) { |
| 799 | pr_debug("expired %u/%u\n", i, j); | 805 | pr_debug("expired %u/%u\n", i, j); |
| 800 | #ifdef IP_SET_HASH_WITH_NETS | 806 | #ifdef IP_SET_HASH_WITH_NETS |
| 801 | del_cidr(h, CIDR(data->cidr), HOST_MASK); | 807 | del_cidr(h, CIDR(data->cidr), nets_length); |
| 802 | #endif | 808 | #endif |
| 803 | if (j != n->pos - 1) | 809 | if (j != n->pos - 1) |
| 804 | /* Not last one */ | 810 | /* Not last one */ |
| @@ -839,7 +845,7 @@ type_pf_tresize(struct ip_set *set, bool retried) | |||
| 839 | if (!retried) { | 845 | if (!retried) { |
| 840 | i = h->elements; | 846 | i = h->elements; |
| 841 | write_lock_bh(&set->lock); | 847 | write_lock_bh(&set->lock); |
| 842 | type_pf_expire(set->data); | 848 | type_pf_expire(set->data, NETS_LENGTH(set->family)); |
| 843 | write_unlock_bh(&set->lock); | 849 | write_unlock_bh(&set->lock); |
| 844 | if (h->elements < i) | 850 | if (h->elements < i) |
| 845 | return 0; | 851 | return 0; |
| @@ -904,7 +910,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 904 | 910 | ||
| 905 | if (h->elements >= h->maxelem) | 911 | if (h->elements >= h->maxelem) |
| 906 | /* FIXME: when set is full, we slow down here */ | 912 | /* FIXME: when set is full, we slow down here */ |
| 907 | type_pf_expire(h); | 913 | type_pf_expire(h, NETS_LENGTH(set->family)); |
| 908 | if (h->elements >= h->maxelem) { | 914 | if (h->elements >= h->maxelem) { |
| 909 | if (net_ratelimit()) | 915 | if (net_ratelimit()) |
| 910 | pr_warning("Set %s is full, maxelem %u reached\n", | 916 | pr_warning("Set %s is full, maxelem %u reached\n", |
| @@ -933,8 +939,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 933 | if (j != AHASH_MAX(h) + 1) { | 939 | if (j != AHASH_MAX(h) + 1) { |
| 934 | data = ahash_tdata(n, j); | 940 | data = ahash_tdata(n, j); |
| 935 | #ifdef IP_SET_HASH_WITH_NETS | 941 | #ifdef IP_SET_HASH_WITH_NETS |
| 936 | del_cidr(h, CIDR(data->cidr), HOST_MASK); | 942 | del_cidr(h, CIDR(data->cidr), NETS_LENGTH(set->family)); |
| 937 | add_cidr(h, CIDR(d->cidr), HOST_MASK); | 943 | add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); |
| 938 | #endif | 944 | #endif |
| 939 | type_pf_data_copy(data, d); | 945 | type_pf_data_copy(data, d); |
| 940 | type_pf_data_timeout_set(data, timeout); | 946 | type_pf_data_timeout_set(data, timeout); |
| @@ -952,7 +958,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 952 | } | 958 | } |
| 953 | 959 | ||
| 954 | #ifdef IP_SET_HASH_WITH_NETS | 960 | #ifdef IP_SET_HASH_WITH_NETS |
| 955 | add_cidr(h, CIDR(d->cidr), HOST_MASK); | 961 | add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); |
| 956 | #endif | 962 | #endif |
| 957 | h->elements++; | 963 | h->elements++; |
| 958 | out: | 964 | out: |
| @@ -986,7 +992,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) | |||
| 986 | n->pos--; | 992 | n->pos--; |
| 987 | h->elements--; | 993 | h->elements--; |
| 988 | #ifdef IP_SET_HASH_WITH_NETS | 994 | #ifdef IP_SET_HASH_WITH_NETS |
| 989 | del_cidr(h, CIDR(d->cidr), HOST_MASK); | 995 | del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family)); |
| 990 | #endif | 996 | #endif |
| 991 | if (n->pos + AHASH_INIT_SIZE < n->size) { | 997 | if (n->pos + AHASH_INIT_SIZE < n->size) { |
| 992 | void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) | 998 | void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) |
| @@ -1016,9 +1022,9 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) | |||
| 1016 | struct hbucket *n; | 1022 | struct hbucket *n; |
| 1017 | int i, j = 0; | 1023 | int i, j = 0; |
| 1018 | u32 key, multi = 0; | 1024 | u32 key, multi = 0; |
| 1019 | u8 host_mask = SET_HOST_MASK(set->family); | 1025 | u8 nets_length = NETS_LENGTH(set->family); |
| 1020 | 1026 | ||
| 1021 | for (; j < host_mask && h->nets[j].cidr && !multi; j++) { | 1027 | for (; j < nets_length && h->nets[j].nets && !multi; j++) { |
| 1022 | type_pf_data_netmask(d, h->nets[j].cidr); | 1028 | type_pf_data_netmask(d, h->nets[j].cidr); |
| 1023 | key = HKEY(d, h->initval, t->htable_bits); | 1029 | key = HKEY(d, h->initval, t->htable_bits); |
| 1024 | n = hbucket(t, key); | 1030 | n = hbucket(t, key); |
| @@ -1147,7 +1153,7 @@ type_pf_gc(unsigned long ul_set) | |||
| 1147 | 1153 | ||
| 1148 | pr_debug("called\n"); | 1154 | pr_debug("called\n"); |
| 1149 | write_lock_bh(&set->lock); | 1155 | write_lock_bh(&set->lock); |
| 1150 | type_pf_expire(h); | 1156 | type_pf_expire(h, NETS_LENGTH(set->family)); |
| 1151 | write_unlock_bh(&set->lock); | 1157 | write_unlock_bh(&set->lock); |
| 1152 | 1158 | ||
| 1153 | h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; | 1159 | h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; |
diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h index 28f18df36525..8faf3f792d13 100644 --- a/include/linux/netfilter/nf_conntrack_ftp.h +++ b/include/linux/netfilter/nf_conntrack_ftp.h | |||
| @@ -18,13 +18,17 @@ enum nf_ct_ftp_type { | |||
| 18 | 18 | ||
| 19 | #define FTP_PORT 21 | 19 | #define FTP_PORT 21 |
| 20 | 20 | ||
| 21 | #define NF_CT_FTP_SEQ_PICKUP (1 << 0) | ||
| 22 | |||
| 21 | #define NUM_SEQ_TO_REMEMBER 2 | 23 | #define NUM_SEQ_TO_REMEMBER 2 |
| 22 | /* This structure exists only once per master */ | 24 | /* This structure exists only once per master */ |
| 23 | struct nf_ct_ftp_master { | 25 | struct nf_ct_ftp_master { |
| 24 | /* Valid seq positions for cmd matching after newline */ | 26 | /* Valid seq positions for cmd matching after newline */ |
| 25 | u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER]; | 27 | u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER]; |
| 26 | /* 0 means seq_match_aft_nl not set */ | 28 | /* 0 means seq_match_aft_nl not set */ |
| 27 | int seq_aft_nl_num[IP_CT_DIR_MAX]; | 29 | u_int16_t seq_aft_nl_num[IP_CT_DIR_MAX]; |
| 30 | /* pickup sequence tracking, useful for conntrackd */ | ||
| 31 | u_int16_t flags[IP_CT_DIR_MAX]; | ||
| 28 | }; | 32 | }; |
| 29 | 33 | ||
| 30 | struct nf_conntrack_expect; | 34 | struct nf_conntrack_expect; |
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 3b1c1360aedf..70ec8c2bc11a 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h | |||
| @@ -44,6 +44,7 @@ enum nfqnl_attr_type { | |||
| 44 | NFQA_PAYLOAD, /* opaque data payload */ | 44 | NFQA_PAYLOAD, /* opaque data payload */ |
| 45 | NFQA_CT, /* nf_conntrack_netlink.h */ | 45 | NFQA_CT, /* nf_conntrack_netlink.h */ |
| 46 | NFQA_CT_INFO, /* enum ip_conntrack_info */ | 46 | NFQA_CT_INFO, /* enum ip_conntrack_info */ |
| 47 | NFQA_CAP_LEN, /* __u32 length of captured packet */ | ||
| 47 | 48 | ||
| 48 | __NFQA_MAX | 49 | __NFQA_MAX |
| 49 | }; | 50 | }; |
diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h index 7c37fac576c4..095886019396 100644 --- a/include/linux/netfilter/xt_time.h +++ b/include/linux/netfilter/xt_time.h | |||
| @@ -17,6 +17,9 @@ enum { | |||
| 17 | /* Match against local time (instead of UTC) */ | 17 | /* Match against local time (instead of UTC) */ |
| 18 | XT_TIME_LOCAL_TZ = 1 << 0, | 18 | XT_TIME_LOCAL_TZ = 1 << 0, |
| 19 | 19 | ||
| 20 | /* treat timestart > timestop (e.g. 23:00-01:00) as single period */ | ||
| 21 | XT_TIME_CONTIGUOUS = 1 << 1, | ||
| 22 | |||
| 20 | /* Shortcuts */ | 23 | /* Shortcuts */ |
| 21 | XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE, | 24 | XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE, |
| 22 | XT_TIME_ALL_WEEKDAYS = 0xFE, | 25 | XT_TIME_ALL_WEEKDAYS = 0xFE, |
| @@ -24,4 +27,6 @@ enum { | |||
| 24 | XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1, | 27 | XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1, |
| 25 | }; | 28 | }; |
| 26 | 29 | ||
| 30 | #define XT_TIME_ALL_FLAGS (XT_TIME_LOCAL_TZ|XT_TIME_CONTIGUOUS) | ||
| 31 | |||
| 27 | #endif /* _XT_TIME_H */ | 32 | #endif /* _XT_TIME_H */ |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 131e53702e77..d8d6f2a5bf12 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
| @@ -172,23 +172,20 @@ config IP_NF_TARGET_MASQUERADE | |||
| 172 | config IP_NF_TARGET_NETMAP | 172 | config IP_NF_TARGET_NETMAP |
| 173 | tristate "NETMAP target support" | 173 | tristate "NETMAP target support" |
| 174 | depends on NETFILTER_ADVANCED | 174 | depends on NETFILTER_ADVANCED |
| 175 | help | 175 | select NETFILTER_XT_TARGET_NETMAP |
| 176 | NETMAP is an implementation of static 1:1 NAT mapping of network | 176 | ---help--- |
| 177 | addresses. It maps the network address part, while keeping the host | 177 | This is a backwards-compat option for the user's convenience |
| 178 | address part intact. | 178 | (e.g. when running oldconfig). It selects |
| 179 | 179 | CONFIG_NETFILTER_XT_TARGET_NETMAP. | |
| 180 | To compile it as a module, choose M here. If unsure, say N. | ||
| 181 | 180 | ||
| 182 | config IP_NF_TARGET_REDIRECT | 181 | config IP_NF_TARGET_REDIRECT |
| 183 | tristate "REDIRECT target support" | 182 | tristate "REDIRECT target support" |
| 184 | depends on NETFILTER_ADVANCED | 183 | depends on NETFILTER_ADVANCED |
| 185 | help | 184 | select NETFILTER_XT_TARGET_REDIRECT |
| 186 | REDIRECT is a special case of NAT: all incoming connections are | 185 | ---help--- |
| 187 | mapped onto the incoming interface's address, causing the packets to | 186 | This is a backwards-compat option for the user's convenience |
| 188 | come to the local machine instead of passing through. This is | 187 | (e.g. when running oldconfig). It selects |
| 189 | useful for transparent proxies. | 188 | CONFIG_NETFILTER_XT_TARGET_REDIRECT. |
| 190 | |||
| 191 | To compile it as a module, choose M here. If unsure, say N. | ||
| 192 | 189 | ||
| 193 | endif | 190 | endif |
| 194 | 191 | ||
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index b7dd18987237..007b128eecc9 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
| @@ -45,8 +45,6 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o | |||
| 45 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 45 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o |
| 46 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o | 46 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o |
| 47 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o | 47 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o |
| 48 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o | ||
| 49 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o | ||
| 50 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o | 48 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o |
| 51 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o | 49 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o |
| 52 | 50 | ||
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c deleted file mode 100644 index 85028dc0425d..000000000000 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ /dev/null | |||
| @@ -1,101 +0,0 @@ | |||
| 1 | /* NETMAP - static NAT mapping of IP network addresses (1:1). | ||
| 2 | * The mapping can be applied to source (POSTROUTING), | ||
| 3 | * destination (PREROUTING), or both (with separate rules). | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 13 | #include <linux/ip.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include <linux/netfilter.h> | ||
| 17 | #include <linux/netfilter_ipv4.h> | ||
| 18 | #include <linux/netfilter/x_tables.h> | ||
| 19 | #include <net/netfilter/nf_nat.h> | ||
| 20 | |||
| 21 | MODULE_LICENSE("GPL"); | ||
| 22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | ||
| 23 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); | ||
| 24 | |||
| 25 | static int netmap_tg_check(const struct xt_tgchk_param *par) | ||
| 26 | { | ||
| 27 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 28 | |||
| 29 | if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) { | ||
| 30 | pr_debug("bad MAP_IPS.\n"); | ||
| 31 | return -EINVAL; | ||
| 32 | } | ||
| 33 | if (mr->rangesize != 1) { | ||
| 34 | pr_debug("bad rangesize %u.\n", mr->rangesize); | ||
| 35 | return -EINVAL; | ||
| 36 | } | ||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | |||
| 40 | static unsigned int | ||
| 41 | netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 42 | { | ||
| 43 | struct nf_conn *ct; | ||
| 44 | enum ip_conntrack_info ctinfo; | ||
| 45 | __be32 new_ip, netmask; | ||
| 46 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 47 | struct nf_nat_range newrange; | ||
| 48 | |||
| 49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | ||
| 50 | par->hooknum == NF_INET_POST_ROUTING || | ||
| 51 | par->hooknum == NF_INET_LOCAL_OUT || | ||
| 52 | par->hooknum == NF_INET_LOCAL_IN); | ||
| 53 | ct = nf_ct_get(skb, &ctinfo); | ||
| 54 | |||
| 55 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | ||
| 56 | |||
| 57 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
| 58 | par->hooknum == NF_INET_LOCAL_OUT) | ||
| 59 | new_ip = ip_hdr(skb)->daddr & ~netmask; | ||
| 60 | else | ||
| 61 | new_ip = ip_hdr(skb)->saddr & ~netmask; | ||
| 62 | new_ip |= mr->range[0].min_ip & netmask; | ||
| 63 | |||
| 64 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); | ||
| 65 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); | ||
| 66 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; | ||
| 67 | newrange.min_addr.ip = new_ip; | ||
| 68 | newrange.max_addr.ip = new_ip; | ||
| 69 | newrange.min_proto = mr->range[0].min; | ||
| 70 | newrange.max_proto = mr->range[0].max; | ||
| 71 | |||
| 72 | /* Hand modified range to generic setup. */ | ||
| 73 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | ||
| 74 | } | ||
| 75 | |||
| 76 | static struct xt_target netmap_tg_reg __read_mostly = { | ||
| 77 | .name = "NETMAP", | ||
| 78 | .family = NFPROTO_IPV4, | ||
| 79 | .target = netmap_tg, | ||
| 80 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
| 81 | .table = "nat", | ||
| 82 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 83 | (1 << NF_INET_POST_ROUTING) | | ||
| 84 | (1 << NF_INET_LOCAL_OUT) | | ||
| 85 | (1 << NF_INET_LOCAL_IN), | ||
| 86 | .checkentry = netmap_tg_check, | ||
| 87 | .me = THIS_MODULE | ||
| 88 | }; | ||
| 89 | |||
| 90 | static int __init netmap_tg_init(void) | ||
| 91 | { | ||
| 92 | return xt_register_target(&netmap_tg_reg); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void __exit netmap_tg_exit(void) | ||
| 96 | { | ||
| 97 | xt_unregister_target(&netmap_tg_reg); | ||
| 98 | } | ||
| 99 | |||
| 100 | module_init(netmap_tg_init); | ||
| 101 | module_exit(netmap_tg_exit); | ||
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c deleted file mode 100644 index 11407d7d2472..000000000000 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ /dev/null | |||
| @@ -1,113 +0,0 @@ | |||
| 1 | /* Redirect. Simple mapping which alters dst to a local IP address. */ | ||
| 2 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
| 3 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 10 | #include <linux/types.h> | ||
| 11 | #include <linux/ip.h> | ||
| 12 | #include <linux/timer.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/netfilter.h> | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include <linux/if.h> | ||
| 17 | #include <linux/inetdevice.h> | ||
| 18 | #include <net/protocol.h> | ||
| 19 | #include <net/checksum.h> | ||
| 20 | #include <linux/netfilter_ipv4.h> | ||
| 21 | #include <linux/netfilter/x_tables.h> | ||
| 22 | #include <net/netfilter/nf_nat.h> | ||
| 23 | |||
| 24 | MODULE_LICENSE("GPL"); | ||
| 25 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
| 26 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | ||
| 27 | |||
| 28 | /* FIXME: Take multiple ranges --RR */ | ||
| 29 | static int redirect_tg_check(const struct xt_tgchk_param *par) | ||
| 30 | { | ||
| 31 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 32 | |||
| 33 | if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { | ||
| 34 | pr_debug("bad MAP_IPS.\n"); | ||
| 35 | return -EINVAL; | ||
| 36 | } | ||
| 37 | if (mr->rangesize != 1) { | ||
| 38 | pr_debug("bad rangesize %u.\n", mr->rangesize); | ||
| 39 | return -EINVAL; | ||
| 40 | } | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static unsigned int | ||
| 45 | redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 46 | { | ||
| 47 | struct nf_conn *ct; | ||
| 48 | enum ip_conntrack_info ctinfo; | ||
| 49 | __be32 newdst; | ||
| 50 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 51 | struct nf_nat_range newrange; | ||
| 52 | |||
| 53 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | ||
| 54 | par->hooknum == NF_INET_LOCAL_OUT); | ||
| 55 | |||
| 56 | ct = nf_ct_get(skb, &ctinfo); | ||
| 57 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | ||
| 58 | |||
| 59 | /* Local packets: make them go to loopback */ | ||
| 60 | if (par->hooknum == NF_INET_LOCAL_OUT) | ||
| 61 | newdst = htonl(0x7F000001); | ||
| 62 | else { | ||
| 63 | struct in_device *indev; | ||
| 64 | struct in_ifaddr *ifa; | ||
| 65 | |||
| 66 | newdst = 0; | ||
| 67 | |||
| 68 | rcu_read_lock(); | ||
| 69 | indev = __in_dev_get_rcu(skb->dev); | ||
| 70 | if (indev && (ifa = indev->ifa_list)) | ||
| 71 | newdst = ifa->ifa_local; | ||
| 72 | rcu_read_unlock(); | ||
| 73 | |||
| 74 | if (!newdst) | ||
| 75 | return NF_DROP; | ||
| 76 | } | ||
| 77 | |||
| 78 | /* Transfer from original range. */ | ||
| 79 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); | ||
| 80 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); | ||
| 81 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; | ||
| 82 | newrange.min_addr.ip = newdst; | ||
| 83 | newrange.max_addr.ip = newdst; | ||
| 84 | newrange.min_proto = mr->range[0].min; | ||
| 85 | newrange.max_proto = mr->range[0].max; | ||
| 86 | |||
| 87 | /* Hand modified range to generic setup. */ | ||
| 88 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct xt_target redirect_tg_reg __read_mostly = { | ||
| 92 | .name = "REDIRECT", | ||
| 93 | .family = NFPROTO_IPV4, | ||
| 94 | .target = redirect_tg, | ||
| 95 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
| 96 | .table = "nat", | ||
| 97 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | ||
| 98 | .checkentry = redirect_tg_check, | ||
| 99 | .me = THIS_MODULE, | ||
| 100 | }; | ||
| 101 | |||
| 102 | static int __init redirect_tg_init(void) | ||
| 103 | { | ||
| 104 | return xt_register_target(&redirect_tg_reg); | ||
| 105 | } | ||
| 106 | |||
| 107 | static void __exit redirect_tg_exit(void) | ||
| 108 | { | ||
| 109 | xt_unregister_target(&redirect_tg_reg); | ||
| 110 | } | ||
| 111 | |||
| 112 | module_init(redirect_tg_init); | ||
| 113 | module_exit(redirect_tg_exit); | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 3b73254d7bf1..c72532a60d88 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -25,18 +25,6 @@ config NF_CONNTRACK_IPV6 | |||
| 25 | 25 | ||
| 26 | To compile it as a module, choose M here. If unsure, say N. | 26 | To compile it as a module, choose M here. If unsure, say N. |
| 27 | 27 | ||
| 28 | config NF_NAT_IPV6 | ||
| 29 | tristate "IPv6 NAT" | ||
| 30 | depends on NF_CONNTRACK_IPV6 | ||
| 31 | depends on NETFILTER_ADVANCED | ||
| 32 | select NF_NAT | ||
| 33 | help | ||
| 34 | The IPv6 NAT option allows masquerading, port forwarding and other | ||
| 35 | forms of full Network Address Port Translation. It is controlled by | ||
| 36 | the `nat' table in ip6tables, see the man page for ip6tables(8). | ||
| 37 | |||
| 38 | To compile it as a module, choose M here. If unsure, say N. | ||
| 39 | |||
| 40 | config IP6_NF_IPTABLES | 28 | config IP6_NF_IPTABLES |
| 41 | tristate "IP6 tables support (required for filtering)" | 29 | tristate "IP6 tables support (required for filtering)" |
| 42 | depends on INET && IPV6 | 30 | depends on INET && IPV6 |
| @@ -144,48 +132,6 @@ config IP6_NF_TARGET_HL | |||
| 144 | (e.g. when running oldconfig). It selects | 132 | (e.g. when running oldconfig). It selects |
| 145 | CONFIG_NETFILTER_XT_TARGET_HL. | 133 | CONFIG_NETFILTER_XT_TARGET_HL. |
| 146 | 134 | ||
| 147 | config IP6_NF_TARGET_MASQUERADE | ||
| 148 | tristate "MASQUERADE target support" | ||
| 149 | depends on NF_NAT_IPV6 | ||
| 150 | help | ||
| 151 | Masquerading is a special case of NAT: all outgoing connections are | ||
| 152 | changed to seem to come from a particular interface's address, and | ||
| 153 | if the interface goes down, those connections are lost. This is | ||
| 154 | only useful for dialup accounts with dynamic IP address (ie. your IP | ||
| 155 | address will be different on next dialup). | ||
| 156 | |||
| 157 | To compile it as a module, choose M here. If unsure, say N. | ||
| 158 | |||
| 159 | config IP6_NF_TARGET_NETMAP | ||
| 160 | tristate "NETMAP target support" | ||
| 161 | depends on NF_NAT_IPV6 | ||
| 162 | help | ||
| 163 | NETMAP is an implementation of static 1:1 NAT mapping of network | ||
| 164 | addresses. It maps the network address part, while keeping the host | ||
| 165 | address part intact. | ||
| 166 | |||
| 167 | To compile it as a module, choose M here. If unsure, say N. | ||
| 168 | |||
| 169 | config IP6_NF_TARGET_REDIRECT | ||
| 170 | tristate "REDIRECT target support" | ||
| 171 | depends on NF_NAT_IPV6 | ||
| 172 | help | ||
| 173 | REDIRECT is a special case of NAT: all incoming connections are | ||
| 174 | mapped onto the incoming interface's address, causing the packets to | ||
| 175 | come to the local machine instead of passing through. This is | ||
| 176 | useful for transparent proxies. | ||
| 177 | |||
| 178 | To compile it as a module, choose M here. If unsure, say N. | ||
| 179 | |||
| 180 | config IP6_NF_TARGET_NPT | ||
| 181 | tristate "NPT (Network Prefix translation) target support" | ||
| 182 | depends on NETFILTER_ADVANCED | ||
| 183 | help | ||
| 184 | This option adds the `SNPT' and `DNPT' target, which perform | ||
| 185 | stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296. | ||
| 186 | |||
| 187 | To compile it as a module, choose M here. If unsure, say N. | ||
| 188 | |||
| 189 | config IP6_NF_FILTER | 135 | config IP6_NF_FILTER |
| 190 | tristate "Packet filtering" | 136 | tristate "Packet filtering" |
| 191 | default m if NETFILTER_ADVANCED=n | 137 | default m if NETFILTER_ADVANCED=n |
| @@ -235,9 +181,44 @@ config IP6_NF_SECURITY | |||
| 235 | help | 181 | help |
| 236 | This option adds a `security' table to iptables, for use | 182 | This option adds a `security' table to iptables, for use |
| 237 | with Mandatory Access Control (MAC) policy. | 183 | with Mandatory Access Control (MAC) policy. |
| 238 | 184 | ||
| 239 | If unsure, say N. | 185 | If unsure, say N. |
| 240 | 186 | ||
| 187 | config NF_NAT_IPV6 | ||
| 188 | tristate "IPv6 NAT" | ||
| 189 | depends on NF_CONNTRACK_IPV6 | ||
| 190 | depends on NETFILTER_ADVANCED | ||
| 191 | select NF_NAT | ||
| 192 | help | ||
| 193 | The IPv6 NAT option allows masquerading, port forwarding and other | ||
| 194 | forms of full Network Address Port Translation. It is controlled by | ||
| 195 | the `nat' table in ip6tables, see the man page for ip6tables(8). | ||
| 196 | |||
| 197 | To compile it as a module, choose M here. If unsure, say N. | ||
| 198 | |||
| 199 | if NF_NAT_IPV6 | ||
| 200 | |||
| 201 | config IP6_NF_TARGET_MASQUERADE | ||
| 202 | tristate "MASQUERADE target support" | ||
| 203 | help | ||
| 204 | Masquerading is a special case of NAT: all outgoing connections are | ||
| 205 | changed to seem to come from a particular interface's address, and | ||
| 206 | if the interface goes down, those connections are lost. This is | ||
| 207 | only useful for dialup accounts with dynamic IP address (ie. your IP | ||
| 208 | address will be different on next dialup). | ||
| 209 | |||
| 210 | To compile it as a module, choose M here. If unsure, say N. | ||
| 211 | |||
| 212 | config IP6_NF_TARGET_NPT | ||
| 213 | tristate "NPT (Network Prefix translation) target support" | ||
| 214 | help | ||
| 215 | This option adds the `SNPT' and `DNPT' target, which perform | ||
| 216 | stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296. | ||
| 217 | |||
| 218 | To compile it as a module, choose M here. If unsure, say N. | ||
| 219 | |||
| 220 | endif # NF_NAT_IPV6 | ||
| 221 | |||
| 241 | endif # IP6_NF_IPTABLES | 222 | endif # IP6_NF_IPTABLES |
| 242 | 223 | ||
| 243 | endmenu | 224 | endmenu |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 5752132ca159..2d11fcc2cf3c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -35,7 +35,5 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | |||
| 35 | 35 | ||
| 36 | # targets | 36 | # targets |
| 37 | obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o | 37 | obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o |
| 38 | obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o | ||
| 39 | obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o | 38 | obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o |
| 40 | obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o | ||
| 41 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 39 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
diff --git a/net/ipv6/netfilter/ip6t_NETMAP.c b/net/ipv6/netfilter/ip6t_NETMAP.c deleted file mode 100644 index 4f3bf360e50f..000000000000 --- a/net/ipv6/netfilter/ip6t_NETMAP.c +++ /dev/null | |||
| @@ -1,94 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 | ||
| 9 | * NAT funded by Astaro. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/ipv6.h> | ||
| 15 | #include <linux/netfilter.h> | ||
| 16 | #include <linux/netfilter_ipv6.h> | ||
| 17 | #include <linux/netfilter/x_tables.h> | ||
| 18 | #include <net/netfilter/nf_nat.h> | ||
| 19 | |||
| 20 | static unsigned int | ||
| 21 | netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 22 | { | ||
| 23 | const struct nf_nat_range *range = par->targinfo; | ||
| 24 | struct nf_nat_range newrange; | ||
| 25 | struct nf_conn *ct; | ||
| 26 | enum ip_conntrack_info ctinfo; | ||
| 27 | union nf_inet_addr new_addr, netmask; | ||
| 28 | unsigned int i; | ||
| 29 | |||
| 30 | ct = nf_ct_get(skb, &ctinfo); | ||
| 31 | for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++) | ||
| 32 | netmask.ip6[i] = ~(range->min_addr.ip6[i] ^ | ||
| 33 | range->max_addr.ip6[i]); | ||
| 34 | |||
| 35 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
| 36 | par->hooknum == NF_INET_LOCAL_OUT) | ||
| 37 | new_addr.in6 = ipv6_hdr(skb)->daddr; | ||
| 38 | else | ||
| 39 | new_addr.in6 = ipv6_hdr(skb)->saddr; | ||
| 40 | |||
| 41 | for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) { | ||
| 42 | new_addr.ip6[i] &= ~netmask.ip6[i]; | ||
| 43 | new_addr.ip6[i] |= range->min_addr.ip6[i] & | ||
| 44 | netmask.ip6[i]; | ||
| 45 | } | ||
| 46 | |||
| 47 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
| 48 | newrange.min_addr = new_addr; | ||
| 49 | newrange.max_addr = new_addr; | ||
| 50 | newrange.min_proto = range->min_proto; | ||
| 51 | newrange.max_proto = range->max_proto; | ||
| 52 | |||
| 53 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | ||
| 54 | } | ||
| 55 | |||
| 56 | static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) | ||
| 57 | { | ||
| 58 | const struct nf_nat_range *range = par->targinfo; | ||
| 59 | |||
| 60 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) | ||
| 61 | return -EINVAL; | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static struct xt_target netmap_tg6_reg __read_mostly = { | ||
| 66 | .name = "NETMAP", | ||
| 67 | .family = NFPROTO_IPV6, | ||
| 68 | .target = netmap_tg6, | ||
| 69 | .targetsize = sizeof(struct nf_nat_range), | ||
| 70 | .table = "nat", | ||
| 71 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 72 | (1 << NF_INET_POST_ROUTING) | | ||
| 73 | (1 << NF_INET_LOCAL_OUT) | | ||
| 74 | (1 << NF_INET_LOCAL_IN), | ||
| 75 | .checkentry = netmap_tg6_checkentry, | ||
| 76 | .me = THIS_MODULE, | ||
| 77 | }; | ||
| 78 | |||
| 79 | static int __init netmap_tg6_init(void) | ||
| 80 | { | ||
| 81 | return xt_register_target(&netmap_tg6_reg); | ||
| 82 | } | ||
| 83 | |||
| 84 | static void netmap_tg6_exit(void) | ||
| 85 | { | ||
| 86 | xt_unregister_target(&netmap_tg6_reg); | ||
| 87 | } | ||
| 88 | |||
| 89 | module_init(netmap_tg6_init); | ||
| 90 | module_exit(netmap_tg6_exit); | ||
| 91 | |||
| 92 | MODULE_LICENSE("GPL"); | ||
| 93 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets"); | ||
| 94 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
diff --git a/net/ipv6/netfilter/ip6t_REDIRECT.c b/net/ipv6/netfilter/ip6t_REDIRECT.c deleted file mode 100644 index 60497a3c6004..000000000000 --- a/net/ipv6/netfilter/ip6t_REDIRECT.c +++ /dev/null | |||
| @@ -1,98 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 | ||
| 9 | * NAT funded by Astaro. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/netfilter.h> | ||
| 15 | #include <linux/netfilter_ipv6.h> | ||
| 16 | #include <linux/netfilter/x_tables.h> | ||
| 17 | #include <net/addrconf.h> | ||
| 18 | #include <net/netfilter/nf_nat.h> | ||
| 19 | |||
| 20 | static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; | ||
| 21 | |||
| 22 | static unsigned int | ||
| 23 | redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 24 | { | ||
| 25 | const struct nf_nat_range *range = par->targinfo; | ||
| 26 | struct nf_nat_range newrange; | ||
| 27 | struct in6_addr newdst; | ||
| 28 | enum ip_conntrack_info ctinfo; | ||
| 29 | struct nf_conn *ct; | ||
| 30 | |||
| 31 | ct = nf_ct_get(skb, &ctinfo); | ||
| 32 | if (par->hooknum == NF_INET_LOCAL_OUT) | ||
| 33 | newdst = loopback_addr; | ||
| 34 | else { | ||
| 35 | struct inet6_dev *idev; | ||
| 36 | struct inet6_ifaddr *ifa; | ||
| 37 | bool addr = false; | ||
| 38 | |||
| 39 | rcu_read_lock(); | ||
| 40 | idev = __in6_dev_get(skb->dev); | ||
| 41 | if (idev != NULL) { | ||
| 42 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
| 43 | newdst = ifa->addr; | ||
| 44 | addr = true; | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | rcu_read_unlock(); | ||
| 49 | |||
| 50 | if (!addr) | ||
| 51 | return NF_DROP; | ||
| 52 | } | ||
| 53 | |||
| 54 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
| 55 | newrange.min_addr.in6 = newdst; | ||
| 56 | newrange.max_addr.in6 = newdst; | ||
| 57 | newrange.min_proto = range->min_proto; | ||
| 58 | newrange.max_proto = range->max_proto; | ||
| 59 | |||
| 60 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
| 61 | } | ||
| 62 | |||
| 63 | static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) | ||
| 64 | { | ||
| 65 | const struct nf_nat_range *range = par->targinfo; | ||
| 66 | |||
| 67 | if (range->flags & NF_NAT_RANGE_MAP_IPS) | ||
| 68 | return -EINVAL; | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static struct xt_target redirect_tg6_reg __read_mostly = { | ||
| 73 | .name = "REDIRECT", | ||
| 74 | .family = NFPROTO_IPV6, | ||
| 75 | .checkentry = redirect_tg6_checkentry, | ||
| 76 | .target = redirect_tg6, | ||
| 77 | .targetsize = sizeof(struct nf_nat_range), | ||
| 78 | .table = "nat", | ||
| 79 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | ||
| 80 | .me = THIS_MODULE, | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int __init redirect_tg6_init(void) | ||
| 84 | { | ||
| 85 | return xt_register_target(&redirect_tg6_reg); | ||
| 86 | } | ||
| 87 | |||
| 88 | static void __exit redirect_tg6_exit(void) | ||
| 89 | { | ||
| 90 | xt_unregister_target(&redirect_tg6_reg); | ||
| 91 | } | ||
| 92 | |||
| 93 | module_init(redirect_tg6_init); | ||
| 94 | module_exit(redirect_tg6_exit); | ||
| 95 | |||
| 96 | MODULE_LICENSE("GPL"); | ||
| 97 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 98 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 3f4b3b4a7762..fefa514b9917 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -648,6 +648,16 @@ config NETFILTER_XT_TARGET_MARK | |||
| 648 | (e.g. when running oldconfig). It selects | 648 | (e.g. when running oldconfig). It selects |
| 649 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). | 649 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). |
| 650 | 650 | ||
| 651 | config NETFILTER_XT_TARGET_NETMAP | ||
| 652 | tristate '"NETMAP" target support' | ||
| 653 | depends on NF_NAT | ||
| 654 | ---help--- | ||
| 655 | NETMAP is an implementation of static 1:1 NAT mapping of network | ||
| 656 | addresses. It maps the network address part, while keeping the host | ||
| 657 | address part intact. | ||
| 658 | |||
| 659 | To compile it as a module, choose M here. If unsure, say N. | ||
| 660 | |||
| 651 | config NETFILTER_XT_TARGET_NFLOG | 661 | config NETFILTER_XT_TARGET_NFLOG |
| 652 | tristate '"NFLOG" target support' | 662 | tristate '"NFLOG" target support' |
| 653 | default m if NETFILTER_ADVANCED=n | 663 | default m if NETFILTER_ADVANCED=n |
| @@ -680,6 +690,17 @@ config NETFILTER_XT_TARGET_RATEEST | |||
| 680 | 690 | ||
| 681 | To compile it as a module, choose M here. If unsure, say N. | 691 | To compile it as a module, choose M here. If unsure, say N. |
| 682 | 692 | ||
| 693 | config NETFILTER_XT_TARGET_REDIRECT | ||
| 694 | tristate "REDIRECT target support" | ||
| 695 | depends on NF_NAT | ||
| 696 | ---help--- | ||
| 697 | REDIRECT is a special case of NAT: all incoming connections are | ||
| 698 | mapped onto the incoming interface's address, causing the packets to | ||
| 699 | come to the local machine instead of passing through. This is | ||
| 700 | useful for transparent proxies. | ||
| 701 | |||
| 702 | To compile it as a module, choose M here. If unsure, say N. | ||
| 703 | |||
| 683 | config NETFILTER_XT_TARGET_TEE | 704 | config NETFILTER_XT_TARGET_TEE |
| 684 | tristate '"TEE" - packet cloning to alternate destination' | 705 | tristate '"TEE" - packet cloning to alternate destination' |
| 685 | depends on NETFILTER_ADVANCED | 706 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 0baa3f104fcb..32596978df1d 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -83,9 +83,11 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o | |||
| 83 | obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o | 83 | obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o |
| 84 | obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o | 84 | obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o |
| 85 | obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o | 85 | obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o |
| 86 | obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o | ||
| 86 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 87 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
| 87 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 88 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
| 88 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o | 89 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o |
| 90 | obj-$(CONFIG_NETFILTER_XT_TARGET_REDIRECT) += xt_REDIRECT.o | ||
| 89 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | 91 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o |
| 90 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o | 92 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o |
| 91 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | 93 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index 7e1b061aeeba..4a92fd47bd4c 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c | |||
| @@ -27,9 +27,12 @@ | |||
| 27 | #define IP_SET_BITMAP_TIMEOUT | 27 | #define IP_SET_BITMAP_TIMEOUT |
| 28 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 28 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 29 | 29 | ||
| 30 | #define REVISION_MIN 0 | ||
| 31 | #define REVISION_MAX 0 | ||
| 32 | |||
| 30 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 31 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 32 | MODULE_DESCRIPTION("bitmap:ip type of IP sets"); | 35 | IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX); |
| 33 | MODULE_ALIAS("ip_set_bitmap:ip"); | 36 | MODULE_ALIAS("ip_set_bitmap:ip"); |
| 34 | 37 | ||
| 35 | /* Type structure */ | 38 | /* Type structure */ |
| @@ -284,7 +287,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 284 | } else if (tb[IPSET_ATTR_CIDR]) { | 287 | } else if (tb[IPSET_ATTR_CIDR]) { |
| 285 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 288 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 286 | 289 | ||
| 287 | if (cidr > 32) | 290 | if (!cidr || cidr > 32) |
| 288 | return -IPSET_ERR_INVALID_CIDR; | 291 | return -IPSET_ERR_INVALID_CIDR; |
| 289 | ip_set_mask_from_to(ip, ip_to, cidr); | 292 | ip_set_mask_from_to(ip, ip_to, cidr); |
| 290 | } else | 293 | } else |
| @@ -454,7 +457,8 @@ static int | |||
| 454 | bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | 457 | bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) |
| 455 | { | 458 | { |
| 456 | struct bitmap_ip *map; | 459 | struct bitmap_ip *map; |
| 457 | u32 first_ip, last_ip, hosts, elements; | 460 | u32 first_ip, last_ip, hosts; |
| 461 | u64 elements; | ||
| 458 | u8 netmask = 32; | 462 | u8 netmask = 32; |
| 459 | int ret; | 463 | int ret; |
| 460 | 464 | ||
| @@ -497,7 +501,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 497 | 501 | ||
| 498 | if (netmask == 32) { | 502 | if (netmask == 32) { |
| 499 | hosts = 1; | 503 | hosts = 1; |
| 500 | elements = last_ip - first_ip + 1; | 504 | elements = (u64)last_ip - first_ip + 1; |
| 501 | } else { | 505 | } else { |
| 502 | u8 mask_bits; | 506 | u8 mask_bits; |
| 503 | u32 mask; | 507 | u32 mask; |
| @@ -515,7 +519,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 515 | if (elements > IPSET_BITMAP_MAX_RANGE + 1) | 519 | if (elements > IPSET_BITMAP_MAX_RANGE + 1) |
| 516 | return -IPSET_ERR_BITMAP_RANGE_SIZE; | 520 | return -IPSET_ERR_BITMAP_RANGE_SIZE; |
| 517 | 521 | ||
| 518 | pr_debug("hosts %u, elements %u\n", hosts, elements); | 522 | pr_debug("hosts %u, elements %llu\n", |
| 523 | hosts, (unsigned long long)elements); | ||
| 519 | 524 | ||
| 520 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 525 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
| 521 | if (!map) | 526 | if (!map) |
| @@ -554,8 +559,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = { | |||
| 554 | .features = IPSET_TYPE_IP, | 559 | .features = IPSET_TYPE_IP, |
| 555 | .dimension = IPSET_DIM_ONE, | 560 | .dimension = IPSET_DIM_ONE, |
| 556 | .family = NFPROTO_IPV4, | 561 | .family = NFPROTO_IPV4, |
| 557 | .revision_min = 0, | 562 | .revision_min = REVISION_MIN, |
| 558 | .revision_max = 0, | 563 | .revision_max = REVISION_MAX, |
| 559 | .create = bitmap_ip_create, | 564 | .create = bitmap_ip_create, |
| 560 | .create_policy = { | 565 | .create_policy = { |
| 561 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, | 566 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index d7eaf10edb6d..0f92dc24cb89 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c | |||
| @@ -26,9 +26,12 @@ | |||
| 26 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 26 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 27 | #include <linux/netfilter/ipset/ip_set_bitmap.h> | 27 | #include <linux/netfilter/ipset/ip_set_bitmap.h> |
| 28 | 28 | ||
| 29 | #define REVISION_MIN 0 | ||
| 30 | #define REVISION_MAX 0 | ||
| 31 | |||
| 29 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
| 30 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 31 | MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets"); | 34 | IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX); |
| 32 | MODULE_ALIAS("ip_set_bitmap:ip,mac"); | 35 | MODULE_ALIAS("ip_set_bitmap:ip,mac"); |
| 33 | 36 | ||
| 34 | enum { | 37 | enum { |
| @@ -320,11 +323,11 @@ bitmap_ipmac_tlist(const struct ip_set *set, | |||
| 320 | (elem->match == MAC_FILLED && | 323 | (elem->match == MAC_FILLED && |
| 321 | nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, | 324 | nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, |
| 322 | elem->ether))) | 325 | elem->ether))) |
| 323 | goto nla_put_failure; | 326 | goto nla_put_failure; |
| 324 | timeout = elem->match == MAC_UNSET ? elem->timeout | 327 | timeout = elem->match == MAC_UNSET ? elem->timeout |
| 325 | : ip_set_timeout_get(elem->timeout); | 328 | : ip_set_timeout_get(elem->timeout); |
| 326 | if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout))) | 329 | if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout))) |
| 327 | goto nla_put_failure; | 330 | goto nla_put_failure; |
| 328 | ipset_nest_end(skb, nested); | 331 | ipset_nest_end(skb, nested); |
| 329 | } | 332 | } |
| 330 | ipset_nest_end(skb, atd); | 333 | ipset_nest_end(skb, atd); |
| @@ -557,7 +560,8 @@ static int | |||
| 557 | bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], | 560 | bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], |
| 558 | u32 flags) | 561 | u32 flags) |
| 559 | { | 562 | { |
| 560 | u32 first_ip, last_ip, elements; | 563 | u32 first_ip, last_ip; |
| 564 | u64 elements; | ||
| 561 | struct bitmap_ipmac *map; | 565 | struct bitmap_ipmac *map; |
| 562 | int ret; | 566 | int ret; |
| 563 | 567 | ||
| @@ -588,7 +592,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], | |||
| 588 | } else | 592 | } else |
| 589 | return -IPSET_ERR_PROTOCOL; | 593 | return -IPSET_ERR_PROTOCOL; |
| 590 | 594 | ||
| 591 | elements = last_ip - first_ip + 1; | 595 | elements = (u64)last_ip - first_ip + 1; |
| 592 | 596 | ||
| 593 | if (elements > IPSET_BITMAP_MAX_RANGE + 1) | 597 | if (elements > IPSET_BITMAP_MAX_RANGE + 1) |
| 594 | return -IPSET_ERR_BITMAP_RANGE_SIZE; | 598 | return -IPSET_ERR_BITMAP_RANGE_SIZE; |
| @@ -629,8 +633,8 @@ static struct ip_set_type bitmap_ipmac_type = { | |||
| 629 | .features = IPSET_TYPE_IP | IPSET_TYPE_MAC, | 633 | .features = IPSET_TYPE_IP | IPSET_TYPE_MAC, |
| 630 | .dimension = IPSET_DIM_TWO, | 634 | .dimension = IPSET_DIM_TWO, |
| 631 | .family = NFPROTO_IPV4, | 635 | .family = NFPROTO_IPV4, |
| 632 | .revision_min = 0, | 636 | .revision_min = REVISION_MIN, |
| 633 | .revision_max = 0, | 637 | .revision_max = REVISION_MAX, |
| 634 | .create = bitmap_ipmac_create, | 638 | .create = bitmap_ipmac_create, |
| 635 | .create_policy = { | 639 | .create_policy = { |
| 636 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, | 640 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, |
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index b9f1fce7053b..e6b2db76f4c3 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c | |||
| @@ -22,9 +22,12 @@ | |||
| 22 | #define IP_SET_BITMAP_TIMEOUT | 22 | #define IP_SET_BITMAP_TIMEOUT |
| 23 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 23 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 24 | 24 | ||
| 25 | #define REVISION_MIN 0 | ||
| 26 | #define REVISION_MAX 0 | ||
| 27 | |||
| 25 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
| 26 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 29 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 27 | MODULE_DESCRIPTION("bitmap:port type of IP sets"); | 30 | IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX); |
| 28 | MODULE_ALIAS("ip_set_bitmap:port"); | 31 | MODULE_ALIAS("ip_set_bitmap:port"); |
| 29 | 32 | ||
| 30 | /* Type structure */ | 33 | /* Type structure */ |
| @@ -487,8 +490,8 @@ static struct ip_set_type bitmap_port_type = { | |||
| 487 | .features = IPSET_TYPE_PORT, | 490 | .features = IPSET_TYPE_PORT, |
| 488 | .dimension = IPSET_DIM_ONE, | 491 | .dimension = IPSET_DIM_ONE, |
| 489 | .family = NFPROTO_UNSPEC, | 492 | .family = NFPROTO_UNSPEC, |
| 490 | .revision_min = 0, | 493 | .revision_min = REVISION_MIN, |
| 491 | .revision_max = 0, | 494 | .revision_max = REVISION_MAX, |
| 492 | .create = bitmap_port_create, | 495 | .create = bitmap_port_create, |
| 493 | .create_policy = { | 496 | .create_policy = { |
| 494 | [IPSET_ATTR_PORT] = { .type = NLA_U16 }, | 497 | [IPSET_ATTR_PORT] = { .type = NLA_U16 }, |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index ad39ef406851..778465f217fa 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
| @@ -69,7 +69,8 @@ find_set_type(const char *name, u8 family, u8 revision) | |||
| 69 | 69 | ||
| 70 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | 70 | list_for_each_entry_rcu(type, &ip_set_type_list, list) |
| 71 | if (STREQ(type->name, name) && | 71 | if (STREQ(type->name, name) && |
| 72 | (type->family == family || type->family == NFPROTO_UNSPEC) && | 72 | (type->family == family || |
| 73 | type->family == NFPROTO_UNSPEC) && | ||
| 73 | revision >= type->revision_min && | 74 | revision >= type->revision_min && |
| 74 | revision <= type->revision_max) | 75 | revision <= type->revision_max) |
| 75 | return type; | 76 | return type; |
| @@ -149,7 +150,8 @@ __find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max, | |||
| 149 | rcu_read_lock(); | 150 | rcu_read_lock(); |
| 150 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | 151 | list_for_each_entry_rcu(type, &ip_set_type_list, list) |
| 151 | if (STREQ(type->name, name) && | 152 | if (STREQ(type->name, name) && |
| 152 | (type->family == family || type->family == NFPROTO_UNSPEC)) { | 153 | (type->family == family || |
| 154 | type->family == NFPROTO_UNSPEC)) { | ||
| 153 | found = true; | 155 | found = true; |
| 154 | if (type->revision_min < *min) | 156 | if (type->revision_min < *min) |
| 155 | *min = type->revision_min; | 157 | *min = type->revision_min; |
| @@ -368,6 +370,12 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, | |||
| 368 | set->variant->kadt(set, skb, par, IPSET_ADD, opt); | 370 | set->variant->kadt(set, skb, par, IPSET_ADD, opt); |
| 369 | write_unlock_bh(&set->lock); | 371 | write_unlock_bh(&set->lock); |
| 370 | ret = 1; | 372 | ret = 1; |
| 373 | } else { | ||
| 374 | /* --return-nomatch: invert matched element */ | ||
| 375 | if ((opt->flags & IPSET_RETURN_NOMATCH) && | ||
| 376 | (set->type->features & IPSET_TYPE_NOMATCH) && | ||
| 377 | (ret > 0 || ret == -ENOTEMPTY)) | ||
| 378 | ret = -ret; | ||
| 371 | } | 379 | } |
| 372 | 380 | ||
| 373 | /* Convert error codes to nomatch */ | 381 | /* Convert error codes to nomatch */ |
| @@ -721,7 +729,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
| 721 | * by the nfnl mutex. Find the first free index in ip_set_list | 729 | * by the nfnl mutex. Find the first free index in ip_set_list |
| 722 | * and check clashing. | 730 | * and check clashing. |
| 723 | */ | 731 | */ |
| 724 | if ((ret = find_free_id(set->name, &index, &clash)) != 0) { | 732 | ret = find_free_id(set->name, &index, &clash); |
| 733 | if (ret != 0) { | ||
| 725 | /* If this is the same set and requested, ignore error */ | 734 | /* If this is the same set and requested, ignore error */ |
| 726 | if (ret == -EEXIST && | 735 | if (ret == -EEXIST && |
| 727 | (flags & IPSET_FLAG_EXIST) && | 736 | (flags & IPSET_FLAG_EXIST) && |
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index a68dbd4f1e4e..ec3dba5dcd62 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c | |||
| @@ -24,9 +24,12 @@ | |||
| 24 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 24 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 25 | #include <linux/netfilter/ipset/ip_set_hash.h> | 25 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 26 | 26 | ||
| 27 | #define REVISION_MIN 0 | ||
| 28 | #define REVISION_MAX 0 | ||
| 29 | |||
| 27 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
| 28 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 31 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 29 | MODULE_DESCRIPTION("hash:ip type of IP sets"); | 32 | IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX); |
| 30 | MODULE_ALIAS("ip_set_hash:ip"); | 33 | MODULE_ALIAS("ip_set_hash:ip"); |
| 31 | 34 | ||
| 32 | /* Type specific function prefix */ | 35 | /* Type specific function prefix */ |
| @@ -114,7 +117,7 @@ nla_put_failure: | |||
| 114 | static inline void | 117 | static inline void |
| 115 | hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d) | 118 | hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d) |
| 116 | { | 119 | { |
| 117 | h->next.ip = ntohl(d->ip); | 120 | h->next.ip = d->ip; |
| 118 | } | 121 | } |
| 119 | 122 | ||
| 120 | static int | 123 | static int |
| @@ -179,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 179 | } else if (tb[IPSET_ATTR_CIDR]) { | 182 | } else if (tb[IPSET_ATTR_CIDR]) { |
| 180 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 183 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 181 | 184 | ||
| 182 | if (cidr > 32) | 185 | if (!cidr || cidr > 32) |
| 183 | return -IPSET_ERR_INVALID_CIDR; | 186 | return -IPSET_ERR_INVALID_CIDR; |
| 184 | ip_set_mask_from_to(ip, ip_to, cidr); | 187 | ip_set_mask_from_to(ip, ip_to, cidr); |
| 185 | } else | 188 | } else |
| @@ -188,7 +191,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 188 | hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); | 191 | hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); |
| 189 | 192 | ||
| 190 | if (retried) | 193 | if (retried) |
| 191 | ip = h->next.ip; | 194 | ip = ntohl(h->next.ip); |
| 192 | for (; !before(ip_to, ip); ip += hosts) { | 195 | for (; !before(ip_to, ip); ip += hosts) { |
| 193 | nip = htonl(ip); | 196 | nip = htonl(ip); |
| 194 | if (nip == 0) | 197 | if (nip == 0) |
| @@ -452,8 +455,8 @@ static struct ip_set_type hash_ip_type __read_mostly = { | |||
| 452 | .features = IPSET_TYPE_IP, | 455 | .features = IPSET_TYPE_IP, |
| 453 | .dimension = IPSET_DIM_ONE, | 456 | .dimension = IPSET_DIM_ONE, |
| 454 | .family = NFPROTO_UNSPEC, | 457 | .family = NFPROTO_UNSPEC, |
| 455 | .revision_min = 0, | 458 | .revision_min = REVISION_MIN, |
| 456 | .revision_max = 0, | 459 | .revision_max = REVISION_MAX, |
| 457 | .create = hash_ip_create, | 460 | .create = hash_ip_create, |
| 458 | .create_policy = { | 461 | .create_policy = { |
| 459 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 462 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 92722bb82eea..0171f7502fa5 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
| @@ -25,9 +25,12 @@ | |||
| 25 | #include <linux/netfilter/ipset/ip_set_getport.h> | 25 | #include <linux/netfilter/ipset/ip_set_getport.h> |
| 26 | #include <linux/netfilter/ipset/ip_set_hash.h> | 26 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 27 | 27 | ||
| 28 | #define REVISION_MIN 0 | ||
| 29 | #define REVISION_MAX 1 /* SCTP and UDPLITE support added */ | ||
| 30 | |||
| 28 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 29 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 32 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 30 | MODULE_DESCRIPTION("hash:ip,port type of IP sets"); | 33 | IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX); |
| 31 | MODULE_ALIAS("ip_set_hash:ip,port"); | 34 | MODULE_ALIAS("ip_set_hash:ip,port"); |
| 32 | 35 | ||
| 33 | /* Type specific function prefix */ | 36 | /* Type specific function prefix */ |
| @@ -130,8 +133,8 @@ static inline void | |||
| 130 | hash_ipport4_data_next(struct ip_set_hash *h, | 133 | hash_ipport4_data_next(struct ip_set_hash *h, |
| 131 | const struct hash_ipport4_elem *d) | 134 | const struct hash_ipport4_elem *d) |
| 132 | { | 135 | { |
| 133 | h->next.ip = ntohl(d->ip); | 136 | h->next.ip = d->ip; |
| 134 | h->next.port = ntohs(d->port); | 137 | h->next.port = d->port; |
| 135 | } | 138 | } |
| 136 | 139 | ||
| 137 | static int | 140 | static int |
| @@ -217,7 +220,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 217 | } else if (tb[IPSET_ATTR_CIDR]) { | 220 | } else if (tb[IPSET_ATTR_CIDR]) { |
| 218 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 221 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 219 | 222 | ||
| 220 | if (cidr > 32) | 223 | if (!cidr || cidr > 32) |
| 221 | return -IPSET_ERR_INVALID_CIDR; | 224 | return -IPSET_ERR_INVALID_CIDR; |
| 222 | ip_set_mask_from_to(ip, ip_to, cidr); | 225 | ip_set_mask_from_to(ip, ip_to, cidr); |
| 223 | } else | 226 | } else |
| @@ -231,9 +234,10 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 231 | } | 234 | } |
| 232 | 235 | ||
| 233 | if (retried) | 236 | if (retried) |
| 234 | ip = h->next.ip; | 237 | ip = ntohl(h->next.ip); |
| 235 | for (; !before(ip_to, ip); ip++) { | 238 | for (; !before(ip_to, ip); ip++) { |
| 236 | p = retried && ip == h->next.ip ? h->next.port : port; | 239 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
| 240 | : port; | ||
| 237 | for (; p <= port_to; p++) { | 241 | for (; p <= port_to; p++) { |
| 238 | data.ip = htonl(ip); | 242 | data.ip = htonl(ip); |
| 239 | data.port = htons(p); | 243 | data.port = htons(p); |
| @@ -349,7 +353,7 @@ static inline void | |||
| 349 | hash_ipport6_data_next(struct ip_set_hash *h, | 353 | hash_ipport6_data_next(struct ip_set_hash *h, |
| 350 | const struct hash_ipport6_elem *d) | 354 | const struct hash_ipport6_elem *d) |
| 351 | { | 355 | { |
| 352 | h->next.port = ntohs(d->port); | 356 | h->next.port = d->port; |
| 353 | } | 357 | } |
| 354 | 358 | ||
| 355 | static int | 359 | static int |
| @@ -431,7 +435,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 431 | swap(port, port_to); | 435 | swap(port, port_to); |
| 432 | 436 | ||
| 433 | if (retried) | 437 | if (retried) |
| 434 | port = h->next.port; | 438 | port = ntohs(h->next.port); |
| 435 | for (; port <= port_to; port++) { | 439 | for (; port <= port_to; port++) { |
| 436 | data.port = htons(port); | 440 | data.port = htons(port); |
| 437 | ret = adtfn(set, &data, timeout, flags); | 441 | ret = adtfn(set, &data, timeout, flags); |
| @@ -522,8 +526,8 @@ static struct ip_set_type hash_ipport_type __read_mostly = { | |||
| 522 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, | 526 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, |
| 523 | .dimension = IPSET_DIM_TWO, | 527 | .dimension = IPSET_DIM_TWO, |
| 524 | .family = NFPROTO_UNSPEC, | 528 | .family = NFPROTO_UNSPEC, |
| 525 | .revision_min = 0, | 529 | .revision_min = REVISION_MIN, |
| 526 | .revision_max = 1, /* SCTP and UDPLITE support added */ | 530 | .revision_max = REVISION_MAX, |
| 527 | .create = hash_ipport_create, | 531 | .create = hash_ipport_create, |
| 528 | .create_policy = { | 532 | .create_policy = { |
| 529 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 533 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 0637ce096def..6344ef551ec8 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
| @@ -25,9 +25,12 @@ | |||
| 25 | #include <linux/netfilter/ipset/ip_set_getport.h> | 25 | #include <linux/netfilter/ipset/ip_set_getport.h> |
| 26 | #include <linux/netfilter/ipset/ip_set_hash.h> | 26 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 27 | 27 | ||
| 28 | #define REVISION_MIN 0 | ||
| 29 | #define REVISION_MAX 1 /* SCTP and UDPLITE support added */ | ||
| 30 | |||
| 28 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 29 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 32 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 30 | MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets"); | 33 | IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX); |
| 31 | MODULE_ALIAS("ip_set_hash:ip,port,ip"); | 34 | MODULE_ALIAS("ip_set_hash:ip,port,ip"); |
| 32 | 35 | ||
| 33 | /* Type specific function prefix */ | 36 | /* Type specific function prefix */ |
| @@ -133,8 +136,8 @@ static inline void | |||
| 133 | hash_ipportip4_data_next(struct ip_set_hash *h, | 136 | hash_ipportip4_data_next(struct ip_set_hash *h, |
| 134 | const struct hash_ipportip4_elem *d) | 137 | const struct hash_ipportip4_elem *d) |
| 135 | { | 138 | { |
| 136 | h->next.ip = ntohl(d->ip); | 139 | h->next.ip = d->ip; |
| 137 | h->next.port = ntohs(d->port); | 140 | h->next.port = d->port; |
| 138 | } | 141 | } |
| 139 | 142 | ||
| 140 | static int | 143 | static int |
| @@ -225,7 +228,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 225 | } else if (tb[IPSET_ATTR_CIDR]) { | 228 | } else if (tb[IPSET_ATTR_CIDR]) { |
| 226 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 229 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 227 | 230 | ||
| 228 | if (cidr > 32) | 231 | if (!cidr || cidr > 32) |
| 229 | return -IPSET_ERR_INVALID_CIDR; | 232 | return -IPSET_ERR_INVALID_CIDR; |
| 230 | ip_set_mask_from_to(ip, ip_to, cidr); | 233 | ip_set_mask_from_to(ip, ip_to, cidr); |
| 231 | } else | 234 | } else |
| @@ -239,9 +242,10 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 239 | } | 242 | } |
| 240 | 243 | ||
| 241 | if (retried) | 244 | if (retried) |
| 242 | ip = h->next.ip; | 245 | ip = ntohl(h->next.ip); |
| 243 | for (; !before(ip_to, ip); ip++) { | 246 | for (; !before(ip_to, ip); ip++) { |
| 244 | p = retried && ip == h->next.ip ? h->next.port : port; | 247 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
| 248 | : port; | ||
| 245 | for (; p <= port_to; p++) { | 249 | for (; p <= port_to; p++) { |
| 246 | data.ip = htonl(ip); | 250 | data.ip = htonl(ip); |
| 247 | data.port = htons(p); | 251 | data.port = htons(p); |
| @@ -362,7 +366,7 @@ static inline void | |||
| 362 | hash_ipportip6_data_next(struct ip_set_hash *h, | 366 | hash_ipportip6_data_next(struct ip_set_hash *h, |
| 363 | const struct hash_ipportip6_elem *d) | 367 | const struct hash_ipportip6_elem *d) |
| 364 | { | 368 | { |
| 365 | h->next.port = ntohs(d->port); | 369 | h->next.port = d->port; |
| 366 | } | 370 | } |
| 367 | 371 | ||
| 368 | static int | 372 | static int |
| @@ -449,7 +453,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 449 | swap(port, port_to); | 453 | swap(port, port_to); |
| 450 | 454 | ||
| 451 | if (retried) | 455 | if (retried) |
| 452 | port = h->next.port; | 456 | port = ntohs(h->next.port); |
| 453 | for (; port <= port_to; port++) { | 457 | for (; port <= port_to; port++) { |
| 454 | data.port = htons(port); | 458 | data.port = htons(port); |
| 455 | ret = adtfn(set, &data, timeout, flags); | 459 | ret = adtfn(set, &data, timeout, flags); |
| @@ -540,8 +544,8 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { | |||
| 540 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, | 544 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, |
| 541 | .dimension = IPSET_DIM_THREE, | 545 | .dimension = IPSET_DIM_THREE, |
| 542 | .family = NFPROTO_UNSPEC, | 546 | .family = NFPROTO_UNSPEC, |
| 543 | .revision_min = 0, | 547 | .revision_min = REVISION_MIN, |
| 544 | .revision_max = 1, /* SCTP and UDPLITE support added */ | 548 | .revision_max = REVISION_MAX, |
| 545 | .create = hash_ipportip_create, | 549 | .create = hash_ipportip_create, |
| 546 | .create_policy = { | 550 | .create_policy = { |
| 547 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 551 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 1ce21ca976e1..cb71f9a774e7 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
| @@ -25,9 +25,14 @@ | |||
| 25 | #include <linux/netfilter/ipset/ip_set_getport.h> | 25 | #include <linux/netfilter/ipset/ip_set_getport.h> |
| 26 | #include <linux/netfilter/ipset/ip_set_hash.h> | 26 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 27 | 27 | ||
| 28 | #define REVISION_MIN 0 | ||
| 29 | /* 1 SCTP and UDPLITE support added */ | ||
| 30 | /* 2 Range as input support for IPv4 added */ | ||
| 31 | #define REVISION_MAX 3 /* nomatch flag support added */ | ||
| 32 | |||
| 28 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 29 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 30 | MODULE_DESCRIPTION("hash:ip,port,net type of IP sets"); | 35 | IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX); |
| 31 | MODULE_ALIAS("ip_set_hash:ip,port,net"); | 36 | MODULE_ALIAS("ip_set_hash:ip,port,net"); |
| 32 | 37 | ||
| 33 | /* Type specific function prefix */ | 38 | /* Type specific function prefix */ |
| @@ -99,10 +104,10 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags) | |||
| 99 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); | 104 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); |
| 100 | } | 105 | } |
| 101 | 106 | ||
| 102 | static inline bool | 107 | static inline int |
| 103 | hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) | 108 | hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) |
| 104 | { | 109 | { |
| 105 | return !elem->nomatch; | 110 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 106 | } | 111 | } |
| 107 | 112 | ||
| 108 | static inline void | 113 | static inline void |
| @@ -173,9 +178,9 @@ static inline void | |||
| 173 | hash_ipportnet4_data_next(struct ip_set_hash *h, | 178 | hash_ipportnet4_data_next(struct ip_set_hash *h, |
| 174 | const struct hash_ipportnet4_elem *d) | 179 | const struct hash_ipportnet4_elem *d) |
| 175 | { | 180 | { |
| 176 | h->next.ip = ntohl(d->ip); | 181 | h->next.ip = d->ip; |
| 177 | h->next.port = ntohs(d->port); | 182 | h->next.port = d->port; |
| 178 | h->next.ip2 = ntohl(d->ip2); | 183 | h->next.ip2 = d->ip2; |
| 179 | } | 184 | } |
| 180 | 185 | ||
| 181 | static int | 186 | static int |
| @@ -290,7 +295,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 290 | } else if (tb[IPSET_ATTR_CIDR]) { | 295 | } else if (tb[IPSET_ATTR_CIDR]) { |
| 291 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 296 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 292 | 297 | ||
| 293 | if (cidr > 32) | 298 | if (!cidr || cidr > 32) |
| 294 | return -IPSET_ERR_INVALID_CIDR; | 299 | return -IPSET_ERR_INVALID_CIDR; |
| 295 | ip_set_mask_from_to(ip, ip_to, cidr); | 300 | ip_set_mask_from_to(ip, ip_to, cidr); |
| 296 | } | 301 | } |
| @@ -314,14 +319,17 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 314 | } | 319 | } |
| 315 | 320 | ||
| 316 | if (retried) | 321 | if (retried) |
| 317 | ip = h->next.ip; | 322 | ip = ntohl(h->next.ip); |
| 318 | for (; !before(ip_to, ip); ip++) { | 323 | for (; !before(ip_to, ip); ip++) { |
| 319 | data.ip = htonl(ip); | 324 | data.ip = htonl(ip); |
| 320 | p = retried && ip == h->next.ip ? h->next.port : port; | 325 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
| 326 | : port; | ||
| 321 | for (; p <= port_to; p++) { | 327 | for (; p <= port_to; p++) { |
| 322 | data.port = htons(p); | 328 | data.port = htons(p); |
| 323 | ip2 = retried && ip == h->next.ip && p == h->next.port | 329 | ip2 = retried |
| 324 | ? h->next.ip2 : ip2_from; | 330 | && ip == ntohl(h->next.ip) |
| 331 | && p == ntohs(h->next.port) | ||
| 332 | ? ntohl(h->next.ip2) : ip2_from; | ||
| 325 | while (!after(ip2, ip2_to)) { | 333 | while (!after(ip2, ip2_to)) { |
| 326 | data.ip2 = htonl(ip2); | 334 | data.ip2 = htonl(ip2); |
| 327 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, | 335 | ip2_last = ip_set_range_to_cidr(ip2, ip2_to, |
| @@ -403,10 +411,10 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags) | |||
| 403 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); | 411 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); |
| 404 | } | 412 | } |
| 405 | 413 | ||
| 406 | static inline bool | 414 | static inline int |
| 407 | hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) | 415 | hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) |
| 408 | { | 416 | { |
| 409 | return !elem->nomatch; | 417 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 410 | } | 418 | } |
| 411 | 419 | ||
| 412 | static inline void | 420 | static inline void |
| @@ -486,7 +494,7 @@ static inline void | |||
| 486 | hash_ipportnet6_data_next(struct ip_set_hash *h, | 494 | hash_ipportnet6_data_next(struct ip_set_hash *h, |
| 487 | const struct hash_ipportnet6_elem *d) | 495 | const struct hash_ipportnet6_elem *d) |
| 488 | { | 496 | { |
| 489 | h->next.port = ntohs(d->port); | 497 | h->next.port = d->port; |
| 490 | } | 498 | } |
| 491 | 499 | ||
| 492 | static int | 500 | static int |
| @@ -598,7 +606,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 598 | swap(port, port_to); | 606 | swap(port, port_to); |
| 599 | 607 | ||
| 600 | if (retried) | 608 | if (retried) |
| 601 | port = h->next.port; | 609 | port = ntohs(h->next.port); |
| 602 | for (; port <= port_to; port++) { | 610 | for (; port <= port_to; port++) { |
| 603 | data.port = htons(port); | 611 | data.port = htons(port); |
| 604 | ret = adtfn(set, &data, timeout, flags); | 612 | ret = adtfn(set, &data, timeout, flags); |
| @@ -689,13 +697,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 689 | static struct ip_set_type hash_ipportnet_type __read_mostly = { | 697 | static struct ip_set_type hash_ipportnet_type __read_mostly = { |
| 690 | .name = "hash:ip,port,net", | 698 | .name = "hash:ip,port,net", |
| 691 | .protocol = IPSET_PROTOCOL, | 699 | .protocol = IPSET_PROTOCOL, |
| 692 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, | 700 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 | |
| 701 | IPSET_TYPE_NOMATCH, | ||
| 693 | .dimension = IPSET_DIM_THREE, | 702 | .dimension = IPSET_DIM_THREE, |
| 694 | .family = NFPROTO_UNSPEC, | 703 | .family = NFPROTO_UNSPEC, |
| 695 | .revision_min = 0, | 704 | .revision_min = REVISION_MIN, |
| 696 | /* 1 SCTP and UDPLITE support added */ | 705 | .revision_max = REVISION_MAX, |
| 697 | /* 2 Range as input support for IPv4 added */ | ||
| 698 | .revision_max = 3, /* nomatch flag support added */ | ||
| 699 | .create = hash_ipportnet_create, | 706 | .create = hash_ipportnet_create, |
| 700 | .create_policy = { | 707 | .create_policy = { |
| 701 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 708 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index c57a6a09906d..29e94b981f3f 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
| @@ -23,9 +23,13 @@ | |||
| 23 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 23 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 24 | #include <linux/netfilter/ipset/ip_set_hash.h> | 24 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 25 | 25 | ||
| 26 | #define REVISION_MIN 0 | ||
| 27 | /* 1 Range as input support for IPv4 added */ | ||
| 28 | #define REVISION_MAX 2 /* nomatch flag support added */ | ||
| 29 | |||
| 26 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
| 27 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 31 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 28 | MODULE_DESCRIPTION("hash:net type of IP sets"); | 32 | IP_SET_MODULE_DESC("hash:net", REVISION_MIN, REVISION_MAX); |
| 29 | MODULE_ALIAS("ip_set_hash:net"); | 33 | MODULE_ALIAS("ip_set_hash:net"); |
| 30 | 34 | ||
| 31 | /* Type specific function prefix */ | 35 | /* Type specific function prefix */ |
| @@ -86,10 +90,10 @@ hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) | |||
| 86 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; | 90 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; |
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | static inline bool | 93 | static inline int |
| 90 | hash_net4_data_match(const struct hash_net4_elem *elem) | 94 | hash_net4_data_match(const struct hash_net4_elem *elem) |
| 91 | { | 95 | { |
| 92 | return !elem->nomatch; | 96 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | static inline void | 99 | static inline void |
| @@ -152,7 +156,7 @@ static inline void | |||
| 152 | hash_net4_data_next(struct ip_set_hash *h, | 156 | hash_net4_data_next(struct ip_set_hash *h, |
| 153 | const struct hash_net4_elem *d) | 157 | const struct hash_net4_elem *d) |
| 154 | { | 158 | { |
| 155 | h->next.ip = ntohl(d->ip); | 159 | h->next.ip = d->ip; |
| 156 | } | 160 | } |
| 157 | 161 | ||
| 158 | static int | 162 | static int |
| @@ -235,7 +239,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 235 | return -IPSET_ERR_HASH_RANGE; | 239 | return -IPSET_ERR_HASH_RANGE; |
| 236 | } | 240 | } |
| 237 | if (retried) | 241 | if (retried) |
| 238 | ip = h->next.ip; | 242 | ip = ntohl(h->next.ip); |
| 239 | while (!after(ip, ip_to)) { | 243 | while (!after(ip, ip_to)) { |
| 240 | data.ip = htonl(ip); | 244 | data.ip = htonl(ip); |
| 241 | last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); | 245 | last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); |
| @@ -307,10 +311,10 @@ hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags) | |||
| 307 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; | 311 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; |
| 308 | } | 312 | } |
| 309 | 313 | ||
| 310 | static inline bool | 314 | static inline int |
| 311 | hash_net6_data_match(const struct hash_net6_elem *elem) | 315 | hash_net6_data_match(const struct hash_net6_elem *elem) |
| 312 | { | 316 | { |
| 313 | return !elem->nomatch; | 317 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 314 | } | 318 | } |
| 315 | 319 | ||
| 316 | static inline void | 320 | static inline void |
| @@ -532,12 +536,11 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 532 | static struct ip_set_type hash_net_type __read_mostly = { | 536 | static struct ip_set_type hash_net_type __read_mostly = { |
| 533 | .name = "hash:net", | 537 | .name = "hash:net", |
| 534 | .protocol = IPSET_PROTOCOL, | 538 | .protocol = IPSET_PROTOCOL, |
| 535 | .features = IPSET_TYPE_IP, | 539 | .features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH, |
| 536 | .dimension = IPSET_DIM_ONE, | 540 | .dimension = IPSET_DIM_ONE, |
| 537 | .family = NFPROTO_UNSPEC, | 541 | .family = NFPROTO_UNSPEC, |
| 538 | .revision_min = 0, | 542 | .revision_min = REVISION_MIN, |
| 539 | /* = 1 Range as input support for IPv4 added */ | 543 | .revision_max = REVISION_MAX, |
| 540 | .revision_max = 2, /* nomatch flag support added */ | ||
| 541 | .create = hash_net_create, | 544 | .create = hash_net_create, |
| 542 | .create_policy = { | 545 | .create_policy = { |
| 543 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 546 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index d5d3607ae7bc..b9a63381e349 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
| @@ -24,9 +24,13 @@ | |||
| 24 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 24 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 25 | #include <linux/netfilter/ipset/ip_set_hash.h> | 25 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 26 | 26 | ||
| 27 | #define REVISION_MIN 0 | ||
| 28 | /* 1 nomatch flag support added */ | ||
| 29 | #define REVISION_MAX 2 /* /0 support added */ | ||
| 30 | |||
| 27 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 28 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 32 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 29 | MODULE_DESCRIPTION("hash:net,iface type of IP sets"); | 33 | IP_SET_MODULE_DESC("hash:net,iface", REVISION_MIN, REVISION_MAX); |
| 30 | MODULE_ALIAS("ip_set_hash:net,iface"); | 34 | MODULE_ALIAS("ip_set_hash:net,iface"); |
| 31 | 35 | ||
| 32 | /* Interface name rbtree */ | 36 | /* Interface name rbtree */ |
| @@ -140,7 +144,7 @@ struct hash_netiface4_elem_hashed { | |||
| 140 | u8 physdev; | 144 | u8 physdev; |
| 141 | u8 cidr; | 145 | u8 cidr; |
| 142 | u8 nomatch; | 146 | u8 nomatch; |
| 143 | u8 padding; | 147 | u8 elem; |
| 144 | }; | 148 | }; |
| 145 | 149 | ||
| 146 | #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) | 150 | #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) |
| @@ -151,7 +155,7 @@ struct hash_netiface4_elem { | |||
| 151 | u8 physdev; | 155 | u8 physdev; |
| 152 | u8 cidr; | 156 | u8 cidr; |
| 153 | u8 nomatch; | 157 | u8 nomatch; |
| 154 | u8 padding; | 158 | u8 elem; |
| 155 | const char *iface; | 159 | const char *iface; |
| 156 | }; | 160 | }; |
| 157 | 161 | ||
| @@ -161,7 +165,7 @@ struct hash_netiface4_telem { | |||
| 161 | u8 physdev; | 165 | u8 physdev; |
| 162 | u8 cidr; | 166 | u8 cidr; |
| 163 | u8 nomatch; | 167 | u8 nomatch; |
| 164 | u8 padding; | 168 | u8 elem; |
| 165 | const char *iface; | 169 | const char *iface; |
| 166 | unsigned long timeout; | 170 | unsigned long timeout; |
| 167 | }; | 171 | }; |
| @@ -181,18 +185,14 @@ hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, | |||
| 181 | static inline bool | 185 | static inline bool |
| 182 | hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem) | 186 | hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem) |
| 183 | { | 187 | { |
| 184 | return elem->cidr == 0; | 188 | return elem->elem == 0; |
| 185 | } | 189 | } |
| 186 | 190 | ||
| 187 | static inline void | 191 | static inline void |
| 188 | hash_netiface4_data_copy(struct hash_netiface4_elem *dst, | 192 | hash_netiface4_data_copy(struct hash_netiface4_elem *dst, |
| 189 | const struct hash_netiface4_elem *src) | 193 | const struct hash_netiface4_elem *src) |
| 190 | { | 194 | { |
| 191 | dst->ip = src->ip; | 195 | memcpy(dst, src, sizeof(*dst)); |
| 192 | dst->cidr = src->cidr; | ||
| 193 | dst->physdev = src->physdev; | ||
| 194 | dst->iface = src->iface; | ||
| 195 | dst->nomatch = src->nomatch; | ||
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static inline void | 198 | static inline void |
| @@ -201,10 +201,10 @@ hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) | |||
| 201 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; | 201 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | static inline bool | 204 | static inline int |
| 205 | hash_netiface4_data_match(const struct hash_netiface4_elem *elem) | 205 | hash_netiface4_data_match(const struct hash_netiface4_elem *elem) |
| 206 | { | 206 | { |
| 207 | return !elem->nomatch; | 207 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static inline void | 210 | static inline void |
| @@ -217,7 +217,7 @@ hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr) | |||
| 217 | static inline void | 217 | static inline void |
| 218 | hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem) | 218 | hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem) |
| 219 | { | 219 | { |
| 220 | elem->cidr = 0; | 220 | elem->elem = 0; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static bool | 223 | static bool |
| @@ -277,7 +277,7 @@ static inline void | |||
| 277 | hash_netiface4_data_next(struct ip_set_hash *h, | 277 | hash_netiface4_data_next(struct ip_set_hash *h, |
| 278 | const struct hash_netiface4_elem *d) | 278 | const struct hash_netiface4_elem *d) |
| 279 | { | 279 | { |
| 280 | h->next.ip = ntohl(d->ip); | 280 | h->next.ip = d->ip; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static int | 283 | static int |
| @@ -288,7 +288,8 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
| 288 | struct ip_set_hash *h = set->data; | 288 | struct ip_set_hash *h = set->data; |
| 289 | ipset_adtfn adtfn = set->variant->adt[adt]; | 289 | ipset_adtfn adtfn = set->variant->adt[adt]; |
| 290 | struct hash_netiface4_elem data = { | 290 | struct hash_netiface4_elem data = { |
| 291 | .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK | 291 | .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, |
| 292 | .elem = 1, | ||
| 292 | }; | 293 | }; |
| 293 | int ret; | 294 | int ret; |
| 294 | 295 | ||
| @@ -339,7 +340,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 339 | { | 340 | { |
| 340 | struct ip_set_hash *h = set->data; | 341 | struct ip_set_hash *h = set->data; |
| 341 | ipset_adtfn adtfn = set->variant->adt[adt]; | 342 | ipset_adtfn adtfn = set->variant->adt[adt]; |
| 342 | struct hash_netiface4_elem data = { .cidr = HOST_MASK }; | 343 | struct hash_netiface4_elem data = { .cidr = HOST_MASK, .elem = 1 }; |
| 343 | u32 ip = 0, ip_to, last; | 344 | u32 ip = 0, ip_to, last; |
| 344 | u32 timeout = h->timeout; | 345 | u32 timeout = h->timeout; |
| 345 | char iface[IFNAMSIZ]; | 346 | char iface[IFNAMSIZ]; |
| @@ -360,7 +361,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 360 | 361 | ||
| 361 | if (tb[IPSET_ATTR_CIDR]) { | 362 | if (tb[IPSET_ATTR_CIDR]) { |
| 362 | data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 363 | data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 363 | if (!data.cidr || data.cidr > HOST_MASK) | 364 | if (data.cidr > HOST_MASK) |
| 364 | return -IPSET_ERR_INVALID_CIDR; | 365 | return -IPSET_ERR_INVALID_CIDR; |
| 365 | } | 366 | } |
| 366 | 367 | ||
| @@ -389,7 +390,6 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 389 | if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) | 390 | if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) |
| 390 | flags |= (cadt_flags << 16); | 391 | flags |= (cadt_flags << 16); |
| 391 | } | 392 | } |
| 392 | |||
| 393 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { | 393 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { |
| 394 | data.ip = htonl(ip & ip_set_hostmask(data.cidr)); | 394 | data.ip = htonl(ip & ip_set_hostmask(data.cidr)); |
| 395 | ret = adtfn(set, &data, timeout, flags); | 395 | ret = adtfn(set, &data, timeout, flags); |
| @@ -409,7 +409,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | if (retried) | 411 | if (retried) |
| 412 | ip = h->next.ip; | 412 | ip = ntohl(h->next.ip); |
| 413 | while (!after(ip, ip_to)) { | 413 | while (!after(ip, ip_to)) { |
| 414 | data.ip = htonl(ip); | 414 | data.ip = htonl(ip); |
| 415 | last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); | 415 | last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); |
| @@ -442,7 +442,7 @@ struct hash_netiface6_elem_hashed { | |||
| 442 | u8 physdev; | 442 | u8 physdev; |
| 443 | u8 cidr; | 443 | u8 cidr; |
| 444 | u8 nomatch; | 444 | u8 nomatch; |
| 445 | u8 padding; | 445 | u8 elem; |
| 446 | }; | 446 | }; |
| 447 | 447 | ||
| 448 | #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) | 448 | #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) |
| @@ -452,7 +452,7 @@ struct hash_netiface6_elem { | |||
| 452 | u8 physdev; | 452 | u8 physdev; |
| 453 | u8 cidr; | 453 | u8 cidr; |
| 454 | u8 nomatch; | 454 | u8 nomatch; |
| 455 | u8 padding; | 455 | u8 elem; |
| 456 | const char *iface; | 456 | const char *iface; |
| 457 | }; | 457 | }; |
| 458 | 458 | ||
| @@ -461,7 +461,7 @@ struct hash_netiface6_telem { | |||
| 461 | u8 physdev; | 461 | u8 physdev; |
| 462 | u8 cidr; | 462 | u8 cidr; |
| 463 | u8 nomatch; | 463 | u8 nomatch; |
| 464 | u8 padding; | 464 | u8 elem; |
| 465 | const char *iface; | 465 | const char *iface; |
| 466 | unsigned long timeout; | 466 | unsigned long timeout; |
| 467 | }; | 467 | }; |
| @@ -481,7 +481,7 @@ hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, | |||
| 481 | static inline bool | 481 | static inline bool |
| 482 | hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem) | 482 | hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem) |
| 483 | { | 483 | { |
| 484 | return elem->cidr == 0; | 484 | return elem->elem == 0; |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | static inline void | 487 | static inline void |
| @@ -497,16 +497,16 @@ hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags) | |||
| 497 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; | 497 | dst->nomatch = flags & IPSET_FLAG_NOMATCH; |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | static inline bool | 500 | static inline int |
| 501 | hash_netiface6_data_match(const struct hash_netiface6_elem *elem) | 501 | hash_netiface6_data_match(const struct hash_netiface6_elem *elem) |
| 502 | { | 502 | { |
| 503 | return !elem->nomatch; | 503 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | static inline void | 506 | static inline void |
| 507 | hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) | 507 | hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) |
| 508 | { | 508 | { |
| 509 | elem->cidr = 0; | 509 | elem->elem = 0; |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | static inline void | 512 | static inline void |
| @@ -590,7 +590,8 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
| 590 | struct ip_set_hash *h = set->data; | 590 | struct ip_set_hash *h = set->data; |
| 591 | ipset_adtfn adtfn = set->variant->adt[adt]; | 591 | ipset_adtfn adtfn = set->variant->adt[adt]; |
| 592 | struct hash_netiface6_elem data = { | 592 | struct hash_netiface6_elem data = { |
| 593 | .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK | 593 | .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, |
| 594 | .elem = 1, | ||
| 594 | }; | 595 | }; |
| 595 | int ret; | 596 | int ret; |
| 596 | 597 | ||
| @@ -637,7 +638,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 637 | { | 638 | { |
| 638 | struct ip_set_hash *h = set->data; | 639 | struct ip_set_hash *h = set->data; |
| 639 | ipset_adtfn adtfn = set->variant->adt[adt]; | 640 | ipset_adtfn adtfn = set->variant->adt[adt]; |
| 640 | struct hash_netiface6_elem data = { .cidr = HOST_MASK }; | 641 | struct hash_netiface6_elem data = { .cidr = HOST_MASK, .elem = 1 }; |
| 641 | u32 timeout = h->timeout; | 642 | u32 timeout = h->timeout; |
| 642 | char iface[IFNAMSIZ]; | 643 | char iface[IFNAMSIZ]; |
| 643 | int ret; | 644 | int ret; |
| @@ -659,7 +660,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 659 | 660 | ||
| 660 | if (tb[IPSET_ATTR_CIDR]) | 661 | if (tb[IPSET_ATTR_CIDR]) |
| 661 | data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | 662 | data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); |
| 662 | if (!data.cidr || data.cidr > HOST_MASK) | 663 | if (data.cidr > HOST_MASK) |
| 663 | return -IPSET_ERR_INVALID_CIDR; | 664 | return -IPSET_ERR_INVALID_CIDR; |
| 664 | ip6_netmask(&data.ip, data.cidr); | 665 | ip6_netmask(&data.ip, data.cidr); |
| 665 | 666 | ||
| @@ -773,11 +774,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 773 | static struct ip_set_type hash_netiface_type __read_mostly = { | 774 | static struct ip_set_type hash_netiface_type __read_mostly = { |
| 774 | .name = "hash:net,iface", | 775 | .name = "hash:net,iface", |
| 775 | .protocol = IPSET_PROTOCOL, | 776 | .protocol = IPSET_PROTOCOL, |
| 776 | .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE, | 777 | .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE | |
| 778 | IPSET_TYPE_NOMATCH, | ||
| 777 | .dimension = IPSET_DIM_TWO, | 779 | .dimension = IPSET_DIM_TWO, |
| 778 | .family = NFPROTO_UNSPEC, | 780 | .family = NFPROTO_UNSPEC, |
| 779 | .revision_min = 0, | 781 | .revision_min = REVISION_MIN, |
| 780 | .revision_max = 1, /* nomatch flag support added */ | 782 | .revision_max = REVISION_MAX, |
| 781 | .create = hash_netiface_create, | 783 | .create = hash_netiface_create, |
| 782 | .create_policy = { | 784 | .create_policy = { |
| 783 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 785 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index fc3143a2d41b..7ef700de596c 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
| @@ -24,9 +24,14 @@ | |||
| 24 | #include <linux/netfilter/ipset/ip_set_getport.h> | 24 | #include <linux/netfilter/ipset/ip_set_getport.h> |
| 25 | #include <linux/netfilter/ipset/ip_set_hash.h> | 25 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 26 | 26 | ||
| 27 | #define REVISION_MIN 0 | ||
| 28 | /* 1 SCTP and UDPLITE support added */ | ||
| 29 | /* 2 Range as input support for IPv4 added */ | ||
| 30 | #define REVISION_MAX 3 /* nomatch flag support added */ | ||
| 31 | |||
| 27 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
| 28 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 29 | MODULE_DESCRIPTION("hash:net,port type of IP sets"); | 34 | IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX); |
| 30 | MODULE_ALIAS("ip_set_hash:net,port"); | 35 | MODULE_ALIAS("ip_set_hash:net,port"); |
| 31 | 36 | ||
| 32 | /* Type specific function prefix */ | 37 | /* Type specific function prefix */ |
| @@ -99,10 +104,10 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags) | |||
| 99 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); | 104 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); |
| 100 | } | 105 | } |
| 101 | 106 | ||
| 102 | static inline bool | 107 | static inline int |
| 103 | hash_netport4_data_match(const struct hash_netport4_elem *elem) | 108 | hash_netport4_data_match(const struct hash_netport4_elem *elem) |
| 104 | { | 109 | { |
| 105 | return !elem->nomatch; | 110 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 106 | } | 111 | } |
| 107 | 112 | ||
| 108 | static inline void | 113 | static inline void |
| @@ -171,8 +176,8 @@ static inline void | |||
| 171 | hash_netport4_data_next(struct ip_set_hash *h, | 176 | hash_netport4_data_next(struct ip_set_hash *h, |
| 172 | const struct hash_netport4_elem *d) | 177 | const struct hash_netport4_elem *d) |
| 173 | { | 178 | { |
| 174 | h->next.ip = ntohl(d->ip); | 179 | h->next.ip = d->ip; |
| 175 | h->next.port = ntohs(d->port); | 180 | h->next.port = d->port; |
| 176 | } | 181 | } |
| 177 | 182 | ||
| 178 | static int | 183 | static int |
| @@ -289,12 +294,13 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 289 | } | 294 | } |
| 290 | 295 | ||
| 291 | if (retried) | 296 | if (retried) |
| 292 | ip = h->next.ip; | 297 | ip = ntohl(h->next.ip); |
| 293 | while (!after(ip, ip_to)) { | 298 | while (!after(ip, ip_to)) { |
| 294 | data.ip = htonl(ip); | 299 | data.ip = htonl(ip); |
| 295 | last = ip_set_range_to_cidr(ip, ip_to, &cidr); | 300 | last = ip_set_range_to_cidr(ip, ip_to, &cidr); |
| 296 | data.cidr = cidr - 1; | 301 | data.cidr = cidr - 1; |
| 297 | p = retried && ip == h->next.ip ? h->next.port : port; | 302 | p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) |
| 303 | : port; | ||
| 298 | for (; p <= port_to; p++) { | 304 | for (; p <= port_to; p++) { |
| 299 | data.port = htons(p); | 305 | data.port = htons(p); |
| 300 | ret = adtfn(set, &data, timeout, flags); | 306 | ret = adtfn(set, &data, timeout, flags); |
| @@ -369,10 +375,10 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags) | |||
| 369 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); | 375 | dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); |
| 370 | } | 376 | } |
| 371 | 377 | ||
| 372 | static inline bool | 378 | static inline int |
| 373 | hash_netport6_data_match(const struct hash_netport6_elem *elem) | 379 | hash_netport6_data_match(const struct hash_netport6_elem *elem) |
| 374 | { | 380 | { |
| 375 | return !elem->nomatch; | 381 | return elem->nomatch ? -ENOTEMPTY : 1; |
| 376 | } | 382 | } |
| 377 | 383 | ||
| 378 | static inline void | 384 | static inline void |
| @@ -450,7 +456,7 @@ static inline void | |||
| 450 | hash_netport6_data_next(struct ip_set_hash *h, | 456 | hash_netport6_data_next(struct ip_set_hash *h, |
| 451 | const struct hash_netport6_elem *d) | 457 | const struct hash_netport6_elem *d) |
| 452 | { | 458 | { |
| 453 | h->next.port = ntohs(d->port); | 459 | h->next.port = d->port; |
| 454 | } | 460 | } |
| 455 | 461 | ||
| 456 | static int | 462 | static int |
| @@ -554,7 +560,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
| 554 | swap(port, port_to); | 560 | swap(port, port_to); |
| 555 | 561 | ||
| 556 | if (retried) | 562 | if (retried) |
| 557 | port = h->next.port; | 563 | port = ntohs(h->next.port); |
| 558 | for (; port <= port_to; port++) { | 564 | for (; port <= port_to; port++) { |
| 559 | data.port = htons(port); | 565 | data.port = htons(port); |
| 560 | ret = adtfn(set, &data, timeout, flags); | 566 | ret = adtfn(set, &data, timeout, flags); |
| @@ -644,13 +650,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
| 644 | static struct ip_set_type hash_netport_type __read_mostly = { | 650 | static struct ip_set_type hash_netport_type __read_mostly = { |
| 645 | .name = "hash:net,port", | 651 | .name = "hash:net,port", |
| 646 | .protocol = IPSET_PROTOCOL, | 652 | .protocol = IPSET_PROTOCOL, |
| 647 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, | 653 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH, |
| 648 | .dimension = IPSET_DIM_TWO, | 654 | .dimension = IPSET_DIM_TWO, |
| 649 | .family = NFPROTO_UNSPEC, | 655 | .family = NFPROTO_UNSPEC, |
| 650 | .revision_min = 0, | 656 | .revision_min = REVISION_MIN, |
| 651 | /* 1 SCTP and UDPLITE support added */ | 657 | .revision_max = REVISION_MAX, |
| 652 | /* 2, Range as input support for IPv4 added */ | ||
| 653 | .revision_max = 3, /* nomatch flag support added */ | ||
| 654 | .create = hash_netport_create, | 658 | .create = hash_netport_create, |
| 655 | .create_policy = { | 659 | .create_policy = { |
| 656 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 660 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 6cb1225765f9..8371c2bac2e4 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
| @@ -16,9 +16,12 @@ | |||
| 16 | #include <linux/netfilter/ipset/ip_set_timeout.h> | 16 | #include <linux/netfilter/ipset/ip_set_timeout.h> |
| 17 | #include <linux/netfilter/ipset/ip_set_list.h> | 17 | #include <linux/netfilter/ipset/ip_set_list.h> |
| 18 | 18 | ||
| 19 | #define REVISION_MIN 0 | ||
| 20 | #define REVISION_MAX 0 | ||
| 21 | |||
| 19 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
| 20 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 23 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
| 21 | MODULE_DESCRIPTION("list:set type of IP sets"); | 24 | IP_SET_MODULE_DESC("list:set", REVISION_MIN, REVISION_MAX); |
| 22 | MODULE_ALIAS("ip_set_list:set"); | 25 | MODULE_ALIAS("ip_set_list:set"); |
| 23 | 26 | ||
| 24 | /* Member elements without and with timeout */ | 27 | /* Member elements without and with timeout */ |
| @@ -579,8 +582,8 @@ static struct ip_set_type list_set_type __read_mostly = { | |||
| 579 | .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST, | 582 | .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST, |
| 580 | .dimension = IPSET_DIM_ONE, | 583 | .dimension = IPSET_DIM_ONE, |
| 581 | .family = NFPROTO_UNSPEC, | 584 | .family = NFPROTO_UNSPEC, |
| 582 | .revision_min = 0, | 585 | .revision_min = REVISION_MIN, |
| 583 | .revision_max = 0, | 586 | .revision_max = REVISION_MAX, |
| 584 | .create = list_set_create, | 587 | .create = list_set_create, |
| 585 | .create_policy = { | 588 | .create_policy = { |
| 586 | [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, | 589 | [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index dcb27910ab3c..0f241be28f9e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -1224,6 +1224,8 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), | |||
| 1224 | spin_lock_bh(&nf_conntrack_lock); | 1224 | spin_lock_bh(&nf_conntrack_lock); |
| 1225 | for (; *bucket < net->ct.htable_size; (*bucket)++) { | 1225 | for (; *bucket < net->ct.htable_size; (*bucket)++) { |
| 1226 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { | 1226 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { |
| 1227 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | ||
| 1228 | continue; | ||
| 1227 | ct = nf_ct_tuplehash_to_ctrack(h); | 1229 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 1228 | if (iter(ct, data)) | 1230 | if (iter(ct, data)) |
| 1229 | goto found; | 1231 | goto found; |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index f8cc26ad4456..1ce3befb7c8a 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
| @@ -396,6 +396,12 @@ static int help(struct sk_buff *skb, | |||
| 396 | 396 | ||
| 397 | /* Look up to see if we're just after a \n. */ | 397 | /* Look up to see if we're just after a \n. */ |
| 398 | if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { | 398 | if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { |
| 399 | /* We're picking up this, clear flags and let it continue */ | ||
| 400 | if (unlikely(ct_ftp_info->flags[dir] & NF_CT_FTP_SEQ_PICKUP)) { | ||
| 401 | ct_ftp_info->flags[dir] ^= NF_CT_FTP_SEQ_PICKUP; | ||
| 402 | goto skip_nl_seq; | ||
| 403 | } | ||
| 404 | |||
| 399 | /* Now if this ends in \n, update ftp info. */ | 405 | /* Now if this ends in \n, update ftp info. */ |
| 400 | pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", | 406 | pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", |
| 401 | ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", | 407 | ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", |
| @@ -406,6 +412,7 @@ static int help(struct sk_buff *skb, | |||
| 406 | goto out_update_nl; | 412 | goto out_update_nl; |
| 407 | } | 413 | } |
| 408 | 414 | ||
| 415 | skip_nl_seq: | ||
| 409 | /* Initialize IP/IPv6 addr to expected address (it's not mentioned | 416 | /* Initialize IP/IPv6 addr to expected address (it's not mentioned |
| 410 | in EPSV responses) */ | 417 | in EPSV responses) */ |
| 411 | cmd.l3num = nf_ct_l3num(ct); | 418 | cmd.l3num = nf_ct_l3num(ct); |
| @@ -512,6 +519,19 @@ out_update_nl: | |||
| 512 | return ret; | 519 | return ret; |
| 513 | } | 520 | } |
| 514 | 521 | ||
| 522 | static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct) | ||
| 523 | { | ||
| 524 | struct nf_ct_ftp_master *ftp = nfct_help_data(ct); | ||
| 525 | |||
| 526 | /* This conntrack has been injected from user-space, always pick up | ||
| 527 | * sequence tracking. Otherwise, the first FTP command after the | ||
| 528 | * failover breaks. | ||
| 529 | */ | ||
| 530 | ftp->flags[IP_CT_DIR_ORIGINAL] |= NF_CT_FTP_SEQ_PICKUP; | ||
| 531 | ftp->flags[IP_CT_DIR_REPLY] |= NF_CT_FTP_SEQ_PICKUP; | ||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 515 | static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; | 535 | static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; |
| 516 | 536 | ||
| 517 | static const struct nf_conntrack_expect_policy ftp_exp_policy = { | 537 | static const struct nf_conntrack_expect_policy ftp_exp_policy = { |
| @@ -561,6 +581,7 @@ static int __init nf_conntrack_ftp_init(void) | |||
| 561 | ftp[i][j].expect_policy = &ftp_exp_policy; | 581 | ftp[i][j].expect_policy = &ftp_exp_policy; |
| 562 | ftp[i][j].me = THIS_MODULE; | 582 | ftp[i][j].me = THIS_MODULE; |
| 563 | ftp[i][j].help = help; | 583 | ftp[i][j].help = help; |
| 584 | ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr; | ||
| 564 | if (ports[i] == FTP_PORT) | 585 | if (ports[i] == FTP_PORT) |
| 565 | sprintf(ftp[i][j].name, "ftp"); | 586 | sprintf(ftp[i][j].name, "ftp"); |
| 566 | else | 587 | else |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 2dcd080b8c4f..7bbfb3deea30 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -1238,7 +1238,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
| 1238 | if (help) { | 1238 | if (help) { |
| 1239 | if (help->helper == helper) { | 1239 | if (help->helper == helper) { |
| 1240 | /* update private helper data if allowed. */ | 1240 | /* update private helper data if allowed. */ |
| 1241 | if (helper->from_nlattr && helpinfo) | 1241 | if (helper->from_nlattr) |
| 1242 | helper->from_nlattr(helpinfo, ct); | 1242 | helper->from_nlattr(helpinfo, ct); |
| 1243 | return 0; | 1243 | return 0; |
| 1244 | } else | 1244 | } else |
| @@ -1467,7 +1467,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
| 1467 | goto err2; | 1467 | goto err2; |
| 1468 | } | 1468 | } |
| 1469 | /* set private helper data if allowed. */ | 1469 | /* set private helper data if allowed. */ |
| 1470 | if (helper->from_nlattr && helpinfo) | 1470 | if (helper->from_nlattr) |
| 1471 | helper->from_nlattr(helpinfo, ct); | 1471 | helper->from_nlattr(helpinfo, ct); |
| 1472 | 1472 | ||
| 1473 | /* not in hash table yet so not strictly necessary */ | 1473 | /* not in hash table yet so not strictly necessary */ |
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 1816ad381485..5f2f9109f461 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
| @@ -201,10 +201,8 @@ find_appropriate_src(struct net *net, u16 zone, | |||
| 201 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 201 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
| 202 | result->dst = tuple->dst; | 202 | result->dst = tuple->dst; |
| 203 | 203 | ||
| 204 | if (in_range(l3proto, l4proto, result, range)) { | 204 | if (in_range(l3proto, l4proto, result, range)) |
| 205 | rcu_read_unlock(); | ||
| 206 | return 1; | 205 | return 1; |
| 207 | } | ||
| 208 | } | 206 | } |
| 209 | } | 207 | } |
| 210 | return 0; | 208 | return 0; |
| @@ -481,6 +479,8 @@ static int nf_nat_proto_clean(struct nf_conn *i, void *data) | |||
| 481 | 479 | ||
| 482 | if (!nat) | 480 | if (!nat) |
| 483 | return 0; | 481 | return 0; |
| 482 | if (!(i->status & IPS_SRC_NAT_DONE)) | ||
| 483 | return 0; | ||
| 484 | if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || | 484 | if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || |
| 485 | (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) | 485 | (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) |
| 486 | return 0; | 486 | return 0; |
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 3678073360a3..945950a8b1f1 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c | |||
| @@ -85,6 +85,9 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) | |||
| 85 | { | 85 | { |
| 86 | const struct nf_conn_help *help = nfct_help(ct); | 86 | const struct nf_conn_help *help = nfct_help(ct); |
| 87 | 87 | ||
| 88 | if (attr == NULL) | ||
| 89 | return -EINVAL; | ||
| 90 | |||
| 88 | if (help->helper->data_len == 0) | 91 | if (help->helper->data_len == 0) |
| 89 | return -EINVAL; | 92 | return -EINVAL; |
| 90 | 93 | ||
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 43de3a03ee76..e12d44e75b21 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
| @@ -225,7 +225,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
| 225 | { | 225 | { |
| 226 | sk_buff_data_t old_tail; | 226 | sk_buff_data_t old_tail; |
| 227 | size_t size; | 227 | size_t size; |
| 228 | size_t data_len = 0; | 228 | size_t data_len = 0, cap_len = 0; |
| 229 | struct sk_buff *skb; | 229 | struct sk_buff *skb; |
| 230 | struct nlattr *nla; | 230 | struct nlattr *nla; |
| 231 | struct nfqnl_msg_packet_hdr *pmsg; | 231 | struct nfqnl_msg_packet_hdr *pmsg; |
| @@ -247,7 +247,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
| 247 | #endif | 247 | #endif |
| 248 | + nla_total_size(sizeof(u_int32_t)) /* mark */ | 248 | + nla_total_size(sizeof(u_int32_t)) /* mark */ |
| 249 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) | 249 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) |
| 250 | + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); | 250 | + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp) |
| 251 | + nla_total_size(sizeof(u_int32_t))); /* cap_len */ | ||
| 251 | 252 | ||
| 252 | outdev = entry->outdev; | 253 | outdev = entry->outdev; |
| 253 | 254 | ||
| @@ -266,6 +267,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
| 266 | data_len = entskb->len; | 267 | data_len = entskb->len; |
| 267 | 268 | ||
| 268 | size += nla_total_size(data_len); | 269 | size += nla_total_size(data_len); |
| 270 | cap_len = entskb->len; | ||
| 269 | break; | 271 | break; |
| 270 | } | 272 | } |
| 271 | 273 | ||
| @@ -402,6 +404,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
| 402 | if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) | 404 | if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) |
| 403 | goto nla_put_failure; | 405 | goto nla_put_failure; |
| 404 | 406 | ||
| 407 | if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) | ||
| 408 | goto nla_put_failure; | ||
| 409 | |||
| 405 | nlh->nlmsg_len = skb->tail - old_tail; | 410 | nlh->nlmsg_len = skb->tail - old_tail; |
| 406 | return skb; | 411 | return skb; |
| 407 | 412 | ||
| @@ -526,9 +531,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue, | |||
| 526 | 531 | ||
| 527 | case NFQNL_COPY_PACKET: | 532 | case NFQNL_COPY_PACKET: |
| 528 | queue->copy_mode = mode; | 533 | queue->copy_mode = mode; |
| 529 | /* we're using struct nlattr which has 16bit nla_len */ | 534 | /* We're using struct nlattr which has 16bit nla_len. Note that |
| 530 | if (range > 0xffff) | 535 | * nla_len includes the header length. Thus, the maximum packet |
| 531 | queue->copy_range = 0xffff; | 536 | * length that we support is 65531 bytes. We send truncated |
| 537 | * packets if the specified length is larger than that. | ||
| 538 | */ | ||
| 539 | if (range > 0xffff - NLA_HDRLEN) | ||
| 540 | queue->copy_range = 0xffff - NLA_HDRLEN; | ||
| 532 | else | 541 | else |
| 533 | queue->copy_range = range; | 542 | queue->copy_range = range; |
| 534 | break; | 543 | break; |
diff --git a/net/netfilter/xt_NETMAP.c b/net/netfilter/xt_NETMAP.c new file mode 100644 index 000000000000..b253e07cb1c5 --- /dev/null +++ b/net/netfilter/xt_NETMAP.c | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* | ||
| 2 | * (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk> | ||
| 3 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/ip.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/netdevice.h> | ||
| 14 | #include <linux/ipv6.h> | ||
| 15 | #include <linux/netfilter.h> | ||
| 16 | #include <linux/netfilter_ipv4.h> | ||
| 17 | #include <linux/netfilter_ipv6.h> | ||
| 18 | #include <linux/netfilter/x_tables.h> | ||
| 19 | #include <net/netfilter/nf_nat.h> | ||
| 20 | |||
| 21 | static unsigned int | ||
| 22 | netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 23 | { | ||
| 24 | const struct nf_nat_range *range = par->targinfo; | ||
| 25 | struct nf_nat_range newrange; | ||
| 26 | struct nf_conn *ct; | ||
| 27 | enum ip_conntrack_info ctinfo; | ||
| 28 | union nf_inet_addr new_addr, netmask; | ||
| 29 | unsigned int i; | ||
| 30 | |||
| 31 | ct = nf_ct_get(skb, &ctinfo); | ||
| 32 | for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++) | ||
| 33 | netmask.ip6[i] = ~(range->min_addr.ip6[i] ^ | ||
| 34 | range->max_addr.ip6[i]); | ||
| 35 | |||
| 36 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
| 37 | par->hooknum == NF_INET_LOCAL_OUT) | ||
| 38 | new_addr.in6 = ipv6_hdr(skb)->daddr; | ||
| 39 | else | ||
| 40 | new_addr.in6 = ipv6_hdr(skb)->saddr; | ||
| 41 | |||
| 42 | for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) { | ||
| 43 | new_addr.ip6[i] &= ~netmask.ip6[i]; | ||
| 44 | new_addr.ip6[i] |= range->min_addr.ip6[i] & | ||
| 45 | netmask.ip6[i]; | ||
| 46 | } | ||
| 47 | |||
| 48 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
| 49 | newrange.min_addr = new_addr; | ||
| 50 | newrange.max_addr = new_addr; | ||
| 51 | newrange.min_proto = range->min_proto; | ||
| 52 | newrange.max_proto = range->max_proto; | ||
| 53 | |||
| 54 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | ||
| 55 | } | ||
| 56 | |||
| 57 | static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) | ||
| 58 | { | ||
| 59 | const struct nf_nat_range *range = par->targinfo; | ||
| 60 | |||
| 61 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) | ||
| 62 | return -EINVAL; | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static unsigned int | ||
| 67 | netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 68 | { | ||
| 69 | struct nf_conn *ct; | ||
| 70 | enum ip_conntrack_info ctinfo; | ||
| 71 | __be32 new_ip, netmask; | ||
| 72 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 73 | struct nf_nat_range newrange; | ||
| 74 | |||
| 75 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | ||
| 76 | par->hooknum == NF_INET_POST_ROUTING || | ||
| 77 | par->hooknum == NF_INET_LOCAL_OUT || | ||
| 78 | par->hooknum == NF_INET_LOCAL_IN); | ||
| 79 | ct = nf_ct_get(skb, &ctinfo); | ||
| 80 | |||
| 81 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | ||
| 82 | |||
| 83 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
| 84 | par->hooknum == NF_INET_LOCAL_OUT) | ||
| 85 | new_ip = ip_hdr(skb)->daddr & ~netmask; | ||
| 86 | else | ||
| 87 | new_ip = ip_hdr(skb)->saddr & ~netmask; | ||
| 88 | new_ip |= mr->range[0].min_ip & netmask; | ||
| 89 | |||
| 90 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); | ||
| 91 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); | ||
| 92 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; | ||
| 93 | newrange.min_addr.ip = new_ip; | ||
| 94 | newrange.max_addr.ip = new_ip; | ||
| 95 | newrange.min_proto = mr->range[0].min; | ||
| 96 | newrange.max_proto = mr->range[0].max; | ||
| 97 | |||
| 98 | /* Hand modified range to generic setup. */ | ||
| 99 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | ||
| 100 | } | ||
| 101 | |||
| 102 | static int netmap_tg4_check(const struct xt_tgchk_param *par) | ||
| 103 | { | ||
| 104 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 105 | |||
| 106 | if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) { | ||
| 107 | pr_debug("bad MAP_IPS.\n"); | ||
| 108 | return -EINVAL; | ||
| 109 | } | ||
| 110 | if (mr->rangesize != 1) { | ||
| 111 | pr_debug("bad rangesize %u.\n", mr->rangesize); | ||
| 112 | return -EINVAL; | ||
| 113 | } | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static struct xt_target netmap_tg_reg[] __read_mostly = { | ||
| 118 | { | ||
| 119 | .name = "NETMAP", | ||
| 120 | .family = NFPROTO_IPV6, | ||
| 121 | .revision = 0, | ||
| 122 | .target = netmap_tg6, | ||
| 123 | .targetsize = sizeof(struct nf_nat_range), | ||
| 124 | .table = "nat", | ||
| 125 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 126 | (1 << NF_INET_POST_ROUTING) | | ||
| 127 | (1 << NF_INET_LOCAL_OUT) | | ||
| 128 | (1 << NF_INET_LOCAL_IN), | ||
| 129 | .checkentry = netmap_tg6_checkentry, | ||
| 130 | .me = THIS_MODULE, | ||
| 131 | }, | ||
| 132 | { | ||
| 133 | .name = "NETMAP", | ||
| 134 | .family = NFPROTO_IPV4, | ||
| 135 | .revision = 0, | ||
| 136 | .target = netmap_tg4, | ||
| 137 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
| 138 | .table = "nat", | ||
| 139 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 140 | (1 << NF_INET_POST_ROUTING) | | ||
| 141 | (1 << NF_INET_LOCAL_OUT) | | ||
| 142 | (1 << NF_INET_LOCAL_IN), | ||
| 143 | .checkentry = netmap_tg4_check, | ||
| 144 | .me = THIS_MODULE, | ||
| 145 | }, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int __init netmap_tg_init(void) | ||
| 149 | { | ||
| 150 | return xt_register_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg)); | ||
| 151 | } | ||
| 152 | |||
| 153 | static void netmap_tg_exit(void) | ||
| 154 | { | ||
| 155 | xt_unregister_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg)); | ||
| 156 | } | ||
| 157 | |||
| 158 | module_init(netmap_tg_init); | ||
| 159 | module_exit(netmap_tg_exit); | ||
| 160 | |||
| 161 | MODULE_LICENSE("GPL"); | ||
| 162 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets"); | ||
| 163 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 164 | MODULE_ALIAS("ip6t_NETMAP"); | ||
| 165 | MODULE_ALIAS("ipt_NETMAP"); | ||
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c new file mode 100644 index 000000000000..22a10309297c --- /dev/null +++ b/net/netfilter/xt_REDIRECT.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * (C) 1999-2001 Paul `Rusty' Russell | ||
| 3 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
| 4 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 | ||
| 11 | * NAT funded by Astaro. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/if.h> | ||
| 15 | #include <linux/inetdevice.h> | ||
| 16 | #include <linux/ip.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/netdevice.h> | ||
| 20 | #include <linux/netfilter.h> | ||
| 21 | #include <linux/types.h> | ||
| 22 | #include <linux/netfilter_ipv4.h> | ||
| 23 | #include <linux/netfilter_ipv6.h> | ||
| 24 | #include <linux/netfilter/x_tables.h> | ||
| 25 | #include <net/addrconf.h> | ||
| 26 | #include <net/checksum.h> | ||
| 27 | #include <net/protocol.h> | ||
| 28 | #include <net/netfilter/nf_nat.h> | ||
| 29 | |||
| 30 | static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; | ||
| 31 | |||
| 32 | static unsigned int | ||
| 33 | redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 34 | { | ||
| 35 | const struct nf_nat_range *range = par->targinfo; | ||
| 36 | struct nf_nat_range newrange; | ||
| 37 | struct in6_addr newdst; | ||
| 38 | enum ip_conntrack_info ctinfo; | ||
| 39 | struct nf_conn *ct; | ||
| 40 | |||
| 41 | ct = nf_ct_get(skb, &ctinfo); | ||
| 42 | if (par->hooknum == NF_INET_LOCAL_OUT) | ||
| 43 | newdst = loopback_addr; | ||
| 44 | else { | ||
| 45 | struct inet6_dev *idev; | ||
| 46 | struct inet6_ifaddr *ifa; | ||
| 47 | bool addr = false; | ||
| 48 | |||
| 49 | rcu_read_lock(); | ||
| 50 | idev = __in6_dev_get(skb->dev); | ||
| 51 | if (idev != NULL) { | ||
| 52 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
| 53 | newdst = ifa->addr; | ||
| 54 | addr = true; | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | rcu_read_unlock(); | ||
| 59 | |||
| 60 | if (!addr) | ||
| 61 | return NF_DROP; | ||
| 62 | } | ||
| 63 | |||
| 64 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
| 65 | newrange.min_addr.in6 = newdst; | ||
| 66 | newrange.max_addr.in6 = newdst; | ||
| 67 | newrange.min_proto = range->min_proto; | ||
| 68 | newrange.max_proto = range->max_proto; | ||
| 69 | |||
| 70 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
| 71 | } | ||
| 72 | |||
| 73 | static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) | ||
| 74 | { | ||
| 75 | const struct nf_nat_range *range = par->targinfo; | ||
| 76 | |||
| 77 | if (range->flags & NF_NAT_RANGE_MAP_IPS) | ||
| 78 | return -EINVAL; | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* FIXME: Take multiple ranges --RR */ | ||
| 83 | static int redirect_tg4_check(const struct xt_tgchk_param *par) | ||
| 84 | { | ||
| 85 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 86 | |||
| 87 | if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { | ||
| 88 | pr_debug("bad MAP_IPS.\n"); | ||
| 89 | return -EINVAL; | ||
| 90 | } | ||
| 91 | if (mr->rangesize != 1) { | ||
| 92 | pr_debug("bad rangesize %u.\n", mr->rangesize); | ||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static unsigned int | ||
| 99 | redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 100 | { | ||
| 101 | struct nf_conn *ct; | ||
| 102 | enum ip_conntrack_info ctinfo; | ||
| 103 | __be32 newdst; | ||
| 104 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
| 105 | struct nf_nat_range newrange; | ||
| 106 | |||
| 107 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | ||
| 108 | par->hooknum == NF_INET_LOCAL_OUT); | ||
| 109 | |||
| 110 | ct = nf_ct_get(skb, &ctinfo); | ||
| 111 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | ||
| 112 | |||
| 113 | /* Local packets: make them go to loopback */ | ||
| 114 | if (par->hooknum == NF_INET_LOCAL_OUT) | ||
| 115 | newdst = htonl(0x7F000001); | ||
| 116 | else { | ||
| 117 | struct in_device *indev; | ||
| 118 | struct in_ifaddr *ifa; | ||
| 119 | |||
| 120 | newdst = 0; | ||
| 121 | |||
| 122 | rcu_read_lock(); | ||
| 123 | indev = __in_dev_get_rcu(skb->dev); | ||
| 124 | if (indev && (ifa = indev->ifa_list)) | ||
| 125 | newdst = ifa->ifa_local; | ||
| 126 | rcu_read_unlock(); | ||
| 127 | |||
| 128 | if (!newdst) | ||
| 129 | return NF_DROP; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Transfer from original range. */ | ||
| 133 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); | ||
| 134 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); | ||
| 135 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; | ||
| 136 | newrange.min_addr.ip = newdst; | ||
| 137 | newrange.max_addr.ip = newdst; | ||
| 138 | newrange.min_proto = mr->range[0].min; | ||
| 139 | newrange.max_proto = mr->range[0].max; | ||
| 140 | |||
| 141 | /* Hand modified range to generic setup. */ | ||
| 142 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
| 143 | } | ||
| 144 | |||
| 145 | static struct xt_target redirect_tg_reg[] __read_mostly = { | ||
| 146 | { | ||
| 147 | .name = "REDIRECT", | ||
| 148 | .family = NFPROTO_IPV6, | ||
| 149 | .revision = 0, | ||
| 150 | .table = "nat", | ||
| 151 | .checkentry = redirect_tg6_checkentry, | ||
| 152 | .target = redirect_tg6, | ||
| 153 | .targetsize = sizeof(struct nf_nat_range), | ||
| 154 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 155 | (1 << NF_INET_LOCAL_OUT), | ||
| 156 | .me = THIS_MODULE, | ||
| 157 | }, | ||
| 158 | { | ||
| 159 | .name = "REDIRECT", | ||
| 160 | .family = NFPROTO_IPV4, | ||
| 161 | .revision = 0, | ||
| 162 | .table = "nat", | ||
| 163 | .target = redirect_tg4, | ||
| 164 | .checkentry = redirect_tg4_check, | ||
| 165 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
| 166 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
| 167 | (1 << NF_INET_LOCAL_OUT), | ||
| 168 | .me = THIS_MODULE, | ||
| 169 | }, | ||
| 170 | }; | ||
| 171 | |||
| 172 | static int __init redirect_tg_init(void) | ||
| 173 | { | ||
| 174 | return xt_register_targets(redirect_tg_reg, | ||
| 175 | ARRAY_SIZE(redirect_tg_reg)); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void __exit redirect_tg_exit(void) | ||
| 179 | { | ||
| 180 | xt_unregister_targets(redirect_tg_reg, ARRAY_SIZE(redirect_tg_reg)); | ||
| 181 | } | ||
| 182 | |||
| 183 | module_init(redirect_tg_init); | ||
| 184 | module_exit(redirect_tg_exit); | ||
| 185 | |||
| 186 | MODULE_LICENSE("GPL"); | ||
| 187 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 188 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | ||
| 189 | MODULE_ALIAS("ip6t_REDIRECT"); | ||
| 190 | MODULE_ALIAS("ipt_REDIRECT"); | ||
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index c6f7db720d84..865a9e54f3ad 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c | |||
| @@ -356,6 +356,27 @@ static struct xt_match set_matches[] __read_mostly = { | |||
| 356 | .destroy = set_match_v1_destroy, | 356 | .destroy = set_match_v1_destroy, |
| 357 | .me = THIS_MODULE | 357 | .me = THIS_MODULE |
| 358 | }, | 358 | }, |
| 359 | /* --return-nomatch flag support */ | ||
| 360 | { | ||
| 361 | .name = "set", | ||
| 362 | .family = NFPROTO_IPV4, | ||
| 363 | .revision = 2, | ||
| 364 | .match = set_match_v1, | ||
| 365 | .matchsize = sizeof(struct xt_set_info_match_v1), | ||
| 366 | .checkentry = set_match_v1_checkentry, | ||
| 367 | .destroy = set_match_v1_destroy, | ||
| 368 | .me = THIS_MODULE | ||
| 369 | }, | ||
| 370 | { | ||
| 371 | .name = "set", | ||
| 372 | .family = NFPROTO_IPV6, | ||
| 373 | .revision = 2, | ||
| 374 | .match = set_match_v1, | ||
| 375 | .matchsize = sizeof(struct xt_set_info_match_v1), | ||
| 376 | .checkentry = set_match_v1_checkentry, | ||
| 377 | .destroy = set_match_v1_destroy, | ||
| 378 | .me = THIS_MODULE | ||
| 379 | }, | ||
| 359 | }; | 380 | }; |
| 360 | 381 | ||
| 361 | static struct xt_target set_targets[] __read_mostly = { | 382 | static struct xt_target set_targets[] __read_mostly = { |
| @@ -389,6 +410,7 @@ static struct xt_target set_targets[] __read_mostly = { | |||
| 389 | .destroy = set_target_v1_destroy, | 410 | .destroy = set_target_v1_destroy, |
| 390 | .me = THIS_MODULE | 411 | .me = THIS_MODULE |
| 391 | }, | 412 | }, |
| 413 | /* --timeout and --exist flags support */ | ||
| 392 | { | 414 | { |
| 393 | .name = "SET", | 415 | .name = "SET", |
| 394 | .revision = 2, | 416 | .revision = 2, |
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index c48975ff8ea2..0ae55a36f492 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c | |||
| @@ -42,6 +42,7 @@ static const u_int16_t days_since_leapyear[] = { | |||
| 42 | */ | 42 | */ |
| 43 | enum { | 43 | enum { |
| 44 | DSE_FIRST = 2039, | 44 | DSE_FIRST = 2039, |
| 45 | SECONDS_PER_DAY = 86400, | ||
| 45 | }; | 46 | }; |
| 46 | static const u_int16_t days_since_epoch[] = { | 47 | static const u_int16_t days_since_epoch[] = { |
| 47 | /* 2039 - 2030 */ | 48 | /* 2039 - 2030 */ |
| @@ -78,7 +79,7 @@ static inline unsigned int localtime_1(struct xtm *r, time_t time) | |||
| 78 | unsigned int v, w; | 79 | unsigned int v, w; |
| 79 | 80 | ||
| 80 | /* Each day has 86400s, so finding the hour/minute is actually easy. */ | 81 | /* Each day has 86400s, so finding the hour/minute is actually easy. */ |
| 81 | v = time % 86400; | 82 | v = time % SECONDS_PER_DAY; |
| 82 | r->second = v % 60; | 83 | r->second = v % 60; |
| 83 | w = v / 60; | 84 | w = v / 60; |
| 84 | r->minute = w % 60; | 85 | r->minute = w % 60; |
| @@ -199,6 +200,18 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 199 | if (packet_time < info->daytime_start && | 200 | if (packet_time < info->daytime_start && |
| 200 | packet_time > info->daytime_stop) | 201 | packet_time > info->daytime_stop) |
| 201 | return false; | 202 | return false; |
| 203 | |||
| 204 | /** if user asked to ignore 'next day', then e.g. | ||
| 205 | * '1 PM Wed, August 1st' should be treated | ||
| 206 | * like 'Tue 1 PM July 31st'. | ||
| 207 | * | ||
| 208 | * This also causes | ||
| 209 | * 'Monday, "23:00 to 01:00", to match for 2 hours, starting | ||
| 210 | * Monday 23:00 to Tuesday 01:00. | ||
| 211 | */ | ||
| 212 | if ((info->flags & XT_TIME_CONTIGUOUS) && | ||
| 213 | packet_time <= info->daytime_stop) | ||
| 214 | stamp -= SECONDS_PER_DAY; | ||
| 202 | } | 215 | } |
| 203 | 216 | ||
| 204 | localtime_2(¤t_time, stamp); | 217 | localtime_2(¤t_time, stamp); |
| @@ -227,6 +240,15 @@ static int time_mt_check(const struct xt_mtchk_param *par) | |||
| 227 | return -EDOM; | 240 | return -EDOM; |
| 228 | } | 241 | } |
| 229 | 242 | ||
| 243 | if (info->flags & ~XT_TIME_ALL_FLAGS) { | ||
| 244 | pr_info("unknown flags 0x%x\n", info->flags & ~XT_TIME_ALL_FLAGS); | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | |||
| 248 | if ((info->flags & XT_TIME_CONTIGUOUS) && | ||
| 249 | info->daytime_start < info->daytime_stop) | ||
| 250 | return -EINVAL; | ||
| 251 | |||
| 230 | return 0; | 252 | return 0; |
| 231 | } | 253 | } |
| 232 | 254 | ||
