openvswitch: checking wrong variable in queue_userspace_packet()
[linux-flexiantxendom0-3.2.10.git] / net / openvswitch / datapath.c
index d9d01cb..e66341e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2011 Nicira Networks.
+ * Copyright (c) 2007-2012 Nicira Networks.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -38,7 +38,6 @@
 #include <linux/udp.h>
 #include <linux/ethtool.h>
 #include <linux/wait.h>
-#include <asm/system.h>
 #include <asm/div64.h>
 #include <linux/highmem.h>
 #include <linux/netfilter_bridge.h>
@@ -322,7 +321,7 @@ static int queue_userspace_packet(int dp_ifindex, struct sk_buff *skb,
                        return -ENOMEM;
 
                nskb = __vlan_put_tag(nskb, vlan_tx_tag_get(nskb));
-               if (!skb)
+               if (!nskb)
                        return -ENOMEM;
 
                nskb->vlan_tci = 0;
@@ -422,6 +421,19 @@ static int validate_sample(const struct nlattr *attr,
        return validate_actions(actions, key, depth + 1);
 }
 
+static int validate_tp_port(const struct sw_flow_key *flow_key)
+{
+       if (flow_key->eth.type == htons(ETH_P_IP)) {
+               if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst)
+                       return 0;
+       } else if (flow_key->eth.type == htons(ETH_P_IPV6)) {
+               if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst)
+                       return 0;
+       }
+
+       return -EINVAL;
+}
+
 static int validate_set(const struct nlattr *a,
                        const struct sw_flow_key *flow_key)
 {
@@ -463,18 +475,13 @@ static int validate_set(const struct nlattr *a,
                if (flow_key->ip.proto != IPPROTO_TCP)
                        return -EINVAL;
 
-               if (!flow_key->ipv4.tp.src || !flow_key->ipv4.tp.dst)
-                       return -EINVAL;
-
-               break;
+               return validate_tp_port(flow_key);
 
        case OVS_KEY_ATTR_UDP:
                if (flow_key->ip.proto != IPPROTO_UDP)
                        return -EINVAL;
 
-               if (!flow_key->ipv4.tp.src || !flow_key->ipv4.tp.dst)
-                       return -EINVAL;
-               break;
+               return validate_tp_port(flow_key);
 
        default:
                return -EINVAL;
@@ -1396,9 +1403,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int i = 0;
 
        list_for_each_entry(dp, &dps, list_node) {
-               if (i < skip)
-                       continue;
-               if (ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid,
+               if (i >= skip &&
+                   ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid,
                                         cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                         OVS_DP_CMD_NEW) < 0)
                        break;
@@ -1522,6 +1528,9 @@ static struct vport *lookup_vport(struct ovs_header *ovs_header,
                vport = ovs_vport_locate(nla_data(a[OVS_VPORT_ATTR_NAME]));
                if (!vport)
                        return ERR_PTR(-ENODEV);
+               if (ovs_header->dp_ifindex &&
+                   ovs_header->dp_ifindex != get_dpifindex(vport->dp))
+                       return ERR_PTR(-ENODEV);
                return vport;
        } else if (a[OVS_VPORT_ATTR_PORT_NO]) {
                u32 port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);
@@ -1640,10 +1649,9 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
        reply = ovs_vport_cmd_build_info(vport, info->snd_pid, info->snd_seq,
                                         OVS_VPORT_CMD_NEW);
        if (IS_ERR(reply)) {
-               err = PTR_ERR(reply);
                netlink_set_err(init_net.genl_sock, 0,
-                               ovs_dp_vport_multicast_group.id, err);
-               return 0;
+                               ovs_dp_vport_multicast_group.id, PTR_ERR(reply));
+               goto exit_unlock;
        }
 
        genl_notify(reply, genl_info_net(info), info->snd_pid,