]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/ip-address-access.c
Add IP address address ACL representation and parser
[thirdparty/systemd.git] / src / core / ip-address-access.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2016 Daniel Mack
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "alloc-util.h"
24 #include "extract-word.h"
25 #include "hostname-util.h"
26 #include "ip-address-access.h"
27 #include "parse-util.h"
28 #include "string-util.h"
29
30 int config_parse_ip_address_access(
31 const char *unit,
32 const char *filename,
33 unsigned line,
34 const char *section,
35 unsigned section_line,
36 const char *lvalue,
37 int ltype,
38 const char *rvalue,
39 void *data,
40 void *userdata) {
41
42 IPAddressAccessItem **list = data;
43 const char *p;
44 int r;
45
46 assert(list);
47
48 if (isempty(rvalue)) {
49 *list = ip_address_access_free_all(*list);
50 return 0;
51 }
52
53 p = rvalue;
54
55 for (;;) {
56 _cleanup_free_ IPAddressAccessItem *a = NULL;
57 _cleanup_free_ char *word = NULL;
58
59 r = extract_first_word(&p, &word, NULL, 0);
60 if (r == 0)
61 break;
62 if (r == -ENOMEM)
63 return log_oom();
64 if (r < 0) {
65 log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
66 break;
67 }
68
69 a = new0(IPAddressAccessItem, 1);
70 if (!a)
71 return log_oom();
72
73 if (streq(word, "any")) {
74 /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
75
76 a->family = AF_INET;
77 LIST_APPEND(items, *list, a);
78
79 a = new0(IPAddressAccessItem, 1);
80 if (!a)
81 return log_oom();
82
83 a->family = AF_INET6;
84
85 } else if (is_localhost(word)) {
86 /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
87
88 a->family = AF_INET;
89 a->address.in.s_addr = htobe32(0x7f000000);
90 a->prefixlen = 8;
91 LIST_APPEND(items, *list, a);
92
93 a = new0(IPAddressAccessItem, 1);
94 if (!a)
95 return log_oom();
96
97 a->family = AF_INET6;
98 a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
99 a->prefixlen = 128;
100
101 } else if (streq(word, "link-local")) {
102
103 /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
104
105 a->family = AF_INET;
106 a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
107 a->prefixlen = 16;
108 LIST_APPEND(items, *list, a);
109
110 a = new0(IPAddressAccessItem, 1);
111 if (!a)
112 return log_oom();
113
114 a->family = AF_INET6;
115 a->address.in6 = (struct in6_addr) {
116 .__in6_u.__u6_addr32[0] = htobe32(0xfe800000)
117 };
118 a->prefixlen = 64;
119
120 } else if (streq(word, "multicast")) {
121
122 /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
123
124 a->family = AF_INET;
125 a->address.in.s_addr = htobe32((UINT32_C(224) << 24));
126 a->prefixlen = 4;
127 LIST_APPEND(items, *list, a);
128
129 a = new0(IPAddressAccessItem, 1);
130 if (!a)
131 return log_oom();
132
133 a->family = AF_INET6;
134 a->address.in6 = (struct in6_addr) {
135 .__in6_u.__u6_addr32[0] = htobe32(0xff000000)
136 };
137 a->prefixlen = 8;
138
139 } else {
140 r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen);
141 if (r < 0) {
142 log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word);
143 return 0;
144 }
145 }
146
147 LIST_APPEND(items, *list, a);
148 a = NULL;
149 }
150
151 return 0;
152 }
153
154 IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
155 IPAddressAccessItem *next, *p = first;
156
157 while (p) {
158 next = p->items_next;
159 free(p);
160
161 p = next;
162 }
163
164 return NULL;
165 }