X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fipt_addrtype.c;h=3b216be3bc9fbcf940d00dff5c8d428ec229fe59;hb=a83d8e8d099fc373a5ca7112ad08c553bb2c180f;hp=5fdf85d0efcfeb1b54861fd4cf8598779014543c;hpb=c49867347404c46f137a261643ed4fce4376f324;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index 5fdf85d..3b216be 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -2,6 +2,7 @@ * iptables module to match inet_addr_type() of an ip. * * Copyright (c) 2004 Patrick McHardy + * (C) 2007 Laszlo Attila Toth * * 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 @@ -16,50 +17,118 @@ #include #include -#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Patrick McHardy "); -MODULE_DESCRIPTION("iptables addrtype match"); +MODULE_DESCRIPTION("Xtables: address type match for IPv4"); -static inline int match_type(u_int32_t addr, u_int16_t mask) +static inline bool match_type(struct net *net, const struct net_device *dev, + __be32 addr, u_int16_t mask) { - return !!(mask & (1 << inet_addr_type(addr))); + return !!(mask & (1 << inet_dev_addr_type(net, dev, addr))); } -static int match(const struct sk_buff *skb, - const struct net_device *in, const struct net_device *out, - const struct xt_match *match, const void *matchinfo, - int offset, unsigned int protoff, int *hotdrop) +static bool +addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) { - const struct ipt_addrtype_info *info = matchinfo; - const struct iphdr *iph = skb->nh.iph; - int ret = 1; + struct net *net = dev_net(par->in ? par->in : par->out); + const struct ipt_addrtype_info *info = par->matchinfo; + const struct iphdr *iph = ip_hdr(skb); + bool ret = true; if (info->source) - ret &= match_type(iph->saddr, info->source)^info->invert_source; + ret &= match_type(net, NULL, iph->saddr, info->source) ^ + info->invert_source; if (info->dest) - ret &= match_type(iph->daddr, info->dest)^info->invert_dest; - + ret &= match_type(net, NULL, iph->daddr, info->dest) ^ + info->invert_dest; + + return ret; +} + +static bool +addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) +{ + struct net *net = dev_net(par->in ? par->in : par->out); + const struct ipt_addrtype_info_v1 *info = par->matchinfo; + const struct iphdr *iph = ip_hdr(skb); + const struct net_device *dev = NULL; + bool ret = true; + + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) + dev = par->in; + else if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) + dev = par->out; + + if (info->source) + ret &= match_type(net, dev, iph->saddr, info->source) ^ + (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); + if (ret && info->dest) + ret &= match_type(net, dev, iph->daddr, info->dest) ^ + !!(info->flags & IPT_ADDRTYPE_INVERT_DEST); return ret; } -static struct ipt_match addrtype_match = { - .name = "addrtype", - .match = match, - .matchsize = sizeof(struct ipt_addrtype_info), - .me = THIS_MODULE +static bool addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par) +{ + struct ipt_addrtype_info_v1 *info = par->matchinfo; + + if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN && + info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printk(KERN_ERR "ipt_addrtype: both incoming and outgoing " + "interface limitation cannot be selected\n"); + return false; + } + + if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN)) && + info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { + printk(KERN_ERR "ipt_addrtype: output interface limitation " + "not valid in PRE_ROUTING and INPUT\n"); + return false; + } + + if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) | + (1 << NF_INET_LOCAL_OUT)) && + info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { + printk(KERN_ERR "ipt_addrtype: input interface limitation " + "not valid in POST_ROUTING and OUTPUT\n"); + return false; + } + + return true; +} + +static struct xt_match addrtype_mt_reg[] __read_mostly = { + { + .name = "addrtype", + .family = NFPROTO_IPV4, + .match = addrtype_mt_v0, + .matchsize = sizeof(struct ipt_addrtype_info), + .me = THIS_MODULE + }, + { + .name = "addrtype", + .family = NFPROTO_IPV4, + .revision = 1, + .match = addrtype_mt_v1, + .checkentry = addrtype_mt_checkentry_v1, + .matchsize = sizeof(struct ipt_addrtype_info_v1), + .me = THIS_MODULE + } }; -static int __init init(void) +static int __init addrtype_mt_init(void) { - return ipt_register_match(&addrtype_match); + return xt_register_matches(addrtype_mt_reg, + ARRAY_SIZE(addrtype_mt_reg)); } -static void __exit fini(void) +static void __exit addrtype_mt_exit(void) { - ipt_unregister_match(&addrtype_match); + xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg)); } -module_init(init); -module_exit(fini); +module_init(addrtype_mt_init); +module_exit(addrtype_mt_exit);