summaryrefslogtreecommitdiff
path: root/lib/vconn.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2013-01-04 12:41:01 -0800
committerBen Pfaff <blp@nicira.com>2013-01-24 14:57:24 -0800
commit4766ce7a6438c11743c354fddad9d1164c76c467 (patch)
tree4880b10c8ad9925c66ca1a46e46765aaeb68055d /lib/vconn.c
parent539b741f5999e22de02b14a35cc3e3855e2dc51d (diff)
downloadopenvswitch-4766ce7a6438c11743c354fddad9d1164c76c467.tar.gz
rconn: Fix null pointer dereference in rconn_add_monitor().
rconn_add_monitor() tries to check the version of the controller connection being monitored, so that it can decide what OpenFlow version to tell the monitor connection to negotiate. But at any given time an rconn may not have a controller connection (e.g. during backoff), so rc->vconn may be null and thus vconn_get_version(rc->vconn) dereferences a null pointer. Fixing the problem in a local way would require the rconn to remember the previous version negotiated, and that fails if the rconn hasn't yet connected or if the next connection negotiates a new version. This commit instead adds the ability to a vconn to accept any OpenFlow message version and modifies "ovs-ofctl snoop" to use that feature, thus removing the need to negotiate the "correct" version on snoops. Bug #14265. Reported-by: Pratap Reddy <preddy@nicira.com> Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Ethan Jackson <ethan@nicira.com>
Diffstat (limited to 'lib/vconn.c')
-rw-r--r--lib/vconn.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/lib/vconn.c b/lib/vconn.c
index e0223cd5e..ea1e13012 100644
--- a/lib/vconn.c
+++ b/lib/vconn.c
@@ -394,6 +394,27 @@ vconn_get_version(const struct vconn *vconn)
return vconn->version ? vconn->version : -1;
}
+/* By default, a vconn accepts only OpenFlow messages whose version matches the
+ * one negotiated for the connection. A message received with a different
+ * version is an error that causes the vconn to drop the connection.
+ *
+ * This functions allows 'vconn' to accept messages with any OpenFlow version.
+ * This is useful in the special case where 'vconn' is used as an rconn
+ * "monitor" connection (see rconn_add_monitor()), that is, where 'vconn' is
+ * used as a target for mirroring OpenFlow messages for debugging and
+ * troubleshooting.
+ *
+ * This function should be called after a successful vconn_open() or
+ * pvconn_accept() but before the connection completes, that is, before
+ * vconn_connect() returns success. Otherwise, messages that arrive on 'vconn'
+ * beforehand with an unexpected version will the vconn to drop the
+ * connection. */
+void
+vconn_set_recv_any_version(struct vconn *vconn)
+{
+ vconn->recv_any_version = true;
+}
+
static void
vcs_connecting(struct vconn *vconn)
{
@@ -600,7 +621,7 @@ vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
if (!retval) {
retval = do_recv(vconn, &msg);
}
- if (!retval) {
+ if (!retval && !vconn->recv_any_version) {
const struct ofp_header *oh = msg->data;
if (oh->version != vconn->version) {
enum ofptype type;