Merge changes from citrix branch into master.
authorBen Pfaff <blp@nicira.com>
Mon, 15 Jun 2009 23:04:54 +0000 (16:04 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 15 Jun 2009 23:04:54 +0000 (16:04 -0700)
16 files changed:
1  2 
datapath/brc_sysfs.h
datapath/brc_sysfs_dp.c
datapath/brc_sysfs_if.c
datapath/brcompat.c
datapath/datapath.c
datapath/datapath.h
lib/socket-util.c
lib/socket-util.h
lib/vconn-ssl.c
lib/vconn-stream.c
lib/vconn-tcp.c
lib/vconn-unix.c
lib/vconn.c
secchan/discovery.c
secchan/main.c
utilities/ovs-discover.c

diff --combined datapath/brc_sysfs.h
@@@ -1,3 -1,11 +1,11 @@@
+ /*
+  * Copyright (c) 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
+  */
  #ifndef BRC_SYSFS_H
  #define BRC_SYSFS_H 1
  
@@@ -12,5 -20,14 +20,5 @@@ int brc_sysfs_del_dp(struct datapath *d
  int brc_sysfs_add_if(struct net_bridge_port *p);
  int brc_sysfs_del_if(struct net_bridge_port *p);
  
 -#include <linux/version.h>
 -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
 -#define SUPPORT_SYSFS 1
 -#else
 -/* We only support sysfs on Linux 2.6.18 because that's the only place we
 - * really need it (on Xen, for brcompat) and it's a big pain to try to support
 - * multiple versions. */
 -#endif
 -
  #endif /* brc_sysfs.h */
  
diff --combined datapath/brc_sysfs_dp.c
@@@ -1,3 -1,11 +1,11 @@@
+ /*
+  * Copyright (c) 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
+  */
  #include <linux/version.h>
  
  /*
  #include "datapath.h"
  #include "dp_dev.h"
  
 -#ifdef SUPPORT_SYSFS
 +#ifdef CONFIG_SYSFS
  #define to_dev(obj)   container_of(obj, struct device, kobj)
  
  /* Hack to attempt to build on more platforms. */
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
 -#define to_kobj(d) &(d)->class_dev.kobj
  #define BRC_DEVICE_ATTR CLASS_DEVICE_ATTR
 +#define DEVICE_PARAMS struct class_device *d
 +#define DEVICE_ARGS d
 +#define DEV_ATTR(NAME) class_device_attr_##NAME
  #else
 -#define to_kobj(d) &(d)->dev.kobj
  #define BRC_DEVICE_ATTR DEVICE_ATTR
 +#define DEVICE_PARAMS struct device *d, struct device_attribute *attr
 +#define DEVICE_ARGS d, attr
 +#define DEV_ATTR(NAME) dev_attr_##NAME
  #endif
  
  /*
   * Common code for storing bridge parameters.
   */
 -static ssize_t store_bridge_parm(struct class_device *d,
 +static ssize_t store_bridge_parm(DEVICE_PARAMS,
                                 const char *buf, size_t len,
                                 void (*set)(struct datapath *, unsigned long))
  {
@@@ -72,7 -76,8 +80,7 @@@
  }
  
  
 -static ssize_t show_forward_delay(struct class_device *d,
 -                                char *buf)
 +static ssize_t show_forward_delay(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@@ -94,15 -99,15 +102,15 @@@ static void set_forward_delay(struct da
  #endif
  }
  
 -static ssize_t store_forward_delay(struct class_device *d,
 +static ssize_t store_forward_delay(DEVICE_PARAMS,
                                   const char *buf, size_t len)
  {
 -      return store_bridge_parm(d, buf, len, set_forward_delay);
 +      return store_bridge_parm(DEVICE_ARGS, buf, len, set_forward_delay);
  }
  static BRC_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
                   show_forward_delay, store_forward_delay);
  
 -static ssize_t show_hello_time(struct class_device *d, char *buf)
 +static ssize_t show_hello_time(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return sprintf(buf, "%lu\n",
@@@ -124,16 -129,17 +132,16 @@@ static void set_hello_time(struct datap
  #endif
  }
  
 -static ssize_t store_hello_time(struct class_device *d,
 +static ssize_t store_hello_time(DEVICE_PARAMS,
                                const char *buf,
                                size_t len)
  {
 -      return store_bridge_parm(d, buf, len, set_hello_time);
 +      return store_bridge_parm(DEVICE_ARGS, buf, len, set_hello_time);
  }
  static BRC_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
                   store_hello_time);
  
 -static ssize_t show_max_age(struct class_device *d, 
 -                          char *buf)
 +static ssize_t show_max_age(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return sprintf(buf, "%lu\n",
@@@ -155,14 -161,15 +163,14 @@@ static void set_max_age(struct datapat
  #endif
  }
  
 -static ssize_t store_max_age(struct class_device *d, 
 +static ssize_t store_max_age(DEVICE_PARAMS,
                             const char *buf, size_t len)
  {
 -      return store_bridge_parm(d, buf, len, set_max_age);
 +      return store_bridge_parm(DEVICE_ARGS, buf, len, set_max_age);
  }
  static BRC_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
  
 -static ssize_t show_ageing_time(struct class_device *d,
 -                              char *buf)
 +static ssize_t show_ageing_time(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@@ -181,15 -188,16 +189,15 @@@ static void set_ageing_time(struct data
  #endif
  }
  
 -static ssize_t store_ageing_time(struct class_device *d,
 +static ssize_t store_ageing_time(DEVICE_PARAMS,
                                 const char *buf, size_t len)
  {
 -      return store_bridge_parm(d, buf, len, set_ageing_time);
 +      return store_bridge_parm(DEVICE_ARGS, buf, len, set_ageing_time);
  }
  static BRC_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
                   store_ageing_time);
  
 -static ssize_t show_stp_state(struct class_device *d,
 -                            char *buf)
 +static ssize_t show_stp_state(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  }
  
  
 -static ssize_t store_stp_state(struct class_device *d,
 +static ssize_t store_stp_state(DEVICE_PARAMS,
                               const char *buf,
                               size_t len)
  {
  static BRC_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
                   store_stp_state);
  
 -static ssize_t show_priority(struct class_device *d, 
 -                           char *buf)
 +static ssize_t show_priority(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@@ -248,14 -257,15 +256,14 @@@ static void set_priority(struct datapat
  #endif
  }
  
 -static ssize_t store_priority(struct class_device *d, 
 +static ssize_t store_priority(DEVICE_PARAMS,
                               const char *buf, size_t len)
  {
 -      return store_bridge_parm(d, buf, len, set_priority);
 +      return store_bridge_parm(DEVICE_ARGS, buf, len, set_priority);
  }
  static BRC_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
  
 -static ssize_t show_root_id(struct class_device *d, 
 -                          char *buf)
 +static ssize_t show_root_id(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
  }
  static BRC_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
  
 -static ssize_t show_bridge_id(struct class_device *d, 
 -                            char *buf)
 +static ssize_t show_bridge_id(DEVICE_PARAMS, char *buf)
  {
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
        const unsigned char *addr = dp->ports[ODPP_LOCAL]->dev->dev_addr;
  }
  static BRC_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
  
 -static ssize_t show_root_port(struct class_device *d, 
 -                            char *buf)
 +static ssize_t show_root_port(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->root_port);
  }
  static BRC_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
  
 -static ssize_t show_root_path_cost(struct class_device *d,
 -                                 char *buf)
 +static ssize_t show_root_path_cost(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
  }
  static BRC_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
  
 -static ssize_t show_topology_change(struct class_device *d,
 -                                  char *buf)
 +static ssize_t show_topology_change(DEVICE_PARAMS, char *buf)
  {
  #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
  }
  static BRC_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
  
 -static ssize_t show_topology_change_detected(struct class_device *d,
 -                                           char *buf)
 +static ssize_t show_topology_change_detected(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  static BRC_DEVICE_ATTR(topology_change_detected, S_IRUGO,
                   show_topology_change_detected, NULL);
  
 -static ssize_t show_hello_timer(struct class_device *d,
 -                              char *buf)
 +static ssize_t show_hello_timer(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  }
  static BRC_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
  
 -static ssize_t show_tcn_timer(struct class_device *d, 
 -                            char *buf)
 +static ssize_t show_tcn_timer(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  }
  static BRC_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
  
 -static ssize_t show_topology_change_timer(struct class_device *d,
 -                                        char *buf)
 +static ssize_t show_topology_change_timer(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  static BRC_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
                   NULL);
  
 -static ssize_t show_gc_timer(struct class_device *d, 
 -                           char *buf)
 +static ssize_t show_gc_timer(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  }
  static BRC_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
  
 -static ssize_t show_group_addr(struct class_device *d,
 -                             char *buf)
 +static ssize_t show_group_addr(DEVICE_PARAMS, char *buf)
  {
  #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
  #endif
  }
  
 -static ssize_t store_group_addr(struct class_device *d,
 +static ssize_t store_group_addr(DEVICE_PARAMS,
                                const char *buf, size_t len)
  {
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@@ -419,23 -439,23 +427,23 @@@ static BRC_DEVICE_ATTR(group_addr, S_IR
                   show_group_addr, store_group_addr);
  
  static struct attribute *bridge_attrs[] = {
 -      &class_device_attr_forward_delay.attr,
 -      &class_device_attr_hello_time.attr,
 -      &class_device_attr_max_age.attr,
 -      &class_device_attr_ageing_time.attr,
 -      &class_device_attr_stp_state.attr,
 -      &class_device_attr_priority.attr,
 -      &class_device_attr_bridge_id.attr,
 -      &class_device_attr_root_id.attr,
 -      &class_device_attr_root_path_cost.attr,
 -      &class_device_attr_root_port.attr,
 -      &class_device_attr_topology_change.attr,
 -      &class_device_attr_topology_change_detected.attr,
 -      &class_device_attr_hello_timer.attr,
 -      &class_device_attr_tcn_timer.attr,
 -      &class_device_attr_topology_change_timer.attr,
 -      &class_device_attr_gc_timer.attr,
 -      &class_device_attr_group_addr.attr,
 +      &DEV_ATTR(forward_delay).attr,
 +      &DEV_ATTR(hello_time).attr,
 +      &DEV_ATTR(max_age).attr,
 +      &DEV_ATTR(ageing_time).attr,
 +      &DEV_ATTR(stp_state).attr,
 +      &DEV_ATTR(priority).attr,
 +      &DEV_ATTR(bridge_id).attr,
 +      &DEV_ATTR(root_id).attr,
 +      &DEV_ATTR(root_path_cost).attr,
 +      &DEV_ATTR(root_port).attr,
 +      &DEV_ATTR(topology_change).attr,
 +      &DEV_ATTR(topology_change_detected).attr,
 +      &DEV_ATTR(hello_timer).attr,
 +      &DEV_ATTR(tcn_timer).attr,
 +      &DEV_ATTR(topology_change_timer).attr,
 +      &DEV_ATTR(gc_timer).attr,
 +      &DEV_ATTR(group_addr).attr,
        NULL
  };
  
@@@ -456,7 -476,7 +464,7 @@@ static struct attribute_group bridge_gr
   */
  int brc_sysfs_add_dp(struct datapath *dp)
  {
 -      struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
 +      struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
        int err;
  
        err = sysfs_create_group(kobj, &bridge_group);
        err = kobject_register(&dp->ifobj);
        if (err) {
                pr_info("%s: can't add kobject (directory) %s/%s\n",
 -                              __FUNCTION__, dp_name(dp), dp->ifobj.name);
 +                      __FUNCTION__, dp_name(dp), kobject_name(&dp->ifobj));
                goto out2;
        }
  #else
 -      br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
 -      if (!br->ifobj) {
 +      dp->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
 +      if (!dp->ifobj) {
                pr_info("%s: can't add kobject (directory) %s/%s\n",
                        __func__, dp_name(dp), SYSFS_BRIDGE_PORT_SUBDIR);
                goto out2;
  
  int brc_sysfs_del_dp(struct datapath *dp)
  {
 -      struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
 +      struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
  
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        kobject_unregister(&dp->ifobj);
  
        return 0;
  }
 -#else /* !SUPPORT_SYSFS */
 +#else /* !CONFIG_SYSFS */
  int brc_sysfs_add_dp(struct datapath *dp) { return 0; }
  int brc_sysfs_del_dp(struct datapath *dp) { return 0; }
  int brc_sysfs_add_if(struct net_bridge_port *p) { return 0; }
@@@ -517,4 -537,4 +525,4 @@@ int brc_sysfs_del_if(struct net_bridge_
        kfree(p);
        return 0;
  }
 -#endif /* !SUPPORT_SYSFS */
 +#endif /* !CONFIG_SYSFS */
diff --combined datapath/brc_sysfs_if.c
@@@ -1,3 -1,11 +1,11 @@@
+ /*
+  * Copyright (c) 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
+  */
  /*
   *    Sysfs attributes of bridge ports for Open vSwitch
   *
@@@ -13,7 -21,7 +21,7 @@@
  #include "brc_sysfs.h"
  #include "datapath.h"
  
 -#ifdef SUPPORT_SYSFS
 +#ifdef CONFIG_SYSFS
  
  struct brport_attribute {
        struct attribute        attr;
@@@ -281,14 -289,18 +289,14 @@@ int brc_sysfs_add_if(struct net_bridge_
        struct brport_attribute **a;
        int err;
  
 -      kobject_init(&p->kobj);
 -      kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
 -      p->kobj.ktype = &brport_ktype;
 -      p->kobj.kset = NULL;
 -      p->kobj.parent = &(p->dev->class_dev.kobj);
 -
 -      err = kobject_add(&p->kobj);
 +      err = kobject_init_and_add(&p->kobj, &brport_ktype,
 +                                 &(p->dev->NETDEV_DEV_MEMBER.kobj),
 +                                 SYSFS_BRIDGE_PORT_ATTR);
        if (err)
 -              goto err_put;
 +              goto err;
  
        err = sysfs_create_link(&p->kobj,
 -                              &dp->ports[ODPP_LOCAL]->dev->class_dev.kobj,
 +                              &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj,
                                SYSFS_BRIDGE_PORT_LINK);
        if (err)
                goto err_del;
                        goto err_del;
        }
  
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        err = sysfs_create_link(&dp->ifobj, &p->kobj, p->dev->name);
 +#else
 +      err = sysfs_create_link(dp->ifobj, &p->kobj, p->dev->name);
 +#endif
        if (err)
                goto err_del;
  
  
  err_del:
        kobject_del(&p->kobj);
 -err_put:
        kobject_put(&p->kobj);
 +err:
        return err;
  }
  
@@@ -331,4 -339,4 +339,4 @@@ int brc_sysfs_del_if(struct net_bridge_
  
        return 0;
  }
 -#endif /* SUPPORT_SYSFS */
 +#endif /* CONFIG_SYSFS */
diff --combined datapath/brcompat.c
@@@ -1,3 -1,11 +1,11 @@@
+ /*
+  * Copyright (c) 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
+  */
  #include <linux/kernel.h>
  #include <asm/uaccess.h>
  #include <linux/completion.h>
@@@ -404,14 -412,18 +412,14 @@@ int brc_add_dp(struct datapath *dp
  {
        if (!try_module_get(THIS_MODULE))
                return -ENODEV;
 -#ifdef SUPPORT_SYSFS
        brc_sysfs_add_dp(dp);
 -#endif
  
        return 0;
  }
  
  int brc_del_dp(struct datapath *dp) 
  {
 -#ifdef SUPPORT_SYSFS
        brc_sysfs_del_dp(dp);
 -#endif
        module_put(THIS_MODULE);
  
        return 0;
@@@ -446,8 -458,10 +454,8 @@@ __init brc_init(void
        dp_del_dp_hook = brc_del_dp;
  
        /* Register hooks for interface adds and deletes */
 -#ifdef SUPPORT_SYSFS
        dp_add_if_hook = brc_sysfs_add_if;
        dp_del_if_hook = brc_sysfs_del_if;
 -#endif
  
        /* Randomize the initial sequence number.  This is not a security
         * feature; it only helps avoid crossed wires between userspace and
diff --combined datapath/datapath.c
@@@ -1,6 -1,9 +1,9 @@@
  /*
-  * Distributed under the terms of the GNU GPL version 2.
   * Copyright (c) 2007, 2008, 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
   */
  
  /* Functions for managing the dp interface/device. */
@@@ -421,13 -424,10 +424,13 @@@ int dp_del_port(struct net_bridge_port 
  {
        ASSERT_RTNL();
  
 -#ifdef SUPPORT_SYSFS
 -      if (p->port_no != ODPP_LOCAL && dp_del_if_hook)
 +      if (p->port_no != ODPP_LOCAL && dp_del_if_hook) {
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
                sysfs_remove_link(&p->dp->ifobj, p->dev->name);
 +#else
 +              sysfs_remove_link(p->dp->ifobj, p->dev->name);
  #endif
 +      }
        dp_ifinfo_notify(RTM_DELLINK, p);
  
        p->dp->n_ports--;
@@@ -577,7 -577,6 +580,7 @@@ static int dp_frame_hook(struct net_bri
  #endif
  
  #ifdef CONFIG_XEN
 +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
  /* This code is copied verbatim from net/dev/core.c in Xen's
   * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644.  We can't call those functions
   * directly because they aren't exported. */
@@@ -624,8 -623,7 +627,8 @@@ int skb_checksum_setup(struct sk_buff *
  out:
        return -EPROTO;
  }
 -#endif
 +#endif /* linux == 2.6.18 */
 +#endif /* CONFIG_XEN */
  
  int
  dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
diff --combined datapath/datapath.h
@@@ -1,3 -1,11 +1,11 @@@
+ /*
+  * Copyright (c) 2009 Nicira Networks.
+  * Distributed under the terms of the GNU GPL version 2.
+  *
+  * Significant portions of this file may be copied from parts of the Linux
+  * kernel, by Linus Torvalds and others.
+  */
  /* Interface exported by openvswitch_mod. */
  
  #ifndef DATAPATH_H
@@@ -10,7 -18,6 +18,7 @@@
  #include <linux/netdevice.h>
  #include <linux/workqueue.h>
  #include <linux/skbuff.h>
 +#include <linux/version.h>
  #include "flow.h"
  #include "brc_sysfs.h"
  
@@@ -59,12 -66,8 +67,12 @@@ struct datapath 
        struct mutex mutex;
        int dp_idx;
  
 -#ifdef SUPPORT_SYSFS
 +#ifdef CONFIG_SYSFS
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        struct kobject ifobj;
 +#else
 +      struct kobject *ifobj;
 +#endif
  #endif
  
        int drop_frags;
@@@ -93,7 -96,7 +101,7 @@@ struct net_bridge_port 
        u16 port_no;
        struct datapath *dp;
        struct net_device *dev;
 -#ifdef SUPPORT_SYSFS
 +#ifdef CONFIG_SYSFS
        struct kobject kobj;
  #endif
        struct list_head node;   /* Element in datapath.ports. */
diff --combined lib/socket-util.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -23,7 -23,6 +23,7 @@@
  #include <poll.h>
  #include <stddef.h>
  #include <stdio.h>
 +#include <stdlib.h>
  #include <string.h>
  #include <sys/resource.h>
  #include <sys/un.h>
@@@ -300,172 -299,6 +300,172 @@@ guess_netmask(uint32_t ip
              : htonl(0));                          /* ??? */
  }
  
 +/* Opens a non-blocking TCP socket and connects to 'target', which should be a
 + * string in the format "<host>[:<port>]", where <host> is required and <port>
 + * is optional, with 'default_port' assumed if <port> is omitted.
 + *
 + * On success, returns 0 (indicating connection complete) or EAGAIN (indicating
 + * connection in progress), in which case the new file descriptor is stored
 + * into '*fdp'.  On failure, returns a positive errno value other than EAGAIN
 + * and stores -1 into '*fdp'.
 + *
 + * If 'sinp' is non-null, then on success the target address is stored into
 + * '*sinp'. */
 +int
 +tcp_open_active(const char *target_, uint16_t default_port,
 +                struct sockaddr_in *sinp, int *fdp)
 +{
 +    char *target = xstrdup(target_);
 +    char *save_ptr = NULL;
 +    const char *host_name;
 +    const char *port_string;
 +    struct sockaddr_in sin;
 +    int fd = -1;
 +    int error;
 +
 +    /* Defaults. */
 +    memset(&sin, 0, sizeof sin);
 +    sin.sin_family = AF_INET;
 +    sin.sin_port = htons(default_port);
 +
 +    /* Tokenize. */
 +    host_name = strtok_r(target, ":", &save_ptr);
 +    port_string = strtok_r(NULL, ":", &save_ptr);
 +    if (!host_name) {
 +        ovs_error(0, "%s: bad peer name format", target_);
 +        error = EAFNOSUPPORT;
 +        goto exit;
 +    }
 +
 +    /* Look up IP, port. */
 +    error = lookup_ip(host_name, &sin.sin_addr);
 +    if (error) {
 +        goto exit;
 +    }
 +    if (port_string && atoi(port_string)) {
 +        sin.sin_port = htons(atoi(port_string));
 +    }
 +
 +    /* Create non-blocking socket. */
 +    fd = socket(AF_INET, SOCK_STREAM, 0);
 +    if (fd < 0) {
 +        VLOG_ERR("%s: socket: %s", target_, strerror(errno));
 +        error = errno;
 +        goto exit;
 +    }
 +    error = set_nonblocking(fd);
 +    if (error) {
 +        goto exit_close;
 +    }
 +
 +    /* Connect. */
 +    error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
 +    if (error == EINPROGRESS) {
 +        error = EAGAIN;
 +    } else if (error && error != EAGAIN) {
 +        goto exit_close;
 +    }
 +
 +    /* Success: error is 0 or EAGAIN. */
 +    goto exit;
 +
 +exit_close:
 +    close(fd);
 +exit:
 +    if (!error || error == EAGAIN) {
 +        if (sinp) {
 +            *sinp = sin;
 +        }
 +        *fdp = fd;
 +    } else {
 +        *fdp = -1;
 +    }
 +    free(target);
 +    return error;
 +}
 +
 +/* Opens a non-blocking TCP socket, binds to 'target', and listens for incoming
 + * connections.  'target' should be a string in the format "[<port>][:<ip>]",
 + * where both <port> and <ip> are optional.  If <port> is omitted, it defaults
 + * to 'default_port'; if <ip> is omitted it defaults to the wildcard IP
 + * address.
 + *
 + * The socket will have SO_REUSEADDR turned on.
 + *
 + * On success, returns a non-negative file descriptor.  On failure, returns a
 + * negative errno value. */
 +int
 +tcp_open_passive(const char *target_, uint16_t default_port)
 +{
 +    char *target = xstrdup(target_);
 +    char *string_ptr = target;
 +    struct sockaddr_in sin;
 +    const char *host_name;
 +    const char *port_string;
 +    int fd, error;
 +    unsigned int yes  = 1;
 +
 +    /* Address defaults. */
 +    memset(&sin, 0, sizeof sin);
 +    sin.sin_family = AF_INET;
 +    sin.sin_addr.s_addr = htonl(INADDR_ANY);
 +    sin.sin_port = htons(default_port);
 +
 +    /* Parse optional port number. */
 +    port_string = strsep(&string_ptr, ":");
 +    if (port_string && atoi(port_string)) {
 +        sin.sin_port = htons(atoi(port_string));
 +    }
 +
 +    /* Parse optional bind IP. */
 +    host_name = strsep(&string_ptr, ":");
 +    if (host_name && host_name[0]) {
 +        error = lookup_ip(host_name, &sin.sin_addr);
 +        if (error) {
 +            goto exit;
 +        }
 +    }
 +
 +    /* Create non-blocking socket, set SO_REUSEADDR. */
 +    fd = socket(AF_INET, SOCK_STREAM, 0);
 +    if (fd < 0) {
 +        error = errno;
 +        VLOG_ERR("%s: socket: %s", target_, strerror(error));
 +        goto exit;
 +    }
 +    error = set_nonblocking(fd);
 +    if (error) {
 +        goto exit_close;
 +    }
 +    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
 +        error = errno;
 +        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target_, strerror(error));
 +        goto exit_close;
 +    }
 +
 +    /* Bind. */
 +    if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
 +        error = errno;
 +        VLOG_ERR("%s: bind: %s", target_, strerror(error));
 +        goto exit_close;
 +    }
 +
 +    /* Listen. */
 +    if (listen(fd, 10) < 0) {
 +        error = errno;
 +        VLOG_ERR("%s: listen: %s", target_, strerror(error));
 +        goto exit_close;
 +    }
 +    error = 0;
 +    goto exit;
 +
 +exit_close:
 +    close(fd);
 +exit:
 +    free(target);
 +    return error ? -error : fd;
 +}
 +
  int
  read_fully(int fd, void *p_, size_t size, size_t *bytes_read)
  {
diff --combined lib/socket-util.h
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #ifndef SOCKET_UTIL_H
@@@ -33,10 -33,6 +33,10 @@@ int make_unix_socket(int style, bool no
  int get_unix_name_len(socklen_t sun_len);
  uint32_t guess_netmask(uint32_t ip);
  
 +int tcp_open_active(const char *target, uint16_t default_port,
 +                    struct sockaddr_in *sinp, int *fdp);
 +int tcp_open_passive(const char *target, uint16_t default_port);
 +
  int read_fully(int fd, void *, size_t, size_t *bytes_read);
  int write_fully(int fd, const void *, size_t, size_t *bytes_written);
  
diff --combined lib/vconn-ssl.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -269,21 -269,58 +269,21 @@@ ssl_vconn_cast(struct vconn *vconn
  static int
  ssl_open(const char *name, char *suffix, struct vconn **vconnp)
  {
 -    char *save_ptr, *host_name, *port_string;
      struct sockaddr_in sin;
 -    int retval;
 -    int fd;
 -
 -    retval = ssl_init();
 -    if (retval) {
 -        return retval;
 -    }
 -
 -    host_name = strtok_r(suffix, ":", &save_ptr);
 -    port_string = strtok_r(NULL, ":", &save_ptr);
 -    if (!host_name) {
 -        ovs_error(0, "%s: bad peer name format", name);
 -        return EAFNOSUPPORT;
 -    }
 -
 -    memset(&sin, 0, sizeof sin);
 -    sin.sin_family = AF_INET;
 -    if (lookup_ip(host_name, &sin.sin_addr)) {
 -        return ENOENT;
 -    }
 -    sin.sin_port = htons(port_string && *port_string ? atoi(port_string)
 -                         : OFP_SSL_PORT);
 +    int error, fd;
  
 -    /* Create socket. */
 -    fd = socket(AF_INET, SOCK_STREAM, 0);
 -    if (fd < 0) {
 -        VLOG_ERR("%s: socket: %s", name, strerror(errno));
 -        return errno;
 -    }
 -    retval = set_nonblocking(fd);
 -    if (retval) {
 -        close(fd);
 -        return retval;
 +    error = ssl_init();
 +    if (error) {
 +        return error;
      }
  
 -    /* Connect socket. */
 -    retval = connect(fd, (struct sockaddr *) &sin, sizeof sin);
 -    if (retval < 0) {
 -        if (errno == EINPROGRESS) {
 -            return new_ssl_vconn(name, fd, CLIENT, STATE_TCP_CONNECTING,
 -                                 &sin, vconnp);
 -        } else {
 -            int error = errno;
 -            VLOG_ERR("%s: connect: %s", name, strerror(error));
 -            close(fd);
 -            return error;
 -        }
 +    error = tcp_open_active(suffix, OFP_SSL_PORT, &sin, &fd);
 +    if (fd >= 0) {
 +        int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING;
 +        return new_ssl_vconn(name, fd, CLIENT, state, &sin, vconnp);
      } else {
 -        return new_ssl_vconn(name, fd, CLIENT, STATE_SSL_CONNECTING,
 -                             &sin, vconnp);
 +        VLOG_ERR("%s: connect: %s", name, strerror(error));
 +        return error;
      }
  }
  
@@@ -756,18 -793,55 +756,18 @@@ pssl_pvconn_cast(struct pvconn *pvconn
  static int
  pssl_open(const char *name, char *suffix, struct pvconn **pvconnp)
  {
 -    struct sockaddr_in sin;
      struct pssl_pvconn *pssl;
      int retval;
      int fd;
 -    unsigned int yes = 1;
  
      retval = ssl_init();
      if (retval) {
          return retval;
      }
  
 -    /* Create socket. */
 -    fd = socket(AF_INET, SOCK_STREAM, 0);
 +    fd = tcp_open_passive(suffix, OFP_SSL_PORT);
      if (fd < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: socket: %s", name, strerror(error));
 -        return error;
 -    }
 -
 -    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", name, strerror(errno));
 -        return error;
 -    }
 -
 -    memset(&sin, 0, sizeof sin);
 -    sin.sin_family = AF_INET;
 -    sin.sin_addr.s_addr = htonl(INADDR_ANY);
 -    sin.sin_port = htons(atoi(suffix) ? atoi(suffix) : OFP_SSL_PORT);
 -    retval = bind(fd, (struct sockaddr *) &sin, sizeof sin);
 -    if (retval < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: bind: %s", name, strerror(error));
 -        close(fd);
 -        return error;
 -    }
 -
 -    retval = listen(fd, 10);
 -    if (retval < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: listen: %s", name, strerror(error));
 -        close(fd);
 -        return error;
 -    }
 -
 -    retval = set_nonblocking(fd);
 -    if (retval) {
 -        close(fd);
 -        return retval;
 +        return -fd;
      }
  
      pssl = xmalloc(sizeof *pssl);
diff --combined lib/vconn-stream.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -270,7 -270,23 +270,7 @@@ new_pstream_pvconn(const char *name, in
                                     size_t sa_len, struct vconn **),
                    struct pvconn **pvconnp)
  {
 -    struct pstream_pvconn *ps;
 -    int retval;
 -
 -    retval = set_nonblocking(fd);
 -    if (retval) {
 -        close(fd);
 -        return retval;
 -    }
 -
 -    if (listen(fd, 10) < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: listen: %s", name, strerror(error));
 -        close(fd);
 -        return error;
 -    }
 -
 -    ps = xmalloc(sizeof *ps);
 +    struct pstream_pvconn *ps = xmalloc(sizeof *ps);
      pvconn_init(&ps->pvconn, &pstream_pvconn_class, name);
      ps->fd = fd;
      ps->accept_cb = accept_cb;
diff --combined lib/vconn-tcp.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -57,15 -57,51 +57,15 @@@ new_tcp_vconn(const char *name, int fd
  static int
  tcp_open(const char *name, char *suffix, struct vconn **vconnp)
  {
 -    char *save_ptr;
 -    const char *host_name;
 -    const char *port_string;
      struct sockaddr_in sin;
 -    int retval;
 -    int fd;
 -
 -    host_name = strtok_r(suffix, ":", &save_ptr);
 -    port_string = strtok_r(NULL, ":", &save_ptr);
 -    if (!host_name) {
 -        ovs_error(0, "%s: bad peer name format", name);
 -        return EAFNOSUPPORT;
 -    }
 -
 -    memset(&sin, 0, sizeof sin);
 -    sin.sin_family = AF_INET;
 -    if (lookup_ip(host_name, &sin.sin_addr)) {
 -        return ENOENT;
 -    }
 -    sin.sin_port = htons(port_string ? atoi(port_string) : OFP_TCP_PORT);
 -
 -    fd = socket(AF_INET, SOCK_STREAM, 0);
 -    if (fd < 0) {
 -        VLOG_ERR("%s: socket: %s", name, strerror(errno));
 -        return errno;
 -    }
 -
 -    retval = set_nonblocking(fd);
 -    if (retval) {
 -        close(fd);
 -        return retval;
 -    }
 +    int fd, error;
  
 -    retval = connect(fd, (struct sockaddr *) &sin, sizeof sin);
 -    if (retval < 0) {
 -        if (errno == EINPROGRESS) {
 -            return new_tcp_vconn(name, fd, EAGAIN, &sin, vconnp);
 -        } else {
 -            int error = errno;
 -            VLOG_ERR("%s: connect: %s", name, strerror(error));
 -            close(fd);
 -            return error;
 -        }
 +    error = tcp_open_active(suffix, OFP_TCP_PORT, NULL, &fd);
 +    if (fd >= 0) {
 +        return new_tcp_vconn(name, fd, error, &sin, vconnp);
      } else {
 -        return new_tcp_vconn(name, fd, 0, &sin, vconnp);
 +        VLOG_ERR("%s: connect: %s", name, strerror(error));
 +        return error;
      }
  }
  
@@@ -85,16 -121,37 +85,16 @@@ static int ptcp_accept(int fd, const st
                         struct vconn **vconnp);
  
  static int
 -ptcp_open(const char *name, char *suffix, struct pvconn **pvconnp)
 +ptcp_open(const char *name UNUSED, char *suffix, struct pvconn **pvconnp)
  {
 -    struct sockaddr_in sin;
 -    int retval;
      int fd;
 -    unsigned int yes  = 1;
  
 -    fd = socket(AF_INET, SOCK_STREAM, 0);
 +    fd = tcp_open_passive(suffix, OFP_TCP_PORT);
      if (fd < 0) {
 -        VLOG_ERR("%s: socket: %s", name, strerror(errno));
 -        return errno;
 -    }
 -
 -    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
 -        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", name, strerror(errno));
 -        return errno;
 -    }
 -
 -    memset(&sin, 0, sizeof sin);
 -    sin.sin_family = AF_INET;
 -    sin.sin_addr.s_addr = htonl(INADDR_ANY);
 -    sin.sin_port = htons(atoi(suffix) ? atoi(suffix) : OFP_TCP_PORT);
 -    retval = bind(fd, (struct sockaddr *) &sin, sizeof sin);
 -    if (retval < 0) {
 -        int error = errno;
 -        VLOG_ERR("%s: bind: %s", name, strerror(error));
 -        close(fd);
 -        return error;
 +        return -fd;
 +    } else {
 +        return new_pstream_pvconn("ptcp", fd, ptcp_accept, pvconnp);
      }
 -
 -    return new_pstream_pvconn("ptcp", fd, ptcp_accept, pvconnp);
  }
  
  static int
diff --combined lib/vconn-unix.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -81,7 -81,7 +81,7 @@@ static int punix_accept(int fd, const s
  static int
  punix_open(const char *name UNUSED, char *suffix, struct pvconn **pvconnp)
  {
 -    int fd;
 +    int fd, error;
  
      fd = make_unix_socket(SOCK_STREAM, true, true, suffix, NULL);
      if (fd < 0) {
          return errno;
      }
  
 +    error = set_nonblocking(fd);
 +    if (error) {
 +        close(fd);
 +        return error;
 +    }
 +
 +    if (listen(fd, 10) < 0) {
 +        error = errno;
 +        VLOG_ERR("%s: listen: %s", name, strerror(error));
 +        close(fd);
 +        return error;
 +    }
 +
      return new_pstream_pvconn("punix", fd, punix_accept, pvconnp);
  }
  
diff --combined lib/vconn.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -139,12 -139,12 +139,12 @@@ vconn_usage(bool active, bool passive, 
  
      if (passive) {
          printf("Passive OpenFlow connection methods:\n");
 -        printf("  ptcp:[PORT]             "
 -               "listen to TCP PORT (default: %d)\n",
 +        printf("  ptcp:[PORT][:IP]        "
 +               "listen to TCP PORT (default: %d) on IP\n",
                 OFP_TCP_PORT);
  #ifdef HAVE_OPENSSL
 -        printf("  pssl:[PORT]             "
 -               "listen for SSL on PORT (default: %d)\n",
 +        printf("  pssl:[PORT][:IP]        "
 +               "listen for SSL on PORT (default: %d) on IP\n",
                 OFP_SSL_PORT);
  #endif
          printf("  punix:FILE              "
@@@ -339,7 -339,7 +339,7 @@@ vcs_recv_hello(struct vconn *vconn
  
      if (retval != EAGAIN) {
          vconn->state = VCS_DISCONNECTED;
 -        vconn->error = retval;
 +        vconn->error = retval == EOF ? ECONNRESET : retval;
      }
  }
  
@@@ -433,7 -433,10 +433,7 @@@ vconn_recv(struct vconn *vconn, struct 
  static int
  do_recv(struct vconn *vconn, struct ofpbuf **msgp)
  {
 -    int retval;
 -
 -again:
 -    retval = (vconn->class->recv)(vconn, msgp);
 +    int retval = (vconn->class->recv)(vconn, msgp);
      if (!retval) {
          struct ofp_header *oh;
  
              && oh->type != OFPT_VENDOR)
          {
              if (vconn->version < 0) {
 -                if (oh->type == OFPT_PACKET_IN
 -                    || oh->type == OFPT_FLOW_EXPIRED
 -                    || oh->type == OFPT_PORT_STATUS) {
 -                    /* The kernel datapath is stateless and doesn't really
 -                     * support version negotiation, so it can end up sending
 -                     * these asynchronous message before version negotiation
 -                     * is complete.  Just ignore them.
 -                     *
 -                     * (After we move OFPT_PORT_STATUS messages from the kernel
 -                     * into secchan, we won't get those here, since secchan
 -                     * does proper version negotiation.) */
 -                    ofpbuf_delete(*msgp);
 -                    goto again;
 -                }
                  VLOG_ERR_RL(&bad_ofmsg_rl,
                              "%s: received OpenFlow message type %"PRIu8" "
                              "before version negotiation complete",
diff --combined secchan/discovery.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -168,7 -168,7 +168,7 @@@ discovery_set_accept_controller_re(stru
      int error;
      char *re;
  
 -    re = (!re_ ? xstrdup(vconn_ssl_is_configured() ? "^ssl:.*" : ".*")
 +    re = (!re_ ? xstrdup(vconn_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*")
            : re_[0] == '^' ? xstrdup(re_) : xasprintf("^%s", re_));
      regex = xmalloc(sizeof *regex);
      error = regcomp(regex, re, REG_NOSUB | REG_EXTENDED);
diff --combined secchan/main.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -497,8 -497,7 +497,8 @@@ parse_options(int argc, char *argv[], s
  
      /* Set accept_controller_regex. */
      if (!s->accept_controller_re) {
 -        s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*";
 +        s->accept_controller_re
 +            = vconn_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*";
      }
  
      /* Mode of operation. */
diff --combined utilities/ovs-discover.c
@@@ -1,17 -1,17 +1,17 @@@
  /*
   * Copyright (c) 2008, 2009 Nicira Networks.
   *
-  * Permission to use, copy, modify, and/or distribute this software for any
-  * purpose with or without fee is hereby granted, provided that the above
-  * copyright notice and this permission notice appear in all copies.
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
   *
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
   */
  
  #include <config.h>
@@@ -48,7 -48,7 +48,7 @@@ static int n_ifaces
  
  /* --accept-vconn: Regular expression specifying the class of controller vconns
   * that we will accept during autodiscovery. */
 -static const char *accept_controller_re = ".*";
 +static const char *accept_controller_re = "tcp:.*";
  static regex_t accept_controller_regex;
  
  /* --exit-without-bind: Exit after discovering the controller, without binding