aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_tables.c93
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
575static int 575static void cleanup_match(struct ipt_entry_match *m, struct net *net)
576cleanup_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
593static int 588static int
@@ -612,8 +607,7 @@ check_entry(const struct ipt_entry *e, const char *name)
612} 607}
613 608
614static int 609static int
615check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, 610check_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
635static int 628static int
636find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, 629find_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
1067static inline int
1068compat_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
1074static int compat_calc_entry(const struct ipt_entry *e, 1059static 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
1518static int
1519compat_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,
1621out: 1589out:
1622 module_put(t->u.kernel.target->me); 1590 module_put(t->u.kernel.target->me);
1623release_matches: 1591release_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