/* * We never received any response. Deal with the traumatic rejection. */ static void ni_dhcp4_fsm_timeout(ni_dhcp4_device_t *dev) { ni_debug_dhcp("%s: timeout in state %s", dev->ifname, ni_dhcp4_fsm_state_name(dev->fsm.state)); dev->fsm.timer = NULL; switch (dev->fsm.state) { case NI_DHCP4_STATE_INIT: /* We get here if we previously received a NAK, and have * started to back off, or if we declined a lease because * the address was already in use. */ ni_dhcp4_device_drop_lease(dev); ni_dhcp4_fsm_discover(dev); break; case NI_DHCP4_STATE_SELECTING: if (!dev->dhcp4.accept_any_offer) { ni_dhcp4_config_t *conf = dev->config; /* We were scanning all offers to check for a best offer. * There was no perfect match, but we may have a "good enough" * match. Check for it. */ if (dev->best_offer.lease) { ni_addrconf_lease_t *lease = dev->best_offer.lease; ni_debug_dhcp("accepting lease offer from %s; server weight=%d", inet_ntoa(lease->dhcp4.server_id), dev->best_offer.weight); ni_dhcp4_process_offer(dev, lease); return; } ni_dhcp4_fsm_fail_lease(dev); if (conf->initial_discovery_timeout < conf->request_timeout) { __ni_dhcp4_fsm_discover(dev, 0); return; } } /* fallthrough */ case NI_DHCP4_STATE_REQUESTING: ni_error("%s: DHCP4 discovery failed", dev->ifname); ni_dhcp4_fsm_fail_lease(dev); ni_dhcp4_fsm_restart(dev); ni_dhcp4_send_event(NI_DHCP4_EVENT_LOST, dev, NULL); /* Now decide whether we should keep trying */ if (dev->config->request_timeout == ~0U) ni_dhcp4_fsm_discover(dev); break; case NI_DHCP4_STATE_VALIDATING: /* Send the next ARP probe */ ni_dhcp4_fsm_arp_validate(dev); break; case NI_DHCP4_STATE_BOUND: ni_dhcp4_fsm_renewal(dev); break; case NI_DHCP4_STATE_RENEWING: ni_error("unable to renew lease within renewal period; trying to rebind"); ni_dhcp4_fsm_rebind(dev); break; case NI_DHCP4_STATE_REBINDING: ni_error("unable to rebind lease"); ni_dhcp4_fsm_restart(dev); /* FIXME: now decide whether we should try to re-discover */ break; case NI_DHCP4_STATE_REBOOT: ni_error("unable to confirm lease"); ni_dhcp4_fsm_commit_lease(dev, NULL); break; default: ; } }
/* * Process a request to reconfigure the device (ie rebind a lease, or discover * a new lease). */ int ni_dhcp4_acquire(ni_dhcp4_device_t *dev, const ni_dhcp4_request_t *info) { ni_dhcp4_config_t *config; const char *classid; size_t len; int rv; if ((rv = ni_dhcp4_device_refresh(dev)) < 0) return rv; config = xcalloc(1, sizeof(*config)); config->dry_run = info->dry_run; config->resend_timeout = NI_DHCP4_RESEND_TIMEOUT_INIT; config->request_timeout = info->acquire_timeout?: NI_DHCP4_REQUEST_TIMEOUT; config->initial_discovery_timeout = NI_DHCP4_DISCOVERY_TIMEOUT; config->uuid = info->uuid; config->flags = info->flags; config->update = info->update; config->route_priority = info->route_priority; config->start_delay = info->start_delay; config->recover_lease = info->recover_lease; config->release_lease = info->release_lease; config->max_lease_time = ni_dhcp4_config_max_lease_time(); if (config->max_lease_time == 0) config->max_lease_time = ~0U; if (info->lease_time && info->lease_time < config->max_lease_time) config->max_lease_time = info->lease_time; if ((len = ni_string_len(info->hostname)) > 0) { if (ni_check_domain_name(info->hostname, len, 0)) { strncpy(config->hostname, info->hostname, sizeof(config->hostname) - 1); } else { ni_debug_dhcp("Discarded request to use suspect hostname: '%s'", ni_print_suspect(info->hostname, len)); } } if (info->clientid) { ni_dhcp4_parse_client_id(&config->client_id, dev->system.hwaddr.type, info->clientid); } else { /* Set client ID from interface hwaddr */ ni_dhcp4_set_client_id(&config->client_id, &dev->system.hwaddr); } if ((classid = info->vendor_class) == NULL) classid = ni_dhcp4_config_vendor_class(); if (classid) strncpy(config->classid, classid, sizeof(config->classid) - 1); config->doflags = DHCP4_DO_DEFAULT; config->doflags |= ni_dhcp4_do_bits(info->update); if (ni_debug & NI_TRACE_DHCP) { ni_trace("Received request:"); ni_trace(" acquire-timeout %u", config->request_timeout); ni_trace(" lease-time %u", config->max_lease_time); ni_trace(" start-delay %u", config->start_delay); ni_trace(" hostname %s", config->hostname[0]? config->hostname : "<none>"); ni_trace(" vendor-class %s", config->classid[0]? config->classid : "<none>"); ni_trace(" client-id %s", ni_print_hex(config->client_id.data, config->client_id.len)); ni_trace(" uuid %s", ni_uuid_print(&config->uuid)); ni_trace(" update-flags %s", __ni_dhcp4_print_doflags(config->doflags)); ni_trace(" recover_lease %s", config->recover_lease ? "true" : "false"); ni_trace(" release_lease %s", config->release_lease ? "true" : "false"); } ni_dhcp4_device_set_config(dev, config); if (!dev->lease) ni_dhcp4_recover_lease(dev); if (dev->lease) { if (!ni_addrconf_lease_is_valid(dev->lease) || (config->client_id.len && !ni_opaque_eq(&config->client_id, &dev->lease->dhcp4.client_id))) { ni_debug_dhcp("%s: lease doesn't match request", dev->ifname); ni_dhcp4_device_drop_lease(dev); dev->notify = 1; } } ni_note("%s: Request to acquire DHCPv4 lease with UUID %s", dev->ifname, ni_uuid_print(&config->uuid)); if (ni_dhcp4_device_start(dev) < 0) return -1; return 1; }