vconn: Make errors in vconn names non-fatal errors.
authorBen Pfaff <blp@nicira.com>
Mon, 14 Jul 2008 21:01:06 +0000 (14:01 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 18 Jul 2008 21:16:40 +0000 (14:16 -0700)
This prevents bad vconn names obtained via discovery from killing
the secure channel.

include/rconn.h
lib/rconn.c
lib/vconn-netlink.c
lib/vconn-ssl.c
lib/vconn-tcp.c
lib/vconn.c
secchan/secchan.c
switch/switch.c

index 0e9f4a7a602d2006fab5e61bf328e4fe6fd103ad..228b8e89480ea0d19c18544cbace3f852ad7a03c 100644 (file)
@@ -59,7 +59,7 @@ struct rconn *rconn_new_from_vconn(const char *name, int txq_limit,
                                    struct vconn *);
 struct rconn *rconn_create(int txq_limit, int inactivity_probe_interval,
                            int max_backoff);
-void rconn_connect(struct rconn *, const char *name);
+int rconn_connect(struct rconn *, const char *name);
 void rconn_connect_unreliably(struct rconn *,
                               const char *name, struct vconn *vconn);
 void rconn_disconnect(struct rconn *);
index 7f5a1dcf3de365f059387a0bc6e0bd5260a4db0a..a145e4e3181f1454b7e11d7c3828edc1695f0f8e 100644 (file)
@@ -116,7 +116,7 @@ static unsigned int elapsed_in_this_state(const struct rconn *);
 static bool timeout(struct rconn *, unsigned int secs);
 static void state_transition(struct rconn *, enum state);
 static int try_send(struct rconn *);
-static void reconnect(struct rconn *);
+static int reconnect(struct rconn *);
 static void disconnect(struct rconn *, int error);
 static void question_connectivity(struct rconn *);
 
@@ -187,14 +187,14 @@ rconn_create(int txq_limit, int probe_interval, int max_backoff)
     return rc;
 }
 
-void
+int
 rconn_connect(struct rconn *rc, const char *name)
 {
     rconn_disconnect(rc);
     free(rc->name);
     rc->name = xstrdup(name);
     rc->reliable = true;
-    reconnect(rc);
+    return reconnect(rc);
 }
 
 void
@@ -246,7 +246,7 @@ run_VOID(struct rconn *rc)
     /* Nothing to do. */
 }
 
-static void
+static int
 reconnect(struct rconn *rc)
 {
     int retval;
@@ -260,6 +260,7 @@ reconnect(struct rconn *rc)
         VLOG_WARN("%s: connection failed (%s)", rc->name, strerror(retval));
         disconnect(rc, 0);
     }
+    return retval;
 }
 
 static void
