1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2017 Susant Sahani
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <linux/if_addrlabel.h>
24 #include "alloc-util.h"
25 #include "conf-parser.h"
26 #include "networkd-address-label.h"
27 #include "netlink-util.h"
28 #include "networkd-manager.h"
29 #include "parse-util.h"
30 #include "socket-util.h"
32 int address_label_new(AddressLabel
**ret
) {
33 _cleanup_address_label_free_ AddressLabel
*addrlabel
= NULL
;
35 addrlabel
= new0(AddressLabel
, 1);
39 *ret
= TAKE_PTR(addrlabel
);
44 void address_label_free(AddressLabel
*label
) {
49 LIST_REMOVE(labels
, label
->network
->address_labels
, label
);
50 assert(label
->network
->n_address_labels
> 0);
51 label
->network
->n_address_labels
--;
54 hashmap_remove(label
->network
->address_labels_by_section
, label
->section
);
55 network_config_section_free(label
->section
);
62 static int address_label_new_static(Network
*network
, const char *filename
, unsigned section_line
, AddressLabel
**ret
) {
63 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
64 _cleanup_address_label_free_ AddressLabel
*label
= NULL
;
69 assert(!!filename
== (section_line
> 0));
71 r
= network_config_section_new(filename
, section_line
, &n
);
75 label
= hashmap_get(network
->address_labels_by_section
, n
);
77 *ret
= TAKE_PTR(label
);
82 r
= address_label_new(&label
);
86 label
->section
= TAKE_PTR(n
);
88 r
= hashmap_put(network
->address_labels_by_section
, label
->section
, label
);
92 label
->network
= network
;
93 LIST_APPEND(labels
, network
->address_labels
, label
);
94 network
->n_address_labels
++;
96 *ret
= TAKE_PTR(label
);
101 int address_label_configure(
104 sd_netlink_message_handler_t callback
,
107 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
112 assert(link
->ifindex
> 0);
113 assert(link
->manager
);
114 assert(link
->manager
->rtnl
);
116 r
= sd_rtnl_message_new_addrlabel(link
->manager
->rtnl
, &req
, RTM_NEWADDRLABEL
,
117 link
->ifindex
, AF_INET6
);
119 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
121 r
= sd_rtnl_message_addrlabel_set_prefixlen(req
, label
->prefixlen
);
123 return log_error_errno(r
, "Could not set prefixlen: %m");
125 r
= sd_netlink_message_append_u32(req
, IFAL_LABEL
, label
->label
);
127 return log_error_errno(r
, "Could not append IFAL_LABEL attribute: %m");
129 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &label
->in_addr
.in6
);
131 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
133 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
135 return log_error_errno(r
, "Could not send rtnetlink message: %m");
142 int config_parse_address_label_prefix(const char *unit
,
143 const char *filename
,
146 unsigned section_line
,
153 _cleanup_address_label_free_ AddressLabel
*n
= NULL
;
154 Network
*network
= userdata
;
163 r
= address_label_new_static(network
, filename
, section_line
, &n
);
167 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &n
->in_addr
, &n
->prefixlen
);
169 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address label is invalid, ignoring assignment: %s", rvalue
);
178 int config_parse_address_label(
180 const char *filename
,
183 unsigned section_line
,
190 _cleanup_address_label_free_ AddressLabel
*n
= NULL
;
191 Network
*network
= userdata
;
201 r
= address_label_new_static(network
, filename
, section_line
, &n
);
205 r
= safe_atou32(rvalue
, &k
);
207 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address label, ignoring: %s", rvalue
);
211 if (k
== 0xffffffffUL
) {
212 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Adress label is invalid, ignoring: %s", rvalue
);