1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2016 Daniel Mack
9 #include "alloc-util.h"
10 #include "bpf-firewall.h"
11 #include "extract-word.h"
12 #include "hostname-util.h"
13 #include "ip-address-access.h"
14 #include "parse-util.h"
15 #include "string-util.h"
17 int config_parse_ip_address_access(
22 unsigned section_line
,
29 IPAddressAccessItem
**list
= data
;
35 if (isempty(rvalue
)) {
36 *list
= ip_address_access_free_all(*list
);
43 _cleanup_free_ IPAddressAccessItem
*a
= NULL
;
44 _cleanup_free_
char *word
= NULL
;
46 r
= extract_first_word(&p
, &word
, NULL
, 0);
52 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Invalid syntax, ignoring: %s", rvalue
);
56 a
= new0(IPAddressAccessItem
, 1);
60 if (streq(word
, "any")) {
61 /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
64 LIST_APPEND(items
, *list
, a
);
66 a
= new0(IPAddressAccessItem
, 1);
72 } else if (is_localhost(word
)) {
73 /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
76 a
->address
.in
.s_addr
= htobe32(0x7f000000);
78 LIST_APPEND(items
, *list
, a
);
80 a
= new0(IPAddressAccessItem
, 1);
85 a
->address
.in6
= (struct in6_addr
) IN6ADDR_LOOPBACK_INIT
;
88 } else if (streq(word
, "link-local")) {
90 /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
93 a
->address
.in
.s_addr
= htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
95 LIST_APPEND(items
, *list
, a
);
97 a
= new0(IPAddressAccessItem
, 1);
101 a
->family
= AF_INET6
;
102 a
->address
.in6
= (struct in6_addr
) {
103 .s6_addr32
[0] = htobe32(0xfe800000)
107 } else if (streq(word
, "multicast")) {
109 /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
112 a
->address
.in
.s_addr
= htobe32((UINT32_C(224) << 24));
114 LIST_APPEND(items
, *list
, a
);
116 a
= new0(IPAddressAccessItem
, 1);
120 a
->family
= AF_INET6
;
121 a
->address
.in6
= (struct in6_addr
) {
122 .s6_addr32
[0] = htobe32(0xff000000)
127 r
= in_addr_prefix_from_string_auto(word
, &a
->family
, &a
->address
, &a
->prefixlen
);
129 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Address prefix is invalid, ignoring assignment: %s", word
);
134 LIST_APPEND(items
, *list
, a
);
138 *list
= ip_address_access_reduce(*list
);
141 r
= bpf_firewall_supported();
144 if (r
== BPF_FIREWALL_UNSUPPORTED
) {
145 static bool warned
= false;
147 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
148 "File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"
149 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)", filename
, line
, lvalue
, rvalue
);
158 IPAddressAccessItem
* ip_address_access_free_all(IPAddressAccessItem
*first
) {
159 IPAddressAccessItem
*next
, *p
= first
;
162 next
= p
->items_next
;
171 IPAddressAccessItem
* ip_address_access_reduce(IPAddressAccessItem
*first
) {
172 IPAddressAccessItem
*a
, *b
, *tmp
;
175 /* Drops all entries from the list that are covered by another entry in full, thus removing all redundant
178 LIST_FOREACH_SAFE(items
, a
, tmp
, first
) {
180 /* Drop irrelevant bits */
181 (void) in_addr_mask(a
->family
, &a
->address
, a
->prefixlen
);
183 LIST_FOREACH(items
, b
, first
) {
188 if (a
->family
!= b
->family
)
191 if (b
->prefixlen
> a
->prefixlen
)
194 r
= in_addr_prefix_covers(b
->family
,
199 /* b covers a fully, then let's drop a */
200 LIST_REMOVE(items
, first
, a
);