From b36672e072e32060d6c25acfb51e409bc617b754 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 3 Nov 2016 17:30:06 +0100 Subject: [PATCH] Add IP address address ACL representation and parser 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 | 165 ++++++++++++++++++++++++++++++++++++++++ src/core/ip-address-access.h | 36 +++++++++ src/core/meson.build | 176 ++++++++++++++++++++++--------------------- 3 files changed, 290 insertions(+), 87 deletions(-) create mode 100644 src/core/ip-address-access.c create mode 100644 src/core/ip-address-access.h diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c new file mode 100644 index 0000000..6a89bb2 --- /dev/null +++ b/src/core/ip-address-access.c @@ -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 . +***/ + +#include +#include + +#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 index 0000000..eea20b4 --- /dev/null +++ b/src/core/ip-address-access.h @@ -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 . +***/ + +#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); diff --git a/src/core/meson.build b/src/core/meson.build index 569eed9..bea0d35 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -1,114 +1,116 @@ 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( -- 2.7.4