void handle_carrier(int carrier, int flags, const char *ifname) { struct interface *ifp; if (!(options & DHCPCD_LINK)) return; ifp = find_interface(ifname); if (ifp == NULL) { handle_interface(1, ifname); return; } if (!(ifp->options->options & DHCPCD_LINK)) return; if (carrier == LINK_UNKNOWN) carrier = carrier_status(ifp); /* will set ifp->flags */ else ifp->flags = flags; if (carrier == LINK_UNKNOWN) syslog(LOG_ERR, "%s: carrier_status: %m", ifname); /* IFF_RUNNING is checked, if needed, earlier and is OS dependant */ else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) { if (ifp->carrier != LINK_DOWN) { if (ifp->carrier == LINK_UP) syslog(LOG_INFO, "%s: carrier lost", ifp->name); ifp->carrier = LINK_DOWN; dhcp_close(ifp); dhcp6_drop(ifp, "EXPIRE6"); ipv6rs_drop(ifp); /* Don't blindly delete our knowledge of LL addresses. * We need to listen to what the kernel does with * them as some OS's will remove, mark tentative or * do nothing. */ ipv6_free_ll_callbacks(ifp); dhcp_drop(ifp, "NOCARRIER"); } } else if (carrier == LINK_UP && ifp->flags & IFF_UP) { if (ifp->carrier != LINK_UP) { syslog(LOG_INFO, "%s: carrier acquired", ifp->name); ifp->carrier = LINK_UP; #if !defined(__linux__) && !defined(__NetBSD__) /* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the * hardware address changes so we have to go * through the disovery process to work it out. */ handle_interface(0, ifp->name); #endif if (ifp->wireless) getifssid(ifp->name, ifp->ssid); configure_interface(ifp, margc, margv); script_runreason(ifp, "CARRIER"); start_interface(ifp); } } }
static void stop_interface(struct interface *ifp) { syslog(LOG_INFO, "%s: removing interface", ifp->name); ifp->options->options |= DHCPCD_STOPPING; // Remove the interface from our list TAILQ_REMOVE(ifaces, ifp, next); dhcp6_drop(ifp, NULL); ipv6rs_drop(ifp); dhcp_drop(ifp, "STOP"); dhcp_close(ifp); eloop_timeout_delete(NULL, ifp); if (ifp->options->options & DHCPCD_DEPARTED) script_runreason(ifp, "DEPARTED"); free_interface(ifp); if (!(options & (DHCPCD_MASTER | DHCPCD_TEST))) exit(EXIT_FAILURE); }
void ipv4ll_handle_failure(void *arg) { struct interface *ifp = arg; struct dhcp_state *state = D_STATE(ifp); time_t up; if (state->fail.s_addr == state->addr.s_addr) { /* RFC 3927 Section 2.5 */ up = uptime(); if (state->defend + DEFEND_INTERVAL > up) { syslog(LOG_WARNING, "%s: IPv4LL %d second defence failed", ifp->name, DEFEND_INTERVAL); dhcp_drop(ifp, "EXPIRE"); state->conflicts = -1; } else { syslog(LOG_DEBUG, "%s: defended IPv4LL address", ifp->name); state->defend = up; return; } } free(state->offer); state->offer = NULL; eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); if (++state->conflicts > MAX_CONFLICTS) { syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address", ifp->name); if (ifp->options->options & DHCPCD_DHCP) { state->interval = RATE_LIMIT_INTERVAL / 2; dhcp_discover(ifp); } else eloop_timeout_add_sec(ifp->ctx->eloop, RATE_LIMIT_INTERVAL, ipv4ll_start, ifp); } else { eloop_timeout_add_sec(ifp->ctx->eloop, PROBE_WAIT, ipv4ll_start, ifp); } }