aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/x_tables.h10
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h6
-rw-r--r--net/ipv4/netfilter/ip_tables.c78
-rw-r--r--net/ipv6/netfilter/ip6_tables.c78
-rw-r--r--net/netfilter/xt_TCPMSS.c12
6 files changed, 141 insertions, 49 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 9df3f5a8f9f7..84c7c928e9eb 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -120,6 +120,7 @@ struct xt_counters_info {
120 120
121#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 121#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
122 122
123#ifndef __KERNEL__
123/* fn returns 0 to continue iteration */ 124/* fn returns 0 to continue iteration */
124#define XT_MATCH_ITERATE(type, e, fn, args...) \ 125#define XT_MATCH_ITERATE(type, e, fn, args...) \
125({ \ 126({ \
@@ -139,7 +140,6 @@ struct xt_counters_info {
139 __ret; \ 140 __ret; \
140}) 141})
141 142
142#ifndef __KERNEL__
143/* fn returns 0 to continue iteration */ 143/* fn returns 0 to continue iteration */
144#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \ 144#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
145({ \ 145({ \
@@ -172,6 +172,14 @@ struct xt_counters_info {
172 (pos) < (typeof(pos))((char *)(ehead) + (esize)); \ 172 (pos) < (typeof(pos))((char *)(ehead) + (esize)); \
173 (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset)) 173 (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
174 174
175/* can only be xt_entry_match, so no use of typeof here */
176#define xt_ematch_foreach(pos, entry) \
177 for ((pos) = (struct xt_entry_match *)entry->elems; \
178 (pos) < (struct xt_entry_match *)((char *)(entry) + \
179 (entry)->target_offset); \
180 (pos) = (struct xt_entry_match *)((char *)(pos) + \
181 (pos)->u.match_size))
182
175#ifdef __KERNEL__ 183#ifdef __KERNEL__
176 184
177#include <linux/netdevice.h> 185#include <linux/netdevice.h>
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 5b20ae724b41..704a7b6e8169 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -223,11 +223,11 @@ ipt_get_target(struct ipt_entry *e)
223 return (void *)e + e->target_offset; 223 return (void *)e + e->target_offset;
224} 224}
225 225
226#ifndef __KERNEL__
226/* fn returns 0 to continue iteration */ 227/* fn returns 0 to continue iteration */
227#define IPT_MATCH_ITERATE(e, fn, args...) \ 228#define IPT_MATCH_ITERATE(e, fn, args...) \
228 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) 229 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
229 230
230#ifndef __KERNEL__
231/* fn returns 0 to continue iteration */ 231/* fn returns 0 to continue iteration */
232#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ 232#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
233 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) 233 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
@@ -315,10 +315,6 @@ compat_ipt_get_target(struct compat_ipt_entry *e)
315 315
316#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) 316#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
317 317
318/* fn returns 0 to continue iteration */
319#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \
320 XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)
321
322#endif /* CONFIG_COMPAT */ 318#endif /* CONFIG_COMPAT */
323#endif /*__KERNEL__*/ 319#endif /*__KERNEL__*/
324#endif /* _IPTABLES_H */ 320#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 8bb3f5ba5ff2..e5ba03d783c6 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -280,11 +280,11 @@ ip6t_get_target(struct ip6t_entry *e)
280 return (void *)e + e->target_offset; 280 return (void *)e + e->target_offset;
281} 281}
282 282
283#ifndef __KERNEL__
283/* fn returns 0 to continue iteration */ 284/* fn returns 0 to continue iteration */
284#define IP6T_MATCH_ITERATE(e, fn, args...) \ 285#define IP6T_MATCH_ITERATE(e, fn, args...) \
285 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) 286 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
286 287
287#ifndef __KERNEL__
288/* fn returns 0 to continue iteration */ 288/* fn returns 0 to continue iteration */
289#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ 289#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
290 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) 290 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
@@ -343,10 +343,6 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e)
343 343
344#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s) 344#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s)
345 345
346/* fn returns 0 to continue iteration */
347#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \
348 XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args)
349
350#endif /* CONFIG_COMPAT */ 346#endif /* CONFIG_COMPAT */
351#endif /*__KERNEL__*/ 347#endif /*__KERNEL__*/
352#endif /* _IP6_TABLES_H */ 348#endif /* _IP6_TABLES_H */
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 9c8aa394c51c..3a7fc732b918 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -366,16 +366,21 @@ ipt_do_table(struct sk_buff *skb,
366 366
367 do { 367 do {
368 const struct ipt_entry_target *t; 368 const struct ipt_entry_target *t;
369 const struct xt_entry_match *ematch;
369 370
370 IP_NF_ASSERT(e); 371 IP_NF_ASSERT(e);
371 IP_NF_ASSERT(back); 372 IP_NF_ASSERT(back);
372 if (!ip_packet_match(ip, indev, outdev, 373 if (!ip_packet_match(ip, indev, outdev,
373 &e->ip, mtpar.fragoff) || 374 &e->ip, mtpar.fragoff)) {
374 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { 375 no_match:
375 e = ipt_next_entry(e); 376 e = ipt_next_entry(e);
376 continue; 377 continue;
377 } 378 }
378 379
380 xt_ematch_foreach(ematch, e)
381 if (do_match(ematch, skb, &mtpar) != 0)
382 goto no_match;
383
379 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 384 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
380 385
381 t = ipt_get_target(e); 386 t = ipt_get_target(e);
@@ -686,6 +691,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
686 int ret; 691 int ret;
687 unsigned int j; 692 unsigned int j;
688 struct xt_mtchk_param mtpar; 693 struct xt_mtchk_param mtpar;
694 struct xt_entry_match *ematch;
689 695
690 ret = check_entry(e, name); 696 ret = check_entry(e, name);
691 if (ret) 697 if (ret)
@@ -697,7 +703,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
697 mtpar.entryinfo = &e->ip; 703 mtpar.entryinfo = &e->ip;
698 mtpar.hook_mask = e->comefrom; 704 mtpar.hook_mask = e->comefrom;
699 mtpar.family = NFPROTO_IPV4; 705 mtpar.family = NFPROTO_IPV4;
700 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 706 xt_ematch_foreach(ematch, e) {
707 ret = find_check_match(ematch, &mtpar, &j);
708 if (ret != 0)
709 break;
710 }
701 if (ret != 0) 711 if (ret != 0)
702 goto cleanup_matches; 712 goto cleanup_matches;
703 713
@@ -720,7 +730,9 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
720 err: 730 err:
721 module_put(t->u.kernel.target->me); 731 module_put(t->u.kernel.target->me);
722 cleanup_matches: 732 cleanup_matches:
723 IPT_MATCH_ITERATE(e, cleanup_match, net, &j); 733 xt_ematch_foreach(ematch, e)
734 if (cleanup_match(ematch, net, &j) != 0)
735 break;
724 return ret; 736 return ret;
725} 737}
726 738
@@ -791,9 +803,12 @@ cleanup_entry(struct ipt_entry *e, struct net *net)
791{ 803{
792 struct xt_tgdtor_param par; 804 struct xt_tgdtor_param par;
793 struct ipt_entry_target *t; 805 struct ipt_entry_target *t;
806 struct xt_entry_match *ematch;
794 807
795 /* Cleanup all matches */ 808 /* Cleanup all matches */
796 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); 809 xt_ematch_foreach(ematch, e)
810 if (cleanup_match(ematch, net, NULL) != 0)
811 break;
797 t = ipt_get_target(e); 812 t = ipt_get_target(e);
798 813
799 par.net = net; 814 par.net = net;
@@ -1060,13 +1075,16 @@ static int compat_calc_entry(const struct ipt_entry *e,
1060 const struct xt_table_info *info, 1075 const struct xt_table_info *info,
1061 const void *base, struct xt_table_info *newinfo) 1076 const void *base, struct xt_table_info *newinfo)
1062{ 1077{
1078 const struct xt_entry_match *ematch;
1063 const struct ipt_entry_target *t; 1079 const struct ipt_entry_target *t;
1064 unsigned int entry_offset; 1080 unsigned int entry_offset;
1065 int off, i, ret; 1081 int off, i, ret;
1066 1082
1067 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1083 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1068 entry_offset = (void *)e - base; 1084 entry_offset = (void *)e - base;
1069 IPT_MATCH_ITERATE(e, compat_calc_match, &off); 1085 xt_ematch_foreach(ematch, e)
1086 if (compat_calc_match(ematch, &off) != 0)
1087 break;
1070 t = ipt_get_target_c(e); 1088 t = ipt_get_target_c(e);
1071 off += xt_compat_target_offset(t->u.kernel.target); 1089 off += xt_compat_target_offset(t->u.kernel.target);
1072 newinfo->size -= off; 1090 newinfo->size -= off;
@@ -1441,7 +1459,8 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1441 struct compat_ipt_entry __user *ce; 1459 struct compat_ipt_entry __user *ce;
1442 u_int16_t target_offset, next_offset; 1460 u_int16_t target_offset, next_offset;
1443 compat_uint_t origsize; 1461 compat_uint_t origsize;
1444 int ret; 1462 const struct xt_entry_match *ematch;
1463 int ret = 0;
1445 1464
1446 origsize = *size; 1465 origsize = *size;
1447 ce = (struct compat_ipt_entry __user *)*dstptr; 1466 ce = (struct compat_ipt_entry __user *)*dstptr;
@@ -1453,7 +1472,11 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1453 *dstptr += sizeof(struct compat_ipt_entry); 1472 *dstptr += sizeof(struct compat_ipt_entry);
1454 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1473 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1455 1474
1456 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); 1475 xt_ematch_foreach(ematch, e) {
1476 ret = xt_compat_match_to_user(ematch, dstptr, size);
1477 if (ret != 0)
1478 break;
1479 }
1457 target_offset = e->target_offset - (origsize - *size); 1480 target_offset = e->target_offset - (origsize - *size);
1458 if (ret) 1481 if (ret)
1459 return ret; 1482 return ret;
@@ -1505,9 +1528,12 @@ compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1505static void compat_release_entry(struct compat_ipt_entry *e) 1528static void compat_release_entry(struct compat_ipt_entry *e)
1506{ 1529{
1507 struct ipt_entry_target *t; 1530 struct ipt_entry_target *t;
1531 struct xt_entry_match *ematch;
1508 1532
1509 /* Cleanup all matches */ 1533 /* Cleanup all matches */
1510 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL); 1534 xt_ematch_foreach(ematch, e)
1535 if (compat_release_match(ematch, NULL) != 0)
1536 break;
1511 t = compat_ipt_get_target(e); 1537 t = compat_ipt_get_target(e);
1512 module_put(t->u.kernel.target->me); 1538 module_put(t->u.kernel.target->me);
1513} 1539}
@@ -1522,6 +1548,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1522 const unsigned int *underflows, 1548 const unsigned int *underflows,
1523 const char *name) 1549 const char *name)
1524{ 1550{
1551 struct xt_entry_match *ematch;
1525 struct ipt_entry_target *t; 1552 struct ipt_entry_target *t;
1526 struct xt_target *target; 1553 struct xt_target *target;
1527 unsigned int entry_offset; 1554 unsigned int entry_offset;
@@ -1550,8 +1577,12 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1550 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1577 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1551 entry_offset = (void *)e - (void *)base; 1578 entry_offset = (void *)e - (void *)base;
1552 j = 0; 1579 j = 0;
1553 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name, 1580 xt_ematch_foreach(ematch, e) {
1554 &e->ip, e->comefrom, &off, &j); 1581 ret = compat_find_calc_match(ematch, name,
1582 &e->ip, e->comefrom, &off, &j);
1583 if (ret != 0)
1584 break;
1585 }
1555 if (ret != 0) 1586 if (ret != 0)
1556 goto release_matches; 1587 goto release_matches;
1557 1588
@@ -1590,7 +1621,9 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1590out: 1621out:
1591 module_put(t->u.kernel.target->me); 1622 module_put(t->u.kernel.target->me);
1592release_matches: 1623release_matches:
1593 IPT_MATCH_ITERATE(e, compat_release_match, &j); 1624 xt_ematch_foreach(ematch, e)
1625 if (compat_release_match(ematch, &j) != 0)
1626 break;
1594 return ret; 1627 return ret;
1595} 1628}
1596 1629
@@ -1604,6 +1637,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1604 struct ipt_entry *de; 1637 struct ipt_entry *de;
1605 unsigned int origsize; 1638 unsigned int origsize;
1606 int ret, h; 1639 int ret, h;
1640 struct xt_entry_match *ematch;
1607 1641
1608 ret = 0; 1642 ret = 0;
1609 origsize = *size; 1643 origsize = *size;
@@ -1614,8 +1648,11 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1614 *dstptr += sizeof(struct ipt_entry); 1648 *dstptr += sizeof(struct ipt_entry);
1615 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1649 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1616 1650
1617 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user, 1651 xt_ematch_foreach(ematch, e) {
1618 dstptr, size); 1652 ret = xt_compat_match_from_user(ematch, dstptr, size);
1653 if (ret != 0)
1654 break;
1655 }
1619 if (ret) 1656 if (ret)
1620 return ret; 1657 return ret;
1621 de->target_offset = e->target_offset - (origsize - *size); 1658 de->target_offset = e->target_offset - (origsize - *size);
@@ -1636,9 +1673,10 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1636static int 1673static int
1637compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) 1674compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1638{ 1675{
1676 struct xt_entry_match *ematch;
1639 struct xt_mtchk_param mtpar; 1677 struct xt_mtchk_param mtpar;
1640 unsigned int j; 1678 unsigned int j;
1641 int ret; 1679 int ret = 0;
1642 1680
1643 j = 0; 1681 j = 0;
1644 mtpar.net = net; 1682 mtpar.net = net;
@@ -1646,7 +1684,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1646 mtpar.entryinfo = &e->ip; 1684 mtpar.entryinfo = &e->ip;
1647 mtpar.hook_mask = e->comefrom; 1685 mtpar.hook_mask = e->comefrom;
1648 mtpar.family = NFPROTO_IPV4; 1686 mtpar.family = NFPROTO_IPV4;
1649 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j); 1687 xt_ematch_foreach(ematch, e) {
1688 ret = check_match(ematch, &mtpar, &j);
1689 if (ret != 0)
1690 break;
1691 }
1650 if (ret) 1692 if (ret)
1651 goto cleanup_matches; 1693 goto cleanup_matches;
1652 1694
@@ -1656,7 +1698,9 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1656 return 0; 1698 return 0;
1657 1699
1658 cleanup_matches: 1700 cleanup_matches:
1659 IPT_MATCH_ITERATE(e, cleanup_match, net, &j); 1701 xt_ematch_foreach(ematch, e)
1702 if (cleanup_match(ematch, net, &j) != 0)
1703 break;
1660 return ret; 1704 return ret;
1661} 1705}
1662 1706
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index b7e27c19c7ab..1537e6bad5d9 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -393,16 +393,21 @@ ip6t_do_table(struct sk_buff *skb,
393 393
394 do { 394 do {
395 const struct ip6t_entry_target *t; 395 const struct ip6t_entry_target *t;
396 const struct xt_entry_match *ematch;
396 397
397 IP_NF_ASSERT(e); 398 IP_NF_ASSERT(e);
398 IP_NF_ASSERT(back); 399 IP_NF_ASSERT(back);
399 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, 400 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
400 &mtpar.thoff, &mtpar.fragoff, &hotdrop) || 401 &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {
401 IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { 402 no_match:
402 e = ip6t_next_entry(e); 403 e = ip6t_next_entry(e);
403 continue; 404 continue;
404 } 405 }
405 406
407 xt_ematch_foreach(ematch, e)
408 if (do_match(ematch, skb, &mtpar) != 0)
409 goto no_match;
410
406 ADD_COUNTER(e->counters, 411 ADD_COUNTER(e->counters,
407 ntohs(ipv6_hdr(skb)->payload_len) + 412 ntohs(ipv6_hdr(skb)->payload_len) +
408 sizeof(struct ipv6hdr), 1); 413 sizeof(struct ipv6hdr), 1);
@@ -717,6 +722,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
717 int ret; 722 int ret;
718 unsigned int j; 723 unsigned int j;
719 struct xt_mtchk_param mtpar; 724 struct xt_mtchk_param mtpar;
725 struct xt_entry_match *ematch;
720 726
721 ret = check_entry(e, name); 727 ret = check_entry(e, name);
722 if (ret) 728 if (ret)
@@ -728,7 +734,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
728 mtpar.entryinfo = &e->ipv6; 734 mtpar.entryinfo = &e->ipv6;
729 mtpar.hook_mask = e->comefrom; 735 mtpar.hook_mask = e->comefrom;
730 mtpar.family = NFPROTO_IPV6; 736 mtpar.family = NFPROTO_IPV6;
731 ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 737 xt_ematch_foreach(ematch, e) {
738 ret = find_check_match(ematch, &mtpar, &j);
739 if (ret != 0)
740 break;
741 }
732 if (ret != 0) 742 if (ret != 0)
733 goto cleanup_matches; 743 goto cleanup_matches;
734 744
@@ -751,7 +761,9 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
751 err: 761 err:
752 module_put(t->u.kernel.target->me); 762 module_put(t->u.kernel.target->me);
753 cleanup_matches: 763 cleanup_matches:
754 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); 764 xt_ematch_foreach(ematch, e)
765 if (cleanup_match(ematch, net, &j) != 0)
766 break;
755 return ret; 767 return ret;
756} 768}
757 769
@@ -821,9 +833,12 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net)
821{ 833{
822 struct xt_tgdtor_param par; 834 struct xt_tgdtor_param par;
823 struct ip6t_entry_target *t; 835 struct ip6t_entry_target *t;
836 struct xt_entry_match *ematch;
824 837
825 /* Cleanup all matches */ 838 /* Cleanup all matches */
826 IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); 839 xt_ematch_foreach(ematch, e)
840 if (cleanup_match(ematch, net, NULL) != 0)
841 break;
827 t = ip6t_get_target(e); 842 t = ip6t_get_target(e);
828 843
829 par.net = net; 844 par.net = net;
@@ -1090,13 +1105,16 @@ static int compat_calc_entry(const struct ip6t_entry *e,
1090 const struct xt_table_info *info, 1105 const struct xt_table_info *info,
1091 const void *base, struct xt_table_info *newinfo) 1106 const void *base, struct xt_table_info *newinfo)
1092{ 1107{
1108 const struct xt_entry_match *ematch;
1093 const struct ip6t_entry_target *t; 1109 const struct ip6t_entry_target *t;
1094 unsigned int entry_offset; 1110 unsigned int entry_offset;
1095 int off, i, ret; 1111 int off, i, ret;
1096 1112
1097 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1113 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1098 entry_offset = (void *)e - base; 1114 entry_offset = (void *)e - base;
1099 IP6T_MATCH_ITERATE(e, compat_calc_match, &off); 1115 xt_ematch_foreach(ematch, e)
1116 if (compat_calc_match(ematch, &off) != 0)
1117 break;
1100 t = ip6t_get_target_c(e); 1118 t = ip6t_get_target_c(e);
1101 off += xt_compat_target_offset(t->u.kernel.target); 1119 off += xt_compat_target_offset(t->u.kernel.target);
1102 newinfo->size -= off; 1120 newinfo->size -= off;
@@ -1474,7 +1492,8 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
1474 struct compat_ip6t_entry __user *ce; 1492 struct compat_ip6t_entry __user *ce;
1475 u_int16_t target_offset, next_offset; 1493 u_int16_t target_offset, next_offset;
1476 compat_uint_t origsize; 1494 compat_uint_t origsize;
1477 int ret; 1495 const struct xt_entry_match *ematch;
1496 int ret = 0;
1478 1497
1479 origsize = *size; 1498 origsize = *size;
1480 ce = (struct compat_ip6t_entry __user *)*dstptr; 1499 ce = (struct compat_ip6t_entry __user *)*dstptr;
@@ -1486,7 +1505,11 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
1486 *dstptr += sizeof(struct compat_ip6t_entry); 1505 *dstptr += sizeof(struct compat_ip6t_entry);
1487 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1506 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1488 1507
1489 ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); 1508 xt_ematch_foreach(ematch, e) {
1509 ret = xt_compat_match_to_user(ematch, dstptr, size);
1510 if (ret != 0)
1511 break;
1512 }
1490 target_offset = e->target_offset - (origsize - *size); 1513 target_offset = e->target_offset - (origsize - *size);
1491 if (ret) 1514 if (ret)
1492 return ret; 1515 return ret;
@@ -1538,9 +1561,12 @@ compat_release_match(struct ip6t_entry_match *m, unsigned int *i)
1538static void compat_release_entry(struct compat_ip6t_entry *e) 1561static void compat_release_entry(struct compat_ip6t_entry *e)
1539{ 1562{
1540 struct ip6t_entry_target *t; 1563 struct ip6t_entry_target *t;
1564 struct xt_entry_match *ematch;
1541 1565
1542 /* Cleanup all matches */ 1566 /* Cleanup all matches */
1543 COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); 1567 xt_ematch_foreach(ematch, e)
1568 if (compat_release_match(ematch, NULL) != 0)
1569 break;
1544 t = compat_ip6t_get_target(e); 1570 t = compat_ip6t_get_target(e);
1545 module_put(t->u.kernel.target->me); 1571 module_put(t->u.kernel.target->me);
1546} 1572}
@@ -1555,6 +1581,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1555 const unsigned int *underflows, 1581 const unsigned int *underflows,
1556 const char *name) 1582 const char *name)
1557{ 1583{
1584 struct xt_entry_match *ematch;
1558 struct ip6t_entry_target *t; 1585 struct ip6t_entry_target *t;
1559 struct xt_target *target; 1586 struct xt_target *target;
1560 unsigned int entry_offset; 1587 unsigned int entry_offset;
@@ -1583,8 +1610,12 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1583 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1610 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1584 entry_offset = (void *)e - (void *)base; 1611 entry_offset = (void *)e - (void *)base;
1585 j = 0; 1612 j = 0;
1586 ret = COMPAT_IP6T_MATCH_ITERATE(e, compat_find_calc_match, name, 1613 xt_ematch_foreach(ematch, e) {
1587 &e->ipv6, e->comefrom, &off, &j); 1614 ret = compat_find_calc_match(ematch, name,
1615 &e->ipv6, e->comefrom, &off, &j);
1616 if (ret != 0)
1617 break;
1618 }
1588 if (ret != 0) 1619 if (ret != 0)
1589 goto release_matches; 1620 goto release_matches;
1590 1621
@@ -1623,7 +1654,9 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1623out: 1654out:
1624 module_put(t->u.kernel.target->me); 1655 module_put(t->u.kernel.target->me);
1625release_matches: 1656release_matches:
1626 IP6T_MATCH_ITERATE(e, compat_release_match, &j); 1657 xt_ematch_foreach(ematch, e)
1658 if (compat_release_match(ematch, &j) != 0)
1659 break;
1627 return ret; 1660 return ret;
1628} 1661}
1629 1662
@@ -1637,6 +1670,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1637 struct ip6t_entry *de; 1670 struct ip6t_entry *de;
1638 unsigned int origsize; 1671 unsigned int origsize;
1639 int ret, h; 1672 int ret, h;
1673 struct xt_entry_match *ematch;
1640 1674
1641 ret = 0; 1675 ret = 0;
1642 origsize = *size; 1676 origsize = *size;
@@ -1647,8 +1681,11 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1647 *dstptr += sizeof(struct ip6t_entry); 1681 *dstptr += sizeof(struct ip6t_entry);
1648 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1682 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1649 1683
1650 ret = COMPAT_IP6T_MATCH_ITERATE(e, xt_compat_match_from_user, 1684 xt_ematch_foreach(ematch, e) {
1651 dstptr, size); 1685 ret = xt_compat_match_from_user(ematch, dstptr, size);
1686 if (ret != 0)
1687 break;
1688 }
1652 if (ret) 1689 if (ret)
1653 return ret; 1690 return ret;
1654 de->target_offset = e->target_offset - (origsize - *size); 1691 de->target_offset = e->target_offset - (origsize - *size);
@@ -1670,8 +1707,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1670 const char *name) 1707 const char *name)
1671{ 1708{
1672 unsigned int j; 1709 unsigned int j;
1673 int ret; 1710 int ret = 0;
1674 struct xt_mtchk_param mtpar; 1711 struct xt_mtchk_param mtpar;
1712 struct xt_entry_match *ematch;
1675 1713
1676 j = 0; 1714 j = 0;
1677 mtpar.net = net; 1715 mtpar.net = net;
@@ -1679,7 +1717,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1679 mtpar.entryinfo = &e->ipv6; 1717 mtpar.entryinfo = &e->ipv6;
1680 mtpar.hook_mask = e->comefrom; 1718 mtpar.hook_mask = e->comefrom;
1681 mtpar.family = NFPROTO_IPV6; 1719 mtpar.family = NFPROTO_IPV6;
1682 ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j); 1720 xt_ematch_foreach(ematch, e) {
1721 ret = check_match(ematch, &mtpar, &j);
1722 if (ret != 0)
1723 break;
1724 }
1683 if (ret) 1725 if (ret)
1684 goto cleanup_matches; 1726 goto cleanup_matches;
1685 1727
@@ -1689,7 +1731,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1689 return 0; 1731 return 0;
1690 1732
1691 cleanup_matches: 1733 cleanup_matches:
1692 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); 1734 xt_ematch_foreach(ematch, e)
1735 if (cleanup_match(ematch, net, &j) != 0)
1736 break;
1693 return ret; 1737 return ret;
1694} 1738}
1695 1739
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 6f21b4377dbb..0e357ac9a2a8 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -239,6 +239,7 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
239{ 239{
240 const struct xt_tcpmss_info *info = par->targinfo; 240 const struct xt_tcpmss_info *info = par->targinfo;
241 const struct ipt_entry *e = par->entryinfo; 241 const struct ipt_entry *e = par->entryinfo;
242 const struct xt_entry_match *ematch;
242 243
243 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 244 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
244 (par->hook_mask & ~((1 << NF_INET_FORWARD) | 245 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
@@ -248,8 +249,9 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
248 "FORWARD, OUTPUT and POSTROUTING hooks\n"); 249 "FORWARD, OUTPUT and POSTROUTING hooks\n");
249 return false; 250 return false;
250 } 251 }
251 if (IPT_MATCH_ITERATE(e, find_syn_match)) 252 xt_ematch_foreach(ematch, e)
252 return true; 253 if (find_syn_match(ematch))
254 return true;
253 printk("xt_TCPMSS: Only works on TCP SYN packets\n"); 255 printk("xt_TCPMSS: Only works on TCP SYN packets\n");
254 return false; 256 return false;
255} 257}
@@ -259,6 +261,7 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
259{ 261{
260 const struct xt_tcpmss_info *info = par->targinfo; 262 const struct xt_tcpmss_info *info = par->targinfo;
261 const struct ip6t_entry *e = par->entryinfo; 263 const struct ip6t_entry *e = par->entryinfo;
264 const struct xt_entry_match *ematch;
262 265
263 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 266 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
264 (par->hook_mask & ~((1 << NF_INET_FORWARD) | 267 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
@@ -268,8 +271,9 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
268 "FORWARD, OUTPUT and POSTROUTING hooks\n"); 271 "FORWARD, OUTPUT and POSTROUTING hooks\n");
269 return false; 272 return false;
270 } 273 }
271 if (IP6T_MATCH_ITERATE(e, find_syn_match)) 274 xt_ematch_foreach(ematch, e)
272 return true; 275 if (find_syn_match(ematch))
276 return true;
273 printk("xt_TCPMSS: Only works on TCP SYN packets\n"); 277 printk("xt_TCPMSS: Only works on TCP SYN packets\n");
274 return false; 278 return false;
275} 279}