[ovs-dev] [PATCH v2 2/3] socket-util: Change ss_format_address() to take a dynamic string.

Ben Pfaff blp at ovn.org
Fri Jul 14 21:33:45 UTC 2017


It's occasionally convenient to format into a fixed-size buffer, but
as the use cases, and the text to be formatted, get more sophisticated,
it becomes easier to deal with "struct ds *" than a buffer pointer and
length pair.  An upcoming commit will make ss_format_address() do more
work, and I think that this is the point at which it becomes easier to
take a dynamic string.  This commit makes the parameter type change
without yet changing what is formatted.

Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 lib/socket-util.c | 36 ++++++++++++++++--------------------
 lib/socket-util.h |  6 +++---
 lib/stream-ssl.c  | 25 +++++++++++++------------
 lib/stream-tcp.c  | 30 +++++++++++++-----------------
 4 files changed, 45 insertions(+), 52 deletions(-)

diff --git a/lib/socket-util.c b/lib/socket-util.c
index 04401d49de27..82975aa62981 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -808,11 +808,8 @@ describe_sockaddr(struct ds *string, int fd,
 
     if (!getaddr(fd, (struct sockaddr *) &ss, &len)) {
         if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
-            char addrbuf[SS_NTOP_BUFSIZE];
-
-            ds_put_format(string, "%s:%"PRIu16,
-                          ss_format_address(&ss, addrbuf, sizeof addrbuf),
-                          ss_get_port(&ss));
+            ss_format_address(&ss, string);
+            ds_put_format(string, ":%"PRIu16, ss_get_port(&ss));
 #ifndef _WIN32
         } else if (ss.ss_family == AF_UNIX) {
             struct sockaddr_un sun;
@@ -961,33 +958,32 @@ ss_get_port(const struct sockaddr_storage *ss)
     }
 }
 
-/* Formats the IPv4 or IPv6 address in 'ss' into the 'bufsize' bytes in 'buf'.
- * If 'ss' is an IPv6 address, puts square brackets around the address.
- * 'bufsize' should be at least SS_NTOP_BUFSIZE.
- *
- * Returns 'buf'. */
-char *
-ss_format_address(const struct sockaddr_storage *ss,
-                  char *buf, size_t bufsize)
+
+/* Formats the IPv4 or IPv6 address in 'ss' into 's'.  If 'ss' is an IPv6
+ * address, puts square brackets around the address.  'bufsize' should be at
+ * least SS_NTOP_BUFSIZE. */
+void
+ss_format_address(const struct sockaddr_storage *ss, struct ds *s)
 {
-    ovs_assert(bufsize >= SS_NTOP_BUFSIZE);
     if (ss->ss_family == AF_INET) {
         const struct sockaddr_in *sin
             = ALIGNED_CAST(const struct sockaddr_in *, ss);
 
-        snprintf(buf, bufsize, IP_FMT, IP_ARGS(sin->sin_addr.s_addr));
+        ds_put_format(s, IP_FMT, IP_ARGS(sin->sin_addr.s_addr));
     } else if (ss->ss_family == AF_INET6) {
         const struct sockaddr_in6 *sin6
             = ALIGNED_CAST(const struct sockaddr_in6 *, ss);
 
-        buf[0] = '[';
-        inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, buf + 1, bufsize - 1);
-        strcpy(strchr(buf, '\0'), "]");
+        ds_put_char(s, '[');
+        ds_reserve(s, s->length + INET6_ADDRSTRLEN);
+        char *tail = &s->string[s->length];
+        inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, tail, INET6_ADDRSTRLEN);
+        s->length += strlen(tail);
+
+        ds_put_char(s, ']');
     } else {
         OVS_NOT_REACHED();
     }
-
-    return buf;
 }
 
 size_t
diff --git a/lib/socket-util.h b/lib/socket-util.h
index ef316cb8cc72..1782745fa2c0 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -28,6 +28,8 @@
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 
+struct ds;
+
 int set_nonblocking(int fd);
 void xset_nonblocking(int fd);
 void setsockopt_tcp_nodelay(int fd);
@@ -71,9 +73,7 @@ char *describe_fd(int fd);
 /* Functions for working with sockaddr_storage that might contain an IPv4 or
  * IPv6 address. */
 uint16_t ss_get_port(const struct sockaddr_storage *);
-#define SS_NTOP_BUFSIZE (1 + INET6_ADDRSTRLEN + 1)
-char *ss_format_address(const struct sockaddr_storage *,
-                        char *buf, size_t bufsize);
+void ss_format_address(const struct sockaddr_storage *, struct ds *);
 size_t ss_length(const struct sockaddr_storage *);
 const char *sock_strerror(int error);
 
diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c
index 6dc6f25fddf9..a198d6783dbb 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -825,8 +825,6 @@ static int
 pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
           uint8_t dscp)
 {
-    char bound_name[SS_NTOP_BUFSIZE + 16];
-    char addrbuf[SS_NTOP_BUFSIZE];
     struct sockaddr_storage ss;
     struct pssl_pstream *pssl;
     uint16_t port;
@@ -844,14 +842,18 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
     }
 
     port = ss_get_port(&ss);
