chiark / gitweb /
tmpfiles: Fix parse_acl error message
[elogind.git] / src / network / networkd-address.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 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 <net/if.h>
23
24 #include "utf8.h"
25 #include "util.h"
26 #include "conf-parser.h"
27 #include "fw-util.h"
28 #include "network-internal.h"
29 #include "networkd.h"
30 #include "networkd-link.h"
31
32 static void address_init(Address *address) {
33         assert(address);
34
35         address->family = AF_UNSPEC;
36         address->scope = RT_SCOPE_UNIVERSE;
37         address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
38         address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
39 }
40
41 int address_new_static(Network *network, unsigned section, Address **ret) {
42         _cleanup_address_free_ Address *address = NULL;
43
44         if (section) {
45                 address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
46                 if (address) {
47                         *ret = address;
48                         address = NULL;
49
50                         return 0;
51                 }
52         }
53
54         address = new0(Address, 1);
55         if (!address)
56                 return -ENOMEM;
57
58         address_init(address);
59
60         address->network = network;
61
62         LIST_APPEND(addresses, network->static_addresses, address);
63
64         if (section) {
65                 address->section = section;
66                 hashmap_put(network->addresses_by_section,
67                             UINT_TO_PTR(address->section), address);
68         }
69
70         *ret = address;
71         address = NULL;
72
73         return 0;
74 }
75
76 int address_new_dynamic(Address **ret) {
77         _cleanup_address_free_ Address *address = NULL;
78
79         address = new0(Address, 1);
80         if (!address)
81                 return -ENOMEM;
82
83         address_init(address);
84
85         *ret = address;
86         address = NULL;
87
88         return 0;
89 }
90
91 void address_free(Address *address) {
92         if (!address)
93                 return;
94
95         if (address->network) {
96                 LIST_REMOVE(addresses, address->network->static_addresses, address);
97
98                 if (address->section)
99                         hashmap_remove(address->network->addresses_by_section,
100                                        UINT_TO_PTR(address->section));
101         }
102
103         free(address);
104 }
105
106 int address_establish(Address *address, Link *link) {
107         bool masq;
108         int r;
109
110         assert(address);
111         assert(link);
112
113         masq = link->network &&
114                 link->network->ip_masquerade &&
115                 address->family == AF_INET &&
116                 address->scope < RT_SCOPE_LINK;
117
118         /* Add firewall entry if this is requested */
119         if (address->ip_masquerade_done != masq) {
120                 union in_addr_union masked = address->in_addr;
121                 in_addr_mask(address->family, &masked, address->prefixlen);
122
123                 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
124                 if (r < 0)
125                         log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
126
127                 address->ip_masquerade_done = masq;
128         }
129
130         return 0;
131 }
132
133 int address_release(Address *address, Link *link) {
134         int r;
135
136         assert(address);
137         assert(link);
138
139         /* Remove masquerading firewall entry if it was added */
140         if (address->ip_masquerade_done) {
141                 union in_addr_union masked = address->in_addr;
142                 in_addr_mask(address->family, &masked, address->prefixlen);
143
144                 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
145                 if (r < 0)
146                         log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m");
147
148                 address->ip_masquerade_done = false;
149         }
150
151         return 0;
152 }
153
154 int address_drop(Address *address, Link *link,
155                  sd_rtnl_message_handler_t callback) {
156         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
157         int r;
158
159         assert(address);
160         assert(address->family == AF_INET || address->family == AF_INET6);
161         assert(link);
162         assert(link->ifindex > 0);
163         assert(link->manager);
164         assert(link->manager->rtnl);
165
166         address_release(address, link);
167
168         r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
169                                      link->ifindex, address->family);
170         if (r < 0)
171                 return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
172
173         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
174         if (r < 0)
175                 return log_error_errno(r, "Could not set prefixlen: %m");
176
177         if (address->family == AF_INET)
178                 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
179         else if (address->family == AF_INET6)
180                 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
181         if (r < 0)
182                 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
183
184         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
185         if (r < 0)
186                 return log_error_errno(r, "Could not send rtnetlink message: %m");
187
188         link_ref(link);
189
190         return 0;
191 }
192
193 int address_update(Address *address, Link *link,
194                    sd_rtnl_message_handler_t callback) {
195         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
196         int r;
197
198         assert(address);
199         assert(address->family == AF_INET || address->family == AF_INET6);
200         assert(link->ifindex > 0);
201         assert(link->manager);
202         assert(link->manager->rtnl);
203
204         r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
205                                      link->ifindex, address->family);
206         if (r < 0)
207                 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
208
209         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
210         if (r < 0)
211                 return log_error_errno(r, "Could not set prefixlen: %m");
212
213         r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
214         if (r < 0)
215                 return log_error_errno(r, "Could not set flags: %m");
216
217         r = sd_rtnl_message_addr_set_scope(req, address->scope);
218         if (r < 0)
219                 return log_error_errno(r, "Could not set scope: %m");
220
221         if (address->family == AF_INET)
222                 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
223         else if (address->family == AF_INET6)
224                 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
225         if (r < 0)
226                 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
227
228         if (address->family == AF_INET) {
229                 r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
230                 if (r < 0)
231                         return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
232         }
233
234         if (address->label) {
235                 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
236                 if (r < 0)
237                         return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
238         }
239
240         r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
241         if (r < 0)
242                 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
243
244         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
245         if (r < 0)
246                 return log_error_errno(r, "Could not send rtnetlink message: %m");
247
248         link_ref(link);
249
250         return 0;
251 }
252
253 static int address_acquire(Link *link, Address *original, Address **ret) {
254         union in_addr_union in_addr = {};
255         struct in_addr broadcast = {};
256         _cleanup_address_free_ Address *na = NULL;
257         int r;
258
259         assert(link);
260         assert(original);
261         assert(ret);
262
263         /* Something useful was configured? just use it */
264         if (in_addr_is_null(original->family, &original->in_addr) <= 0)
265                 return 0;
266
267         /* The address is configured to be 0.0.0.0 or [::] by the user?
268          * Then let's acquire something more useful from the pool. */
269         r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
270         if (r < 0) {
271                 log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r));
272                 return r;
273         }
274         if (r == 0) {
275                 log_link_error(link, "Couldn't find free address for interface, all taken.");
276                 return -EBUSY;
277         }
278
279         if (original->family == AF_INET) {
280                 /* Pick first address in range for ourselves ... */
281                 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
282
283                 /* .. and use last as broadcast address */
284                 broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
285         } else if (original->family == AF_INET6)
286                 in_addr.in6.s6_addr[15] |= 1;
287
288         r = address_new_dynamic(&na);
289         if (r < 0)
290                 return r;
291
292         na->family = original->family;
293         na->prefixlen = original->prefixlen;
294         na->scope = original->scope;
295         na->cinfo = original->cinfo;
296
297         if (original->label) {
298                 na->label = strdup(original->label);
299                 if (!na->label)
300                         return -ENOMEM;
301         }
302
303         na->broadcast = broadcast;
304         na->in_addr = in_addr;
305
306         LIST_PREPEND(addresses, link->pool_addresses, na);
307
308         *ret = na;
309         na = NULL;
310
311         return 0;
312 }
313
314 int address_configure(Address *address, Link *link,
315                       sd_rtnl_message_handler_t callback) {
316         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
317         int r;
318
319         assert(address);
320         assert(address->family == AF_INET || address->family == AF_INET6);
321         assert(link);
322         assert(link->ifindex > 0);
323         assert(link->manager);
324         assert(link->manager->rtnl);
325
326         r = address_acquire(link, address, &address);
327         if (r < 0)
328                 return r;
329
330         r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
331                                      link->ifindex, address->family);
332         if (r < 0)
333                 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
334
335         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
336         if (r < 0)
337                 return log_error_errno(r, "Could not set prefixlen: %m");
338
339         r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
340         if (r < 0)
341                 return log_error_errno(r, "Could not set flags: %m");
342
343         r = sd_rtnl_message_addr_set_scope(req, address->scope);
344         if (r < 0)
345                 return log_error_errno(r, "Could not set scope: %m");
346
347         if (address->family == AF_INET)
348                 r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
349         else if (address->family == AF_INET6)
350                 r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
351         if (r < 0)
352                 return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
353
354         if (!in_addr_is_null(address->family, &address->in_addr_peer)) {
355                 if (address->family == AF_INET)
356                         r = sd_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
357                 else if (address->family == AF_INET6)
358                         r = sd_rtnl_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
359                 if (r < 0)
360                         return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
361         } else {
362                 if (address->family == AF_INET) {
363                         r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
364                         if (r < 0)
365                                 return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
366                 }
367         }
368
369         if (address->label) {
370                 r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
371                 if (r < 0)
372                         return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
373         }
374
375         r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
376                                               &address->cinfo);
377         if (r < 0)
378                 return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
379
380         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
381         if (r < 0)
382                 return log_error_errno(r, "Could not send rtnetlink message: %m");
383
384         link_ref(link);
385
386         address_establish(address, link);
387
388         return 0;
389 }
390
391 int config_parse_broadcast(
392                 const char *unit,
393                 const char *filename,
394                 unsigned line,
395                 const char *section,
396                 unsigned section_line,
397                 const char *lvalue,
398                 int ltype,
399                 const char *rvalue,
400                 void *data,
401                 void *userdata) {
402
403         Network *network = userdata;
404         _cleanup_address_free_ Address *n = NULL;
405         int r;
406
407         assert(filename);
408         assert(section);
409         assert(lvalue);
410         assert(rvalue);
411         assert(data);
412
413         r = address_new_static(network, section_line, &n);
414         if (r < 0)
415                 return r;
416
417         if (n->family == AF_INET6) {
418                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
419                            "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
420                 return 0;
421         }
422
423         r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
424         if (r < 0) {
425                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
426                            "Broadcast is invalid, ignoring assignment: %s", rvalue);
427                 return 0;
428         }
429
430         n->family = AF_INET;
431         n = NULL;
432
433         return 0;
434 }
435
436 int config_parse_address(const char *unit,
437                 const char *filename,
438                 unsigned line,
439                 const char *section,
440                 unsigned section_line,
441                 const char *lvalue,
442                 int ltype,
443                 const char *rvalue,
444                 void *data,
445                 void *userdata) {
446
447         Network *network = userdata;
448         _cleanup_address_free_ Address *n = NULL;
449         const char *address, *e;
450         union in_addr_union buffer;
451         int r, f;
452
453         assert(filename);
454         assert(section);
455         assert(lvalue);
456         assert(rvalue);
457         assert(data);
458
459         if (streq(section, "Network")) {
460                 /* we are not in an Address section, so treat
461                  * this as the special '0' section */
462                 section_line = 0;
463         }
464
465         r = address_new_static(network, section_line, &n);
466         if (r < 0)
467                 return r;
468
469         /* Address=address/prefixlen */
470
471         /* prefixlen */
472         e = strchr(rvalue, '/');
473         if (e) {
474                 unsigned i;
475                 r = safe_atou(e + 1, &i);
476                 if (r < 0) {
477                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
478                                    "Prefix length is invalid, ignoring assignment: %s", e + 1);
479                         return 0;
480                 }
481
482                 n->prefixlen = (unsigned char) i;
483
484                 address = strndupa(rvalue, e - rvalue);
485         } else
486                 address = rvalue;
487
488         r = in_addr_from_string_auto(address, &f, &buffer);
489         if (r < 0) {
490                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
491                            "Address is invalid, ignoring assignment: %s", address);
492                 return 0;
493         }
494
495         if (!e && f == AF_INET) {
496                 r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen);
497                 if (r < 0) {
498                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
499                                    "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
500                         return 0;
501                 }
502         }
503
504         if (n->family != AF_UNSPEC && f != n->family) {
505                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
506                            "Address is incompatible, ignoring assignment: %s", address);
507                 return 0;
508         }
509
510         n->family = f;
511
512         if (streq(lvalue, "Address"))
513                 n->in_addr = buffer;
514         else
515                 n->in_addr_peer = buffer;
516
517         if (n->family == AF_INET && n->broadcast.s_addr == 0)
518                 n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen);
519
520         n = NULL;
521
522         return 0;
523 }
524
525 int config_parse_label(const char *unit,
526                 const char *filename,
527                 unsigned line,
528                 const char *section,
529                 unsigned section_line,
530                 const char *lvalue,
531                 int ltype,
532                 const char *rvalue,
533                 void *data,
534                 void *userdata) {
535         Network *network = userdata;
536         _cleanup_address_free_ Address *n = NULL;
537         char *label;
538         int r;
539
540         assert(filename);
541         assert(section);
542         assert(lvalue);
543         assert(rvalue);
544         assert(data);
545
546         r = address_new_static(network, section_line, &n);
547         if (r < 0)
548                 return r;
549
550         label = strdup(rvalue);
551         if (!label)
552                 return log_oom();
553
554         if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
555                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
556                            "Interface label is not ASCII clean or is too"
557                            " long, ignoring assignment: %s", rvalue);
558                 free(label);
559                 return 0;
560         }
561
562         free(n->label);
563         if (*label)
564                 n->label = label;
565         else {
566                 free(label);
567                 n->label = NULL;
568         }
569
570         n = NULL;
571
572         return 0;
573 }
574
575 bool address_equal(Address *a1, Address *a2) {
576         /* same object */
577         if (a1 == a2)
578                 return true;
579
580         /* one, but not both, is NULL */
581         if (!a1 || !a2)
582                 return false;
583
584         if (a1->family != a2->family)
585                 return false;
586
587         switch (a1->family) {
588         /* use the same notion of equality as the kernel does */
589         case AF_UNSPEC:
590                 return true;
591
592         case AF_INET:
593                 if (a1->prefixlen != a2->prefixlen)
594                         return false;
595                 else if (a1->prefixlen == 0)
596                         /* make sure we don't try to shift by 32.
597                          * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
598                         return true;
599                 else {
600                         uint32_t b1, b2;
601
602                         b1 = be32toh(a1->in_addr.in.s_addr);
603                         b2 = be32toh(a2->in_addr.in.s_addr);
604
605                         return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
606                 }
607
608         case AF_INET6: {
609                 uint64_t *b1, *b2;
610
611                 b1 = (uint64_t*)&a1->in_addr.in6;
612                 b2 = (uint64_t*)&a2->in_addr.in6;
613
614                 return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
615         }
616
617         default:
618                 assert_not_reached("Invalid address family");
619         }
620 }