basic: introduce socket_protocol_{from,to}_name()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 23 Dec 2017 10:32:04 +0000 (19:32 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 23 Dec 2017 10:32:04 +0000 (19:32 +0900)
And use them where they can be applicable.

src/basic/generate-socket-protocol-list.sh [new file with mode: 0755]
src/basic/meson.build
src/basic/socket-protocol-list.c [new file with mode: 0644]
src/basic/socket-protocol-list.h [new file with mode: 0644]
src/basic/socket-protocol-to-name.awk [new file with mode: 0644]
src/core/dbus-socket.c
src/core/load-fragment.c
src/core/socket.c
src/shared/bus-unit-util.c

diff --git a/src/basic/generate-socket-protocol-list.sh b/src/basic/generate-socket-protocol-list.sh
new file mode 100755 (executable)
index 0000000..18a540f
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -eu
+
+$1 -dM -include netinet/in.h - </dev/null | \
+        awk '/^#define[ \t]+IPPROTO_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
+        sed -e 's/IPPROTO_//'
index a37e279..f751ee3 100644 (file)
@@ -176,6 +176,8 @@ basic_sources_plain = files('''
         smack-util.c
         smack-util.h
         socket-label.c
+        socket-protocol-list.c
+        socket-protocol-list.h
         socket-util.c
         socket-util.h
         sparse-endian.h
@@ -255,11 +257,19 @@ errno_list_txt = custom_target(
         command : [generate_errno_list, cpp],
         capture : true)
 
+generate_socket_protocol_list = find_program('generate-socket-protocol-list.sh')
+socket_protocol_list_txt = custom_target(
+        'socket-protocol-list.txt',
+        output : 'socket-protocol-list.txt',
+        command : [generate_socket_protocol_list, cpp],
+        capture : true)
+
 generated_gperf_headers = []
 foreach item : [['af',     af_list_txt,     'af',         ''],
                 ['arphrd', arphrd_list_txt, 'arphrd',     'ARPHRD_'],
                 ['cap',    cap_list_txt,    'capability', ''],
-                ['errno',  errno_list_txt,  'errno',      '']]
+                ['errno',  errno_list_txt,  'errno',      ''],
+                ['socket-protocol', socket_protocol_list_txt, 'socket_protocol',     'IPPROTO_']]
 
         fname = '@0@-from-name.gperf'.format(item[0])
         gperf_file = custom_target(
diff --git a/src/basic/socket-protocol-list.c b/src/basic/socket-protocol-list.c
new file mode 100644 (file)
index 0000000..9ab93d1
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/in.h>
+#include <string.h>
+
+#include "socket-protocol-list.h"
+#include "macro.h"
+
+static const struct socket_protocol_name* lookup_socket_protocol(register const char *str, register GPERF_LEN_TYPE len);
+
+#include "socket-protocol-from-name.h"
+#include "socket-protocol-to-name.h"
+
+const char *socket_protocol_to_name(int id) {
+
+        if (id < 0)
+                return NULL;
+
+        if (id >= (int) ELEMENTSOF(socket_protocol_names))
+                return NULL;
+
+        return socket_protocol_names[id];
+}
+
+int socket_protocol_from_name(const char *name) {
+        const struct socket_protocol_name *sc;
+
+        assert(name);
+
+        sc = lookup_socket_protocol(name, strlen(name));
+        if (!sc)
+                return 0;
+
+        return sc->id;
+}
+
+int socket_protocol_max(void) {
+        return ELEMENTSOF(socket_protocol_names);
+}
diff --git a/src/basic/socket-protocol-list.h b/src/basic/socket-protocol-list.h
new file mode 100644 (file)
index 0000000..12fd053
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+const char *socket_protocol_to_name(int id);
+int socket_protocol_from_name(const char *name);
+
+int socket_protocol_max(void);
diff --git a/src/basic/socket-protocol-to-name.awk b/src/basic/socket-protocol-to-name.awk
new file mode 100644 (file)
index 0000000..4848a76
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "static const char* const socket_protocol_names[] = { "
+}
+!/HOPOPTS/ {
+        printf "        [IPPROTO_%s] = \"%s\",\n", $1, tolower($1)
+}
+END{
+        print "};"
+}
index 6c5d594..26ab6b9 100644 (file)
@@ -28,6 +28,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "socket.h"
+#include "socket-protocol-list.h"
 #include "socket-util.h"
 #include "string-util.h"
 #include "unit.h"
@@ -268,18 +269,23 @@ static int bus_socket_set_transient_property(
                 return 1;
 
         } else if (streq(name, "SocketProtocol")) {
+                const char *p;
                 int32_t i;
 
                 r = sd_bus_message_read(message, "i", &i);
                 if (r < 0)
                         return r;
 
-                if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
+                p = socket_protocol_to_name(i);
+                if (!p)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
 
+                if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported socket protocol: %s", p);
+
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->socket_protocol = i;
-                        unit_write_settingf(u, flags, name, "%s=%s", name, i == IPPROTO_UDPLITE ? "udplite" : "sctp");
+                        unit_write_settingf(u, flags, name, "%s=%s", name, p);
                 }
 
                 return 1;
@@ -557,7 +563,7 @@ static int bus_socket_set_transient_property(
                         if (!p)
                                 return log_oom();
 
-                        p->type = socket_type_from_string(t);
+                        p->type = socket_port_type_from_string(t);
                         if (p->type < 0)
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown Socket type: %s", t);
 
index 469b2fc..28920e4 100644 (file)
@@ -64,6 +64,7 @@
 #include "securebits.h"
 #include "securebits-util.h"
 #include "signal-util.h"
+#include "socket-protocol-list.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -454,6 +455,7 @@ int config_parse_socket_protocol(const char *unit,
                                  void *data,
                                  void *userdata) {
         Socket *s;
+        int r;
 
         assert(filename);
         assert(lvalue);
@@ -462,15 +464,17 @@ int config_parse_socket_protocol(const char *unit,
 
         s = SOCKET(data);
 
-        if (streq(rvalue, "udplite"))
-                s->socket_protocol = IPPROTO_UDPLITE;
-        else if (streq(rvalue, "sctp"))
-                s->socket_protocol = IPPROTO_SCTP;
-        else {
+        r = socket_protocol_from_name(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid socket protocol, ignoring: %s", rvalue);
+                return 0;
+        } else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
                 return 0;
         }
 
+        s->socket_protocol = r;
+
         return 0;
 }
 
index 553bbe9..d45b528 100644 (file)
@@ -53,6 +53,7 @@
 #include "signal-util.h"
 #include "smack-util.h"
 #include "socket.h"
+#include "socket-protocol-list.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -2783,16 +2784,16 @@ const char* socket_port_type_to_string(SocketPort *p) {
 SocketType socket_port_type_from_string(const char *s) {
         assert(s);
 
-        if (STR_IN_SET(t, "Stream", "Datagram", "SequentialPacket", "Netlink"))
-                return SOCKET_SOCKET;
-        else if (streq(t, "Special"))
-                return SOCKET_SPECIAL;
-        else if (streq(t, "MessageQueue"))
-                return SOCKET_MQUEUE;
-        else if (streq(t, "FIFO"))
-                return SOCKET_FIFO;
-        else if (streq(t, "USBFunction"))
-                return SOCKET_USB_FUNCTION;
+        if (STR_IN_SET(s, "Stream", "Datagram", "SequentialPacket", "Netlink"))
+                return SOCKET_SOCKET;
+        else if (streq(s, "Special"))
+                return SOCKET_SPECIAL;
+        else if (streq(s, "MessageQueue"))
+                return SOCKET_MQUEUE;
+        else if (streq(s, "FIFO"))
+                return SOCKET_FIFO;
+        else if (streq(s, "USBFunction"))
+                return SOCKET_USB_FUNCTION;
         else
                 return _SOCKET_TYPE_INVALID;
 }
index 805ad30..b9224bb 100644 (file)
@@ -42,6 +42,7 @@
 #include "rlimit-util.h"
 #include "securebits-util.h"
 #include "signal-util.h"
+#include "socket-protocol-list.h"
 #include "string-util.h"
 #include "syslog-util.h"
 #include "terminal-util.h"
@@ -113,6 +114,7 @@ DEFINE_BUS_APPEND_PARSE("i", parse_errno)
 DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string)
 DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string)
 DEFINE_BUS_APPEND_PARSE("i", signal_from_string_try_harder)
+DEFINE_BUS_APPEND_PARSE("i", socket_protocol_from_name)
 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority)
 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice)
 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi)
@@ -1250,21 +1252,9 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
 
                 return bus_append_strv(m, field, eq, EXTRACT_QUOTES);
 
-        if (streq(field, "SocketProtocol")) {
+        if (streq(field, "SocketProtocol"))
 
-                if (streq(eq, "udplite"))
-                        r = sd_bus_message_append(m, "(sv)", field, "i", IPPROTO_UDPLITE);
-                else if (streq(eq, "sctp"))
-                        r = sd_bus_message_append(m, "(sv)", field, "i", IPPROTO_SCTP);
-                else {
-                        log_error("Unsupported Socket protocol: %s", eq);
-                        return -EINVAL;
-                }
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                return 1;
-        }
+                return bus_append_socket_protocol_from_name(m, field, eq);
 
         if (STR_IN_SET(field,
                        "ListenStream", "ListenDatagram", "ListenSequentialPacket", "ListenNetlink",