diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2010-02-24 12:35:37 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-02-24 12:35:37 -0500 |
commit | 6bdb331bc6910d1ccb74dc9852fc858c5916c927 (patch) | |
tree | d77dd2df2d6d43ce25703ce8c9ecab0173c14a7f /net/ipv4 | |
parent | dcea992aca82cb08b4674c4c783e325835408d1e (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/ipv4')
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 93 |
1 files changed, 31 insertions, 62 deletions
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3a7fc732b918..36edc7d5f284 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -572,14 +572,10 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
572 | return 1; | 572 | return 1; |
573 | } | 573 | } |
574 | 574 | ||
575 | static int | 575 | static void cleanup_match(struct ipt_entry_match *m, struct net *net) |
576 | cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) | ||
577 | { | 576 | { |
578 | struct xt_mtdtor_param par; | 577 | struct xt_mtdtor_param par; |
579 | 578 | ||
580 | if (i && (*i)-- == 0) | ||
581 | return 1; | ||
582 | |||
583 | par.net = net; | 579 | par.net = net; |
584 | par.match = m->u.kernel.match; | 580 | par.match = m->u.kernel.match; |
585 | par.matchinfo = m->data; | 581 | par.matchinfo = m->data; |
@@ -587,7 +583,6 @@ cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) | |||
587 | if (par.match->destroy != NULL) | 583 | if (par.match->destroy != NULL) |
588 | par.match->destroy(&par); | 584 | par.match->destroy(&par); |
589 | module_put(par.match->me); | 585 | module_put(par.match->me); |
590 | return 0; | ||
591 | } | 586 | } |
592 | 587 | ||
593 | static int | 588 | static int |
@@ -612,8 +607,7 @@ check_entry(const struct ipt_entry *e, const char *name) | |||
612 | } | 607 | } |
613 | 608 | ||
614 | static int | 609 | static int |
615 | check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | 610 | check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) |
616 | unsigned int *i) | ||
617 | { | 611 | { |
618 | const struct ipt_ip *ip = par->entryinfo; | 612 | const struct ipt_ip *ip = par->entryinfo; |
619 | int ret; | 613 | int ret; |
@@ -628,13 +622,11 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | |||
628 | par.match->name); | 622 | par.match->name); |
629 | return ret; | 623 | return ret; |
630 | } | 624 | } |
631 | ++*i; | ||
632 | return 0; | 625 | return 0; |
633 | } | 626 | } |
634 | 627 | ||
635 | static int | 628 | static int |
636 | find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | 629 | find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) |
637 | unsigned int *i) | ||
638 | { | 630 | { |
639 | struct xt_match *match; | 631 | struct xt_match *match; |
640 | int ret; | 632 | int ret; |
@@ -648,7 +640,7 @@ find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | |||
648 | } | 640 | } |
649 | m->u.kernel.match = match; | 641 | m->u.kernel.match = match; |
650 | 642 | ||
651 | ret = check_match(m, par, i); | 643 | ret = check_match(m, par); |
652 | if (ret) | 644 | if (ret) |
653 | goto err; | 645 | goto err; |
654 | 646 | ||
@@ -704,12 +696,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, | |||
704 | mtpar.hook_mask = e->comefrom; | 696 | mtpar.hook_mask = e->comefrom; |
705 | mtpar.family = NFPROTO_IPV4; | 697 | mtpar.family = NFPROTO_IPV4; |
706 | xt_ematch_foreach(ematch, e) { | 698 | xt_ematch_foreach(ematch, e) { |
707 | ret = find_check_match(ematch, &mtpar, &j); | 699 | ret = find_check_match(ematch, &mtpar); |
708 | if (ret != 0) | 700 | if (ret != 0) |
709 | break; | 701 | goto cleanup_matches; |
702 | ++j; | ||
710 | } | 703 | } |
711 | if (ret != 0) | ||
712 | goto cleanup_matches; | ||
713 | 704 | ||
714 | t = ipt_get_target(e); | 705 | t = ipt_get_target(e); |
715 | target = try_then_request_module(xt_find_target(AF_INET, | 706 | target = try_then_request_module(xt_find_target(AF_INET, |
@@ -730,9 +721,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, | |||
730 | err: | 721 | err: |
731 | module_put(t->u.kernel.target->me); | 722 | module_put(t->u.kernel.target->me); |
732 | cleanup_matches: | 723 | cleanup_matches: |
733 | xt_ematch_foreach(ematch, e) | 724 | xt_ematch_foreach(ematch, e) { |
734 | if (cleanup_match(ematch, net, &j) != 0) | 725 | if (j-- == 0) |
735 | break; | 726 | break; |
727 | cleanup_match(ematch, net); | ||
728 | } | ||
736 | return ret; | 729 | return ret; |
737 | } | 730 | } |
738 | 731 | ||
@@ -807,8 +800,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net) | |||
807 | 800 | ||
808 | /* Cleanup all matches */ | 801 | /* Cleanup all matches */ |
809 | xt_ematch_foreach(ematch, e) | 802 | xt_ematch_foreach(ematch, e) |
810 | if (cleanup_match(ematch, net, NULL) != 0) | 803 | cleanup_match(ematch, net); |
811 | break; | ||
812 | t = ipt_get_target(e); | 804 | t = ipt_get_target(e); |
813 | 805 | ||
814 | par.net = net; | 806 | par.net = net; |
@@ -1064,13 +1056,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) | |||
1064 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; | 1056 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; |
1065 | } | 1057 | } |
1066 | 1058 | ||
1067 | static inline int | ||
1068 | compat_calc_match(const struct ipt_entry_match *m, int *size) | ||
1069 | { | ||
1070 | *size += xt_compat_match_offset(m->u.kernel.match); | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | static int compat_calc_entry(const struct ipt_entry *e, | 1059 | static int compat_calc_entry(const struct ipt_entry *e, |
1075 | const struct xt_table_info *info, | 1060 | const struct xt_table_info *info, |
1076 | const void *base, struct xt_table_info *newinfo) | 1061 | const void *base, struct xt_table_info *newinfo) |
@@ -1083,8 +1068,7 @@ static int compat_calc_entry(const struct ipt_entry *e, | |||
1083 | off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); | 1068 | off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); |
1084 | entry_offset = (void *)e - base; | 1069 | entry_offset = (void *)e - base; |
1085 | xt_ematch_foreach(ematch, e) | 1070 | xt_ematch_foreach(ematch, e) |
1086 | if (compat_calc_match(ematch, &off) != 0) | 1071 | off += xt_compat_match_offset(ematch->u.kernel.match); |
1087 | break; | ||
1088 | t = ipt_get_target_c(e); | 1072 | t = ipt_get_target_c(e); |
1089 | off += xt_compat_target_offset(t->u.kernel.target); | 1073 | off += xt_compat_target_offset(t->u.kernel.target); |
1090 | newinfo->size -= off; | 1074 | newinfo->size -= off; |
@@ -1475,11 +1459,9 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, | |||
1475 | xt_ematch_foreach(ematch, e) { | 1459 | xt_ematch_foreach(ematch, e) { |
1476 | ret = xt_compat_match_to_user(ematch, dstptr, size); | 1460 | ret = xt_compat_match_to_user(ematch, dstptr, size); |
1477 | if (ret != 0) | 1461 | if (ret != 0) |
1478 | break; | 1462 | return ret; |
1479 | } | 1463 | } |
1480 | target_offset = e->target_offset - (origsize - *size); | 1464 | target_offset = e->target_offset - (origsize - *size); |
1481 | if (ret) | ||
1482 | return ret; | ||
1483 | t = ipt_get_target(e); | 1465 | t = ipt_get_target(e); |
1484 | ret = xt_compat_target_to_user(t, dstptr, size); | 1466 | ret = xt_compat_target_to_user(t, dstptr, size); |
1485 | if (ret) | 1467 | if (ret) |
@@ -1496,7 +1478,7 @@ compat_find_calc_match(struct ipt_entry_match *m, | |||
1496 | const char *name, | 1478 | const char *name, |
1497 | const struct ipt_ip *ip, | 1479 | const struct ipt_ip *ip, |
1498 | unsigned int hookmask, | 1480 | unsigned int hookmask, |
1499 | int *size, unsigned int *i) | 1481 | int *size) |
1500 | { | 1482 | { |
1501 | struct xt_match *match; | 1483 | struct xt_match *match; |
1502 | 1484 | ||
@@ -1510,18 +1492,6 @@ compat_find_calc_match(struct ipt_entry_match *m, | |||
1510 | } | 1492 | } |
1511 | m->u.kernel.match = match; | 1493 | m->u.kernel.match = match; |
1512 | *size += xt_compat_match_offset(match); | 1494 | *size += xt_compat_match_offset(match); |
1513 | |||
1514 | (*i)++; | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | static int | ||
1519 | compat_release_match(struct ipt_entry_match *m, unsigned int *i) | ||
1520 | { | ||
1521 | if (i && (*i)-- == 0) | ||
1522 | return 1; | ||
1523 | |||
1524 | module_put(m->u.kernel.match->me); | ||
1525 | return 0; | 1495 | return 0; |
1526 | } | 1496 | } |
1527 | 1497 | ||
@@ -1532,8 +1502,7 @@ static void compat_release_entry(struct compat_ipt_entry *e) | |||
1532 | 1502 | ||
1533 | /* Cleanup all matches */ | 1503 | /* Cleanup all matches */ |
1534 | xt_ematch_foreach(ematch, e) | 1504 | xt_ematch_foreach(ematch, e) |
1535 | if (compat_release_match(ematch, NULL) != 0) | 1505 | module_put(ematch->u.kernel.match->me); |
1536 | break; | ||
1537 | t = compat_ipt_get_target(e); | 1506 | t = compat_ipt_get_target(e); |
1538 | module_put(t->u.kernel.target->me); | 1507 | module_put(t->u.kernel.target->me); |
1539 | } | 1508 | } |
@@ -1579,12 +1548,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1579 | j = 0; | 1548 | j = 0; |
1580 | xt_ematch_foreach(ematch, e) { | 1549 | xt_ematch_foreach(ematch, e) { |
1581 | ret = compat_find_calc_match(ematch, name, | 1550 | ret = compat_find_calc_match(ematch, name, |
1582 | &e->ip, e->comefrom, &off, &j); | 1551 | &e->ip, e->comefrom, &off); |
1583 | if (ret != 0) | 1552 | if (ret != 0) |
1584 | break; | 1553 | goto release_matches; |
1554 | ++j; | ||
1585 | } | 1555 | } |
1586 | if (ret != 0) | ||
1587 | goto release_matches; | ||
1588 | 1556 | ||
1589 | t = compat_ipt_get_target(e); | 1557 | t = compat_ipt_get_target(e); |
1590 | target = try_then_request_module(xt_find_target(AF_INET, | 1558 | target = try_then_request_module(xt_find_target(AF_INET, |
@@ -1621,9 +1589,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1621 | out: | 1589 | out: |
1622 | module_put(t->u.kernel.target->me); | 1590 | module_put(t->u.kernel.target->me); |
1623 | release_matches: | 1591 | release_matches: |
1624 | xt_ematch_foreach(ematch, e) | 1592 | xt_ematch_foreach(ematch, e) { |
1625 | if (compat_release_match(ematch, &j) != 0) | 1593 | if (j-- == 0) |
1626 | break; | 1594 | break; |
1595 | module_put(ematch->u.kernel.match->me); | ||
1596 | } | ||
1627 | return ret; | 1597 | return ret; |
1628 | } | 1598 | } |
1629 | 1599 | ||
@@ -1651,10 +1621,8 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, | |||
1651 | xt_ematch_foreach(ematch, e) { | 1621 | xt_ematch_foreach(ematch, e) { |
1652 | ret = xt_compat_match_from_user(ematch, dstptr, size); | 1622 | ret = xt_compat_match_from_user(ematch, dstptr, size); |
1653 | if (ret != 0) | 1623 | if (ret != 0) |
1654 | break; | 1624 | return ret; |
1655 | } | 1625 | } |
1656 | if (ret) | ||
1657 | return ret; | ||
1658 | de->target_offset = e->target_offset - (origsize - *size); | 1626 | de->target_offset = e->target_offset - (origsize - *size); |
1659 | t = compat_ipt_get_target(e); | 1627 | t = compat_ipt_get_target(e); |
1660 | target = t->u.kernel.target; | 1628 | target = t->u.kernel.target; |
@@ -1685,12 +1653,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) | |||
1685 | mtpar.hook_mask = e->comefrom; | 1653 | mtpar.hook_mask = e->comefrom; |
1686 | mtpar.family = NFPROTO_IPV4; | 1654 | mtpar.family = NFPROTO_IPV4; |
1687 | xt_ematch_foreach(ematch, e) { | 1655 | xt_ematch_foreach(ematch, e) { |
1688 | ret = check_match(ematch, &mtpar, &j); | 1656 | ret = check_match(ematch, &mtpar); |
1689 | if (ret != 0) | 1657 | if (ret != 0) |
1690 | break; | 1658 | goto cleanup_matches; |
1659 | ++j; | ||
1691 | } | 1660 | } |
1692 | if (ret) | ||
1693 | goto cleanup_matches; | ||
1694 | 1661 | ||
1695 | ret = check_target(e, net, name); | 1662 | ret = check_target(e, net, name); |
1696 | if (ret) | 1663 | if (ret) |
@@ -1698,9 +1665,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) | |||
1698 | return 0; | 1665 | return 0; |
1699 | 1666 | ||
1700 | cleanup_matches: | 1667 | cleanup_matches: |
1701 | xt_ematch_foreach(ematch, e) | 1668 | xt_ematch_foreach(ematch, e) { |
1702 | if (cleanup_match(ematch, net, &j) != 0) | 1669 | if (j-- == 0) |
1703 | break; | 1670 | break; |
1671 | cleanup_match(ematch, net); | ||
1672 | } | ||
1704 | return ret; | 1673 | return ret; |
1705 | } | 1674 | } |
1706 | 1675 | ||