void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { sd_ipv4ll *ll = userdata; IPV4LL_DONT_DESTROY(ll); int r; assert(acd); assert(ll); switch (event) { case SD_IPV4ACD_EVENT_STOP: ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); ll->claimed_address = 0; break; case SD_IPV4ACD_EVENT_BIND: ll->claimed_address = ll->address; ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); break; case SD_IPV4ACD_EVENT_CONFLICT: /* if an address was already bound we must call up to the user to handle this, otherwise we just try again */ if (ll->claimed_address != 0) { ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT); ll->claimed_address = 0; } else { r = ipv4ll_pick_address(ll); if (r < 0) goto error; r = sd_ipv4acd_start(ll->acd); if (r < 0) goto error; } break; default: assert_not_reached("Invalid IPv4ACD event."); } return; error: ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); }
int sd_ipv4ll_start(sd_ipv4ll *ll) { int r; assert_return(ll, -EINVAL); assert_return(ll->random_data, -EINVAL); if (ll->address == 0) { r = ipv4ll_pick_address(ll); if (r < 0) return r; } r = sd_ipv4acd_start(ll->acd); if (r < 0) return r; return 0; }
static int client_run(int ifindex, const struct in_addr *pa, const struct ether_addr *ha, sd_event *e) { sd_ipv4acd *acd; assert_se(sd_ipv4acd_new(&acd) >= 0); assert_se(sd_ipv4acd_attach_event(acd, e, 0) >= 0); assert_se(sd_ipv4acd_set_index(acd, ifindex) >= 0); assert_se(sd_ipv4acd_set_mac(acd, ha) >= 0); assert_se(sd_ipv4acd_set_address(acd, pa) >= 0); assert_se(sd_ipv4acd_set_callback(acd, acd_handler, NULL) >= 0); log_info("starting IPv4ACD client"); assert_se(sd_ipv4acd_start(acd) >= 0); assert_se(sd_event_loop(e) >= 0); assert_se(!sd_ipv4acd_unref(acd)); return EXIT_SUCCESS; }