void ni_autoip_device_drop_lease(ni_autoip_device_t *dev) { ni_addrconf_lease_t *lease; if ((lease = dev->lease) != NULL) { /* if we've configured the network using this * lease, we need to isse a link down request */ dev->notify = 1; /* delete the lease file. */ ni_addrconf_lease_file_remove(dev->ifname, lease->type, lease->family); ni_autoip_device_set_lease(dev, NULL); /* Go back to square one */ dev->fsm.state = NI_AUTOIP_STATE_INIT; } }
/* * Write a lease to a file */ int ni_addrconf_lease_file_write(const char *ifname, ni_addrconf_lease_t *lease) { char tempname[PATH_MAX] = {'\0'}; ni_bool_t fallback = FALSE; char *filename = NULL; xml_node_t *xml = NULL; FILE *fp = NULL; int ret = -1; int fd; if (lease->state == NI_ADDRCONF_STATE_RELEASED) { ni_addrconf_lease_file_remove(ifname, lease->type, lease->family); return 0; } if (!__ni_addrconf_lease_file_path(&filename, ni_config_storedir(), ifname, lease->type, lease->family)) { ni_error("Cannot construct lease file name: %m"); return -1; } ni_debug_dhcp("Preparing xml lease data for '%s'", filename); if ((ret = ni_addrconf_lease_to_xml(lease, &xml)) != 0) { if (ret > 0) { ni_debug_dhcp("Skipped, %s:%s leases are disabled", ni_addrfamily_type_to_name(lease->family), ni_addrconf_type_to_name(lease->type)); } else { ni_error("Unable to represent %s:%s lease as XML", ni_addrfamily_type_to_name(lease->family), ni_addrconf_type_to_name(lease->type)); } goto failed; } snprintf(tempname, sizeof(tempname), "%s.XXXXXX", filename); if ((fd = mkstemp(tempname)) < 0) { if (errno == EROFS && __ni_addrconf_lease_file_path(&filename, ni_config_statedir(), ifname, lease->type, lease->family)) { ni_debug_dhcp("Read-only filesystem, try fallback to %s", filename); snprintf(tempname, sizeof(tempname), "%s.XXXXXX", filename); fd = mkstemp(tempname); fallback = TRUE; } if (fd < 0) { ni_error("Cannot create temporary lease file '%s': %m", tempname); tempname[0] = '\0'; ret = -1; goto failed; } } if ((fp = fdopen(fd, "we")) == NULL) { ret = -1; close(fd); ni_error("Cannot reopen temporary lease file '%s': %m", tempname); goto failed; } ni_debug_dhcp("Writing lease to temporary file for '%s'", filename); xml_node_print(xml, fp); fclose(fp); xml_node_free(xml); if ((ret = rename(tempname, filename)) != 0) { ni_error("Unable to rename temporary lease file '%s' to '%s': %m", tempname, filename); goto failed; } else if (!fallback) { __ni_addrconf_lease_file_remove(ni_config_statedir(), ifname, lease->type, lease->family); } ni_debug_dhcp("Lease written to file '%s'", filename); ni_string_free(&filename); return 0; failed: if (fp) fclose(fp); if (xml) xml_node_free(xml); if (tempname[0]) unlink(tempname); ni_string_free(&filename); return -1; }
int ni_dhcp4_fsm_commit_lease(ni_dhcp4_device_t *dev, ni_addrconf_lease_t *lease) { ni_capture_free(dev->capture); dev->capture = NULL; if (lease) { ni_debug_dhcp("%s: committing lease", dev->ifname); if (dev->config->dry_run == NI_DHCP4_RUN_NORMAL) { ni_debug_dhcp("%s: schedule renewal of lease in %u seconds", dev->ifname, lease->dhcp4.renewal_time); ni_dhcp4_fsm_set_timeout(dev, lease->dhcp4.renewal_time); } /* If the user requested a specific route metric, apply it now */ if (dev->config) { ni_route_table_t *tab; ni_route_t *rp; unsigned int i; for (tab = lease->routes; tab; tab = tab->next) { for (i = 0; i < tab->routes.count; ++i) { if ((rp = tab->routes.data[i]) == NULL) continue; rp->protocol = RTPROT_DHCP; rp->priority = dev->config->route_priority; } } } ni_dhcp4_device_set_lease(dev, lease); dev->fsm.state = NI_DHCP4_STATE_BOUND; ni_note("%s: Committed DHCPv4 lease with address %s " "(lease time %u sec, renew in %u sec, rebind in %u sec)", dev->ifname, inet_ntoa(lease->dhcp4.address), lease->dhcp4.lease_time, lease->dhcp4.renewal_time, lease->dhcp4.rebind_time); /* Write the lease to lease cache */ if (dev->config->dry_run != NI_DHCP4_RUN_OFFER) { ni_addrconf_lease_file_write(dev->ifname, lease); } /* Notify anyone who cares that we've (re-)acquired the lease */ ni_dhcp4_send_event(NI_DHCP4_EVENT_ACQUIRED, dev, lease); if (dev->config->dry_run != NI_DHCP4_RUN_NORMAL) { ni_dhcp4_fsm_restart(dev); ni_dhcp4_device_stop(dev); } } else { /* Delete old lease file */ if ((lease = dev->lease) != NULL) { ni_note("%s: Dropped DHCPv4 lease with UUID %s", dev->ifname, ni_uuid_print(&lease->uuid)); lease->state = NI_ADDRCONF_STATE_RELEASED; ni_dhcp4_send_event(NI_DHCP4_EVENT_RELEASED, dev, lease); if (!dev->config || dev->config->dry_run != NI_DHCP4_RUN_OFFER) { ni_addrconf_lease_file_remove(dev->ifname, lease->type, lease->family); } ni_dhcp4_device_drop_lease(dev); } ni_dhcp4_fsm_restart(dev); } return 0; }