+static int ipv4ll_address_lost(sd_ipv4ll *ll, Link *link) {
+ int r;
+ struct in_addr addr;
+
+ assert(ll);
+ assert(link);
+
+ r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
+ if (r >= 0) {
+ _cleanup_address_free_ Address *address = NULL;
+ _cleanup_route_free_ Route *route = NULL;
+
+ log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
+ ADDRESS_FMT_VAL(addr));
+
+ r = address_new_dynamic(&address);
+ if (r < 0) {
+ log_error_link(link, "Could not allocate address: %s", strerror(-r));
+ return r;
+ }
+
+ address->family = AF_INET;
+ address->in_addr.in = addr;
+ address->prefixlen = 16;
+ address->scope = RT_SCOPE_LINK;
+
+ address_drop(address, link, &address_drop_handler);
+
+ r = route_new_dynamic(&route);
+ if (r < 0) {
+ log_error_link(link, "Could not allocate route: %s",
+ strerror(-r));
+ return r;
+ }
+
+ route->family = AF_INET;
+ route->scope = RT_SCOPE_LINK;
+ route->metrics = 99;
+
+ route_drop(route, link, &route_drop_handler);
+ }
+
+ return 0;
+}
+
+static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
+ struct in_addr address;
+ int r;
+
+ assert(ll);
+ assert(link);
+
+ r = sd_ipv4ll_get_address(ll, &address);
+ if (r < 0)
+ return r;
+
+ log_struct_link(LOG_INFO, link,
+ "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
+ link->ifname,
+ ADDRESS_FMT_VAL(address),
+ NULL);
+
+ link_enter_set_addresses(link);
+
+ return 0;
+}
+
+static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
+ Link *link = userdata;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+
+ switch(event) {
+ case IPV4LL_EVENT_STOP:
+ case IPV4LL_EVENT_CONFLICT:
+ r = ipv4ll_address_lost(ll, link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return;
+ }
+ break;
+ case IPV4LL_EVENT_BIND:
+ r = ipv4ll_address_claimed(ll, link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return;
+ }
+ break;
+ default:
+ if (event < 0)
+ log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
+ else
+ log_warning_link(link, "IPv4 link-local unknown event: %d", event);
+ break;
+ }
+}
+