aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDmitry Mishin <dim@openvz.org>2006-12-12 03:29:26 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-13 19:48:22 -0500
commita96be24679198469df28976c809575423e70d843 (patch)
tree7bbdc2c1933c2e791789e6203945b37b58f596b4 /net
parent11078c371e2ecfce011d1dffb67888c6fed1b664 (diff)
[NETFILTER]: ip_tables: ipt and ipt_compat checks unification
Matches and targets verification is duplicated in normal and compat processing ways. This patch refactors code in order to remove this. Signed-off-by: Dmitry Mishin <dim@openvz.org> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ip_tables.c176
1 files changed, 79 insertions, 97 deletions
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 0ff2956d35e5..83ebbeb80b6e 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -484,7 +484,47 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
484} 484}
485 485
486static inline int 486static inline int
487check_match(struct ipt_entry_match *m, 487check_entry(struct ipt_entry *e, const char *name)
488{
489 struct ipt_entry_target *t;
490
491 if (!ip_checkentry(&e->ip)) {
492 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
493 return -EINVAL;
494 }
495
496 if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
497 return -EINVAL;
498
499 t = ipt_get_target(e);
500 if (e->target_offset + t->u.target_size > e->next_offset)
501 return -EINVAL;
502
503 return 0;
504}
505
506static inline int check_match(struct ipt_entry_match *m, const char *name,
507 const struct ipt_ip *ip, unsigned int hookmask)
508{
509 struct ipt_match *match;
510 int ret;
511
512 match = m->u.kernel.match;
513 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
514 name, hookmask, ip->proto,
515 ip->invflags & IPT_INV_PROTO);
516 if (!ret && m->u.kernel.match->checkentry
517 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
518 hookmask)) {
519 duprintf("ip_tables: check failed for `%s'.\n",
520 m->u.kernel.match->name);
521 ret = -EINVAL;
522 }
523 return ret;
524}
525
526static inline int
527find_check_match(struct ipt_entry_match *m,
488 const char *name, 528 const char *name,
489 const struct ipt_ip *ip, 529 const struct ipt_ip *ip,
490 unsigned int hookmask, 530 unsigned int hookmask,
@@ -497,26 +537,15 @@ check_match(struct ipt_entry_match *m,
497 m->u.user.revision), 537 m->u.user.revision),
498 "ipt_%s", m->u.user.name); 538 "ipt_%s", m->u.user.name);
499 if (IS_ERR(match) || !match) { 539 if (IS_ERR(match) || !match) {
500 duprintf("check_match: `%s' not found\n", m->u.user.name); 540 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
501 return match ? PTR_ERR(match) : -ENOENT; 541 return match ? PTR_ERR(match) : -ENOENT;
502 } 542 }
503 m->u.kernel.match = match; 543 m->u.kernel.match = match;
504 544
505 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), 545 ret = check_match(m, name, ip, hookmask);
506 name, hookmask, ip->proto,
507 ip->invflags & IPT_INV_PROTO);
508 if (ret) 546 if (ret)
509 goto err; 547 goto err;
510 548
511 if (m->u.kernel.match->checkentry
512 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
513 hookmask)) {
514 duprintf("ip_tables: check failed for `%s'.\n",
515 m->u.kernel.match->name);
516 ret = -EINVAL;
517 goto err;
518 }
519
520 (*i)++; 549 (*i)++;
521 return 0; 550 return 0;
522err: 551err:
@@ -524,10 +553,29 @@ err:
524 return ret; 553 return ret;
525} 554}
526 555
527static struct ipt_target ipt_standard_target; 556static inline int check_target(struct ipt_entry *e, const char *name)
557{
558 struct ipt_entry_target *t;
559 struct ipt_target *target;
560 int ret;
561
562 t = ipt_get_target(e);
563 target = t->u.kernel.target;
564 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
565 name, e->comefrom, e->ip.proto,
566 e->ip.invflags & IPT_INV_PROTO);
567 if (!ret && t->u.kernel.target->checkentry
568 && !t->u.kernel.target->checkentry(name, e, target,
569 t->data, e->comefrom)) {
570 duprintf("ip_tables: check failed for `%s'.\n",
571 t->u.kernel.target->name);
572 ret = -EINVAL;
573 }
574 return ret;
575}
528 576
529static inline int 577static inline int
530check_entry(struct ipt_entry *e, const char *name, unsigned int size, 578find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
531 unsigned int *i) 579 unsigned int *i)
532{ 580{
533 struct ipt_entry_target *t; 581 struct ipt_entry_target *t;
@@ -535,49 +583,32 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
535 int ret; 583 int ret;
536 unsigned int j; 584 unsigned int j;
537 585
538 if (!ip_checkentry(&e->ip)) { 586 ret = check_entry(e, name);
539 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 587 if (ret)
540 return -EINVAL; 588 return ret;
541 }
542
543 if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
544 return -EINVAL;
545 589
546 j = 0; 590 j = 0;
547 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); 591 ret = IPT_MATCH_ITERATE(e, find_check_match, name, &e->ip,
592 e->comefrom, &j);
548 if (ret != 0) 593 if (ret != 0)
549 goto cleanup_matches; 594 goto cleanup_matches;
550 595
551 t = ipt_get_target(e); 596 t = ipt_get_target(e);
552 ret = -EINVAL;
553 if (e->target_offset + t->u.target_size > e->next_offset)
554 goto cleanup_matches;
555 target = try_then_request_module(xt_find_target(AF_INET, 597 target = try_then_request_module(xt_find_target(AF_INET,
556 t->u.user.name, 598 t->u.user.name,
557 t->u.user.revision), 599 t->u.user.revision),
558 "ipt_%s", t->u.user.name); 600 "ipt_%s", t->u.user.name);
559 if (IS_ERR(target) || !target) { 601 if (IS_ERR(target) || !target) {
560 duprintf("check_entry: `%s' not found\n", t->u.user.name); 602 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
561 ret = target ? PTR_ERR(target) : -ENOENT; 603 ret = target ? PTR_ERR(target) : -ENOENT;
562 goto cleanup_matches; 604 goto cleanup_matches;
563 } 605 }
564 t->u.kernel.target = target; 606 t->u.kernel.target = target;
565 607
566 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 608 ret = check_target(e, name);
567 name, e->comefrom, e->ip.proto,
568 e->ip.invflags & IPT_INV_PROTO);
569 if (ret) 609 if (ret)
570 goto err; 610 goto err;
571 611
572 if (t->u.kernel.target->checkentry
573 && !t->u.kernel.target->checkentry(name, e, target, t->data,
574 e->comefrom)) {
575 duprintf("ip_tables: check failed for `%s'.\n",
576 t->u.kernel.target->name);
577 ret = -EINVAL;
578 goto err;
579 }
580
581 (*i)++; 612 (*i)++;
582 return 0; 613 return 0;
583 err: 614 err:
@@ -712,7 +743,7 @@ translate_table(const char *name,
712 /* Finally, each sanity check must pass */ 743 /* Finally, each sanity check must pass */
713 i = 0; 744 i = 0;
714 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 745 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
715 check_entry, name, size, &i); 746 find_check_entry, name, size, &i);
716 747
717 if (ret != 0) { 748 if (ret != 0) {
718 IPT_ENTRY_ITERATE(entry0, newinfo->size, 749 IPT_ENTRY_ITERATE(entry0, newinfo->size,
@@ -1452,14 +1483,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
1452 return -EINVAL; 1483 return -EINVAL;
1453 } 1484 }
1454 1485
1455 if (!ip_checkentry(&e->ip)) { 1486 ret = check_entry(e, name);
1456 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 1487 if (ret)
1457 return -EINVAL; 1488 return ret;
1458 }
1459
1460 if (e->target_offset + sizeof(struct compat_xt_entry_target) >
1461 e->next_offset)
1462 return -EINVAL;
1463 1489
1464 off = 0; 1490 off = 0;
1465 entry_offset = (void *)e - (void *)base; 1491 entry_offset = (void *)e - (void *)base;
@@ -1470,15 +1496,13 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
1470 goto cleanup_matches; 1496 goto cleanup_matches;
1471 1497
1472 t = ipt_get_target(e); 1498 t = ipt_get_target(e);
1473 ret = -EINVAL;
1474 if (e->target_offset + t->u.target_size > e->next_offset)
1475 goto cleanup_matches;
1476 target = try_then_request_module(xt_find_target(AF_INET, 1499 target = try_then_request_module(xt_find_target(AF_INET,
1477 t->u.user.name, 1500 t->u.user.name,
1478 t->u.user.revision), 1501 t->u.user.revision),
1479 "ipt_%s", t->u.user.name); 1502 "ipt_%s", t->u.user.name);
1480 if (IS_ERR(target) || !target) { 1503 if (IS_ERR(target) || !target) {
1481 duprintf("check_entry: `%s' not found\n", t->u.user.name); 1504 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1505 t->u.user.name);
1482 ret = target ? PTR_ERR(target) : -ENOENT; 1506 ret = target ? PTR_ERR(target) : -ENOENT;
1483 goto cleanup_matches; 1507 goto cleanup_matches;
1484 } 1508 }
@@ -1555,57 +1579,15 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1555 return ret; 1579 return ret;
1556} 1580}
1557 1581
1558static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
1559 const struct ipt_ip *ip, unsigned int hookmask)
1560{
1561 struct ipt_match *match;
1562 int ret;
1563
1564 match = m->u.kernel.match;
1565 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
1566 name, hookmask, ip->proto,
1567 ip->invflags & IPT_INV_PROTO);
1568 if (!ret && m->u.kernel.match->checkentry
1569 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
1570 hookmask)) {
1571 duprintf("ip_tables: compat: check failed for `%s'.\n",
1572 m->u.kernel.match->name);
1573 ret = -EINVAL;
1574 }
1575 return ret;
1576}
1577
1578static inline int compat_check_target(struct ipt_entry *e, const char *name)
1579{
1580 struct ipt_entry_target *t;
1581 struct ipt_target *target;
1582 int ret;
1583
1584 t = ipt_get_target(e);
1585 target = t->u.kernel.target;
1586 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1587 name, e->comefrom, e->ip.proto,
1588 e->ip.invflags & IPT_INV_PROTO);
1589 if (!ret && t->u.kernel.target->checkentry
1590 && !t->u.kernel.target->checkentry(name, e, target,
1591 t->data, e->comefrom)) {
1592 duprintf("ip_tables: compat: check failed for `%s'.\n",
1593 t->u.kernel.target->name);
1594 ret = -EINVAL;
1595 }
1596 return ret;
1597}
1598
1599static inline int compat_check_entry(struct ipt_entry *e, const char *name) 1582static inline int compat_check_entry(struct ipt_entry *e, const char *name)
1600{ 1583{
1601 int ret; 1584 int ret;
1602 1585
1603 ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip, 1586 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
1604 e->comefrom);
1605 if (ret) 1587 if (ret)
1606 return ret; 1588 return ret;
1607 1589
1608 return compat_check_target(e, name); 1590 return check_target(e, name);
1609} 1591}
1610 1592
1611static int 1593static int