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
= false;
22 r
= sd_ipv4ll_get_address(link
->ipv4ll
, &addr
);
26 log_link_debug(link
, "IPv4 link-local release %u.%u.%u.%u", 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
);
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
= 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
= false;
76 r
= sd_ipv4ll_get_address(ll
, &address
);
82 log_link_debug(link
, "IPv4 link-local claim %u.%u.%u.%u",
83 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 int ipv4ll_configure(Link
*link
) {
150 assert(link
->network
);
151 assert(link
->network
->link_local
& (ADDRESS_FAMILY_IPV4
| ADDRESS_FAMILY_FALLBACK_IPV4
));
154 r
= sd_ipv4ll_new(&link
->ipv4ll
);
158 r
= sd_ipv4ll_attach_event(link
->ipv4ll
, NULL
, 0);
163 if (link
->sd_device
&&
164 net_get_unique_predictable_data(link
->sd_device
, true, &seed
) >= 0) {
165 r
= sd_ipv4ll_set_address_seed(link
->ipv4ll
, seed
);
170 r
= sd_ipv4ll_set_mac(link
->ipv4ll
, &link
->mac
);
174 r
= sd_ipv4ll_set_ifindex(link
->ipv4ll
, link
->ifindex
);
178 r
= sd_ipv4ll_set_callback(link
->ipv4ll
, ipv4ll_handler
, link
);
185 int config_parse_ipv4ll(
187 const char *filename
,
190 unsigned section_line
,
197 AddressFamily
*link_local
= data
;
205 /* Note that this is mostly like
206 * config_parse_address_family(), except that it
207 * applies only to IPv4 */
209 r
= parse_boolean(rvalue
);
211 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
212 "Failed to parse %s=%s, ignoring assignment. "
213 "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
214 lvalue
, rvalue
, lvalue
);
218 SET_FLAG(*link_local
, ADDRESS_FAMILY_IPV4
, r
);
220 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
221 "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
222 lvalue
, rvalue
, address_family_to_string(*link_local
));