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 | ||