aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/ipset/ip_set.h15
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h106
-rw-r--r--include/linux/netfilter/nf_conntrack_ftp.h6
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h1
-rw-r--r--include/linux/netfilter/xt_time.h5
-rw-r--r--net/ipv4/netfilter/Kconfig23
-rw-r--r--net/ipv4/netfilter/Makefile2
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c101
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c113
-rw-r--r--net/ipv6/netfilter/Kconfig91
-rw-r--r--net/ipv6/netfilter/Makefile2
-rw-r--r--net/ipv6/netfilter/ip6t_NETMAP.c94
-rw-r--r--net/ipv6/netfilter/ip6t_REDIRECT.c98
-rw-r--r--net/netfilter/Kconfig21
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c19
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c18
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c9
-rw-r--r--net/netfilter/ipset/ip_set_core.c15
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c15
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c24
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c24
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c47
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c25
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c66
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c36
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c9
-rw-r--r--net/netfilter/nf_conntrack_core.c2
-rw-r--r--net/netfilter/nf_conntrack_ftp.c21
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
-rw-r--r--net/netfilter/nf_nat_core.c6
-rw-r--r--net/netfilter/nfnetlink_cthelper.c3
-rw-r--r--net/netfilter/nfnetlink_queue_core.c19
-rw-r--r--net/netfilter/xt_NETMAP.c165
-rw-r--r--net/netfilter/xt_REDIRECT.c190
-rw-r--r--net/netfilter/xt_set.c22
-rw-r--r--net/netfilter/xt_time.c24
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 2edc64cab73..528697b3c15 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 */
213enum ip_set_feature { 221enum 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
427static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, const struct in6_addr *ipaddrptr) 437static 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 b114d35aea5..ef9acd3c845 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 */
143static void 148static void
144add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) 149add_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
165static void 174static void
166del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) 175del_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 */
204static size_t 213static size_t
205ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask) 214ahash_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++;
484out: 490out:
@@ -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
692static int 698static int
693type_pf_kadt(struct ip_set *set, const struct sk_buff * skb, 699type_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);
696static int 702static 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 */
785static void 791static void
786type_pf_expire(struct ip_set_hash *h) 792type_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++;
958out: 964out:
@@ -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 28f18df3652..8faf3f792d1 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 */
23struct nf_ct_ftp_master { 25struct 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
30struct nf_conntrack_expect; 34struct nf_conntrack_expect;
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index 3b1c1360aed..70ec8c2bc11 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 7c37fac576c..09588601939 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 131e53702e7..d8d6f2a5bf1 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -172,23 +172,20 @@ config IP_NF_TARGET_MASQUERADE
172config IP_NF_TARGET_NETMAP 172config 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
182config IP_NF_TARGET_REDIRECT 181config 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
193endif 190endif
194 191
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index b7dd1898723..007b128eecc 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -45,8 +45,6 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o
45obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 45obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
46obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 46obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
47obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 47obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
48obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
49obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
50obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 48obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
51obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 49obj-$(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 85028dc0425..00000000000
--- 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
21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
23MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
24
25static 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
40static unsigned int
41netmap_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
76static 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
90static int __init netmap_tg_init(void)
91{
92 return xt_register_target(&netmap_tg_reg);
93}
94
95static void __exit netmap_tg_exit(void)
96{
97 xt_unregister_target(&netmap_tg_reg);
98}
99
100module_init(netmap_tg_init);
101module_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 11407d7d247..00000000000
--- 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
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
26MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
27
28/* FIXME: Take multiple ranges --RR */
29static 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
44static unsigned int
45redirect_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
91static 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
102static int __init redirect_tg_init(void)
103{
104 return xt_register_target(&redirect_tg_reg);
105}
106
107static void __exit redirect_tg_exit(void)
108{
109 xt_unregister_target(&redirect_tg_reg);
110}
111
112module_init(redirect_tg_init);
113module_exit(redirect_tg_exit);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 3b73254d7bf..c72532a60d8 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
28config 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
40config IP6_NF_IPTABLES 28config 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
147config 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
159config 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
169config 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
180config 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
189config IP6_NF_FILTER 135config 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
187config 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
199if NF_NAT_IPV6
200
201config 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
212config 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
220endif # NF_NAT_IPV6
221
241endif # IP6_NF_IPTABLES 222endif # IP6_NF_IPTABLES
242 223
243endmenu 224endmenu
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 5752132ca15..2d11fcc2cf3 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
37obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o 37obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
38obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o
39obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o 38obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o
40obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o
41obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o 39obj-$(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 4f3bf360e50..00000000000
--- 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
20static unsigned int
21netmap_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
56static 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
65static 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
79static int __init netmap_tg6_init(void)
80{
81 return xt_register_target(&netmap_tg6_reg);
82}
83
84static void netmap_tg6_exit(void)
85{
86 xt_unregister_target(&netmap_tg6_reg);
87}
88
89module_init(netmap_tg6_init);
90module_exit(netmap_tg6_exit);
91
92MODULE_LICENSE("GPL");
93MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets");
94MODULE_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 60497a3c600..00000000000
--- 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
20static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
21
22static unsigned int
23redirect_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
63static 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
72static 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
83static int __init redirect_tg6_init(void)
84{
85 return xt_register_target(&redirect_tg6_reg);
86}
87
88static void __exit redirect_tg6_exit(void)
89{
90 xt_unregister_target(&redirect_tg6_reg);
91}
92
93module_init(redirect_tg6_init);
94module_exit(redirect_tg6_exit);
95
96MODULE_LICENSE("GPL");
97MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
98MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3f4b3b4a776..fefa514b991 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
651config 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
651config NETFILTER_XT_TARGET_NFLOG 661config 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
693config 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
683config NETFILTER_XT_TARGET_TEE 704config 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 0baa3f104fc..32596978df1 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -83,9 +83,11 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
83obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o 83obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
84obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o 84obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
85obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o 85obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
86obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
86obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 87obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
87obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 88obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
88obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o 89obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
90obj-$(CONFIG_NETFILTER_XT_TARGET_REDIRECT) += xt_REDIRECT.o
89obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o 91obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
90obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o 92obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
91obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o 93obj-$(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 7e1b061aeeb..4a92fd47bd4 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
30MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
32MODULE_DESCRIPTION("bitmap:ip type of IP sets"); 35IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX);
33MODULE_ALIAS("ip_set_bitmap:ip"); 36MODULE_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
454bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 457bitmap_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 d7eaf10edb6..0f92dc24cb8 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
29MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
31MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets"); 34IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX);
32MODULE_ALIAS("ip_set_bitmap:ip,mac"); 35MODULE_ALIAS("ip_set_bitmap:ip,mac");
33 36
34enum { 37enum {
@@ -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
557bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], 560bitmap_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 b9f1fce7053..e6b2db76f4c 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
25MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
27MODULE_DESCRIPTION("bitmap:port type of IP sets"); 30IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX);
28MODULE_ALIAS("ip_set_bitmap:port"); 31MODULE_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 ad39ef40685..778465f217f 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 a68dbd4f1e4..ec3dba5dcd6 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
27MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 31MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:ip type of IP sets"); 32IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX);
30MODULE_ALIAS("ip_set_hash:ip"); 33MODULE_ALIAS("ip_set_hash:ip");
31 34
32/* Type specific function prefix */ 35/* Type specific function prefix */
@@ -114,7 +117,7 @@ nla_put_failure:
114static inline void 117static inline void
115hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d) 118hash_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
120static int 123static 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 92722bb82ee..0171f7502fa 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
28MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port type of IP sets"); 33IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX);
31MODULE_ALIAS("ip_set_hash:ip,port"); 34MODULE_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
130hash_ipport4_data_next(struct ip_set_hash *h, 133hash_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
137static int 140static 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
349hash_ipport6_data_next(struct ip_set_hash *h, 353hash_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
355static int 359static 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 0637ce096de..6344ef551ec 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
28MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets"); 33IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX);
31MODULE_ALIAS("ip_set_hash:ip,port,ip"); 34MODULE_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
133hash_ipportip4_data_next(struct ip_set_hash *h, 136hash_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
140static int 143static 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
362hash_ipportip6_data_next(struct ip_set_hash *h, 366hash_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
368static int 372static 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 1ce21ca976e..cb71f9a774e 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
28MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port,net type of IP sets"); 35IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX);
31MODULE_ALIAS("ip_set_hash:ip,port,net"); 36MODULE_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
102static inline bool 107static inline int
103hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) 108hash_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
108static inline void 113static inline void
@@ -173,9 +178,9 @@ static inline void
173hash_ipportnet4_data_next(struct ip_set_hash *h, 178hash_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
181static int 186static 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
406static inline bool 414static inline int
407hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) 415hash_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
412static inline void 420static inline void
@@ -486,7 +494,7 @@ static inline void
486hash_ipportnet6_data_next(struct ip_set_hash *h, 494hash_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
492static int 500static 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)
689static struct ip_set_type hash_ipportnet_type __read_mostly = { 697static 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 c57a6a09906..29e94b981f3 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
26MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
27MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 31MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
28MODULE_DESCRIPTION("hash:net type of IP sets"); 32IP_SET_MODULE_DESC("hash:net", REVISION_MIN, REVISION_MAX);
29MODULE_ALIAS("ip_set_hash:net"); 33MODULE_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
89static inline bool 93static inline int
90hash_net4_data_match(const struct hash_net4_elem *elem) 94hash_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
95static inline void 99static inline void
@@ -152,7 +156,7 @@ static inline void
152hash_net4_data_next(struct ip_set_hash *h, 156hash_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
158static int 162static 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
310static inline bool 314static inline int
311hash_net6_data_match(const struct hash_net6_elem *elem) 315hash_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
316static inline void 320static inline void
@@ -532,12 +536,11 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
532static struct ip_set_type hash_net_type __read_mostly = { 536static 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 d5d3607ae7b..b9a63381e34 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
27MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:net,iface type of IP sets"); 33IP_SET_MODULE_DESC("hash:net,iface", REVISION_MIN, REVISION_MAX);
30MODULE_ALIAS("ip_set_hash:net,iface"); 34MODULE_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,
181static inline bool 185static inline bool
182hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem) 186hash_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
187static inline void 191static inline void
188hash_netiface4_data_copy(struct hash_netiface4_elem *dst, 192hash_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
198static inline void 198static 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
204static inline bool 204static inline int
205hash_netiface4_data_match(const struct hash_netiface4_elem *elem) 205hash_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
210static inline void 210static inline void
@@ -217,7 +217,7 @@ hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
217static inline void 217static inline void
218hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem) 218hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
219{ 219{
220 elem->cidr = 0; 220 elem->elem = 0;
221} 221}
222 222
223static bool 223static bool
@@ -277,7 +277,7 @@ static inline void
277hash_netiface4_data_next(struct ip_set_hash *h, 277hash_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
283static int 283static 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,
481static inline bool 481static inline bool
482hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem) 482hash_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
487static inline void 487static 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
500static inline bool 500static inline int
501hash_netiface6_data_match(const struct hash_netiface6_elem *elem) 501hash_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
506static inline void 506static inline void
507hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) 507hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
508{ 508{
509 elem->cidr = 0; 509 elem->elem = 0;
510} 510}
511 511
512static inline void 512static 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)
773static struct ip_set_type hash_netiface_type __read_mostly = { 774static 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 fc3143a2d41..7ef700de596 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
27MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:net,port type of IP sets"); 34IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX);
30MODULE_ALIAS("ip_set_hash:net,port"); 35MODULE_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
102static inline bool 107static inline int
103hash_netport4_data_match(const struct hash_netport4_elem *elem) 108hash_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
108static inline void 113static inline void
@@ -171,8 +176,8 @@ static inline void
171hash_netport4_data_next(struct ip_set_hash *h, 176hash_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
178static int 183static 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
372static inline bool 378static inline int
373hash_netport6_data_match(const struct hash_netport6_elem *elem) 379hash_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
378static inline void 384static inline void
@@ -450,7 +456,7 @@ static inline void
450hash_netport6_data_next(struct ip_set_hash *h, 456hash_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
456static int 462static 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)
644static struct ip_set_type hash_netport_type __read_mostly = { 650static 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 6cb1225765f..8371c2bac2e 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
19MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 23MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
21MODULE_DESCRIPTION("list:set type of IP sets"); 24IP_SET_MODULE_DESC("list:set", REVISION_MIN, REVISION_MAX);
22MODULE_ALIAS("ip_set_list:set"); 25MODULE_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 dcb27910ab3..0f241be28f9 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 f8cc26ad445..1ce3befb7c8 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
415skip_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
522static 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
515static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; 535static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
516 536
517static const struct nf_conntrack_expect_policy ftp_exp_policy = { 537static 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 2dcd080b8c4..7bbfb3deea3 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 1816ad38148..5f2f9109f46 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 3678073360a..945950a8b1f 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 43de3a03ee7..e12d44e75b2 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 00000000000..b253e07cb1c
--- /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
21static unsigned int
22netmap_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
57static 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
66static unsigned int
67netmap_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
102static 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
117static 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
148static int __init netmap_tg_init(void)
149{
150 return xt_register_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
151}
152
153static void netmap_tg_exit(void)
154{
155 xt_unregister_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
156}
157
158module_init(netmap_tg_init);
159module_exit(netmap_tg_exit);
160
161MODULE_LICENSE("GPL");
162MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets");
163MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
164MODULE_ALIAS("ip6t_NETMAP");
165MODULE_ALIAS("ipt_NETMAP");
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c
new file mode 100644
index 00000000000..22a10309297
--- /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
30static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
31
32static unsigned int
33redirect_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
73static 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 */
83static 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
98static unsigned int
99redirect_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
145static 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
172static int __init redirect_tg_init(void)
173{
174 return xt_register_targets(redirect_tg_reg,
175 ARRAY_SIZE(redirect_tg_reg));
176}
177
178static void __exit redirect_tg_exit(void)
179{
180 xt_unregister_targets(redirect_tg_reg, ARRAY_SIZE(redirect_tg_reg));
181}
182
183module_init(redirect_tg_init);
184module_exit(redirect_tg_exit);
185
186MODULE_LICENSE("GPL");
187MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
188MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
189MODULE_ALIAS("ip6t_REDIRECT");
190MODULE_ALIAS("ipt_REDIRECT");
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index c6f7db720d8..865a9e54f3a 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
361static struct xt_target set_targets[] __read_mostly = { 382static 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 c48975ff8ea..0ae55a36f49 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 */
43enum { 43enum {
44 DSE_FIRST = 2039, 44 DSE_FIRST = 2039,
45 SECONDS_PER_DAY = 86400,
45}; 46};
46static const u_int16_t days_since_epoch[] = { 47static 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(&current_time, stamp); 217 localtime_2(&current_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