Add IP address address ACL representation and parser
authorDaniel Mack <daniel@zonque.org>
Thu, 3 Nov 2016 16:30:06 +0000 (17:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Sep 2017 13:24:54 +0000 (15:24 +0200)
Add a config directive parser that takes multiple space separated IPv4
or IPv6 addresses with optional netmasks in CIDR notation rvalue and
puts a parsed version of it to linked list of IPAddressAccessItem objects.
The code actually using this will be added later.

src/core/ip-address-access.c [new file with mode: 0644]
src/core/ip-address-access.h [new file with mode: 0644]
src/core/meson.build

diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c
new file mode 100644 (file)
index 0000000..6a89bb2
--- /dev/null
@@ -0,0 +1,165 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Daniel Mack
+
+  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 <stdio.h>
+#include <stdlib.h>
+
+#include "alloc-util.h"
+#include "extract-word.h"
+#include "hostname-util.h"
+#include "ip-address-access.h"
+#include "parse-util.h"
+#include "string-util.h"
+
+int config_parse_ip_address_access(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        IPAddressAccessItem **list = data;
+        const char *p;
+        int r;
+
+        assert(list);
+
+        if (isempty(rvalue)) {
+                *list = ip_address_access_free_all(*list);
+                return 0;
+        }
+
+        p = rvalue;
+
+        for (;;) {
+                _cleanup_free_ IPAddressAccessItem *a = NULL;
+                _cleanup_free_ char *word = NULL;
+
+                r = extract_first_word(&p, &word, NULL, 0);
+                if (r == 0)
+                        break;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+                        break;
+                }
+
+                a = new0(IPAddressAccessItem, 1);
+                if (!a)
+                        return log_oom();
+
+                if (streq(word, "any")) {
+                        /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
+
+                        a->family = AF_INET;
+                        LIST_APPEND(items, *list, a);
+
+                        a = new0(IPAddressAccessItem, 1);
+                        if (!a)
+                                return log_oom();
+
+                        a->family = AF_INET6;
+
+                } else if (is_localhost(word)) {
+                        /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
+
+                        a->family = AF_INET;
+                        a->address.in.s_addr = htobe32(0x7f000000);
+                        a->prefixlen = 8;
+                        LIST_APPEND(items, *list, a);
+
+                        a = new0(IPAddressAccessItem, 1);
+                        if (!a)
+                                return log_oom();
+
+                        a->family = AF_INET6;
+                        a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
+                        a->prefixlen = 128;
+
+                } else if (streq(word, "link-local")) {
+
+                        /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
+
+                        a->family = AF_INET;
+                        a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
+                        a->prefixlen = 16;
+                        LIST_APPEND(items, *list, a);
+
+                        a = new0(IPAddressAccessItem, 1);
+                        if (!a)
+                                return log_oom();
+
+                        a->family = AF_INET6;
+                        a->address.in6 = (struct in6_addr) {
+                                .__in6_u.__u6_addr32[0] = htobe32(0xfe800000)
+                        };
+                        a->prefixlen = 64;
+
+                } else if (streq(word, "multicast")) {
+
+                        /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
+
+                        a->family = AF_INET;
+                        a->address.in.s_addr = htobe32((UINT32_C(224) << 24));
+                        a->prefixlen = 4;
+                        LIST_APPEND(items, *list, a);
+
+                        a = new0(IPAddressAccessItem, 1);
+                        if (!a)
+                                return log_oom();
+
+                        a->family = AF_INET6;
+                        a->address.in6 = (struct in6_addr) {
+                                .__in6_u.__u6_addr32[0] = htobe32(0xff000000)
+                        };
+                        a->prefixlen = 8;
+
+                } else {
+                        r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen);
+                        if (r < 0) {
+                                log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word);
+                                return 0;
+                        }
+                }
+
+                LIST_APPEND(items, *list, a);
+                a = NULL;
+        }
+
+        return 0;
+}
+
+IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
+        IPAddressAccessItem *next, *p = first;
+
+        while (p) {
+                next = p->items_next;
+                free(p);
+
+                p = next;
+        }
+
+        return NULL;
+}
diff --git a/src/core/ip-address-access.h b/src/core/ip-address-access.h
new file mode 100644 (file)
index 0000000..eea20b4
--- /dev/null
@@ -0,0 +1,36 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Daniel Mack
+
+  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 "in-addr-util.h"
+#include "list.h"
+
+typedef struct IPAddressAccessItem IPAddressAccessItem;
+
+struct IPAddressAccessItem {
+        int family;
+        unsigned char prefixlen;
+        union in_addr_union address;
+        LIST_FIELDS(IPAddressAccessItem, items);
+};
+
+int config_parse_ip_address_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
index 569eed9..bea0d35 100644 (file)
 libcore_la_sources = '''
-        unit.c
-        unit.h
-        unit-printf.c
-        unit-printf.h
-        job.c
-        job.h
-        manager.c
-        manager.h
-        transaction.c
-        transaction.h
-        load-fragment.c
-        load-fragment.h
-        service.c
-        service.h
-        socket.c
-        socket.h
-        target.c
-        target.h
-        device.c
-        device.h
-        mount.c
-        mount.h
+        audit-fd.c
+        audit-fd.h
         automount.c
         automount.h
-        swap.c
-        swap.h
-        timer.c
-        timer.h
-        path.c
-        path.h
-        slice.c
-        slice.h
-        scope.c
-        scope.h
-        load-dropin.c
-        load-dropin.h
-        execute.c
-        execute.h
-        dynamic-user.c
-        dynamic-user.h
-        kill.c
-        kill.h
-        dbus.c
-        dbus.h
-        dbus-manager.c
-        dbus-manager.h
-        dbus-unit.c
-        dbus-unit.h
+        cgroup.c
+        cgroup.h
+        dbus-automount.c
+        dbus-automount.h
+        dbus-cgroup.c
+        dbus-cgroup.h
+        dbus-device.c
+        dbus-device.h
+        dbus-execute.c
+        dbus-execute.h
         dbus-job.c
         dbus-job.h
+        dbus-kill.c
+        dbus-kill.h
+        dbus-manager.c
+        dbus-manager.h
+        dbus-mount.c
+        dbus-mount.h
+        dbus-path.c
+        dbus-path.h
+        dbus-scope.c
+        dbus-scope.h
         dbus-service.c
         dbus-service.h
+        dbus-slice.c
+        dbus-slice.h
         dbus-socket.c
         dbus-socket.h
-        dbus-target.c
-        dbus-target.h
-        dbus-device.c
-        dbus-device.h
-        dbus-mount.c
-        dbus-mount.h
-        dbus-automount.c
-        dbus-automount.h
         dbus-swap.c
         dbus-swap.h
+        dbus-target.c
+        dbus-target.h
         dbus-timer.c
         dbus-timer.h
-        dbus-path.c
-        dbus-path.h
-        dbus-slice.c
-        dbus-slice.h
-        dbus-scope.c
-        dbus-scope.h
-        dbus-execute.c
-        dbus-execute.h
-        dbus-kill.c
-        dbus-kill.h
-        dbus-cgroup.c
-        dbus-cgroup.h
-        cgroup.c
-        cgroup.h
-        selinux-access.c
-        selinux-access.h
-        selinux-setup.c
-        selinux-setup.h
-        smack-setup.c
-        smack-setup.h
+        dbus-unit.c
+        dbus-unit.h
+        dbus.c
+        dbus.h
+        device.c
+        device.h
+        dynamic-user.c
+        dynamic-user.h
+        emergency-action.c
+        emergency-action.h
+        execute.c
+        execute.h
+        hostname-setup.c
+        hostname-setup.h
         ima-setup.c
         ima-setup.h
-        locale-setup.h
+        ip-address-access.c
+        ip-address-access.h
+        job.c
+        job.h
+        kill.c
+        kill.h
+        killall.c
+        killall.h
+        kmod-setup.c
+        kmod-setup.h
+        load-dropin.c
+        load-dropin.h
+        load-fragment.c
+        load-fragment.h
         locale-setup.c
-        hostname-setup.c
-        hostname-setup.h
+        locale-setup.h
+        loopback-setup.c
+        loopback-setup.h
         machine-id-setup.c
         machine-id-setup.h
+        manager.c
+        manager.h
         mount-setup.c
         mount-setup.h
-        kmod-setup.c
-        kmod-setup.h
-        loopback-setup.h
-        loopback-setup.c
+        mount.c
+        mount.h
         namespace.c
         namespace.h
-        killall.h
-        killall.c
-        audit-fd.c
-        audit-fd.h
+        path.c
+        path.h
+        scope.c
+        scope.h
+        selinux-access.c
+        selinux-access.h
+        selinux-setup.c
+        selinux-setup.h
+        service.c
+        service.h
         show-status.c
         show-status.h
-        emergency-action.c
-        emergency-action.h
+        slice.c
+        slice.h
+        smack-setup.c
+        smack-setup.h
+        socket.c
+        socket.h
+        swap.c
+        swap.h
+        target.c
+        target.h
+        timer.c
+        timer.h
+        transaction.c
+        transaction.h
+        unit-printf.c
+        unit-printf.h
+        unit.c
+        unit.h
 '''.split()
 
 load_fragment_gperf_gperf = custom_target(