@@ -273,18 +274,19 @@ run_BACKOFF(struct rconn *rc)
 static void
 run_CONNECTING(struct rconn *rc)
 {
-    int error = vconn_connect(rc->vconn);
-    if (!error) {
+    int retval = vconn_connect(rc->vconn);
+    if (!retval) {
         VLOG_WARN("%s: connected", rc->name);
         if (vconn_is_passive(rc->vconn)) {
-            fatal(0, "%s: passive vconn not supported in switch",
-                  rc->name);
+            error(0, "%s: passive vconn not supported", rc->name);
+            state_transition(rc, S_VOID);
+        } else {
+            state_transition(rc, S_ACTIVE);
+            rc->last_connected = rc->state_entered;
         }
-        state_transition(rc, S_ACTIVE);
-        rc->last_connected = rc->state_entered;
-    } else if (error != EAGAIN) {
-        VLOG_WARN("%s: connection failed (%s)", rc->name, strerror(error));
-        disconnect(rc, error);
+    } else if (retval != EAGAIN) {
+        VLOG_WARN("%s: connection failed (%s)", rc->name, strerror(retval));
+        disconnect(rc, retval);
     } else if (timeout(rc, MAX(1, rc->backoff))) {
         VLOG_WARN("%s: connection timed out", rc->name);
         rc->backoff_deadline = TIME_MAX; /* Prevent resetting backoff. */
index 6e7e152e69eb94a8038444a6cfa8f6dfd24bdff1..84d7d3548196ae1fc87f62e58da939ae64bc9c80 100644 (file)
@@ -77,7 +77,8 @@ netlink_open(const char *name, char *suffix, struct vconn **vconnp)
 
     subscribe = 1;
     if (sscanf(suffix, "%d:%d", &dp_idx, &subscribe) < 1) {
-        fatal(0, "%s: syntax error", name);
+        error(0, "%s: syntax error", name);
+        return EAFNOSUPPORT;
     }
 
     netlink = xmalloc(sizeof *netlink);
index 0da4c578da8fce6a851d05bf19616a1b5b1d7e90..a7060d74bb9a91e4f1bd7c80829437a9b4132a1a 100644 (file)
@@ -270,7 +270,8 @@ ssl_open(const char *name, char *suffix, struct vconn **vconnp)
     host_name = strtok_r(suffix, "::", &save_ptr);
     port_string = strtok_r(NULL, "::", &save_ptr);
     if (!host_name) {
-        fatal(0, "%s: bad peer name format", name);
+        error(0, "%s: bad peer name format", name);
+        return EAFNOSUPPORT;
     }
 
     memset(&sin, 0, sizeof sin);
index aaff94038ed6eab81796d6ba49bc81c63d7dc007..80c8f56c5b6c558846d3c8686042a592edf763cf 100644 (file)
@@ -117,7 +117,8 @@ tcp_open(const char *name, char *suffix, struct vconn **vconnp)
     host_name = strtok_r(suffix, "::", &save_ptr);
     port_string = strtok_r(NULL, "::", &save_ptr);
     if (!host_name) {
-        fatal(0, "%s: bad peer name format", name);
+        error(0, "%s: bad peer name format", name);
+        return EAFNOSUPPORT;
     }
 
     memset(&sin, 0, sizeof sin);
index db1cc4c526abaf2760a3649d236008de8319cb81..103c9df58b20713c7008bd00eb2d92ca73c67acd 100644 (file)
@@ -143,7 +143,8 @@ vconn_open(const char *name, struct vconn **vconnp)
 
     prefix_len = strcspn(name, ":");
     if (prefix_len == strlen(name)) {
-        fatal(0, "`%s' not correct format for peer name", name);
+        error(0, "`%s' not correct format for peer name", name);
+        return EAFNOSUPPORT;
     }
     for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
         struct vconn_class *class = vconn_classes[i];
@@ -161,8 +162,8 @@ vconn_open(const char *name, struct vconn **vconnp)
             return retval;
         }
     }
-    fatal(0, "unknown peer type `%.*s'", (int) prefix_len, name);
-    abort();
+    error(0, "unknown peer type `%.*s'", (int) prefix_len, name);
+    return EAFNOSUPPORT;
 }
 
 int
index 61039b5b541af695648dba56d8fc224cc93d0b2b..8638dc76a38c90e6a2f6b46ce47fa68814fa236d 100644 (file)
@@ -135,6 +135,7 @@ static bool fail_open_hook(struct relay *r);
 int
 main(int argc, char *argv[])
 {
+    struct rconn *local_rconn, *remote_rconn;
     struct vconn *listen_vconn;
     struct relay *controller_relay;
     const char *nl_name;
@@ -201,10 +202,18 @@ main(int argc, char *argv[])
 
     daemonize();
 
-    controller_relay = relay_create(rconn_new(argv[optind], 1, 0, max_backoff),
-                                    rconn_new(argv[optind + 1], 1,
-                                              probe_interval, max_backoff),
-                                    false);
+    local_rconn = rconn_create(1, 0, max_backoff);
+    retval = rconn_connect(local_rconn, nl_name);
+    if (retval == EAFNOSUPPORT) {
+        fatal(0, "No support for %s vconn", nl_name);
+    }
+
+    remote_rconn = rconn_create(1, probe_interval, max_backoff);
+    retval = rconn_connect(remote_rconn, argv[optind + 1]);
+    if (retval == EAFNOSUPPORT) {
+        fatal(0, "No support for %s vconn", argv[optind + 1]);
+    }
+    controller_relay = relay_create(local_rconn, remote_rconn, false);
     for (;;) {
         struct relay *r, *n;
 
index 77d43bb87d8a70d4a4c26426ddd7160d92fa6d83..01fb4b8218589301d618ae047be255d85783deeb 100644 (file)
@@ -71,6 +71,7 @@ static void add_ports(struct datapath *dp, char *port_list);
 int
 main(int argc, char *argv[])
 {
+    struct rconn *rconn;
     int error;
 
     set_program_name(argv[0]);
@@ -82,7 +83,12 @@ main(int argc, char *argv[])
         fatal(0, "missing controller argument; use --help for usage");
     }
 
-    error = dp_new(&dp, dpid, rconn_new(argv[optind], 128, 60, max_backoff));
+    rconn = rconn_create(128, 60, max_backoff);
+    error = rconn_connect(rconn, argv[optind]);
+    if (error == EAFNOSUPPORT) {
+        fatal(0, "no support for %s vconn", argv[optind]);
+    }
+    error = dp_new(&dp, dpid, rconn);
     if (listen_vconn_name) {
         struct vconn *listen_vconn;
         int retval;