]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - 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
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>
23#include <linux/if.h>
24#include <arpa/inet.h>
25#include <fnmatch.h>
26
27#include "strv.h"
28#include "siphash24.h"
29#include "libudev-private.h"
30#include "network-internal.h"
31#include "log.h"
32#include "utf8.h"
33#include "util.h"
34#include "conf-parser.h"
35#include "condition.h"
36
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;
41 const char *name = NULL, *field = NULL;
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
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,
78 Condition *match_host,
79 Condition *match_virt,
80 Condition *match_kernel,
81 Condition *match_arch,
82 const struct ether_addr *dev_mac,
83 const char *dev_path,
84 const char *dev_parent_driver,
85 const char *dev_driver,
86 const char *dev_type,
87 const char *dev_name) {
88
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
98 if (match_arch && !condition_test_architecture(match_arch))
99 return 0;
100
101 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
102 return 0;
103
104 if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))
105 return 0;
106
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 }
113
114 if (match_type && !streq_ptr(match_type, dev_type))
115 return 0;
116
117 if (match_name && (!dev_name || fnmatch(match_name, dev_name, 0)))
118 return 0;
119
120 return 1;
121}
122
123unsigned net_netmask_to_prefixlen(const struct in_addr *addr) {
124 assert(addr);
125
126 return 32 - u32ctz(be32toh(addr->s_addr));
127}
128
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
170int config_parse_ifname(const char *unit,
171 const char *filename,
172 unsigned line,
173 const char *section,
174 unsigned section_line,
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
211int config_parse_ifalias(const char *unit,
212 const char *filename,
213 unsigned line,
214 const char *section,
215 unsigned section_line,
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
252int config_parse_hwaddr(const char *unit,
253 const char *filename,
254 unsigned line,
255 const char *section,
256 unsigned section_line,
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
271 n = new0(struct ether_addr, 1);
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}
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);
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)
311 return -errno;
312 else {
313 /* not an IPv4 address, so let's try IPv6 */
314 r = inet_pton(AF_INET6, address, dst);
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)
322 return -errno;
323 else
324 return -EINVAL;
325 }
326
327 return 0;
328}
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 }
356
357 kmod_module_unref(mod);
358 }
359
360 kmod_module_unref_list(modlist);
361
362 return r;
363}