Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  ebt_arp
0004  *
0005  *  Authors:
0006  *  Bart De Schuymer <bdschuym@pandora.be>
0007  *  Tim Gardner <timg@tpi.com>
0008  *
0009  *  April, 2002
0010  *
0011  */
0012 #include <linux/if_arp.h>
0013 #include <linux/if_ether.h>
0014 #include <linux/module.h>
0015 #include <linux/netfilter/x_tables.h>
0016 #include <linux/netfilter_bridge/ebtables.h>
0017 #include <linux/netfilter_bridge/ebt_arp.h>
0018 
0019 static bool
0020 ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par)
0021 {
0022     const struct ebt_arp_info *info = par->matchinfo;
0023     const struct arphdr *ah;
0024     struct arphdr _arph;
0025 
0026     ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
0027     if (ah == NULL)
0028         return false;
0029     if ((info->bitmask & EBT_ARP_OPCODE) &&
0030         NF_INVF(info, EBT_ARP_OPCODE, info->opcode != ah->ar_op))
0031         return false;
0032     if ((info->bitmask & EBT_ARP_HTYPE) &&
0033         NF_INVF(info, EBT_ARP_HTYPE, info->htype != ah->ar_hrd))
0034         return false;
0035     if ((info->bitmask & EBT_ARP_PTYPE) &&
0036         NF_INVF(info, EBT_ARP_PTYPE, info->ptype != ah->ar_pro))
0037         return false;
0038 
0039     if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) {
0040         const __be32 *sap, *dap;
0041         __be32 saddr, daddr;
0042 
0043         if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
0044             return false;
0045         sap = skb_header_pointer(skb, sizeof(struct arphdr) +
0046                     ah->ar_hln, sizeof(saddr),
0047                     &saddr);
0048         if (sap == NULL)
0049             return false;
0050         dap = skb_header_pointer(skb, sizeof(struct arphdr) +
0051                     2*ah->ar_hln+sizeof(saddr),
0052                     sizeof(daddr), &daddr);
0053         if (dap == NULL)
0054             return false;
0055         if ((info->bitmask & EBT_ARP_SRC_IP) &&
0056             NF_INVF(info, EBT_ARP_SRC_IP,
0057                 info->saddr != (*sap & info->smsk)))
0058             return false;
0059         if ((info->bitmask & EBT_ARP_DST_IP) &&
0060             NF_INVF(info, EBT_ARP_DST_IP,
0061                 info->daddr != (*dap & info->dmsk)))
0062             return false;
0063         if ((info->bitmask & EBT_ARP_GRAT) &&
0064             NF_INVF(info, EBT_ARP_GRAT, *dap != *sap))
0065             return false;
0066     }
0067 
0068     if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
0069         const unsigned char *mp;
0070         unsigned char _mac[ETH_ALEN];
0071 
0072         if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
0073             return false;
0074         if (info->bitmask & EBT_ARP_SRC_MAC) {
0075             mp = skb_header_pointer(skb, sizeof(struct arphdr),
0076                         sizeof(_mac), &_mac);
0077             if (mp == NULL)
0078                 return false;
0079             if (NF_INVF(info, EBT_ARP_SRC_MAC,
0080                     !ether_addr_equal_masked(mp, info->smaddr,
0081                                  info->smmsk)))
0082                 return false;
0083         }
0084 
0085         if (info->bitmask & EBT_ARP_DST_MAC) {
0086             mp = skb_header_pointer(skb, sizeof(struct arphdr) +
0087                         ah->ar_hln + ah->ar_pln,
0088                         sizeof(_mac), &_mac);
0089             if (mp == NULL)
0090                 return false;
0091             if (NF_INVF(info, EBT_ARP_DST_MAC,
0092                     !ether_addr_equal_masked(mp, info->dmaddr,
0093                                  info->dmmsk)))
0094                 return false;
0095         }
0096     }
0097 
0098     return true;
0099 }
0100 
0101 static int ebt_arp_mt_check(const struct xt_mtchk_param *par)
0102 {
0103     const struct ebt_arp_info *info = par->matchinfo;
0104     const struct ebt_entry *e = par->entryinfo;
0105 
0106     if ((e->ethproto != htons(ETH_P_ARP) &&
0107        e->ethproto != htons(ETH_P_RARP)) ||
0108        e->invflags & EBT_IPROTO)
0109         return -EINVAL;
0110     if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
0111         return -EINVAL;
0112     return 0;
0113 }
0114 
0115 static struct xt_match ebt_arp_mt_reg __read_mostly = {
0116     .name       = "arp",
0117     .revision   = 0,
0118     .family     = NFPROTO_BRIDGE,
0119     .match      = ebt_arp_mt,
0120     .checkentry = ebt_arp_mt_check,
0121     .matchsize  = sizeof(struct ebt_arp_info),
0122     .me     = THIS_MODULE,
0123 };
0124 
0125 static int __init ebt_arp_init(void)
0126 {
0127     return xt_register_match(&ebt_arp_mt_reg);
0128 }
0129 
0130 static void __exit ebt_arp_fini(void)
0131 {
0132     xt_unregister_match(&ebt_arp_mt_reg);
0133 }
0134 
0135 module_init(ebt_arp_init);
0136 module_exit(ebt_arp_fini);
0137 MODULE_DESCRIPTION("Ebtables: ARP protocol packet match");
0138 MODULE_LICENSE("GPL");