aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@medozas.de>2010-02-24 12:35:37 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-24 12:35:37 -0500
commit6bdb331bc6910d1ccb74dc9852fc858c5916c927 (patch)
treed77dd2df2d6d43ce25703ce8c9ecab0173c14a7f /net/ipv6
parentdcea992aca82cb08b4674c4c783e325835408d1e (diff)
netfilter: xtables: optimize call flow around xt_ematch_foreach
Signed-off-by: Jan Engelhardt <jengelh@medozas.de> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c93
1 files changed, 31 insertions, 62 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1537e6bad5d9..c5a963e4b545 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -603,14 +603,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
603 return 1; 603 return 1;
604} 604}
605 605
606static int 606static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
607cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)
608{ 607{
609 struct xt_mtdtor_param par; 608 struct xt_mtdtor_param par;
610 609
611 if (i && (*i)-- == 0)
612 return 1;
613
614 par.net = net; 610 par.net = net;
615 par.match = m->u.kernel.match; 611 par.match = m->u.kernel.match;
616 par.matchinfo = m->data; 612 par.matchinfo = m->data;
@@ -618,7 +614,6 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)
618 if (par.match->destroy != NULL) 614 if (par.match->destroy != NULL)
619 par.match->destroy(&par); 615 par.match->destroy(&par);
620 module_put(par.match->me); 616 module_put(par.match->me);
621 return 0;
622} 617}
623 618
624static int 619static int
@@ -642,8 +637,7 @@ check_entry(const struct ip6t_entry *e, const char *name)
642 return 0; 637 return 0;
643} 638}
644 639
645static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, 640static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
646 unsigned int *i)
647{ 641{
648 const struct ip6t_ip6 *ipv6 = par->entryinfo; 642 const struct ip6t_ip6 *ipv6 = par->entryinfo;
649 int ret; 643 int ret;
@@ -658,13 +652,11 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
658 par.match->name); 652 par.match->name);
659 return ret; 653 return ret;
660 } 654 }
661 ++*i;
662 return 0; 655 return 0;
663} 656}
664 657
665static int 658static int
666find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, 659find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
667 unsigned int *i)
668{ 660{
669 struct xt_match *match; 661 struct xt_match *match;
670 int ret; 662 int ret;
@@ -678,7 +670,7 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
678 } 670 }
679 m->u.kernel.match = match; 671 m->u.kernel.match = match;
680 672
681 ret = check_match(m, par, i); 673 ret = check_match(m, par);
682 if (ret) 674 if (ret)
683 goto err; 675 goto err;
684 676
@@ -735,12 +727,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
735 mtpar.hook_mask = e->comefrom; 727 mtpar.hook_mask = e->comefrom;
736 mtpar.family = NFPROTO_IPV6; 728 mtpar.family = NFPROTO_IPV6;
737 xt_ematch_foreach(ematch, e) { 729 xt_ematch_foreach(ematch, e) {
738 ret = find_check_match(ematch, &mtpar, &j); 730 ret = find_check_match(ematch, &mtpar);
739 if (ret != 0) 731 if (ret != 0)
740 break; 732 goto cleanup_matches;
733 ++j;
741 } 734 }
742 if (ret != 0)
743 goto cleanup_matches;
744 735
745 t = ip6t_get_target(e); 736 t = ip6t_get_target(e);
746 target = try_then_request_module(xt_find_target(AF_INET6, 737 target = try_then_request_module(xt_find_target(AF_INET6,
@@ -761,9 +752,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
761 err: 752 err:
762 module_put(t->u.kernel.target->me); 753 module_put(t->u.kernel.target->me);
763 cleanup_matches: 754 cleanup_matches:
764 xt_ematch_foreach(ematch, e) 755 xt_ematch_foreach(ematch, e) {
765 if (cleanup_match(ematch, net, &j) != 0) 756 if (j-- == 0)
766 break; 757 break;
758 cleanup_match(ematch, net);
759 }
767 return ret; 760 return ret;
768} 761}
769 762
@@ -837,8 +830,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net)
837 830
838 /* Cleanup all matches */ 831 /* Cleanup all matches */
839 xt_ematch_foreach(ematch, e) 832 xt_ematch_foreach(ematch, e)
840 if (cleanup_match(ematch, net, NULL) != 0) 833 cleanup_match(ematch, net);
841 break;
842 t = ip6t_get_target(e); 834 t = ip6t_get_target(e);
843 835
844 par.net = net; 836 par.net = net;
@@ -1094,13 +1086,6 @@ static int compat_standard_to_user(void __user *dst, const void *src)
1094 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 1086 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1095} 1087}
1096 1088
1097static inline int
1098compat_calc_match(const struct ip6t_entry_match *m, int *size)
1099{
1100 *size += xt_compat_match_offset(m->u.kernel.match);
1101 return 0;
1102}
1103
1104static int compat_calc_entry(const struct ip6t_entry *e, 1089static int compat_calc_entry(const struct ip6t_entry *e,
1105 const struct xt_table_info *info, 1090 const struct xt_table_info *info,
1106 const void *base, struct xt_table_info *newinfo) 1091 const void *base, struct xt_table_info *newinfo)
@@ -1113,8 +1098,7 @@ static int compat_calc_entry(const struct ip6t_entry *e,
1113 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1098 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1114 entry_offset = (void *)e - base; 1099 entry_offset = (void *)e - base;
1115 xt_ematch_foreach(ematch, e) 1100 xt_ematch_foreach(ematch, e)
1116 if (compat_calc_match(ematch, &off) != 0) 1101 off += xt_compat_match_offset(ematch->u.kernel.match);
1117 break;
1118 t = ip6t_get_target_c(e); 1102 t = ip6t_get_target_c(e);
1119 off += xt_compat_target_offset(t->u.kernel.target); 1103 off += xt_compat_target_offset(t->u.kernel.target);
1120 newinfo->size -= off; 1104 newinfo->size -= off;
@@ -1508,11 +1492,9 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
1508 xt_ematch_foreach(ematch, e) { 1492 xt_ematch_foreach(ematch, e) {
1509 ret = xt_compat_match_to_user(ematch, dstptr, size); 1493 ret = xt_compat_match_to_user(ematch, dstptr, size);
1510 if (ret != 0) 1494 if (ret != 0)
1511 break; 1495 return ret;
1512 } 1496 }
1513 target_offset = e->target_offset - (origsize - *size); 1497 target_offset = e->target_offset - (origsize - *size);
1514 if (ret)
1515 return ret;
1516 t = ip6t_get_target(e); 1498 t = ip6t_get_target(e);
1517 ret = xt_compat_target_to_user(t, dstptr, size); 1499 ret = xt_compat_target_to_user(t, dstptr, size);
1518 if (ret) 1500 if (ret)
@@ -1529,7 +1511,7 @@ compat_find_calc_match(struct ip6t_entry_match *m,
1529 const char *name, 1511 const char *name,
1530 const struct ip6t_ip6 *ipv6, 1512 const struct ip6t_ip6 *ipv6,
1531 unsigned int hookmask, 1513 unsigned int hookmask,
1532 int *size, unsigned int *i) 1514 int *size)
1533{ 1515{
1534 struct xt_match *match; 1516 struct xt_match *match;
1535 1517
@@ -1543,18 +1525,6 @@ compat_find_calc_match(struct ip6t_entry_match *m,
1543 } 1525 }
1544 m->u.kernel.match = match; 1526 m->u.kernel.match = match;
1545 *size += xt_compat_match_offset(match); 1527 *size += xt_compat_match_offset(match);
1546
1547 (*i)++;
1548 return 0;
1549}
1550
1551static int
1552compat_release_match(struct ip6t_entry_match *m, unsigned int *i)
1553{
1554 if (i && (*i)-- == 0)
1555 return 1;
1556
1557 module_put(m->u.kernel.match->me);
1558 return 0; 1528 return 0;
1559} 1529}
1560 1530
@@ -1565,8 +1535,7 @@ static void compat_release_entry(struct compat_ip6t_entry *e)
1565 1535
1566 /* Cleanup all matches */ 1536 /* Cleanup all matches */
1567 xt_ematch_foreach(ematch, e) 1537 xt_ematch_foreach(ematch, e)
1568 if (compat_release_match(ematch, NULL) != 0) 1538 module_put(ematch->u.kernel.match->me);
1569 break;
1570 t = compat_ip6t_get_target(e); 1539 t = compat_ip6t_get_target(e);
1571 module_put(t->u.kernel.target->me); 1540 module_put(t->u.kernel.target->me);
1572} 1541}
@@ -1612,12 +1581,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1612 j = 0; 1581 j = 0;
1613 xt_ematch_foreach(ematch, e) { 1582 xt_ematch_foreach(ematch, e) {
1614 ret = compat_find_calc_match(ematch, name, 1583 ret = compat_find_calc_match(ematch, name,
1615 &e->ipv6, e->comefrom, &off, &j); 1584 &e->ipv6, e->comefrom, &off);
1616 if (ret != 0) 1585 if (ret != 0)
1617 break; 1586 goto release_matches;
1587 ++j;
1618 } 1588 }
1619 if (ret != 0)
1620 goto release_matches;
1621 1589
1622 t = compat_ip6t_get_target(e); 1590 t = compat_ip6t_get_target(e);
1623 target = try_then_request_module(xt_find_target(AF_INET6, 1591 target = try_then_request_module(xt_find_target(AF_INET6,
@@ -1654,9 +1622,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1654out: 1622out:
1655 module_put(t->u.kernel.target->me); 1623 module_put(t->u.kernel.target->me);
1656release_matches: 1624release_matches:
1657 xt_ematch_foreach(ematch, e) 1625 xt_ematch_foreach(ematch, e) {
1658 if (compat_release_match(ematch, &j) != 0) 1626 if (j-- == 0)
1659 break; 1627 break;
1628 module_put(ematch->u.kernel.match->me);
1629 }
1660 return ret; 1630 return ret;
1661} 1631}
1662 1632
@@ -1684,10 +1654,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1684 xt_ematch_foreach(ematch, e) { 1654 xt_ematch_foreach(ematch, e) {
1685 ret = xt_compat_match_from_user(ematch, dstptr, size); 1655 ret = xt_compat_match_from_user(ematch, dstptr, size);
1686 if (ret != 0) 1656 if (ret != 0)
1687 break; 1657 return ret;
1688 } 1658 }
1689 if (ret)
1690 return ret;
1691 de->target_offset = e->target_offset - (origsize - *size); 1659 de->target_offset = e->target_offset - (origsize - *size);
1692 t = compat_ip6t_get_target(e); 1660 t = compat_ip6t_get_target(e);
1693 target = t->u.kernel.target; 1661 target = t->u.kernel.target;
@@ -1718,12 +1686,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1718 mtpar.hook_mask = e->comefrom; 1686 mtpar.hook_mask = e->comefrom;
1719 mtpar.family = NFPROTO_IPV6; 1687 mtpar.family = NFPROTO_IPV6;
1720 xt_ematch_foreach(ematch, e) { 1688 xt_ematch_foreach(ematch, e) {
1721 ret = check_match(ematch, &mtpar, &j); 1689 ret = check_match(ematch, &mtpar);
1722 if (ret != 0) 1690 if (ret != 0)
1723 break; 1691 goto cleanup_matches;
1692 ++j;
1724 } 1693 }
1725 if (ret)
1726 goto cleanup_matches;
1727 1694
1728 ret = check_target(e, net, name); 1695 ret = check_target(e, net, name);
1729 if (ret) 1696 if (ret)
@@ -1731,9 +1698,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1731 return 0; 1698 return 0;
1732 1699
1733 cleanup_matches: 1700 cleanup_matches:
1734 xt_ematch_foreach(ematch, e) 1701 xt_ematch_foreach(ematch, e) {
1735 if (cleanup_match(ematch, net, &j) != 0) 1702 if (j-- == 0)
1736 break; 1703 break;
1704 cleanup_match(ematch, net);
1705 }
1737 return ret; 1706 return ret;
1738} 1707}
1739 1708