Lines Matching refs:acd
80 #define log_ipv4acd_errno(acd, error, fmt, ...) \ argument
83 sd_ipv4acd, acd, \
85 #define log_ipv4acd(acd, fmt, ...) \ argument
88 sd_ipv4acd, acd, \
103 static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { in ipv4acd_set_state() argument
104 assert(acd); in ipv4acd_set_state()
107 if (st != acd->state) in ipv4acd_set_state()
108 … log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st)); in ipv4acd_set_state()
110 if (st == acd->state && !reset_counter) in ipv4acd_set_state()
111 acd->n_iteration++; in ipv4acd_set_state()
113 acd->state = st; in ipv4acd_set_state()
114 acd->n_iteration = 0; in ipv4acd_set_state()
118 static void ipv4acd_reset(sd_ipv4acd *acd) { in ipv4acd_reset() argument
119 assert(acd); in ipv4acd_reset()
121 (void) event_source_disable(acd->timer_event_source); in ipv4acd_reset()
122 …acd->receive_message_event_source = sd_event_source_disable_unref(acd->receive_message_event_sourc… in ipv4acd_reset()
124 acd->fd = safe_close(acd->fd); in ipv4acd_reset()
126 ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true); in ipv4acd_reset()
129 static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) { in ipv4acd_free() argument
130 assert(acd); in ipv4acd_free()
132 ipv4acd_reset(acd); in ipv4acd_free()
133 sd_event_source_unref(acd->timer_event_source); in ipv4acd_free()
134 sd_ipv4acd_detach_event(acd); in ipv4acd_free()
135 free(acd->ifname); in ipv4acd_free()
136 return mfree(acd); in ipv4acd_free()
142 _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL; in sd_ipv4acd_new()
146 acd = new(sd_ipv4acd, 1); in sd_ipv4acd_new()
147 if (!acd) in sd_ipv4acd_new()
150 *acd = (sd_ipv4acd) { in sd_ipv4acd_new()
157 *ret = TAKE_PTR(acd); in sd_ipv4acd_new()
162 static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { in ipv4acd_client_notify() argument
163 assert(acd); in ipv4acd_client_notify()
165 if (!acd->callback) in ipv4acd_client_notify()
168 acd->callback(acd, event, acd->userdata); in ipv4acd_client_notify()
171 int sd_ipv4acd_stop(sd_ipv4acd *acd) { in sd_ipv4acd_stop() argument
174 if (!acd) in sd_ipv4acd_stop()
177 old_state = acd->state; in sd_ipv4acd_stop()
179 ipv4acd_reset(acd); in sd_ipv4acd_stop()
184 log_ipv4acd(acd, "STOPPED"); in sd_ipv4acd_stop()
186 ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); in sd_ipv4acd_stop()
193 static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) { in ipv4acd_set_next_wakeup() argument
196 assert(acd); in ipv4acd_set_next_wakeup()
203 assert_se(sd_event_now(acd->event, CLOCK_BOOTTIME, &time_now) >= 0); in ipv4acd_set_next_wakeup()
205 return event_reset_time(acd->event, &acd->timer_event_source, in ipv4acd_set_next_wakeup()
208 ipv4acd_on_timeout, acd, in ipv4acd_set_next_wakeup()
209 acd->event_priority, "ipv4acd-timer", true); in ipv4acd_set_next_wakeup()
213 sd_ipv4acd *acd = userdata; in ipv4acd_on_timeout() local
216 assert(acd); in ipv4acd_on_timeout()
218 switch (acd->state) { in ipv4acd_on_timeout()
221 acd->defend_window = 0; in ipv4acd_on_timeout()
223 ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); in ipv4acd_on_timeout()
225 if (acd->n_conflict >= MAX_CONFLICTS) { in ipv4acd_on_timeout()
226 log_ipv4acd(acd, "Max conflicts reached, delaying by %s", in ipv4acd_on_timeout()
228 r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); in ipv4acd_on_timeout()
230 r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); in ipv4acd_on_timeout()
239 r = arp_send_probe(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); in ipv4acd_on_timeout()
241 log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); in ipv4acd_on_timeout()
245 … log_ipv4acd(acd, "Probing "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); in ipv4acd_on_timeout()
247 if (acd->n_iteration < PROBE_NUM - 2) { in ipv4acd_on_timeout()
248 ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); in ipv4acd_on_timeout()
250 … r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); in ipv4acd_on_timeout()
254 ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); in ipv4acd_on_timeout()
256 r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); in ipv4acd_on_timeout()
264 if (acd->n_iteration >= ANNOUNCE_NUM - 1) { in ipv4acd_on_timeout()
265 ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); in ipv4acd_on_timeout()
272 r = arp_send_announcement(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); in ipv4acd_on_timeout()
274 log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); in ipv4acd_on_timeout()
278 … log_ipv4acd(acd, "Announcing "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); in ipv4acd_on_timeout()
280 ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); in ipv4acd_on_timeout()
282 r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); in ipv4acd_on_timeout()
286 if (acd->n_iteration == 0) { in ipv4acd_on_timeout()
287 acd->n_conflict = 0; in ipv4acd_on_timeout()
288 ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); in ipv4acd_on_timeout()
300 sd_ipv4acd_stop(acd); in ipv4acd_on_timeout()
304 static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, const struct ether_arp *arp, bool announced) { in ipv4acd_arp_conflict() argument
305 assert(acd); in ipv4acd_arp_conflict()
312 if (memcmp(arp->arp_spa, &acd->address, sizeof(struct in_addr)) == 0) in ipv4acd_arp_conflict()
326 if (memcmp(arp->arp_tpa, &acd->address, sizeof(struct in_addr)) != 0) in ipv4acd_arp_conflict()
329 if (acd->check_mac_callback && in ipv4acd_arp_conflict()
330 …acd->check_mac_callback(acd, (const struct ether_addr*) arp->arp_sha, acd->check_mac_userdata) > 0) in ipv4acd_arp_conflict()
337 static void ipv4acd_on_conflict(sd_ipv4acd *acd) { in ipv4acd_on_conflict() argument
338 assert(acd); in ipv4acd_on_conflict()
340 acd->n_conflict++; in ipv4acd_on_conflict()
342 …log_ipv4acd(acd, "Conflict on "IPV4_ADDRESS_FMT_STR" (%u)", IPV4_ADDRESS_FMT_VAL(acd->address), ac… in ipv4acd_on_conflict()
344 ipv4acd_reset(acd); in ipv4acd_on_conflict()
345 ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); in ipv4acd_on_conflict()
354 sd_ipv4acd *acd = userdata; in ipv4acd_on_packet() local
360 assert(acd); in ipv4acd_on_packet()
368 log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); in ipv4acd_on_packet()
372 log_ipv4acd(acd, "Ignoring too short ARP packet."); in ipv4acd_on_packet()
376 switch (acd->state) { in ipv4acd_on_packet()
381 if (ipv4acd_arp_conflict(acd, &packet, true)) { in ipv4acd_on_packet()
384 assert_se(sd_event_now(acd->event, CLOCK_BOOTTIME, &ts) >= 0); in ipv4acd_on_packet()
387 if (ts > acd->defend_window) { in ipv4acd_on_packet()
388 acd->defend_window = ts + DEFEND_INTERVAL_USEC; in ipv4acd_on_packet()
389 … r = arp_send_announcement(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); in ipv4acd_on_packet()
391 … log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); in ipv4acd_on_packet()
395 … log_ipv4acd(acd, "Defending "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); in ipv4acd_on_packet()
398 ipv4acd_on_conflict(acd); in ipv4acd_on_packet()
405 if (ipv4acd_arp_conflict(acd, &packet, false)) in ipv4acd_on_packet()
406 ipv4acd_on_conflict(acd); in ipv4acd_on_packet()
416 sd_ipv4acd_stop(acd); in ipv4acd_on_packet()
420 int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { in sd_ipv4acd_set_ifindex() argument
421 assert_return(acd, -EINVAL); in sd_ipv4acd_set_ifindex()
423 assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); in sd_ipv4acd_set_ifindex()
425 acd->ifindex = ifindex; in sd_ipv4acd_set_ifindex()
430 int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) { in sd_ipv4acd_get_ifindex() argument
431 if (!acd) in sd_ipv4acd_get_ifindex()
434 return acd->ifindex; in sd_ipv4acd_get_ifindex()
437 int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *ifname) { in sd_ipv4acd_set_ifname() argument
438 assert_return(acd, -EINVAL); in sd_ipv4acd_set_ifname()
444 return free_and_strdup(&acd->ifname, ifname); in sd_ipv4acd_set_ifname()
447 int sd_ipv4acd_get_ifname(sd_ipv4acd *acd, const char **ret) { in sd_ipv4acd_get_ifname() argument
450 assert_return(acd, -EINVAL); in sd_ipv4acd_get_ifname()
452 r = get_ifname(acd->ifindex, &acd->ifname); in sd_ipv4acd_get_ifname()
457 *ret = acd->ifname; in sd_ipv4acd_get_ifname()
462 int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { in sd_ipv4acd_set_mac() argument
465 assert_return(acd, -EINVAL); in sd_ipv4acd_set_mac()
469 acd->mac_addr = *addr; in sd_ipv4acd_set_mac()
471 if (!sd_ipv4acd_is_running(acd)) in sd_ipv4acd_set_mac()
474 assert(acd->fd >= 0); in sd_ipv4acd_set_mac()
475 r = arp_update_filter(acd->fd, &acd->address, &acd->mac_addr); in sd_ipv4acd_set_mac()
477 ipv4acd_reset(acd); in sd_ipv4acd_set_mac()
484 int sd_ipv4acd_detach_event(sd_ipv4acd *acd) { in sd_ipv4acd_detach_event() argument
485 assert_return(acd, -EINVAL); in sd_ipv4acd_detach_event()
487 acd->event = sd_event_unref(acd->event); in sd_ipv4acd_detach_event()
492 int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) { in sd_ipv4acd_attach_event() argument
495 assert_return(acd, -EINVAL); in sd_ipv4acd_attach_event()
496 assert_return(!acd->event, -EBUSY); in sd_ipv4acd_attach_event()
499 acd->event = sd_event_ref(event); in sd_ipv4acd_attach_event()
501 r = sd_event_default(&acd->event); in sd_ipv4acd_attach_event()
506 acd->event_priority = priority; in sd_ipv4acd_attach_event()
511 int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) { in sd_ipv4acd_set_callback() argument
512 assert_return(acd, -EINVAL); in sd_ipv4acd_set_callback()
514 acd->callback = cb; in sd_ipv4acd_set_callback()
515 acd->userdata = userdata; in sd_ipv4acd_set_callback()
520 int sd_ipv4acd_set_check_mac_callback(sd_ipv4acd *acd, sd_ipv4acd_check_mac_callback_t cb, void *us… in sd_ipv4acd_set_check_mac_callback() argument
521 assert_return(acd, -EINVAL); in sd_ipv4acd_set_check_mac_callback()
523 acd->check_mac_callback = cb; in sd_ipv4acd_set_check_mac_callback()
524 acd->check_mac_userdata = userdata; in sd_ipv4acd_set_check_mac_callback()
528 int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { in sd_ipv4acd_set_address() argument
531 assert_return(acd, -EINVAL); in sd_ipv4acd_set_address()
535 if (in4_addr_equal(&acd->address, address)) in sd_ipv4acd_set_address()
538 acd->address = *address; in sd_ipv4acd_set_address()
540 if (!sd_ipv4acd_is_running(acd)) in sd_ipv4acd_set_address()
543 assert(acd->fd >= 0); in sd_ipv4acd_set_address()
544 r = arp_update_filter(acd->fd, &acd->address, &acd->mac_addr); in sd_ipv4acd_set_address()
548 r = ipv4acd_set_next_wakeup(acd, 0, 0); in sd_ipv4acd_set_address()
552 ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); in sd_ipv4acd_set_address()
556 ipv4acd_reset(acd); in sd_ipv4acd_set_address()
560 int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) { in sd_ipv4acd_get_address() argument
561 assert_return(acd, -EINVAL); in sd_ipv4acd_get_address()
564 *address = acd->address; in sd_ipv4acd_get_address()
569 int sd_ipv4acd_is_running(sd_ipv4acd *acd) { in sd_ipv4acd_is_running() argument
570 assert_return(acd, false); in sd_ipv4acd_is_running()
572 return acd->state != IPV4ACD_STATE_INIT; in sd_ipv4acd_is_running()
575 int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) { in sd_ipv4acd_start() argument
578 assert_return(acd, -EINVAL); in sd_ipv4acd_start()
579 assert_return(acd->event, -EINVAL); in sd_ipv4acd_start()
580 assert_return(acd->ifindex > 0, -EINVAL); in sd_ipv4acd_start()
581 assert_return(in4_addr_is_set(&acd->address), -EINVAL); in sd_ipv4acd_start()
582 assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL); in sd_ipv4acd_start()
583 assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); in sd_ipv4acd_start()
585 r = arp_network_bind_raw_socket(acd->ifindex, &acd->address, &acd->mac_addr); in sd_ipv4acd_start()
589 CLOSE_AND_REPLACE(acd->fd, r); in sd_ipv4acd_start()
592 acd->n_conflict = 0; in sd_ipv4acd_start()
594 …r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_p… in sd_ipv4acd_start()
598 r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority); in sd_ipv4acd_start()
602 …(void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message… in sd_ipv4acd_start()
604 r = ipv4acd_set_next_wakeup(acd, 0, 0); in sd_ipv4acd_start()
608 ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); in sd_ipv4acd_start()
612 ipv4acd_reset(acd); in sd_ipv4acd_start()