]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fragment: add ip protocol to SocketBind{Allow|Deny}=
authorJulia Kartseva <hex@fb.com>
Tue, 15 Jun 2021 02:14:14 +0000 (19:14 -0700)
committerJulia Kartseva <hex@fb.com>
Wed, 30 Jun 2021 07:36:33 +0000 (00:36 -0700)
Add ip protocol token to SocketBind{Allow|Deny}= property parser.

Use parse_socket_bind_item helper.

Replace int32_t with int in cgroup item for socket-bind as it was
requested in [0].

Update tests.

[0] https://github.com/systemd/systemd/pull/19942#discussion_r652150024

src/core/cgroup.c
src/core/cgroup.h
src/core/load-fragment.c
src/test/test-socket-bind.c

index 3cec8a57863b53ee504a13b1736525f9527a6200..1dc5a5b034997c157c202b72144d38820ab057ee 100644 (file)
@@ -20,6 +20,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "ip-protocol-list.h"
 #include "limits-util.h"
 #include "nulstr-util.h"
 #include "parse-util.h"
@@ -593,18 +594,24 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
 }
 
 void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) {
-        const char *family, *colon;
+        const char *family, *colon1, *protocol = "", *colon2 = "";
 
         family = strempty(af_to_ipv4_ipv6(item->address_family));
-        colon = isempty(family) ? "" : ":";
+        colon1 = isempty(family) ? "" : ":";
+
+        if (item->ip_protocol != 0) {
+                protocol = ip_protocol_to_tcp_udp(item->ip_protocol);
+                colon2 = ":";
+        }
 
         if (item->nr_ports == 0)
-                fprintf(f, " %s%sany", family, colon);
+                fprintf(f, " %s%s%s%sany", family, colon1, protocol, colon2);
         else if (item->nr_ports == 1)
-                fprintf(f, " %s%s%" PRIu16, family, colon, item->port_min);
+                fprintf(f, " %s%s%s%s%" PRIu16, family, colon1, protocol, colon2, item->port_min);
         else {
                 uint16_t port_max = item->port_min + item->nr_ports - 1;
-                fprintf(f, " %s%s%" PRIu16 "-%" PRIu16, family, colon, item->port_min, port_max);
+                fprintf(f, " %s%s%s%s%" PRIu16 "-%" PRIu16, family, colon1, protocol, colon2,
+                        item->port_min, port_max);
         }
 }
 
index 526f056d1e8e7a6852ff46351b82dc876e5d91e7..ea929368cbd4d409a6dae3136ddc8d5d5d612a6c 100644 (file)
@@ -104,8 +104,8 @@ struct CGroupBPFForeignProgram {
 
 struct CGroupSocketBindItem {
         LIST_FIELDS(CGroupSocketBindItem, socket_bind_items);
-        int32_t address_family;
-        int32_t ip_protocol;
+        int address_family;
+        int ip_protocol;
         uint16_t nr_ports;
         uint16_t port_min;
 };
index b0f2469540991108751bf4a45e56db5f981c028a..87dfe5d1b0f369976f3f3ecdf0f4b40d850b2244 100644 (file)
@@ -47,6 +47,7 @@
 #include "log.h"
 #include "mountpoint-util.h"
 #include "nulstr-util.h"
+#include "parse-socket-bind-item.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "percent-util.h"
@@ -5633,62 +5634,30 @@ int config_parse_cgroup_socket_bind(
                 void *data,
                 void *userdata) {
         _cleanup_free_ CGroupSocketBindItem *item = NULL;
-        const char *user_port;
-        uint16_t nr_ports = 0, port_min = 0;
         CGroupSocketBindItem **head = data;
-        _cleanup_free_ char *word = NULL;
-        int af, r;
+        uint16_t nr_ports, port_min;
+        int af, ip_protocol, r;
 
         if (isempty(rvalue)) {
                 cgroup_context_remove_socket_bind(head);
                 return 0;
         }
 
-        r = extract_first_word(&rvalue, &word, ":", 0);
+        r = parse_socket_bind_item(rvalue, &af, &ip_protocol, &nr_ports, &port_min);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r <= 0) {
+        if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Unable to parse %s= assignment, ignoring: %s", lvalue, rvalue);
                 return 0;
         }
 
-        if (rvalue) {
-                af = af_from_ipv4_ipv6(word);
-                if (af == AF_UNSPEC) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0,
-                                   "Only \"ipv4\" and \"ipv6\" protocols are supported, ignoring.");
-                        return 0;
-                }
-
-                user_port = rvalue;
-        } else {
-                af = AF_UNSPEC;
-                user_port = word;
-        }
-
-        if (!streq(user_port, "any")) {
-                uint16_t port_max;
-
-                r = parse_ip_port_range(user_port, &port_min, &port_max);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Invalid port or port range, ignoring: %m");
-                        return 0;
-                }
-
-                nr_ports = 1 + port_max - port_min;
-        }
-
         item = new(CGroupSocketBindItem, 1);
         if (!item)
                 return log_oom();
         *item = (CGroupSocketBindItem) {
                 .address_family = af,
-                 /* No ip protocol specified for now. */
-                .ip_protocol = 0,
+                .ip_protocol = ip_protocol,
                 .nr_ports = nr_ports,
                 .port_min = port_min,
         };
index 996aeebbcc5e16047a56baf18b2b99f8caf07aa9..989172eee3b9569686ff5dc9c5df9b206e2dc557 100644 (file)
@@ -146,6 +146,11 @@ int main(int argc, char *argv[]) {
         assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("6667", "6668", ""), STRV_MAKE("any")) >= 0);
         assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "7777", STRV_MAKE_EMPTY, STRV_MAKE_EMPTY) >= 0);
         assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("any"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("ipv6:tcp:8888-8889"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "10000", STRV_MAKE("ipv6:udp:9999-10000"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("ipv4:tcp:6666"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("ipv4:udp:6666"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("tcp:6666"), STRV_MAKE("any")) >= 0);
 
         return 0;
 }