X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fbridge%2Fnetfilter%2Febt_arp.c;h=7c535be75665ce8dd32c23818c866ed972601976;hb=62429f434091586d54b37b8dd46076e7c08b27b9;hp=9c599800a90005b2a4602d6782daf86fb7b576ce;hpb=7e23772f414cdbfb2a08aed237d6e926bb1cb728;p=linux-2.6 diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index 9c599800a9..7c535be756 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c @@ -18,8 +18,9 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - struct ebt_arp_info *info = (struct ebt_arp_info *)data; - struct arphdr _arph, *ah; + const struct ebt_arp_info *info = data; + const struct arphdr *ah; + struct arphdr _arph; ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); if (ah == NULL) @@ -34,41 +35,39 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in ah->ar_pro, EBT_ARP_PTYPE)) return EBT_NOMATCH; - if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { - __be32 _addr, *ap; + if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { + const __be32 *sap, *dap; + __be32 saddr, daddr; - /* IPv4 addresses are always 4 bytes */ - if (ah->ar_pln != sizeof(__be32)) + if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP)) + return EBT_NOMATCH; + sap = skb_header_pointer(skb, sizeof(struct arphdr) + + ah->ar_hln, sizeof(saddr), + &saddr); + if (sap == NULL) + return EBT_NOMATCH; + dap = skb_header_pointer(skb, sizeof(struct arphdr) + + 2*ah->ar_hln+sizeof(saddr), + sizeof(daddr), &daddr); + if (dap == NULL) + return EBT_NOMATCH; + if (info->bitmask & EBT_ARP_SRC_IP && + FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP)) + return EBT_NOMATCH; + if (info->bitmask & EBT_ARP_DST_IP && + FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP)) + return EBT_NOMATCH; + if (info->bitmask & EBT_ARP_GRAT && + FWINV(*dap != *sap, EBT_ARP_GRAT)) return EBT_NOMATCH; - if (info->bitmask & EBT_ARP_SRC_IP) { - ap = skb_header_pointer(skb, sizeof(struct arphdr) + - ah->ar_hln, sizeof(_addr), - &_addr); - if (ap == NULL) - return EBT_NOMATCH; - if (FWINV(info->saddr != (*ap & info->smsk), - EBT_ARP_SRC_IP)) - return EBT_NOMATCH; - } - - if (info->bitmask & EBT_ARP_DST_IP) { - ap = skb_header_pointer(skb, sizeof(struct arphdr) + - 2*ah->ar_hln+sizeof(__be32), - sizeof(_addr), &_addr); - if (ap == NULL) - return EBT_NOMATCH; - if (FWINV(info->daddr != (*ap & info->dmsk), - EBT_ARP_DST_IP)) - return EBT_NOMATCH; - } } if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { - unsigned char _mac[ETH_ALEN], *mp; + const unsigned char *mp; + unsigned char _mac[ETH_ALEN]; uint8_t verdict, i; - /* MAC addresses are 6 bytes */ - if (ah->ar_hln != ETH_ALEN) + if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) return EBT_NOMATCH; if (info->bitmask & EBT_ARP_SRC_MAC) { mp = skb_header_pointer(skb, sizeof(struct arphdr), @@ -104,7 +103,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in static int ebt_arp_check(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *data, unsigned int datalen) { - struct ebt_arp_info *info = (struct ebt_arp_info *)data; + const struct ebt_arp_info *info = data; if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info))) return -EINVAL; @@ -117,8 +116,7 @@ static int ebt_arp_check(const char *tablename, unsigned int hookmask, return 0; } -static struct ebt_match filter_arp = -{ +static struct ebt_match filter_arp __read_mostly = { .name = EBT_ARP_MATCH, .match = ebt_filter_arp, .check = ebt_arp_check, @@ -137,4 +135,5 @@ static void __exit ebt_arp_fini(void) module_init(ebt_arp_init); module_exit(ebt_arp_fini); +MODULE_DESCRIPTION("Ebtables: ARP protocol packet match"); MODULE_LICENSE("GPL");