]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/network-internal.c
sd-login: add C API to query primary session of a user
[thirdparty/systemd.git] / src / libsystemd-network / network-internal.c
CommitLineData
5fde13d7
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <netinet/ether.h>
d2df0d0e 23#include <linux/if.h>
f5284182 24#include <arpa/inet.h>
f28964e3 25#include <fnmatch.h>
5fde13d7 26
b5db00e5
UTL
27#include "strv.h"
28#include "siphash24.h"
29#include "libudev-private.h"
c6f7c917 30#include "network-internal.h"
be32eb9b 31#include "log.h"
5fde13d7 32#include "utf8.h"
a12fa420 33#include "util.h"
5fde13d7 34#include "conf-parser.h"
2cc412b5 35#include "condition.h"
5fde13d7 36
b5db00e5
UTL
37#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
38
39int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
40 size_t l, sz = 0;
9f2a50a3 41 const char *name = NULL, *field = NULL;
b5db00e5
UTL
42 int r;
43 uint8_t *v;
44
45 /* fetch some persistent data unique (on this machine) to this device */
46 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
47 name = udev_device_get_property_value(device, field);
48 if (name)
49 break;
50 }
51
52 if (!name)
53 return -ENOENT;
54
55 l = strlen(name);
56 sz = sizeof(sd_id128_t) + l;
57 v = alloca(sz);
58
59 /* fetch some persistent data unique to this machine */
60 r = sd_id128_get_machine((sd_id128_t*) v);
61 if (r < 0)
62 return r;
63 memcpy(v + sizeof(sd_id128_t), name, l);
64
65 /* Let's hash the machine ID plus the device name. We
66 * use a fixed, but originally randomly created hash
67 * key here. */
68 siphash24(result, v, sz, HASH_KEY.bytes);
69
70 return 0;
71}
72
be32eb9b
TG
73bool net_match_config(const struct ether_addr *match_mac,
74 const char *match_path,
75 const char *match_driver,
76 const char *match_type,
77 const char *match_name,
2cc412b5
TG
78 Condition *match_host,
79 Condition *match_virt,
80 Condition *match_kernel,
edbb03e9 81 Condition *match_arch,
505f8da7 82 const struct ether_addr *dev_mac,
b3e01314 83 const char *dev_path,
bf175aaf 84 const char *dev_parent_driver,
b3e01314
TG
85 const char *dev_driver,
86 const char *dev_type,
87 const char *dev_name) {
be32eb9b 88
2cc412b5
TG
89 if (match_host && !condition_test_host(match_host))
90 return 0;
91
92 if (match_virt && !condition_test_virtualization(match_virt))
93 return 0;
94
95 if (match_kernel && !condition_test_kernel_command_line(match_kernel))
96 return 0;
97
edbb03e9
TG
98 if (match_arch && !condition_test_architecture(match_arch))
99 return 0;
100
505f8da7 101 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
449f7554 102 return 0;
be32eb9b 103
f28964e3 104 if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))
449f7554 105 return 0;
be32eb9b 106
bf175aaf
TG
107 if (match_driver) {
108 if (dev_parent_driver && !streq(match_driver, dev_parent_driver))
109 return 0;
110 else if (!streq_ptr(match_driver, dev_driver))
111 return 0;
112 }
5fde13d7 113
d69b12ac 114 if (match_type && !streq_ptr(match_type, dev_type))
449f7554 115 return 0;
5fde13d7 116
bf175aaf 117 if (match_name && (!dev_name || fnmatch(match_name, dev_name, 0)))
449f7554 118 return 0;
5fde13d7 119
be32eb9b
TG
120 return 1;
121}
5fde13d7 122
377a218f 123unsigned net_netmask_to_prefixlen(const struct in_addr *addr) {
377a218f
TG
124 assert(addr);
125
ba914311 126 return 32 - u32ctz(be32toh(addr->s_addr));
377a218f
TG
127}
128
2cc412b5
TG
129int config_parse_net_condition(const char *unit,
130 const char *filename,
131 unsigned line,
132 const char *section,
133 unsigned section_line,
134 const char *lvalue,
135 int ltype,
136 const char *rvalue,
137 void *data,
138 void *userdata) {
139
140 ConditionType cond = ltype;
141 Condition **ret = data;
142 bool negate;
143 Condition *c;
144 _cleanup_free_ char *s = NULL;
145
146 assert(filename);
147 assert(lvalue);
148 assert(rvalue);
149 assert(data);
150
151 negate = rvalue[0] == '!';
152 if (negate)
153 rvalue++;
154
155 s = strdup(rvalue);
156 if (!s)
157 return log_oom();
158
159 c = condition_new(cond, s, false, negate);
160 if (!c)
161 return log_oom();
162
163 if (*ret)
164 condition_free(*ret);
165
166 *ret = c;
167 return 0;
168}
169
5fde13d7
TG
170int config_parse_ifname(const char *unit,
171 const char *filename,
172 unsigned line,
173 const char *section,
71a61510 174 unsigned section_line,
5fde13d7
TG
175 const char *lvalue,
176 int ltype,
177 const char *rvalue,
178 void *data,
179 void *userdata) {
180
181 char **s = data;
182 char *n;
183
184 assert(filename);
185 assert(lvalue);
186 assert(rvalue);
187 assert(data);
188
189 n = strdup(rvalue);
190 if (!n)
191 return log_oom();
192
193 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
194 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
195 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
196 free(n);
197 return 0;
198 }
199
200 free(*s);
201 if (*n)
202 *s = n;
203 else {
204 free(n);
205 *s = NULL;
206 }
207
208 return 0;
209}
210
d2df0d0e
TG
211int config_parse_ifalias(const char *unit,
212 const char *filename,
213 unsigned line,
214 const char *section,
71a61510 215 unsigned section_line,
d2df0d0e
TG
216 const char *lvalue,
217 int ltype,
218 const char *rvalue,
219 void *data,
220 void *userdata) {
221
222 char **s = data;
223 char *n;
224
225 assert(filename);
226 assert(lvalue);
227 assert(rvalue);
228 assert(data);
229
230 n = strdup(rvalue);
231 if (!n)
232 return log_oom();
233
234 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
235 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
236 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
237 free(n);
238 return 0;
239 }
240
241 free(*s);
242 if (*n)
243 *s = n;
244 else {
245 free(n);
246 *s = NULL;
247 }
248
249 return 0;
250}
251
5fde13d7
TG
252int config_parse_hwaddr(const char *unit,
253 const char *filename,
254 unsigned line,
255 const char *section,
71a61510 256 unsigned section_line,
5fde13d7
TG
257 const char *lvalue,
258 int ltype,
259 const char *rvalue,
260 void *data,
261 void *userdata) {
262 struct ether_addr **hwaddr = data;
263 struct ether_addr *n;
264 int r;
265
266 assert(filename);
267 assert(lvalue);
268 assert(rvalue);
269 assert(data);
270
a12fa420 271 n = new0(struct ether_addr, 1);
5fde13d7
TG
272 if (!n)
273 return log_oom();
274
275 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
276 &n->ether_addr_octet[0],
277 &n->ether_addr_octet[1],
278 &n->ether_addr_octet[2],
279 &n->ether_addr_octet[3],
280 &n->ether_addr_octet[4],
281 &n->ether_addr_octet[5]);
282 if (r != 6) {
283 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
284 "Not a valid MAC address, ignoring assignment: %s", rvalue);
285 free(n);
286 return 0;
287 }
288
289 free(*hwaddr);
290 *hwaddr = n;
291
292 return 0;
293}
f5284182
TG
294
295int net_parse_inaddr(const char *address, unsigned char *family, void *dst) {
296 int r;
297
298 assert(address);
299 assert(family);
300 assert(dst);
301
302 /* IPv4 */
303 r = inet_pton(AF_INET, address, dst);
801bd9e8
TG
304 if (r > 0) {
305 /* succsefully parsed IPv4 address */
306 if (*family == AF_UNSPEC)
307 *family = AF_INET;
308 else if (*family != AF_INET)
309 return -EINVAL;
310 } else if (r < 0)
f5284182
TG
311 return -errno;
312 else {
313 /* not an IPv4 address, so let's try IPv6 */
314 r = inet_pton(AF_INET6, address, dst);
801bd9e8
TG
315 if (r > 0) {
316 /* successfully parsed IPv6 address */
317 if (*family == AF_UNSPEC)
318 *family = AF_INET6;
319 else if (*family != AF_INET6)
320 return -EINVAL;
321 } else if (r < 0)
f5284182
TG
322 return -errno;
323 else
324 return -EINVAL;
325 }
326
327 return 0;
328}
7951dea2
SS
329
330int load_module(struct kmod_ctx *ctx, const char *mod_name) {
331 struct kmod_list *modlist = NULL, *l;
332 int r;
333
334 assert(ctx);
335 assert(mod_name);
336
337 r = kmod_module_new_from_lookup(ctx, mod_name, &modlist);
338 if (r < 0)
339 return r;
340
341 if (!modlist) {
342 log_error("Failed to find module '%s'", mod_name);
343 return -ENOENT;
344 }
345
346 kmod_list_foreach(l, modlist) {
347 struct kmod_module *mod = kmod_module_get_module(l);
348
349 r = kmod_module_probe_insert_module(mod, 0, NULL, NULL, NULL, NULL);
350 if (r == 0)
351 log_info("Inserted module '%s'", kmod_module_get_name(mod));
352 else {
353 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
354 strerror(-r));
355 }
0b44d8c3
TG
356
357 kmod_module_unref(mod);
7951dea2
SS
358 }
359
360 kmod_module_unref_list(modlist);
361
362 return r;
363}