0001
0002
0003
0004
0005
0006
0007
0008
0009
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");