[Babel-users] [PATCH v2] Add support for unix-domain local socket

Julien Cristau jcristau at debian.org
Sat Feb 13 14:13:28 UTC 2016


The absolute path to the socket can be passed to the -g/-G command line
options, or to the new local-path/local-path-readwrite config file
directives.

Signed-off-by: Julien Cristau <jcristau at debian.org>
---
 babeld.c        | 34 +++++++++++++++++++++++++---------
 babeld.h        |  1 +
 babeld.man      | 31 +++++++++++++++++++++++++++----
 configuration.c | 20 ++++++++++++++++++--
 local.c         |  1 +
 local.h         |  1 +
 net.c           | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net.h           |  1 +
 8 files changed, 128 insertions(+), 15 deletions(-)

Changes in v2:
- use consistent style for ifs
- local_server_path is a pointer, dynamically allocated, instead of a static
  array
- avoid code duplication between -g and -G flag handling

diff --git a/babeld.c b/babeld.c
index 203e195..f975ac0 100644
--- a/babeld.c
+++ b/babeld.c
@@ -238,16 +238,22 @@ main(int argc, char **argv)
                 goto usage;
             break;
         case 'g':
-            local_server_port = parse_nat(optarg);
-            local_server_write = 0;
-            if(local_server_port <= 0 || local_server_port > 0xFFFF)
-                goto usage;
-            break;
         case 'G':
-            local_server_port = parse_nat(optarg);
-            local_server_write = 1;
-            if(local_server_port <= 0 || local_server_port > 0xFFFF)
-                goto usage;
+            if(opt == 'g')
+                local_server_write = 0;
+            else
+                local_server_write = 1;
+            if(optarg[0] == '/') {
+                local_server_port = -1;
+                free(local_server_path);
+                local_server_path = strdup(optarg);
+            } else {
+                local_server_port = parse_nat(optarg);
+                free(local_server_path);
+                local_server_path = NULL;
+                if(local_server_port <= 0 || local_server_port > 0xFFFF)
+                    goto usage;
+            }
             break;
         case 'l':
             link_detect = 1;
@@ -526,6 +532,12 @@ main(int argc, char **argv)
             perror("local_server_socket");
             goto fail;
         }
+    } else if(local_server_path) {
+        local_server_socket = unix_server_socket(local_server_path);
+        if(local_server_socket < 0) {
+            perror("local_server_socket");
+            goto fail;
+        }
     }
 
     init_signals();
@@ -836,6 +848,10 @@ main(int argc, char **argv)
         }
         close(fd);
     }
+    if(local_server_socket >= 0 && local_server_path) {
+        unlink(local_server_path);
+        free(local_server_path);
+    }
     if(pidfile)
         unlink(pidfile);
     debugf("Done.\n");
diff --git a/babeld.h b/babeld.h
index 102408d..1c21b4f 100644
--- a/babeld.h
+++ b/babeld.h
@@ -99,6 +99,7 @@ extern int have_id;
 extern const unsigned char zeroes[16], ones[16];
 
 extern int protocol_port, local_server_port;
+extern char *local_server_path;
 extern int local_server_write;
 extern unsigned char protocol_group[16];
 extern int protocol_socket;
diff --git a/babeld.man b/babeld.man
index d799d24..a7c316a 100644
--- a/babeld.man
+++ b/babeld.man
@@ -109,16 +109,20 @@ requests tracing every message sent or received.  A value of
 3 additionally dumps all interactions with the OS kernel.  The default
 is 0.
 .TP
-.BI \-g " port"
+.BI \-g " port\fR,\fP" " \-g" " path"
 Set up a local configuration server on port
 .I port
+or at
+.I path
 in read-only mode.  The protocol is described in the section
 .B Local Configuration Protocol
 below.
 .TP
-.BI \-G " port"
+.BI \-G " port\fR,\fP" " \-G" " path"
 Set up a local configuration server on port
 .I port
+or at
+.I path
 in read-write mode.  This allows any local user to change
 .BR babeld 's
 configuration, and may therefore be a security issue.
@@ -223,10 +227,28 @@ This specifies the TCP port on which
 .B babeld
 will listen for connections from a configuration client in read-write mode,
 and is equivalent to the command-line option
-.BR \-G .  This allows any local user to change
+.BR \-G .
+This allows any local user to change
 .BR babeld 's
 configuration, and may therefore be a security issue.
 .TP
+.BI local-path " path"
+This specifies the filesystem path to a socket on which
+.B babeld
+will listen for connections from a configuration client in read-only mode,
+and is equivalent to the command-line option
+.BR \-g .
+.TP
+.BI local-path-readwrite " path"
+This specifies the filesystem path to a socket on which
+.B babeld
+will listen for connections from a configuration client in read-write mode,
+and is equivalent to the command-line option
+.BR \-G .
+Any user with write access to that socket will be able to change
+.BR babeld 's
+configuration.
+.TP
 .BI export-table " table"
 This specifies the kernel routing table to use for routes inserted by
 .BR babeld ,
