/* * Generic lease properties */ static dbus_bool_t __ni_objectmodel_addrconf_generic_get_lease(const ni_dbus_object_t *object, ni_addrconf_mode_t mode, unsigned int addrfamily, ni_dbus_variant_t *dict, DBusError *error) { ni_netdev_t *dev; const ni_addrconf_lease_t *lease; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; #if 0 NI_TRACE_ENTER_ARGS("dev=%s, af=%s, mode=%s", dev->name, ni_addrfamily_type_to_name(addrfamily), ni_addrconf_type_to_name(mode)); #endif if (!(lease = ni_netdev_get_lease(dev, addrfamily, mode))) return FALSE; ni_dbus_dict_add_uint32(dict, "state", lease->state); if (lease->flags) ni_dbus_dict_add_uint32(dict, "flags", lease->flags); if (!ni_uuid_is_null(&lease->uuid)) ni_dbus_dict_add_uuid(dict, "uuid", &lease->uuid); return TRUE; }
static ni_bool_t ni_dhcp4_tester_req_init(ni_dhcp4_request_t *req, const char *request) { /* Apply some defaults */ req->dry_run = NI_DHCP4_RUN_OFFER; req->update = ~0; req->acquire_timeout = 10; if (!ni_string_empty(request)) { xml_document_t *doc; if (!(doc = xml_document_read(request))) { ni_error("Cannot parse dhcp4 request xml '%s'", request); return FALSE; } if (!ni_dhcp4_tester_req_xml_init(req, doc)) { xml_document_free(doc); return FALSE; } xml_document_free(doc); } /* Always enter dry run mode */ if (ni_uuid_is_null(&req->uuid)) ni_uuid_generate(&req->uuid); return TRUE; }
ni_bool_t ni_duid_init_uuid(ni_opaque_t *duid, const ni_uuid_t *uuid) { ni_duid_data_t *data; memset(duid, 0, sizeof(*duid)); if (ni_uuid_is_null(uuid)) return FALSE; duid->len = sizeof(ni_duid_uuid_t); data = (ni_duid_data_t *)&duid->data; data->uuid.type = htons((uint16_t)NI_DUID_TYPE_UUID); memcpy(&data->uuid.uuid, uuid, sizeof(data->uuid.uuid)); return TRUE; }
int __ni_addrconf_lease_info_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { char hex[32] = { '\0' }; xml_node_new_element("family", node, ni_addrfamily_type_to_name(lease->family)); xml_node_new_element("type", node, ni_addrconf_type_to_name(lease->type)); if (!ni_string_empty(lease->owner)) xml_node_new_element("owner", node, lease->owner); if (!ni_uuid_is_null(&lease->uuid)) xml_node_new_element("uuid", node, ni_uuid_print(&lease->uuid)); xml_node_new_element("state", node, ni_addrconf_state_to_name(lease->state)); snprintf(hex, sizeof(hex), "0x%08x", lease->update); xml_node_new_element("update", node, hex); xml_node_new_element_uint("acquired", node, lease->time_acquired); return 0; }
/* * Generate a uuid. * Not elaborate, but good enough for our purposes. */ ni_uuid_t * ni_uuid_generate(ni_uuid_t *uuid) { static ni_uuid_t req_uuid; if (ni_uuid_is_null(&req_uuid)) { struct timeval tv; gettimeofday(&tv, NULL); req_uuid.words[0] = tv.tv_sec; req_uuid.words[1] = tv.tv_usec; req_uuid.words[2] = getpid(); } req_uuid.words[3]++; *uuid = req_uuid; return uuid; }
/* * Utility functions for handling uuids */ const char * ni_uuid_print(const ni_uuid_t *uuid) { static char buffer[64]; const unsigned char *p; if (!uuid) return NULL; if (ni_uuid_is_null(uuid)) return ""; p = uuid->octets; snprintf(buffer, sizeof(buffer), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); return buffer; }
/* * Callback from addrconf supplicant whenever it acquired, released or lost a lease. * * FIXME SECURITY: * Is it good enough to check for the sender interface to avoid that someone is sending * us spoofed lease messages?! */ void ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data) { ni_dbus_addrconf_forwarder_t *forwarder = user_data; const char *signal_name = dbus_message_get_member(msg); ni_netdev_t *ifp; ni_addrconf_lease_t *lease = NULL; ni_dbus_variant_t argv[16]; ni_uuid_t uuid = NI_UUID_INIT; ni_event_t ifevent; int argc, optind = 0; memset(argv, 0, sizeof(argv)); argc = ni_dbus_message_get_args_variants(msg, argv, 16); if (argc < 0) { ni_error("%s: cannot parse arguments for signal %s", __func__, signal_name); goto done; } ifp = ni_objectmodel_addrconf_path_to_device(dbus_message_get_path(msg)); if (ifp == NULL) { ni_debug_dbus("%s: received signal %s for unknown interface %s", __func__, signal_name, dbus_message_get_path(msg)); goto done; } lease = ni_addrconf_lease_new(forwarder->addrconf, forwarder->addrfamily); if (argc != 1 && argc != 2) { ni_warn("%s: ignoring %s event from %s: bad number of arguments (%u)", __func__, signal_name, dbus_message_get_path(msg), argc); goto done; } if (argc == 2 && !ni_dbus_variant_get_uuid(&argv[optind++], &uuid)) { ni_debug_dbus("%s: unable to parse uuid argument", __func__); goto done; } if (!ni_objectmodel_set_addrconf_lease(lease, &argv[optind++])) { ni_error("%s: unable to parse lease argument received from %s", __func__, dbus_message_get_sender(msg)); goto done; } ni_debug_dbus("received signal %s for interface %s (ifindex %d), lease %s:%s, uuid=%s, update=0x%x, flags=0x%x", signal_name, ifp->name, ifp->link.ifindex, ni_addrfamily_type_to_name(lease->family), ni_addrconf_type_to_name(lease->type), ni_uuid_print(&uuid), lease->update, lease->flags); if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_ACQUIRED_SIGNAL)) { if (lease->state != NI_ADDRCONF_STATE_GRANTED) { ni_error("%s: unexpected lease state in signal %s", __func__, signal_name); goto done; } ifevent = NI_EVENT_ADDRESS_ACQUIRED; if (!__ni_addrconf_should_update(lease->update, NI_ADDRCONF_UPDATE_DEFAULT_ROUTE)) { 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])) continue; if (ni_sockaddr_is_specified(&rp->destination)) continue; if (ni_route_array_delete(&tab->routes, i)) i--; } } } } else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_RELEASED_SIGNAL)) { lease->state = NI_ADDRCONF_STATE_RELEASED; ifevent = NI_EVENT_ADDRESS_RELEASED; } else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_LOST_SIGNAL)) { lease->state = NI_ADDRCONF_STATE_FAILED; ifevent = NI_EVENT_ADDRESS_LOST; } else { /* Ignore unknown signal */ goto done; } /* * The following call updates the system with the information given in * the lease. This includes setting all addresses, as well as updating * resolver and hostname, if provided. * When a lease is dropped, we either fall back to the config information * from the next best lease, or if there is none, we restore the original * system settings. * * Note, lease may be NULL after this, as the interface object * takes ownership of it. */ __ni_system_interface_update_lease(ifp, &lease); /* Potentially, there's a client somewhere waiting for that event. * We use the UUID that's passed back and forth to make sure we * really match the event we were expecting to match. */ { ni_dbus_object_t *object; object = ni_objectmodel_get_netif_object(__ni_objectmodel_server, ifp); if (object) ni_objectmodel_send_netif_event(__ni_objectmodel_server, object, ifevent, ni_uuid_is_null(&uuid)? NULL : &uuid); } done: while (argc--) ni_dbus_variant_destroy(&argv[argc]); if (lease) ni_addrconf_lease_free(lease); }