Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ebt_arp.c
Go to the documentation of this file.
1 /*
2  * ebt_arp
3  *
4  * Authors:
5  * Bart De Schuymer <[email protected]>
6  * Tim Gardner <[email protected]>
7  *
8  * April, 2002
9  *
10  */
11 #include <linux/if_arp.h>
12 #include <linux/if_ether.h>
13 #include <linux/module.h>
14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter_bridge/ebtables.h>
17 
18 static bool
19 ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par)
20 {
21  const struct ebt_arp_info *info = par->matchinfo;
22  const struct arphdr *ah;
23  struct arphdr _arph;
24 
25  ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
26  if (ah == NULL)
27  return false;
28  if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
29  ah->ar_op, EBT_ARP_OPCODE))
30  return false;
31  if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
32  ah->ar_hrd, EBT_ARP_HTYPE))
33  return false;
34  if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
35  ah->ar_pro, EBT_ARP_PTYPE))
36  return false;
37 
39  const __be32 *sap, *dap;
41 
42  if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP))
43  return false;
44  sap = skb_header_pointer(skb, sizeof(struct arphdr) +
45  ah->ar_hln, sizeof(saddr),
46  &saddr);
47  if (sap == NULL)
48  return false;
49  dap = skb_header_pointer(skb, sizeof(struct arphdr) +
50  2*ah->ar_hln+sizeof(saddr),
51  sizeof(daddr), &daddr);
52  if (dap == NULL)
53  return false;
54  if (info->bitmask & EBT_ARP_SRC_IP &&
55  FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP))
56  return false;
57  if (info->bitmask & EBT_ARP_DST_IP &&
58  FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP))
59  return false;
60  if (info->bitmask & EBT_ARP_GRAT &&
61  FWINV(*dap != *sap, EBT_ARP_GRAT))
62  return false;
63  }
64 
65  if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
66  const unsigned char *mp;
67  unsigned char _mac[ETH_ALEN];
68  uint8_t verdict, i;
69 
70  if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER))
71  return false;
72  if (info->bitmask & EBT_ARP_SRC_MAC) {
73  mp = skb_header_pointer(skb, sizeof(struct arphdr),
74  sizeof(_mac), &_mac);
75  if (mp == NULL)
76  return false;
77  verdict = 0;
78  for (i = 0; i < 6; i++)
79  verdict |= (mp[i] ^ info->smaddr[i]) &
80  info->smmsk[i];
81  if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
82  return false;
83  }
84 
85  if (info->bitmask & EBT_ARP_DST_MAC) {
86  mp = skb_header_pointer(skb, sizeof(struct arphdr) +
87  ah->ar_hln + ah->ar_pln,
88  sizeof(_mac), &_mac);
89  if (mp == NULL)
90  return false;
91  verdict = 0;
92  for (i = 0; i < 6; i++)
93  verdict |= (mp[i] ^ info->dmaddr[i]) &
94  info->dmmsk[i];
95  if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
96  return false;
97  }
98  }
99 
100  return true;
101 }
102 
103 static int ebt_arp_mt_check(const struct xt_mtchk_param *par)
104 {
105  const struct ebt_arp_info *info = par->matchinfo;
106  const struct ebt_entry *e = par->entryinfo;
107 
108  if ((e->ethproto != htons(ETH_P_ARP) &&
109  e->ethproto != htons(ETH_P_RARP)) ||
110  e->invflags & EBT_IPROTO)
111  return -EINVAL;
112  if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
113  return -EINVAL;
114  return 0;
115 }
116 
117 static struct xt_match ebt_arp_mt_reg __read_mostly = {
118  .name = "arp",
119  .revision = 0,
120  .family = NFPROTO_BRIDGE,
121  .match = ebt_arp_mt,
122  .checkentry = ebt_arp_mt_check,
123  .matchsize = sizeof(struct ebt_arp_info),
124  .me = THIS_MODULE,
125 };
126 
127 static int __init ebt_arp_init(void)
128 {
129  return xt_register_match(&ebt_arp_mt_reg);
130 }
131 
132 static void __exit ebt_arp_fini(void)
133 {
134  xt_unregister_match(&ebt_arp_mt_reg);
135 }
136 
137 module_init(ebt_arp_init);
138 module_exit(ebt_arp_fini);
139 MODULE_DESCRIPTION("Ebtables: ARP protocol packet match");
140 MODULE_LICENSE("GPL");