@@ -553,7 +575,8 @@ it accepts TCP connections from local clients on the given port and address
 .B ::1
 (the IPv6
 .B localhost
-address).  When a client connects,
+address), or on the given UNIX-domain socket path if the argument starts with
+\[oq]/\[cq].  When a client connects,
 .B babeld
 replies with
 .B BABEL
diff --git a/configuration.c b/configuration.c
index 852df07..f2d7b76 100644
--- a/configuration.c
+++ b/configuration.c
@@ -725,9 +725,13 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
             allow_duplicates = v;
         else if(strcmp(token, "local-port") == 0) {
             local_server_port = v;
+            free(local_server_path);
+            local_server_path = NULL;
             local_server_write = 0;
         } else if(strcmp(token, "local-port-readwrite") == 0) {
             local_server_port = v;
+            free(local_server_path);
+            local_server_path = NULL;
             local_server_write = 1;
         } else if(strcmp(token, "export-table") == 0)
             export_table = v;
@@ -772,7 +776,9 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
         free(group);
     } else if(strcmp(token, "state-file") == 0 ||
               strcmp(token, "log-file") == 0 ||
-              strcmp(token, "pid-file") == 0) {
+              strcmp(token, "pid-file") == 0 ||
+              strcmp(token, "local-path") == 0 ||
+              strcmp(token, "local-path-readwrite") == 0) {
         char *file;
         c = getstring(c, &file, gnc, closure);
         if(c < -1)
@@ -783,7 +789,17 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
             logfile = file;
         else if(strcmp(token, "pid-file") == 0)
             pidfile = file;
-        else
+        else if(strcmp(token, "local-path") == 0) {
+            local_server_port = -1;
+            free(local_server_path);
+            local_server_path = file;
+            local_server_write = 0;
+        } else if(strcmp(token, "local-path-readwrite") == 0) {
+            local_server_port = -1;
+            free(local_server_path);
+            local_server_path = file;
+            local_server_write = 1;
+        } else
             abort();
     } else if(strcmp(token, "debug") == 0) {
         int d;
diff --git a/local.c b/local.c
index 372b418..d3db62f 100644
--- a/local.c
+++ b/local.c
@@ -44,6 +44,7 @@ int local_server_socket = -1;
 struct local_socket local_sockets[MAX_LOCAL_SOCKETS];
 int num_local_sockets = 0;
 int local_server_port = -1;
+char *local_server_path;
 int local_server_write = 0;
 
 static int
diff --git a/local.h b/local.h
index b2fe26b..2316111 100644
--- a/local.h
+++ b/local.h
@@ -45,6 +45,7 @@ extern int local_server_socket;
 extern struct local_socket local_sockets[MAX_LOCAL_SOCKETS];
 extern int num_local_sockets;
 extern int local_server_port;
+extern char *local_server_path;
 
 void local_notify_interface(struct interface *ifp, int kind);
 void local_notify_neighbour(struct neighbour *neigh, int kind);
diff --git a/net.c b/net.c
index d1e404a..1e5890d 100644
--- a/net.c
+++ b/net.c
@@ -28,6 +28,7 @@ THE SOFTWARE.
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
@@ -231,3 +232,56 @@ tcp_server_socket(int port, int local)
     errno = saved_errno;
     return -1;
 }
+
+int
+unix_server_socket(const char *path)
+{
+    struct sockaddr_un sun;
+    int s, rc, saved_errno;
+
+    if(strlen(path) >= sizeof(sun.sun_path))
+        return -1;
+
+    s = socket(PF_UNIX, SOCK_STREAM, 0);
+    if(s < 0)
+        return -1;
+
+    rc = fcntl(s, F_GETFL, 0);
+    if(rc < 0)
+        goto fail;
+
+    rc = fcntl(s, F_SETFL, rc | O_NONBLOCK);
+    if(rc < 0)
+        goto fail;
+
+    rc = fcntl(s, F_GETFD, 0);
+    if(rc < 0)
+        goto fail;
+
+    rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
+    if(rc < 0)
+        goto fail;
+
+    memset(&sun, 0, sizeof(sun));
+    sun.sun_family = AF_UNIX;
+    strncpy(sun.sun_path, path, sizeof(sun.sun_path));
+    rc = bind(s, (struct sockaddr *)&sun, sizeof(sun));
+    if(rc < 0)
+        goto fail;
+
+    rc = listen(s, 2);
+    if(rc < 0)
+        goto fail_unlink;
+
+    return s;
+
+fail_unlink:
+    saved_errno = errno;
+    unlink(path);
+    errno = saved_errno;
+fail:
+    saved_errno = errno;
+    close(s);
+    errno = saved_errno;
+    return -1;
+}
diff --git a/net.h b/net.h
index aa20b86..56c1bb2 100644
--- a/net.h
+++ b/net.h
@@ -26,3 +26,4 @@ int babel_send(int s,
                const void *buf1, int buflen1, const void *buf2, int buflen2,
                const struct sockaddr *sin, int slen);
 int tcp_server_socket(int port, int local);
+int unix_server_socket(const char *path);
-- 
2.7.0




More information about the Babel-users mailing list