1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <netinet/in.h>
6 #include "network-internal.h"
7 #include "networkd-address.h"
8 #include "networkd-ipv4ll.h"
9 #include "networkd-link.h"
10 #include "networkd-manager.h"
11 #include "parse-util.h"
13 static int ipv4ll_address_lost(Link
*link
) {
14 _cleanup_(address_freep
) Address
*address
= NULL
;
20 link
->ipv4ll_address_configured
= false;
22 r
= sd_ipv4ll_get_address(link
->ipv4ll
, &addr
);
26 log_link_debug(link
, "IPv4 link-local release "IPV4_ADDRESS_FMT_STR
, IPV4_ADDRESS_FMT_VAL(addr
));
28 r
= address_new(&address
);
30 return log_link_error_errno(link
, r
, "Could not allocate address: %m");
32 address
->family
= AF_INET
;
33 address
->in_addr
.in
= addr
;
34 address
->prefixlen
= 16;
35 address
->scope
= RT_SCOPE_LINK
;
37 r
= address_remove(address
, link
, NULL
);
41 link_check_ready(link
);
46 static int ipv4ll_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
50 assert(!link
->ipv4ll_address_configured
);
52 r
= sd_netlink_message_get_errno(m
);
53 if (r
< 0 && r
!= -EEXIST
) {
54 log_link_message_warning_errno(link
, m
, r
, "could not set ipv4ll address");
55 link_enter_failed(link
);
58 (void) manager_rtnl_process_address(rtnl
, m
, link
->manager
);
60 link
->ipv4ll_address_configured
= true;
61 link_check_ready(link
);
66 static int ipv4ll_address_claimed(sd_ipv4ll
*ll
, Link
*link
) {
67 _cleanup_(address_freep
) Address
*ll_addr
= NULL
;
68 struct in_addr address
;
74 link
->ipv4ll_address_configured
= false;
76 r
= sd_ipv4ll_get_address(ll
, &address
);
82 log_link_debug(link
, "IPv4 link-local claim "IPV4_ADDRESS_FMT_STR
,
83 IPV4_ADDRESS_FMT_VAL(address
));
85 r
= address_new(&ll_addr
);
89 ll_addr
->family
= AF_INET
;
90 ll_addr
->in_addr
.in
= address
;
91 ll_addr
->prefixlen
= 16;
92 ll_addr
->broadcast
.s_addr
= ll_addr
->in_addr
.in
.s_addr
| htobe32(0xfffffffflu
>> ll_addr
->prefixlen
);
93 ll_addr
->scope
= RT_SCOPE_LINK
;
95 r
= address_configure(ll_addr
, link
, ipv4ll_address_handler
, false, NULL
);
102 static void ipv4ll_handler(sd_ipv4ll
*ll
, int event
, void *userdata
) {
103 Link
*link
= userdata
;
107 assert(link
->network
);
109 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
113 case SD_IPV4LL_EVENT_STOP
:
114 r
= ipv4ll_address_lost(link
);
116 link_enter_failed(link
);
120 case SD_IPV4LL_EVENT_CONFLICT
:
121 r
= ipv4ll_address_lost(link
);
123 link_enter_failed(link
);
127 r
= sd_ipv4ll_restart(ll
);
129 log_link_warning_errno(link
, r
, "Could not acquire IPv4 link-local address: %m");
131 case SD_IPV4LL_EVENT_BIND
:
132 r
= ipv4ll_address_claimed(ll
, link
);
134 log_link_error(link
, "Failed to configure ipv4ll address: %m");
135 link_enter_failed(link
);
140 log_link_warning(link
, "IPv4 link-local unknown event: %d", event
);
145 static int ipv4ll_init(Link
*link
) {
153 r
= sd_ipv4ll_new(&link
->ipv4ll
);
157 r
= sd_ipv4ll_attach_event(link
->ipv4ll
, link
->manager
->event
, 0);
164 int ipv4ll_configure(Link
*link
) {
170 if (!link_ipv4ll_enabled(link
, ADDRESS_FAMILY_IPV4
| ADDRESS_FAMILY_FALLBACK_IPV4
))
173 r
= ipv4ll_init(link
);
177 if (link
->sd_device
&&
178 net_get_unique_predictable_data(link
->sd_device
, true, &seed
) >= 0) {
179 r
= sd_ipv4ll_set_address_seed(link
->ipv4ll
, seed
);
184 r
= sd_ipv4ll_set_mac(link
->ipv4ll
, &link
->mac
);
188 r
= sd_ipv4ll_set_ifindex(link
->ipv4ll
, link
->ifindex
);
192 r
= sd_ipv4ll_set_callback(link
->ipv4ll
, ipv4ll_handler
, link
);
199 int ipv4ll_update_mac(Link
*link
) {
208 restart
= sd_ipv4ll_is_running(link
->ipv4ll
) > 0;
210 r
= sd_ipv4ll_stop(link
->ipv4ll
);
214 r
= sd_ipv4ll_set_mac(link
->ipv4ll
, &link
->mac
);
219 r
= sd_ipv4ll_start(link
->ipv4ll
);
227 int link_serialize_ipv4ll(Link
*link
, FILE *f
) {
228 struct in_addr address
;
236 r
= sd_ipv4ll_get_address(link
->ipv4ll
, &address
);
242 fputs("IPV4LL_ADDRESS=", f
);
243 serialize_in_addrs(f
, &address
, 1, false, NULL
);
249 int link_deserialize_ipv4ll(Link
*link
, const char *ipv4ll_address
) {
250 union in_addr_union address
;
255 if (isempty(ipv4ll_address
))
258 r
= in_addr_from_string(AF_INET
, ipv4ll_address
, &address
);
260 return log_link_debug_errno(link
, r
, "Failed to parse IPv4LL address: %s", ipv4ll_address
);
262 r
= ipv4ll_init(link
);
264 return log_link_debug_errno(link
, r
, "Failed to initialize IPv4LL client: %m");
266 r
= sd_ipv4ll_set_address(link
->ipv4ll
, &address
.in
);
268 return log_link_debug_errno(link
, r
, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address
);
273 int config_parse_ipv4ll(
275 const char *filename
,
278 unsigned section_line
,
285 AddressFamily
*link_local
= data
;
293 /* Note that this is mostly like
294 * config_parse_address_family(), except that it
295 * applies only to IPv4 */
297 r
= parse_boolean(rvalue
);
299 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
300 "Failed to parse %s=%s, ignoring assignment. "
301 "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
302 lvalue
, rvalue
, lvalue
);
306 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, r
);
308 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
309 "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
310 lvalue
, rvalue
, address_family_to_string(*link_local
));