-    snprintf(bound_name, sizeof bound_name, "pssl:%"PRIu16":%s",
-             port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
+
+    struct ds bound_name = DS_EMPTY_INITIALIZER;
+    ds_put_format(&bound_name, "pssl:%"PRIu16":", port);
+    ss_format_address(&ss, &bound_name);
 
     pssl = xmalloc(sizeof *pssl);
-    pstream_init(&pssl->pstream, &pssl_pstream_class, xstrdup(bound_name));
+    pstream_init(&pssl->pstream, &pssl_pstream_class,
+                 ds_steal_cstr(&bound_name));
     pstream_set_bound_port(&pssl->pstream, htons(port));
     pssl->fd = fd;
     *pstreamp = &pssl->pstream;
+
     return 0;
 }
 
@@ -867,8 +869,6 @@ static int
 pssl_accept(struct pstream *pstream, struct stream **new_streamp)
 {
     struct pssl_pstream *pssl = pssl_pstream_cast(pstream);
-    char name[SS_NTOP_BUFSIZE + 16];
-    char addrbuf[SS_NTOP_BUFSIZE];
     struct sockaddr_storage ss;
     socklen_t ss_len = sizeof ss;
     int new_fd;
@@ -894,11 +894,12 @@ pssl_accept(struct pstream *pstream, struct stream **new_streamp)
         return error;
     }
 
-    snprintf(name, sizeof name, "ssl:%s:%"PRIu16,
-             ss_format_address(&ss, addrbuf, sizeof addrbuf),
-             ss_get_port(&ss));
-    return new_ssl_stream(xstrdup(name), new_fd, SERVER, STATE_SSL_CONNECTING,
-                          new_streamp);
+    struct ds name = DS_EMPTY_INITIALIZER;
+    ds_put_cstr(&name, "ssl:");
+    ss_format_address(&ss, &name);
+    ds_put_format(&name, ":%"PRIu16, ss_get_port(&ss));
+    return new_ssl_stream(ds_steal_cstr(&name), new_fd, SERVER,
+                          STATE_SSL_CONNECTING, new_streamp);
 }
 
 static void
diff --git a/lib/stream-tcp.c b/lib/stream-tcp.c
index da88cbafaf9e..4fae731d9b9e 100644
--- a/lib/stream-tcp.c
+++ b/lib/stream-tcp.c
@@ -84,13 +84,9 @@ static int
 new_pstream(char *suffix, const char *name, struct pstream **pstreamp,
             int dscp, char *unlink_path, bool kernel_print_port)
 {
-    char bound_name[SS_NTOP_BUFSIZE + 16];
-    char addrbuf[SS_NTOP_BUFSIZE];
     struct sockaddr_storage ss;
     int error;
-    uint16_t port;
     int fd;
-    char *conn_name = CONST_CAST(char *, name);
 
     fd = inet_open_passive(SOCK_STREAM, suffix, -1, &ss, dscp,
                            kernel_print_port);
@@ -98,17 +94,18 @@ new_pstream(char *suffix, const char *name, struct pstream **pstreamp,
         return -fd;
     }
 
-    port = ss_get_port(&ss);
-    if (!conn_name) {
-        snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s",
-                 port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
-        conn_name = bound_name;
+    struct ds bound_name = DS_EMPTY_INITIALIZER;
+    if (!name) {
+        ds_put_format(&bound_name, "ptcp:%"PRIu16":", ss_get_port(&ss));
+        ss_format_address(&ss, &bound_name);
+    } else {
+        ds_put_cstr(&bound_name, name);
     }
 
-    error = new_fd_pstream(xstrdup(conn_name), fd,
+    error = new_fd_pstream(ds_steal_cstr(&bound_name), fd,
                            ptcp_accept, unlink_path, pstreamp);
     if (!error) {
-        pstream_set_bound_port(*pstreamp, htons(port));
+        pstream_set_bound_port(*pstreamp, htons(ss_get_port(&ss)));
     }
     return error;
 }
@@ -124,13 +121,12 @@ static int
 ptcp_accept(int fd, const struct sockaddr_storage *ss,
             size_t ss_len OVS_UNUSED, struct stream **streamp)
 {
-    char name[SS_NTOP_BUFSIZE + 16];
-    char addrbuf[SS_NTOP_BUFSIZE];
+    struct ds name = DS_EMPTY_INITIALIZER;
+    ds_put_cstr(&name, "tcp:");
+    ss_format_address(ss, &name);
+    ds_put_format(&name, ":%"PRIu16, ss_get_port(ss));
 
-    snprintf(name, sizeof name, "tcp:%s:%"PRIu16,
-             ss_format_address(ss, addrbuf, sizeof addrbuf),
-             ss_get_port(ss));
-    return new_tcp_stream(xstrdup(name), fd, 0, streamp);
+    return new_tcp_stream(ds_steal_cstr(&name), fd, 0, streamp);
 }
 
 const struct pstream_class ptcp_pstream_class = {
-- 
2.10.2



More information about the dev mailing list