stream: Really enable SSL streams.
[openvswitch] / lib / stream-ssl.c
index b14ce550b4dfcb6a92f283fba3f0e7c69811c673..6839341c1cf56161fedfb4923c35ce50ea38b2fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -437,6 +437,14 @@ ssl_close(struct stream *stream)
 {
     struct ssl_stream *sslv = ssl_stream_cast(stream);
     ssl_clear_txbuf(sslv);
+
+    /* Attempt clean shutdown of the SSL connection.  This will work most of
+     * the time, as long as the kernel send buffer has some free space and the
+     * SSL connection isn't renegotiating, etc.  That has to be good enough,
+     * since we don't have any way to continue the close operation in the
+     * background. */
+    SSL_shutdown(sslv->ssl);
+
     SSL_free(sslv->ssl);
     close(sslv->fd);
     free(sslv);
@@ -541,7 +549,8 @@ ssl_recv(struct stream *stream, void *buffer, size_t n)
         if (error == SSL_ERROR_ZERO_RETURN) {
             return 0;
         } else {
-            return interpret_ssl_error("SSL_read", ret, error, &sslv->rx_want);
+            return -interpret_ssl_error("SSL_read", ret, error,
+                                        &sslv->rx_want);
         }
     }
 }
@@ -589,7 +598,7 @@ ssl_send(struct stream *stream, const void *buffer, size_t n)
     struct ssl_stream *sslv = ssl_stream_cast(stream);
 
     if (sslv->txbuf) {
-        return EAGAIN;
+        return -EAGAIN;
     } else {
         int error;
 
@@ -598,13 +607,13 @@ ssl_send(struct stream *stream, const void *buffer, size_t n)
         switch (error) {
         case 0:
             ssl_clear_txbuf(sslv);
-            return 0;
+            return n;
         case EAGAIN:
             leak_checker_claim(buffer);
-            return 0;
+            return n;
         default:
             sslv->txbuf = NULL;
-            return error;
+            return -error;
         }
     }
 }
@@ -710,9 +719,11 @@ pssl_pstream_cast(struct pstream *pstream)
 }
 
 static int
-pssl_open(const char *name, char *suffix, struct pstream **pstreamp)
+pssl_open(const char *name UNUSED, char *suffix, struct pstream **pstreamp)
 {
     struct pssl_pstream *pssl;
+    struct sockaddr_in sin;
+    char bound_name[128];
     int retval;
     int fd;
 
@@ -721,13 +732,15 @@ pssl_open(const char *name, char *suffix, struct pstream **pstreamp)
         return retval;
     }
 
-    fd = inet_open_passive(SOCK_STREAM, suffix, OFP_SSL_PORT);
+    fd = inet_open_passive(SOCK_STREAM, suffix, OFP_SSL_PORT, NULL);
     if (fd < 0) {
         return -fd;
     }
+    sprintf(bound_name, "pssl:%"PRIu16":"IP_FMT,
+            ntohs(sin.sin_port), IP_ARGS(&sin.sin_addr.s_addr));
 
     pssl = xmalloc(sizeof *pssl);
-    pstream_init(&pssl->pstream, &pssl_pstream_class, name);
+    pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name);
     pssl->fd = fd;
     *pstreamp = &pssl->pstream;
     return 0;