1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <linux/if_addrlabel.h>
6 #include "alloc-util.h"
7 #include "conf-parser.h"
8 #include "networkd-address-label.h"
9 #include "netlink-util.h"
10 #include "networkd-manager.h"
11 #include "parse-util.h"
12 #include "socket-util.h"
14 void address_label_free(AddressLabel
*label
) {
19 LIST_REMOVE(labels
, label
->network
->address_labels
, label
);
20 assert(label
->network
->n_address_labels
> 0);
21 label
->network
->n_address_labels
--;
24 hashmap_remove(label
->network
->address_labels_by_section
, label
->section
);
25 network_config_section_free(label
->section
);
32 static int address_label_new_static(Network
*network
, const char *filename
, unsigned section_line
, AddressLabel
**ret
) {
33 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
34 _cleanup_(address_label_freep
) AddressLabel
*label
= NULL
;
39 assert(!!filename
== (section_line
> 0));
42 r
= network_config_section_new(filename
, section_line
, &n
);
46 label
= hashmap_get(network
->address_labels_by_section
, n
);
48 *ret
= TAKE_PTR(label
);
54 label
= new(AddressLabel
, 1);
58 *label
= (AddressLabel
) {
62 LIST_APPEND(labels
, network
->address_labels
, label
);
63 network
->n_address_labels
++;
66 label
->section
= TAKE_PTR(n
);
68 r
= hashmap_ensure_allocated(&network
->address_labels_by_section
, &network_config_hash_ops
);
72 r
= hashmap_put(network
->address_labels_by_section
, label
->section
, label
);
77 *ret
= TAKE_PTR(label
);
82 static int address_label_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
89 assert(link
->address_label_messages
> 0);
91 link
->address_label_messages
--;
93 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
96 r
= sd_netlink_message_get_errno(m
);
97 if (r
< 0 && r
!= -EEXIST
) {
98 log_link_message_warning_errno(link
, m
, r
, "Could not set address label");
99 link_enter_failed(link
);
102 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
104 if (link
->address_label_messages
== 0)
105 log_link_debug(link
, "Addresses label set");
110 int address_label_configure(
113 link_netlink_message_handler_t callback
,
116 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
121 assert(link
->ifindex
> 0);
122 assert(link
->manager
);
123 assert(link
->manager
->rtnl
);
125 r
= sd_rtnl_message_new_addrlabel(link
->manager
->rtnl
, &req
, RTM_NEWADDRLABEL
,
126 link
->ifindex
, AF_INET6
);
128 return log_link_error_errno(link
, r
, "Could not allocate RTM_NEWADDR message: %m");
130 r
= sd_rtnl_message_addrlabel_set_prefixlen(req
, label
->prefixlen
);
132 return log_link_error_errno(link
, r
, "Could not set prefixlen: %m");
134 r
= sd_netlink_message_append_u32(req
, IFAL_LABEL
, label
->label
);
136 return log_link_error_errno(link
, r
, "Could not append IFAL_LABEL attribute: %m");
138 r
= sd_netlink_message_append_in6_addr(req
, IFA_ADDRESS
, &label
->in_addr
.in6
);
140 return log_link_error_errno(link
, r
, "Could not append IFA_ADDRESS attribute: %m");
142 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
,
143 callback
?: address_label_handler
,
144 link_netlink_destroy_callback
, link
);
146 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
153 int config_parse_address_label_prefix(const char *unit
,
154 const char *filename
,
157 unsigned section_line
,
164 _cleanup_(address_label_free_or_set_invalidp
) AddressLabel
*n
= NULL
;
165 Network
*network
= userdata
;
174 r
= address_label_new_static(network
, filename
, section_line
, &n
);
178 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &n
->in_addr
, &n
->prefixlen
);
180 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Address label is invalid, ignoring assignment: %s", rvalue
);
189 int config_parse_address_label(
191 const char *filename
,
194 unsigned section_line
,
201 _cleanup_(address_label_free_or_set_invalidp
) AddressLabel
*n
= NULL
;
202 Network
*network
= userdata
;
212 r
= address_label_new_static(network
, filename
, section_line
, &n
);
216 r
= safe_atou32(rvalue
, &k
);
218 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse address label, ignoring: %s", rvalue
);
222 if (k
== 0xffffffffUL
) {
223 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Address label is invalid, ignoring: %s", rvalue
);