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);
45 void address_label_free(AddressLabel
*label
) {
50 LIST_REMOVE(labels
, label
->network
->address_labels
, label
);
51 assert(label
->network
->n_address_labels
> 0);
52 label
->network
->n_address_labels
--;
55 hashmap_remove(label
->network
->address_labels_by_section
, label
->section
);
56 network_config_section_free(label
->section
);
63 static int address_label_new_static(Network
*network
, const char *filename
, unsigned section_line
, AddressLabel
**ret
) {
64 _cleanup_network_config_section_free_ NetworkConfigSection
*n
= NULL
;
65 _cleanup_address_label_free_ AddressLabel
*label
= NULL
;
70 assert(!!filename
== (section_line
> 0));
72 r
= network_config_section_new(filename
, section_line
, &n
);
76 label
= hashmap_get(network
->address_labels_by_section
, n
);
84 r
= address_label_new(&label
);
91 r
= hashmap_put(network
->address_labels_by_section
, label
->section
, label
);
95 label
->network
= network
;
96 LIST_APPEND(labels
, network
->address_labels
, label
);
97 network
->n_address_labels
++;
105 int address_label_configure(
108 sd_netlink_message_handler_t callback
,
111 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
116 assert(link
->ifindex
> 0);
117 assert(link
->manager
);
118 assert(link
->manager
->rtnl
);
120 r
= sd_rtnl_message_new_addrlabel(link
->manager
->rtnl
, &req
, RTM_NEWADDRLABEL
,
121 link
->ifindex
, AF_INET6
);
123 return log_error_errno(r
, "Could not allocate RTM_NEWADDR message: %m");
125 r
= sd_rtnl_message_addrlabel_set_prefixlen(req
, label
->prefixlen
);
127 return log_error_errno(r
, "Could not set prefixlen: %m");
129 r
= sd_netlink_message_append_u32(req
, IFAL_LABEL
, label
->label
);
131 return log_error_errno(r
, "Could not append IFAL_LABEL attribute: %m");
133 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &label
->in_addr
.in6
);
135 return log_error_errno(r
, "Could not append IFA_ADDRESS attribute: %m");
137 r
= sd_netlink_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
139 return log_error_errno(r
, "Could not send rtnetlink message: %m");
146 int config_parse_address_label_prefix(const char *unit
,
147 const char *filename
,
150 unsigned section_line
,
157 _cleanup_address_label_free_ AddressLabel
*n
= NULL
;
158 Network
*network
= userdata
;
167 r
= address_label_new_static(network
, filename
, section_line
, &n
);
171 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &n
->in_addr
, &n
->prefixlen
);
173 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Address label is invalid, ignoring assignment: %s", rvalue
);
182 int config_parse_address_label(
184 const char *filename
,
187 unsigned section_line
,
194 _cleanup_address_label_free_ AddressLabel
*n
= NULL
;
195 Network
*network
= userdata
;
205 r
= address_label_new_static(network
, filename
, section_line
, &n
);
209 r
= safe_atou32(rvalue
, &k
);
211 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse address label, ignoring: %s", rvalue
);
215 if (k
== 0xffffffffUL
) {
216 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Adress label is invalid, ignoring: %s", rvalue
);