static void ni_dhcp4_tester_protocol_event(enum ni_dhcp4_event ev, const ni_dhcp4_device_t *dev, ni_addrconf_lease_t *lease) { ni_debug_dhcp("%s(ev=%u, dev=%s[%u], config-uuid=%s)", __func__, ev, dev->ifname, dev->link.ifindex, dev->config ? ni_uuid_print(&dev->config->uuid) : "<none>"); switch (ev) { case NI_DHCP4_EVENT_ACQUIRED: if (lease && lease->state == NI_ADDRCONF_STATE_GRANTED) { FILE *fp = stdout; if (dhcp4_tester_opts.output != NULL) { fp = fopen(dhcp4_tester_opts.output, "w"); if (!fp) { ni_error("Cannot open %s for output", dhcp4_tester_opts.output); dhcp4_tester_status = NI_WICKED_RC_ERROR; return; } } if (dhcp4_tester_opts.outfmt == NI_DHCP4_TESTER_OUT_LEASE_XML) { xml_node_t *xml = NULL; if (ni_addrconf_lease_to_xml(lease, &xml, dev->ifname) != 0) { if (dhcp4_tester_opts.output) fclose(fp); dhcp4_tester_status = NI_WICKED_RC_ERROR; return; } xml_node_print(xml, fp); xml_node_free(xml); } else { ni_leaseinfo_dump(fp, lease, dev->ifname, NULL); } fflush(fp); if (dhcp4_tester_opts.output) fclose(fp); dhcp4_tester_status = NI_WICKED_RC_SUCCESS; } break; default: break; } }
/* * 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; }