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 | ||
