X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbridge%2Fnetfilter%2Febt_ip.c;h=65b665ce57b5f3b2da41627f674142eb9c3ac8d8;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=7bab7d065bd3038cd1bc96c081a9f90f77d6078d;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 7bab7d065..65b665ce5 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -28,41 +29,46 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, unsigned int datalen) { struct ebt_ip_info *info = (struct ebt_ip_info *)data; - union {struct iphdr iph; struct tcpudphdr ports;} u; + struct iphdr _iph, *ih; + struct tcpudphdr _ports, *pptr; - if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph))) + ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); + if (ih == NULL) return EBT_NOMATCH; if (info->bitmask & EBT_IP_TOS && - FWINV(info->tos != u.iph.tos, EBT_IP_TOS)) + FWINV(info->tos != ih->tos, EBT_IP_TOS)) return EBT_NOMATCH; if (info->bitmask & EBT_IP_SOURCE && - FWINV((u.iph.saddr & info->smsk) != + FWINV((ih->saddr & info->smsk) != info->saddr, EBT_IP_SOURCE)) return EBT_NOMATCH; if ((info->bitmask & EBT_IP_DEST) && - FWINV((u.iph.daddr & info->dmsk) != + FWINV((ih->daddr & info->dmsk) != info->daddr, EBT_IP_DEST)) return EBT_NOMATCH; if (info->bitmask & EBT_IP_PROTO) { - if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO)) + if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) return EBT_NOMATCH; if (!(info->bitmask & EBT_IP_DPORT) && !(info->bitmask & EBT_IP_SPORT)) return EBT_MATCH; - if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports, - sizeof(u.ports))) + if (ntohs(ih->frag_off) & IP_OFFSET) + return EBT_NOMATCH; + pptr = skb_header_pointer(skb, ih->ihl*4, + sizeof(_ports), &_ports); + if (pptr == NULL) return EBT_NOMATCH; if (info->bitmask & EBT_IP_DPORT) { - u.ports.dst = ntohs(u.ports.dst); - if (FWINV(u.ports.dst < info->dport[0] || - u.ports.dst > info->dport[1], + u32 dst = ntohs(pptr->dst); + if (FWINV(dst < info->dport[0] || + dst > info->dport[1], EBT_IP_DPORT)) return EBT_NOMATCH; } if (info->bitmask & EBT_IP_SPORT) { - u.ports.src = ntohs(u.ports.src); - if (FWINV(u.ports.src < info->sport[0] || - u.ports.src > info->sport[1], + u32 src = ntohs(pptr->src); + if (FWINV(src < info->sport[0] || + src > info->sport[1], EBT_IP_SPORT)) return EBT_NOMATCH; } @@ -77,7 +83,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info))) return -EINVAL; - if (e->ethproto != __constant_htons(ETH_P_IP) || + if (e->ethproto != htons(ETH_P_IP) || e->invflags & EBT_IPROTO) return -EINVAL; if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) @@ -86,7 +92,9 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, if (info->invflags & EBT_IP_PROTO) return -EINVAL; if (info->protocol != IPPROTO_TCP && - info->protocol != IPPROTO_UDP) + info->protocol != IPPROTO_UDP && + info->protocol != IPPROTO_SCTP && + info->protocol != IPPROTO_DCCP) return -EINVAL; } if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) @@ -104,16 +112,16 @@ static struct ebt_match filter_ip = .me = THIS_MODULE, }; -static int __init init(void) +static int __init ebt_ip_init(void) { return ebt_register_match(&filter_ip); } -static void __exit fini(void) +static void __exit ebt_ip_fini(void) { ebt_unregister_match(&filter_ip); } -module_init(init); -module_exit(fini); +module_init(ebt_ip_init); +module_exit(ebt_ip_fini); MODULE_LICENSE("GPL");