aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h30
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c18
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c22
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c22
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c18
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c10
-rw-r--r--net/netfilter/nf_conntrack_sip.c6
-rw-r--r--net/netfilter/nf_nat_core.c40
8 files changed, 115 insertions, 51 deletions
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index 01d25e6fc792..0214c4c146fa 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -291,6 +291,7 @@ ip_set_hash_destroy(struct ip_set *set)
291#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) 291#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
292#define type_pf_data_next TOKEN(TYPE, PF, _data_next) 292#define type_pf_data_next TOKEN(TYPE, PF, _data_next)
293#define type_pf_data_flags TOKEN(TYPE, PF, _data_flags) 293#define type_pf_data_flags TOKEN(TYPE, PF, _data_flags)
294#define type_pf_data_reset_flags TOKEN(TYPE, PF, _data_reset_flags)
294#ifdef IP_SET_HASH_WITH_NETS 295#ifdef IP_SET_HASH_WITH_NETS
295#define type_pf_data_match TOKEN(TYPE, PF, _data_match) 296#define type_pf_data_match TOKEN(TYPE, PF, _data_match)
296#else 297#else
@@ -385,9 +386,9 @@ type_pf_resize(struct ip_set *set, bool retried)
385 struct ip_set_hash *h = set->data; 386 struct ip_set_hash *h = set->data;
386 struct htable *t, *orig = h->table; 387 struct htable *t, *orig = h->table;
387 u8 htable_bits = orig->htable_bits; 388 u8 htable_bits = orig->htable_bits;
388 const struct type_pf_elem *data; 389 struct type_pf_elem *data;
389 struct hbucket *n, *m; 390 struct hbucket *n, *m;
390 u32 i, j; 391 u32 i, j, flags = 0;
391 int ret; 392 int ret;
392 393
393retry: 394retry:
@@ -412,9 +413,16 @@ retry:
412 n = hbucket(orig, i); 413 n = hbucket(orig, i);
413 for (j = 0; j < n->pos; j++) { 414 for (j = 0; j < n->pos; j++) {
414 data = ahash_data(n, j); 415 data = ahash_data(n, j);
416#ifdef IP_SET_HASH_WITH_NETS
417 flags = 0;
418 type_pf_data_reset_flags(data, &flags);
419#endif
415 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 420 m = hbucket(t, HKEY(data, h->initval, htable_bits));
416 ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0); 421 ret = type_pf_elem_add(m, data, AHASH_MAX(h), flags);
417 if (ret < 0) { 422 if (ret < 0) {
423#ifdef IP_SET_HASH_WITH_NETS
424 type_pf_data_flags(data, flags);
425#endif
418 read_unlock_bh(&set->lock); 426 read_unlock_bh(&set->lock);
419 ahash_destroy(t); 427 ahash_destroy(t);
420 if (ret == -EAGAIN) 428 if (ret == -EAGAIN)
@@ -836,9 +844,9 @@ type_pf_tresize(struct ip_set *set, bool retried)
836 struct ip_set_hash *h = set->data; 844 struct ip_set_hash *h = set->data;
837 struct htable *t, *orig = h->table; 845 struct htable *t, *orig = h->table;
838 u8 htable_bits = orig->htable_bits; 846 u8 htable_bits = orig->htable_bits;
839 const struct type_pf_elem *data; 847 struct type_pf_elem *data;
840 struct hbucket *n, *m; 848 struct hbucket *n, *m;
841 u32 i, j; 849 u32 i, j, flags = 0;
842 int ret; 850 int ret;
843 851
844 /* Try to cleanup once */ 852 /* Try to cleanup once */
@@ -873,10 +881,17 @@ retry:
873 n = hbucket(orig, i); 881 n = hbucket(orig, i);
874 for (j = 0; j < n->pos; j++) { 882 for (j = 0; j < n->pos; j++) {
875 data = ahash_tdata(n, j); 883 data = ahash_tdata(n, j);
884#ifdef IP_SET_HASH_WITH_NETS
885 flags = 0;
886 type_pf_data_reset_flags(data, &flags);
887#endif
876 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 888 m = hbucket(t, HKEY(data, h->initval, htable_bits));
877 ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, 889 ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), flags,
878 ip_set_timeout_get(type_pf_data_timeout(data))); 890 ip_set_timeout_get(type_pf_data_timeout(data)));
879 if (ret < 0) { 891 if (ret < 0) {
892#ifdef IP_SET_HASH_WITH_NETS
893 type_pf_data_flags(data, flags);
894#endif
880 read_unlock_bh(&set->lock); 895 read_unlock_bh(&set->lock);
881 ahash_destroy(t); 896 ahash_destroy(t);
882 if (ret == -EAGAIN) 897 if (ret == -EAGAIN)
@@ -1187,6 +1202,7 @@ type_pf_gc_init(struct ip_set *set)
1187#undef type_pf_data_tlist 1202#undef type_pf_data_tlist
1188#undef type_pf_data_next 1203#undef type_pf_data_next
1189#undef type_pf_data_flags 1204#undef type_pf_data_flags
1205#undef type_pf_data_reset_flags
1190#undef type_pf_data_match 1206#undef type_pf_data_match
1191 1207
1192#undef type_pf_elem 1208#undef type_pf_elem
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index f2627226a087..10a30b4fc7db 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -104,6 +104,15 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
105} 105}
106 106
107static inline void
108hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *dst, u32 *flags)
109{
110 if (dst->nomatch) {
111 *flags = IPSET_FLAG_NOMATCH;
112 dst->nomatch = 0;
113 }
114}
115
107static inline int 116static inline int
108hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) 117hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
109{ 118{
@@ -414,6 +423,15 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
414 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 423 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
415} 424}
416 425
426static inline void
427hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *dst, u32 *flags)
428{
429 if (dst->nomatch) {
430 *flags = IPSET_FLAG_NOMATCH;
431 dst->nomatch = 0;
432 }
433}
434
417static inline int 435static inline int
418hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) 436hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
419{ 437{
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 4b677cf6bf7d..d6a59154d710 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -87,7 +87,16 @@ hash_net4_data_copy(struct hash_net4_elem *dst,
87static inline void 87static inline void
88hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) 88hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
89{ 89{
90 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 90 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
91}
92
93static inline void
94hash_net4_data_reset_flags(struct hash_net4_elem *dst, u32 *flags)
95{
96 if (dst->nomatch) {
97 *flags = IPSET_FLAG_NOMATCH;
98 dst->nomatch = 0;
99 }
91} 100}
92 101
93static inline int 102static inline int
@@ -308,7 +317,16 @@ hash_net6_data_copy(struct hash_net6_elem *dst,
308static inline void 317static inline void
309hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags) 318hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
310{ 319{
311 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 320 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
321}
322
323static inline void
324hash_net6_data_reset_flags(struct hash_net6_elem *dst, u32 *flags)
325{
326 if (dst->nomatch) {
327 *flags = IPSET_FLAG_NOMATCH;
328 dst->nomatch = 0;
329 }
312} 330}
313 331
314static inline int 332static inline int
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 6ba985f1c96f..f2b0a3c30130 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -198,7 +198,16 @@ hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
198static inline void 198static inline void
199hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) 199hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
200{ 200{
201 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 201 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
202}
203
204static inline void
205hash_netiface4_data_reset_flags(struct hash_netiface4_elem *dst, u32 *flags)
206{
207 if (dst->nomatch) {
208 *flags = IPSET_FLAG_NOMATCH;
209 dst->nomatch = 0;
210 }
202} 211}
203 212
204static inline int 213static inline int
@@ -494,7 +503,7 @@ hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
494static inline void 503static inline void
495hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags) 504hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
496{ 505{
497 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 506 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
498} 507}
499 508
500static inline int 509static inline int
@@ -504,6 +513,15 @@ hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
504} 513}
505 514
506static inline void 515static inline void
516hash_netiface6_data_reset_flags(struct hash_netiface6_elem *dst, u32 *flags)
517{
518 if (dst->nomatch) {
519 *flags = IPSET_FLAG_NOMATCH;
520 dst->nomatch = 0;
521 }
522}
523
524static inline void
507hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) 525hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
508{ 526{
509 elem->elem = 0; 527 elem->elem = 0;
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index af20c0c5ced2..349deb672a2d 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -104,6 +104,15 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags)
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
105} 105}
106 106
107static inline void
108hash_netport4_data_reset_flags(struct hash_netport4_elem *dst, u32 *flags)
109{
110 if (dst->nomatch) {
111 *flags = IPSET_FLAG_NOMATCH;
112 dst->nomatch = 0;
113 }
114}
115
107static inline int 116static inline int
108hash_netport4_data_match(const struct hash_netport4_elem *elem) 117hash_netport4_data_match(const struct hash_netport4_elem *elem)
109{ 118{
@@ -375,6 +384,15 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
375 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 384 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
376} 385}
377 386
387static inline void
388hash_netport6_data_reset_flags(struct hash_netport6_elem *dst, u32 *flags)
389{
390 if (dst->nomatch) {
391 *flags = IPSET_FLAG_NOMATCH;
392 dst->nomatch = 0;
393 }
394}
395
378static inline int 396static inline int
379hash_netport6_data_match(const struct hash_netport6_elem *elem) 397hash_netport6_data_match(const struct hash_netport6_elem *elem)
380{ 398{
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 8371c2bac2e4..09c744aa8982 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -174,9 +174,13 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
174{ 174{
175 const struct set_elem *e = list_set_elem(map, i); 175 const struct set_elem *e = list_set_elem(map, i);
176 176
177 if (i == map->size - 1 && e->id != IPSET_INVALID_ID) 177 if (e->id != IPSET_INVALID_ID) {
178 /* Last element replaced: e.g. add new,before,last */ 178 const struct set_elem *x = list_set_elem(map, map->size - 1);
179 ip_set_put_byindex(e->id); 179
180 /* Last element replaced or pushed off */
181 if (x->id != IPSET_INVALID_ID)
182 ip_set_put_byindex(x->id);
183 }
180 if (with_timeout(map->timeout)) 184 if (with_timeout(map->timeout))
181 list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); 185 list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
182 else 186 else
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 0e7d423324c3..e0c4373b4747 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1593,10 +1593,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
1593 end += strlen("\r\n\r\n") + clen; 1593 end += strlen("\r\n\r\n") + clen;
1594 1594
1595 msglen = origlen = end - dptr; 1595 msglen = origlen = end - dptr;
1596 if (msglen > datalen) { 1596 if (msglen > datalen)
1597 nf_ct_helper_log(skb, ct, "incomplete/bad SIP message"); 1597 return NF_ACCEPT;
1598 return NF_DROP;
1599 }
1600 1598
1601 ret = process_sip_msg(skb, ct, protoff, dataoff, 1599 ret = process_sip_msg(skb, ct, protoff, dataoff,
1602 &dptr, &msglen); 1600 &dptr, &msglen);
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 8d5769c6d16e..ad24be070e53 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -467,33 +467,22 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
467struct nf_nat_proto_clean { 467struct nf_nat_proto_clean {
468 u8 l3proto; 468 u8 l3proto;
469 u8 l4proto; 469 u8 l4proto;
470 bool hash;
471}; 470};
472 471
473/* Clear NAT section of all conntracks, in case we're loaded again. */ 472/* kill conntracks with affected NAT section */
474static int nf_nat_proto_clean(struct nf_conn *i, void *data) 473static int nf_nat_proto_remove(struct nf_conn *i, void *data)
475{ 474{
476 const struct nf_nat_proto_clean *clean = data; 475 const struct nf_nat_proto_clean *clean = data;
477 struct nf_conn_nat *nat = nfct_nat(i); 476 struct nf_conn_nat *nat = nfct_nat(i);
478 477
479 if (!nat) 478 if (!nat)
480 return 0; 479 return 0;
481 if (!(i->status & IPS_SRC_NAT_DONE)) 480
482 return 0;
483 if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || 481 if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
484 (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) 482 (clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
485 return 0; 483 return 0;
486 484
487 if (clean->hash) { 485 return i->status & IPS_NAT_MASK ? 1 : 0;
488 spin_lock_bh(&nf_nat_lock);
489 hlist_del_rcu(&nat->bysource);
490 spin_unlock_bh(&nf_nat_lock);
491 } else {
492 memset(nat, 0, sizeof(*nat));
493 i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK |
494 IPS_SEQ_ADJUST);
495 }
496 return 0;
497} 486}
498 487
499static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) 488static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
@@ -505,16 +494,8 @@ static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
505 struct net *net; 494 struct net *net;
506 495
507 rtnl_lock(); 496 rtnl_lock();
508 /* Step 1 - remove from bysource hash */
509 clean.hash = true;
510 for_each_net(net) 497 for_each_net(net)
511 nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); 498 nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
512 synchronize_rcu();
513
514 /* Step 2 - clean NAT section */
515 clean.hash = false;
516 for_each_net(net)
517 nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
518 rtnl_unlock(); 499 rtnl_unlock();
519} 500}
520 501
@@ -526,16 +507,9 @@ static void nf_nat_l3proto_clean(u8 l3proto)
526 struct net *net; 507 struct net *net;
527 508
528 rtnl_lock(); 509 rtnl_lock();
529 /* Step 1 - remove from bysource hash */
530 clean.hash = true;
531 for_each_net(net)
532 nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
533 synchronize_rcu();
534 510
535 /* Step 2 - clean NAT section */
536 clean.hash = false;
537 for_each_net(net) 511 for_each_net(net)
538 nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); 512 nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
539 rtnl_unlock(); 513 rtnl_unlock();
540} 514}
541 515
@@ -773,7 +747,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
773{ 747{
774 struct nf_nat_proto_clean clean = {}; 748 struct nf_nat_proto_clean clean = {};
775 749
776 nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean); 750 nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
777 synchronize_rcu(); 751 synchronize_rcu();
778 nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size); 752 nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
779} 753}