X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fiptable_mangle.c;h=c55a210853a7a5e92d10cecf30dabe645a6355c3;hb=720ac7085ce815ea4caec24396575fed7bd711aa;hp=412fc96cc8968c6f22d8d6576a65557f52e00a7a;hpb=65b4b4e81a5094d52cbe372b887b1779abe53f9b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 412fc96..c55a210 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -7,10 +7,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * Extended to all five netfilter hooks by Brad Chapman & Harald Welte */ -#include #include #include #include @@ -18,16 +15,17 @@ #include #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables mangle table"); -#define MANGLE_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | \ - (1 << NF_IP_LOCAL_IN) | \ - (1 << NF_IP_FORWARD) | \ - (1 << NF_IP_LOCAL_OUT) | \ - (1 << NF_IP_POST_ROUTING)) +#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \ + (1 << NF_INET_LOCAL_IN) | \ + (1 << NF_INET_FORWARD) | \ + (1 << NF_INET_LOCAL_OUT) | \ + (1 << NF_INET_POST_ROUTING)) /* Ouch - five different hooks? Maybe this should be a config option..... -- BC */ static struct @@ -35,76 +33,38 @@ static struct struct ipt_replace repl; struct ipt_standard entries[5]; struct ipt_error term; -} initial_table __initdata -= { { "mangle", MANGLE_VALID_HOOKS, 6, - sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), - { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, - { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, - 0, NULL, { } }, - { - /* PRE_ROUTING */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_IN */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* FORWARD */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* POST_ROUTING */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - }, - /* ERROR */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_error), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __net_initdata = { + .repl = { + .name = "mangle", + .valid_hooks = MANGLE_VALID_HOOKS, + .num_entries = 6, + .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), + .hook_entry = { + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + }, + .underflow = { + [NF_INET_PRE_ROUTING] = 0, + [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + }, + }, + .entries = { + IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ + IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ + IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ + }, + .term = IPT_ERROR_INIT, /* ERROR */ }; -static struct ipt_table packet_mangler = { +static struct xt_table packet_mangler = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, @@ -115,146 +75,141 @@ static struct ipt_table packet_mangler = { /* The work comes in here from netfilter.c. */ static unsigned int ipt_route_hook(unsigned int hook, - struct sk_buff **pskb, + struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); + return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); } static unsigned int ipt_local_hook(unsigned int hook, - struct sk_buff **pskb, + struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int ret; + const struct iphdr *iph; u_int8_t tos; - u_int32_t saddr, daddr; - unsigned long nfmark; + __be32 saddr, daddr; + u_int32_t mark; /* root is playing with raw sockets. */ - if ((*pskb)->len < sizeof(struct iphdr) - || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { + if (skb->len < sizeof(struct iphdr) + || ip_hdrlen(skb) < sizeof(struct iphdr)) { if (net_ratelimit()) - printk("ipt_hook: happy cracking.\n"); + printk("iptable_mangle: ignoring short SOCK_RAW " + "packet.\n"); return NF_ACCEPT; } /* Save things which could affect route */ - nfmark = (*pskb)->nfmark; - saddr = (*pskb)->nh.iph->saddr; - daddr = (*pskb)->nh.iph->daddr; - tos = (*pskb)->nh.iph->tos; + mark = skb->mark; + iph = ip_hdr(skb); + saddr = iph->saddr; + daddr = iph->daddr; + tos = iph->tos; - ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); + ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); /* Reroute for ANY change. */ - if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE - && ((*pskb)->nh.iph->saddr != saddr - || (*pskb)->nh.iph->daddr != daddr -#ifdef CONFIG_IP_ROUTE_FWMARK - || (*pskb)->nfmark != nfmark -#endif - || (*pskb)->nh.iph->tos != tos)) - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; + if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { + iph = ip_hdr(skb); + + if (iph->saddr != saddr || + iph->daddr != daddr || + skb->mark != mark || + iph->tos != tos) + if (ip_route_me_harder(skb, RTN_UNSPEC)) + ret = NF_DROP; + } return ret; } -static struct nf_hook_ops ipt_ops[] = { +static struct nf_hook_ops ipt_ops[] __read_mostly = { { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, + .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, + .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_FORWARD, + .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_local_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, + .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_MANGLE, }, { .hook = ipt_route_hook, .owner = THIS_MODULE, .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, + .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_MANGLE, }, }; +static int __net_init iptable_mangle_net_init(struct net *net) +{ + /* Register table */ + net->ipv4.iptable_mangle = + ipt_register_table(net, &packet_mangler, &initial_table.repl); + if (IS_ERR(net->ipv4.iptable_mangle)) + return PTR_ERR(net->ipv4.iptable_mangle); + return 0; +} + +static void __net_exit iptable_mangle_net_exit(struct net *net) +{ + ipt_unregister_table(net->ipv4.iptable_mangle); +} + +static struct pernet_operations iptable_mangle_net_ops = { + .init = iptable_mangle_net_init, + .exit = iptable_mangle_net_exit, +}; + static int __init iptable_mangle_init(void) { int ret; - /* Register table */ - ret = ipt_register_table(&packet_mangler, &initial_table.repl); + ret = register_pernet_subsys(&iptable_mangle_net_ops); if (ret < 0) return ret; /* Register hooks */ - ret = nf_register_hook(&ipt_ops[0]); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ipt_ops[1]); - if (ret < 0) - goto cleanup_hook0; - - ret = nf_register_hook(&ipt_ops[2]); - if (ret < 0) - goto cleanup_hook1; - - ret = nf_register_hook(&ipt_ops[3]); - if (ret < 0) - goto cleanup_hook2; - - ret = nf_register_hook(&ipt_ops[4]); - if (ret < 0) - goto cleanup_hook3; - return ret; - cleanup_hook3: - nf_unregister_hook(&ipt_ops[3]); - cleanup_hook2: - nf_unregister_hook(&ipt_ops[2]); - cleanup_hook1: - nf_unregister_hook(&ipt_ops[1]); - cleanup_hook0: - nf_unregister_hook(&ipt_ops[0]); cleanup_table: - ipt_unregister_table(&packet_mangler); - + unregister_pernet_subsys(&iptable_mangle_net_ops); return ret; } static void __exit iptable_mangle_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ipt_ops[i]); - - ipt_unregister_table(&packet_mangler); + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + unregister_pernet_subsys(&iptable_mangle_net_ops); } module_init(iptable_mangle_init);