chiark / gitweb /
remove unused includes
[elogind.git] / src / libsystemd-network / network-internal.c
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
26 #include "strv.h"
27 #include "siphash24.h"
28 #include "dhcp-lease-internal.h"
29 #include "log.h"
30 #include "utf8.h"
31 #include "util.h"
32 #include "conf-parser.h"
33 #include "condition.h"
34 #include "network-internal.h"
35
36 const char *net_get_name(struct udev_device *device) {
37         const char *name, *field;
38
39         assert(device);
40
41         /* fetch some persistent data unique (on this machine) to this device */
42         FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
43                 name = udev_device_get_property_value(device, field);
44                 if (name)
45                         return name;
46         }
47
48         return NULL;
49 }
50
51 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
52
53 int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
54         size_t l, sz = 0;
55         const char *name = NULL;
56         int r;
57         uint8_t *v;
58
59         assert(device);
60
61         name = net_get_name(device);
62         if (!name)
63                 return -ENOENT;
64
65         l = strlen(name);
66         sz = sizeof(sd_id128_t) + l;
67         v = alloca(sz);
68
69         /* fetch some persistent data unique to this machine */
70         r = sd_id128_get_machine((sd_id128_t*) v);
71         if (r < 0)
72                  return r;
73         memcpy(v + sizeof(sd_id128_t), name, l);
74
75         /* Let's hash the machine ID plus the device name. We
76         * use a fixed, but originally randomly created hash
77         * key here. */
78         siphash24(result, v, sz, HASH_KEY.bytes);
79
80         return 0;
81 }
82
83 bool net_match_config(const struct ether_addr *match_mac,
84                       char * const *match_paths,
85                       char * const *match_drivers,
86                       char * const *match_types,
87                       char * const *match_names,
88                       Condition *match_host,
89                       Condition *match_virt,
90                       Condition *match_kernel,
91                       Condition *match_arch,
92                       const struct ether_addr *dev_mac,
93                       const char *dev_path,
94                       const char *dev_parent_driver,
95                       const char *dev_driver,
96                       const char *dev_type,
97                       const char *dev_name) {
98
99         if (match_host && !condition_test(match_host))
100                 return false;
101
102         if (match_virt && !condition_test(match_virt))
103                 return false;
104
105         if (match_kernel && !condition_test(match_kernel))
106                 return false;
107
108         if (match_arch && !condition_test(match_arch))
109                 return false;
110
111         if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
112                 return false;
113
114         if (!strv_isempty(match_paths) &&
115             (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
116                 return false;
117
118         if (!strv_isempty(match_drivers) &&
119             (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
120                 return false;
121
122         if (!strv_isempty(match_types) &&
123             (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
124                 return false;
125
126         if (!strv_isempty(match_names) &&
127             (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
128                 return false;
129
130         return true;
131 }
132
133 int config_parse_net_condition(const char *unit,
134                                const char *filename,
135                                unsigned line,
136                                const char *section,
137                                unsigned section_line,
138                                const char *lvalue,
139                                int ltype,
140                                const char *rvalue,
141                                void *data,
142                                void *userdata) {
143
144         ConditionType cond = ltype;
145         Condition **ret = data;
146         bool negate;
147         Condition *c;
148         _cleanup_free_ char *s = NULL;
149
150         assert(filename);
151         assert(lvalue);
152         assert(rvalue);
153         assert(data);
154
155         negate = rvalue[0] == '!';
156         if (negate)
157                 rvalue++;
158
159         s = strdup(rvalue);
160         if (!s)
161                 return log_oom();
162
163         c = condition_new(cond, s, false, negate);
164         if (!c)
165                 return log_oom();
166
167         if (*ret)
168                 condition_free(*ret);
169
170         *ret = c;
171         return 0;
172 }
173
174 int config_parse_ifname(const char *unit,
175                         const char *filename,
176                         unsigned line,
177                         const char *section,
178                         unsigned section_line,
179                         const char *lvalue,
180                         int ltype,
181                         const char *rvalue,
182                         void *data,
183                         void *userdata) {
184
185         char **s = data;
186         _cleanup_free_ char *n = NULL;
187
188         assert(filename);
189         assert(lvalue);
190         assert(rvalue);
191         assert(data);
192
193         n = strdup(rvalue);
194         if (!n)
195                 return log_oom();
196
197         if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
198                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
199                            "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
200                 return 0;
201         }
202
203         free(*s);
204         if (*n) {
205                 *s = n;
206                 n = NULL;
207         } else
208                 *s = NULL;
209
210         return 0;
211 }
212
213 int config_parse_ifnames(const char *unit,
214                         const char *filename,
215                         unsigned line,
216                         const char *section,
217                         unsigned section_line,
218                         const char *lvalue,
219                         int ltype,
220                         const char *rvalue,
221                         void *data,
222                         void *userdata) {
223
224         char ***sv = data;
225         const char *word, *state;
226         size_t l;
227         int r;
228
229         assert(filename);
230         assert(lvalue);
231         assert(rvalue);
232         assert(data);
233
234         FOREACH_WORD(word, l, rvalue, state) {
235                 char *n;
236
237                 n = strndup(word, l);
238                 if (!n)
239                         return log_oom();
240
241                 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
242                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
243                                    "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
244                         free(n);
245                         return 0;
246                 }
247
248                 r = strv_consume(sv, n);
249                 if (r < 0)
250                         return log_oom();
251         }
252
253         return 0;
254 }
255
256 int config_parse_ifalias(const char *unit,
257                          const char *filename,
258                          unsigned line,
259                          const char *section,
260                          unsigned section_line,
261                          const char *lvalue,
262                          int ltype,
263                          const char *rvalue,
264                          void *data,
265                          void *userdata) {
266
267         char **s = data;
268         _cleanup_free_ char *n = NULL;
269
270         assert(filename);
271         assert(lvalue);
272         assert(rvalue);
273         assert(data);
274
275         n = strdup(rvalue);
276         if (!n)
277                 return log_oom();
278
279         if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
280                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
281                            "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
282                 return 0;
283         }
284
285         free(*s);
286         if (*n) {
287                 *s = n;
288                 n = NULL;
289         } else
290                 *s = NULL;
291
292         return 0;
293 }
294
295 int config_parse_hwaddr(const char *unit,
296                         const char *filename,
297                         unsigned line,
298                         const char *section,
299                         unsigned section_line,
300                         const char *lvalue,
301                         int ltype,
302                         const char *rvalue,
303                         void *data,
304                         void *userdata) {
305         struct ether_addr **hwaddr = data;
306         struct ether_addr *n;
307         int r;
308
309         assert(filename);
310         assert(lvalue);
311         assert(rvalue);
312         assert(data);
313
314         n = new0(struct ether_addr, 1);
315         if (!n)
316                 return log_oom();
317
318         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
319                    &n->ether_addr_octet[0],
320                    &n->ether_addr_octet[1],
321                    &n->ether_addr_octet[2],
322                    &n->ether_addr_octet[3],
323                    &n->ether_addr_octet[4],
324                    &n->ether_addr_octet[5]);
325         if (r != 6) {
326                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
327                            "Not a valid MAC address, ignoring assignment: %s", rvalue);
328                 free(n);
329                 return 0;
330         }
331
332         free(*hwaddr);
333         *hwaddr = n;
334
335         return 0;
336 }
337
338 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
339         unsigned i;
340
341         assert(f);
342         assert(addresses);
343         assert(size);
344
345         for (i = 0; i < size; i++)
346                 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
347                         (i < (size - 1)) ? " ": "");
348 }
349
350 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
351         _cleanup_free_ struct in_addr *addresses = NULL;
352         int size = 0;
353         const char *word, *state;
354         size_t len;
355
356         assert(ret);
357         assert(string);
358
359         FOREACH_WORD(word, len, string, state) {
360                 _cleanup_free_ char *addr_str = NULL;
361                 struct in_addr *new_addresses;
362                 int r;
363
364                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
365                 if (!new_addresses)
366                         return -ENOMEM;
367                 else
368                         addresses = new_addresses;
369
370                 addr_str = strndup(word, len);
371                 if (!addr_str)
372                         return -ENOMEM;
373
374                 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
375                 if (r <= 0)
376                         continue;
377
378                 size ++;
379         }
380
381         *ret = addresses;
382         addresses = NULL;
383
384         return size;
385 }
386
387 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
388         _cleanup_free_ struct in6_addr *addresses = NULL;
389         int size = 0;
390         const char *word, *state;
391         size_t len;
392
393         assert(ret);
394         assert(string);
395
396         FOREACH_WORD(word, len, string, state) {
397                 _cleanup_free_ char *addr_str = NULL;
398                 struct in6_addr *new_addresses;
399                 int r;
400
401                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
402                 if (!new_addresses)
403                         return -ENOMEM;
404                 else
405                         addresses = new_addresses;
406
407                 addr_str = strndup(word, len);
408                 if (!addr_str)
409                         return -ENOMEM;
410
411                 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
412                 if (r <= 0)
413                         continue;
414
415                 size++;
416         }
417
418         *ret = addresses;
419         addresses = NULL;
420
421         return size;
422 }
423
424 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
425         unsigned i;
426
427         assert(f);
428         assert(key);
429         assert(routes);
430         assert(size);
431
432         fprintf(f, "%s=", key);
433
434         for (i = 0; i < size; i++) {
435                 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
436                         routes[i].dst_prefixlen);
437                 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
438                         (i < (size - 1)) ? " ": "");
439         }
440
441         fputs("\n", f);
442 }
443
444 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
445         _cleanup_free_ struct sd_dhcp_route *routes = NULL;
446         size_t size = 0, allocated = 0;
447         const char *word, *state;
448         size_t len;
449
450         assert(ret);
451         assert(ret_size);
452         assert(ret_allocated);
453         assert(string);
454
455         FOREACH_WORD(word, len, string, state) {
456                 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
457                 _cleanup_free_ char* entry = NULL;
458                 char *tok, *tok_end;
459                 unsigned n;
460                 int r;
461
462                 if (!GREEDY_REALLOC(routes, allocated, size + 1))
463                         return -ENOMEM;
464
465                 entry = strndup(word, len);
466                 if(!entry)
467                         return -ENOMEM;
468
469                 tok = entry;
470
471                 /* get the subnet */
472                 tok_end = strchr(tok, '/');
473                 if (!tok_end)
474                         continue;
475                 *tok_end = '\0';
476
477                 r = inet_aton(tok, &routes[size].dst_addr);
478                 if (r == 0)
479                         continue;
480
481                 tok = tok_end + 1;
482
483                 /* get the prefixlen */
484                 tok_end = strchr(tok, ',');
485                 if (!tok_end)
486                         continue;
487
488                 *tok_end = '\0';
489
490                 r = safe_atou(tok, &n);
491                 if (r < 0 || n > 32)
492                         continue;
493
494                 routes[size].dst_prefixlen = (uint8_t) n;
495                 tok = tok_end + 1;
496
497                 /* get the gateway */
498                 r = inet_aton(tok, &routes[size].gw_addr);
499                 if (r == 0)
500                         continue;
501
502                 size++;
503         }
504
505         *ret_size = size;
506         *ret_allocated = allocated;
507         *ret = routes;
508         routes = NULL;
509
510         return 0;
511 }