classifier: Check all rules of equal priority when inserting.
[sliver-openvswitch.git] / lib / stream-ssl.c
index b14ce55..51ce306 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.
@@ -155,7 +155,7 @@ static void ssl_close(struct stream *);
 static void ssl_clear_txbuf(struct ssl_stream *);
 static int interpret_ssl_error(const char *function, int ret, int error,
                                int *want);
-static DH *tmp_dh_callback(SSL *ssl, int is_export UNUSED, int keylength);
+static DH *tmp_dh_callback(SSL *ssl, int is_export OVS_UNUSED, int keylength);
 static void log_ca_cert(const char *file_name, X509 *cert);
 
 static short int
@@ -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 OVS_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, &sin);
     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;
@@ -842,7 +855,7 @@ do_ssl_init(void)
 }
 
 static DH *
-tmp_dh_callback(SSL *ssl UNUSED, int is_export UNUSED, int keylength)
+tmp_dh_callback(SSL *ssl OVS_UNUSED, int is_export OVS_UNUSED, int keylength)
 {
     struct dh {
         int keylength;
@@ -1061,6 +1074,7 @@ stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap)
             }
             X509_free(certs[i]);
         }
+        free(certs);
 
         /* Set up CAs for OpenSSL to trust in verifying the peer's
          * certificate. */