/* * A lease has changed, and we are asked to update the system configuration. * When we get here, the old lease has already been removed from the interface, * and the new one has been added. */ int ni_system_update_from_lease(const ni_addrconf_lease_t *lease, const unsigned int ifindex, const char *ifname) { ni_bool_t res = TRUE; int ret; unsigned int kind; ni_debug_ifconfig("%s()", __func__); ni_system_updaters_init(); for (kind = 0; kind < __NI_ADDRCONF_UPDATER_MAX; ++kind) { if (can_update_type(lease, kind)) { ni_updater_t *updater = &updaters[kind]; ni_updater_source_array_t sources = NI_UPDATER_SOURCE_ARRAY_INIT; if (!updater->enabled) continue; switch(lease->state) { case NI_ADDRCONF_STATE_GRANTED: if(!ni_system_update_remove_matching_leases(updater, lease, ifindex, ifname)) { ni_error("Failed to remove any matching leases. Storing new lease anyway."); res = FALSE; } /* Remove matching leases before we install a new lease. * This is important for hostname updates in the case * where the interface name has changed. If we don't process * the resulting remove before we install, we will remove * the newly installed (or already present) hostname file * and thus restore the hostname to /etc/HOSTNAME. */ if(!ni_system_updater_install(updater, lease, ifname)) { res = FALSE; } ni_objectmodel_updater_add_source(kind, lease, ifindex, ifname); break; default: if(!ni_system_update_remove_matching_leases(updater, lease, ifindex, ifname)) { ni_error("Failed to remove any matching leases. Storing new lease anyway."); res = FALSE; } /* If we no longer have any lease data for this resource, restore * the system default. */ if (!ni_objectmodel_updater_select_sources(updater, &sources)) { if (!ni_system_updater_restore(updater, ifname)) res = FALSE; } ni_updater_source_array_destroy(&sources); break; } } } return ret = res ? 0 : -1; }
/* * Run all the netif firmware discovery scripts and return their output * as one large buffer. */ static ni_buffer_t * __ni_netconfig_firmware_discovery(const char *root, const char *type, const char *path) { ni_buffer_t *result; ni_config_t *config = ni_global.config; ni_extension_t *ex; ni_assert(config); result = ni_buffer_new_dynamic(1024); for (ex = config->fw_extensions; ex; ex = ex->next) { ni_script_action_t *script; if (ex->c_bindings) ni_warn("builtins specified in a netif-firmware-discovery element: not supported"); for (script = ex->actions; script; script = script->next) { ni_process_t *process; int rv; /* Check if requested to use specific type/name only (e.g. "ibft") */ if (type && !ni_string_eq_nocase(type, script->name)) continue; ni_debug_ifconfig("trying to discover netif config via firmware service \"%s\"", script->name); /* Create an instance of this command */ process = ni_process_new(script->process); /* Add root directory argument if given */ if (root) { ni_string_array_append(&process->argv, "-r"); ni_string_array_append(&process->argv, root); } /* Add firmware type specific path argument if given */ if (type && path) { ni_string_array_append(&process->argv, "-p"); ni_string_array_append(&process->argv, path); } rv = ni_process_run_and_capture_output(process, result); ni_process_free(process); if (rv) { ni_error("unable to discover firmware (script \"%s\")", script->name); ni_buffer_free(result); return NULL; } } } return result; }
ni_bool_t ni_netdev_load_client_state(ni_netdev_t *dev) { ni_client_state_t cs; ni_client_state_init(&cs); if (dev && ni_client_state_load(&cs, dev->link.ifindex)) { ni_netdev_set_client_state(dev, ni_client_state_clone(&cs)); ni_debug_ifconfig("loading %s structure from a file for %s", NI_CLIENT_STATE_XML_NODE, dev->name); return TRUE; } return FALSE; }
/* * Run the netif firmware discovery scripts and return their output * as an XML document. * The optional from parameter allow to specify the firmware extension * type (e.g. ibft) and a firmware type specific path (e.g. ethernet0), * passed as last argument to the discovery script. */ xml_document_t * ni_netconfig_firmware_discovery(const char *root, const char *from) { ni_buffer_t *buffer; xml_document_t *doc; char *path = NULL; char *type = NULL; /* sanity adjustments... */ if (ni_string_empty(root)) root = NULL; if (ni_string_empty(from)) from = NULL; else { ni_string_dup(&type, from); if ((path = strchr(type, ':'))) *path++ = '\0'; if (ni_string_empty(path)) path = NULL; } buffer = __ni_netconfig_firmware_discovery(root, type, path); if (buffer == NULL) { ni_string_free(&type); return NULL; } ni_debug_ifconfig("%s: %s%sbuffer has %u bytes", __func__, (from ? from : ""), (from ? " ": ""), ni_buffer_count(buffer)); doc = xml_document_from_buffer(buffer, from); ni_buffer_free(buffer); ni_string_free(&type); if (doc == NULL) ni_error("%s: error processing document", __func__); return doc; }
static inline int __ni_wireless_process_wpa1(ni_wireless_network_t *net, void *ptr, size_t len) { static unsigned char wpa1_oui[] = {0x00, 0x50, 0xf2}; unsigned char buffer[3]; ni_buffer_t data; ni_buffer_init_reader(&data, ptr, len); if (ni_buffer_get(&data, buffer, 3) < 0) return -1; if (memcmp(buffer, wpa1_oui, 3)) { ni_debug_ifconfig("skipping non-WPA1 IE (OUI=%02x:%02x:%02x)", buffer[0], buffer[1], buffer[0]); return 0; } if (ni_buffer_get(&data, buffer, 1) < 0) return -1; if (buffer[0] != 0x01) return 0; return __ni_wireless_process_wpa_common(net, &data, NI_WIRELESS_AUTH_WPA1, wpa1_oui); }
/* * Remove information from a lease which has been released and already detached * from a device. */ static ni_bool_t ni_system_updater_remove(ni_updater_t *updater, const ni_addrconf_lease_t *lease, const char *ifname) { ni_string_array_t arguments = NI_STRING_ARRAY_INIT; ni_bool_t result = FALSE; ni_debug_ifconfig("Removing system %s settings from %s %s/%s lease", ni_updater_name(updater->kind), ifname, ni_addrconf_type_to_name(lease->type), ni_addrfamily_type_to_name(lease->family)); if (!updater->proc_remove) return TRUE; ni_string_array_append(&arguments, "-i"); ni_string_array_append(&arguments, ifname); ni_string_array_append(&arguments, "-t"); ni_string_array_append(&arguments, ni_addrconf_type_to_name(lease->type)); ni_string_array_append(&arguments, "-f"); ni_string_array_append(&arguments, ni_addrfamily_type_to_name(lease->family)); switch (updater->kind) { case NI_ADDRCONF_UPDATER_GENERIC: switch (updater->format) { case NI_ADDRCONF_UPDATER_FORMAT_INFO: ni_leaseinfo_remove(ifname, lease->type, lease->family); break; default: ni_error("Unsupported %s updater data format.", ni_updater_name(updater->kind)); break; } break; case NI_ADDRCONF_UPDATER_RESOLVER: case NI_ADDRCONF_UPDATER_HOSTNAME: break; default: ni_error("cannot remove old %s settings - file format not understood", ni_updater_name(updater->kind)); goto done; } if (!ni_system_updater_run(updater->proc_remove, &arguments)) { ni_error("failed to remove %s settings", ni_updater_name(updater->kind)); goto done; } result = TRUE; switch (updater->kind) { case NI_ADDRCONF_UPDATER_RESOLVER: if (ni_global.other_event) ni_global.other_event(NI_EVENT_RESOLVER_UPDATED); break; case NI_ADDRCONF_UPDATER_HOSTNAME: if (ni_global.other_event) ni_global.other_event(NI_EVENT_HOSTNAME_UPDATED); break; case NI_ADDRCONF_UPDATER_GENERIC: if (ni_global.other_event) ni_global.other_event(NI_EVENT_GENERIC_UPDATED); break; default: break; } done: ni_string_array_destroy(&arguments); return result; }
/* * Install information from a lease, and remember that we did */ static ni_bool_t ni_system_updater_install(ni_updater_t *updater, const ni_addrconf_lease_t *lease, const char *ifname) { ni_string_array_t arguments = NI_STRING_ARRAY_INIT; const char *statedir = NULL; char *file = NULL; ni_bool_t result = FALSE; int rv = 0; ni_debug_ifconfig("Updating system %s settings from %s/%s lease", ni_updater_name(updater->kind), ni_addrconf_type_to_name(lease->type), ni_addrfamily_type_to_name(lease->family)); if (!updater->proc_install) return TRUE; if (!ifname || (!updater->have_backup && !ni_system_updater_backup(updater, ifname))) return FALSE; ni_string_array_append(&arguments, "-i"); ni_string_array_append(&arguments, ifname); ni_string_array_append(&arguments, "-t"); ni_string_array_append(&arguments, ni_addrconf_type_to_name(lease->type)); ni_string_array_append(&arguments, "-f"); ni_string_array_append(&arguments, ni_addrfamily_type_to_name(lease->family)); switch (updater->kind) { case NI_ADDRCONF_UPDATER_GENERIC: switch (updater->format) { case NI_ADDRCONF_UPDATER_FORMAT_INFO: ni_leaseinfo_dump(NULL, lease, ifname, NULL); if (!(file = ni_leaseinfo_path(ifname, lease->type, lease->family))) { ni_error("Unable to determine leaseinfo file path."); goto done; } ni_string_array_append(&arguments, file); break; default: ni_error("Unsupported %s updater data format.", ni_updater_name(updater->kind)); goto done; } ni_string_array_append(&arguments, ni_updater_format_name(updater->format)); break; case NI_ADDRCONF_UPDATER_RESOLVER: statedir = ni_extension_statedir(ni_updater_name(updater->kind)); if (!statedir) { ni_error("failed to get %s statedir", ni_updater_name(updater->kind)); goto done; } ni_string_printf(&file, "%s/resolv.conf.%s.%s.%s", statedir, ifname, ni_addrconf_type_to_name(lease->type), ni_addrfamily_type_to_name(lease->family)); ni_string_array_append(&arguments, file); if ((rv = ni_resolver_write_resolv_conf(file, lease->resolver, NULL)) < 0) { ni_error("failed to write resolver info to file: %s", ni_strerror(rv)); goto done; } break; case NI_ADDRCONF_UPDATER_HOSTNAME: if (!ni_string_empty(lease->hostname)) { ni_string_array_append(&arguments, lease->hostname); } else { const ni_address_t *ap; char *name = NULL; unsigned int count; /* bnc#861476 workaround */ if (!can_try_reverse_lookup(lease)) goto done; for (count = 0, ap = lease->addrs; ap; ap = ap->next) { if (!ni_sockaddr_is_specified(&ap->local_addr)) continue; if (!ni_resolve_reverse_timed(&ap->local_addr, &name, NI_UPDATER_REVERSE_TIMEOUT)) break; ni_info("Unable to resolve %s to hostname", ni_sockaddr_print(&ap->local_addr)); if (++count >= NI_UPDATER_REVERSE_MAX_CNT) break; } if (ni_string_empty(name)) { ni_note("Skipping hostname update, none available"); goto done; } ni_string_array_append(&arguments, name); ni_string_free(&name); } break; default: ni_error("cannot install new %s settings - file format not understood", ni_updater_name(updater->kind)); goto done; } if (!ni_system_updater_run(updater->proc_install, &arguments)) { ni_error("failed to install %s settings", ni_updater_name(updater->kind)); goto done; } result = TRUE; switch (updater->kind) { case NI_ADDRCONF_UPDATER_RESOLVER: if (ni_global.other_event) ni_global.other_event(NI_EVENT_RESOLVER_UPDATED); break; case NI_ADDRCONF_UPDATER_HOSTNAME: if (ni_global.other_event) ni_global.other_event(NI_EVENT_HOSTNAME_UPDATED); break; case NI_ADDRCONF_UPDATER_GENERIC: if (ni_global.other_event) ni_global.other_event(NI_EVENT_GENERIC_UPDATED); break; default: break; } done: if (file) free(file); ni_string_array_destroy(&arguments); return result; }