Also Paul, I think this takes care of one of the requirements for VMs to send traffic on the wrong lswitch in <a href="http://redmine.nicira.com/issues/3273">3273</a>, so we don't have to worry about that anymore =)<br>
<br><div class="gmail_quote">On Thu, Aug 12, 2010 at 2:07 PM, Martin Casado <span dir="ltr"><<a href="mailto:casado@nicira.com">casado@nicira.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This is great Ben, and sorely needed. Thanks for getting that patch in. ovs security ++.<div><div></div><div class="h5"><br>
<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
"ARP spoofing" is when a host claims an incorrect association between an<br>
IP address and a MAC address for deceptive purposes. OpenFlow by itself<br>
can prevent a host from sending out ARP replies from an incorrect MAC<br>
address in the Ethernet L2 header, but it cannot control the MAC addresses<br>
inside the ARP L3 packet. This commit adds a new action that can be used<br>
to drop these spoofed packets.<br>
<br>
CC: Paul Ingram <<a href="mailto:paul@nicira.com" target="_blank">paul@nicira.com</a>><br>
---<br>
I'm sending this out partly as an RFC, to check with Paul that this<br>
solves the problem that he has, and to make sure that this type of<br>
solution is OK with the other developers.<br>
<br>
I have not tested this code yet.<br>
<br>
datapath/actions.c | 27 +++++++++++++++++++++++++++<br>
datapath/flow.c | 15 ---------------<br>
datapath/flow.h | 16 ++++++++++++++++<br>
include/openflow/nicira-ext.h | 13 ++++++++++++-<br>
include/openvswitch/datapath-protocol.h | 3 ++-<br>
ofproto/ofproto.c | 6 ++++++<br>
6 files changed, 63 insertions(+), 17 deletions(-)<br>
<br>
diff --git a/datapath/actions.c b/datapath/actions.c<br>
index a6771b6..81e1c84 100644<br>
--- a/datapath/actions.c<br>
+++ b/datapath/actions.c<br>
@@ -14,6 +14,7 @@<br>
#include <linux/tcp.h><br>
#include <linux/udp.h><br>
#include <linux/in6.h><br>
+#include <linux/if_arp.h><br>
#include <linux/if_vlan.h><br>
#include <net/inet_ecn.h><br>
#include <net/ip.h><br>
@@ -318,6 +319,26 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb,<br>
return skb;<br>
}<br>
+/* Returns true if 'skb' is an Ethernet+IPv4 ARP packet whose inner and outer<br>
+ * Ethernet address differ. */<br>
+static bool is_spoofed_arp(struct sk_buff *skb, const struct odp_flow_key *key)<br>
+{<br>
+ struct arp_eth_header *arp;<br>
+<br>
+ if (key->dl_type != htons(ETH_P_ARP))<br>
+ return false;<br>
+<br>
+ if (skb_network_offset(skb) + sizeof(struct arp_eth_header) > skb->len)<br>
+ return false;<br>
+<br>
+ arp = (struct arp_eth_header *)skb_network_header(skb);<br>
+ return (arp->ar_hrd == htons(ARPHRD_ETHER) &&<br>
+ arp->ar_pro == htons(ETH_P_IP) &&<br>
+ arp->ar_hln == ETH_ALEN &&<br>
+ arp->ar_pln == 4 &&<br>
+ compare_ether_addr(arp->ar_sha, eth_hdr(skb)->h_source));<br>
+}<br>
+<br>
static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port)<br>
{<br>
struct dp_port *p;<br>
@@ -484,10 +505,16 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,<br>
case ODPAT_POP_PRIORITY:<br>
skb->priority = priority;<br>
break;<br>
+<br>
+ case ODPAT_DROP_SPOOFED_ARP:<br>
+ if (is_spoofed_arp(skb, key))<br>
+ goto exit;<br>
+ break;<br>
}<br>
if (!skb)<br>
return -ENOMEM;<br>
}<br>
+exit:<br>
if (prev_port != -1)<br>
do_output(dp, skb, prev_port);<br>
else<br>
diff --git a/datapath/flow.c b/datapath/flow.c<br>
index f769b14..8074b20 100644<br>
--- a/datapath/flow.c<br>
+++ b/datapath/flow.c<br>
@@ -34,21 +34,6 @@<br>
struct kmem_cache *flow_cache;<br>
static unsigned int hash_seed;<br>
-struct arp_eth_header<br>
-{<br>
- __be16 ar_hrd; /* format of hardware address */<br>
- __be16 ar_pro; /* format of protocol address */<br>
- unsigned char ar_hln; /* length of hardware address */<br>
- unsigned char ar_pln; /* length of protocol address */<br>
- __be16 ar_op; /* ARP opcode (command) */<br>
-<br>
- /* Ethernet+IPv4 specific members. */<br>
- unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */<br>
- unsigned char ar_sip[4]; /* sender IP address */<br>
- unsigned char ar_tha[ETH_ALEN]; /* target hardware address */<br>
- unsigned char ar_tip[4]; /* target IP address */<br>
-} __attribute__((packed));<br>
-<br>
static inline int arphdr_ok(struct sk_buff *skb)<br>
{<br>
int nh_ofs = skb_network_offset(skb);<br>
diff --git a/datapath/flow.h b/datapath/flow.h<br>
index 534c7af..80a5b66 100644<br>
--- a/datapath/flow.h<br>
+++ b/datapath/flow.h<br>
@@ -14,6 +14,7 @@<br>
#include <linux/types.h><br>
#include <linux/rcupdate.h><br>
#include <linux/gfp.h><br>
+#include <linux/if_ether.h><br>
#include <linux/jiffies.h><br>
#include <linux/time.h><br>
@@ -42,6 +43,21 @@ struct sw_flow {<br>
u8 tcp_flags; /* Union of seen TCP flags. */<br>
};<br>
+struct arp_eth_header<br>
+{<br>
+ __be16 ar_hrd; /* format of hardware address */<br>
+ __be16 ar_pro; /* format of protocol address */<br>
+ unsigned char ar_hln; /* length of hardware address */<br>
+ unsigned char ar_pln; /* length of protocol address */<br>
+ __be16 ar_op; /* ARP opcode (command) */<br>
+<br>
+ /* Ethernet+IPv4 specific members. */<br>
+ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */<br>
+ unsigned char ar_sip[4]; /* sender IP address */<br>
+ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */<br>
+ unsigned char ar_tip[4]; /* target IP address */<br>
+} __attribute__((packed));<br>
+<br>
extern struct kmem_cache *flow_cache;<br>
struct sw_flow_actions *flow_actions_alloc(size_t n_actions);<br>
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h<br>
index e6f34ba..f2c5b73 100644<br>
--- a/include/openflow/nicira-ext.h<br>
+++ b/include/openflow/nicira-ext.h<br>
@@ -129,7 +129,18 @@ enum nx_action_subtype {<br>
*/<br>
NXAST_RESUBMIT,<br>
- NXAST_SET_TUNNEL /* Set encapsulating tunnel ID. */<br>
+ /* Set encapsulating tunnel ID. */<br>
+ NXAST_SET_TUNNEL,<br>
+<br>
+ /* Stops processing further actions, if the packet being processed is an<br>
+ * Ethernet+IPv4 ARP packet for which the source Ethernet address inside<br>
+ * the ARP packet differs from the source Ethernet address in the Ethernet<br>
+ * header.<br>
+ *<br>
+ * This is useful because OpenFlow does not provide a way to match on the<br>
+ * Ethernet addresses inside ARP packets, so there is no other way to drop<br>
+ * spoofed ARPs other than sending every packet up to the controller. */<br>
+ NXAST_DROP_SPOOFED_ARP<br>
};<br>
/* Action structure for NXAST_RESUBMIT. */<br>
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h<br>
index c3ec4dc..839c484 100644<br>
--- a/include/openvswitch/datapath-protocol.h<br>
+++ b/include/openvswitch/datapath-protocol.h<br>
@@ -281,7 +281,8 @@ struct odp_flowvec {<br>
#define ODPAT_SET_TUNNEL 13 /* Set the encapsulating tunnel ID. */<br>
#define ODPAT_SET_PRIORITY 14 /* Set skb->priority. */<br>
#define ODPAT_POP_PRIORITY 15 /* Restore original skb->priority. */<br>
-#define ODPAT_N_ACTIONS 16<br>
+#define ODPAT_DROP_SPOOFED_ARP 16 /* Drop ARPs with spoofed source MAC. */<br>
+#define ODPAT_N_ACTIONS 17<br>
struct odp_action_output {<br>
uint16_t type; /* ODPAT_OUTPUT. */<br>
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c<br>
index a466c9c..c0d4acc 100644<br>
--- a/ofproto/ofproto.c<br>
+++ b/ofproto/ofproto.c<br>
@@ -2635,6 +2635,12 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,<br>
ctx->flow.tun_id = oa->tunnel.tun_id = nast->tun_id;<br>
break;<br>
+ case NXAST_DROP_SPOOFED_ARP:<br>
+ if (ctx->flow.dl_type == htons(ETH_TYPE_ARP)) {<br>
+ odp_actions_add(ctx->out, ODPAT_DROP_SPOOFED_ARP);<br>
+ }<br>
+ break;<br>
+<br>
/* If you add a new action here that modifies flow data, don't forget to<br>
* update the flow key in ctx->flow at the same time. */<br>
<br>
</blockquote>
<br>
<br></div></div><div><div></div><div class="h5">
_______________________________________________<br>
dev mailing list<br>
<a href="mailto:dev@openvswitch.org" target="_blank">dev@openvswitch.org</a><br>
<a href="http://openvswitch.org/mailman/listinfo/dev_openvswitch.org" target="_blank">http://openvswitch.org/mailman/listinfo/dev_openvswitch.org</a><br>
</div></div></blockquote></div><br>