Ejemplo n.º 1
0
/*
 * Recover object state from an XML file
 */
static ni_bool_t
ni_objectmodel_recover_object_state_xml(xml_node_t *object_node, ni_dbus_object_t *object, const char **prefix_list)
{
	xml_node_t *prop_node;

	/* Now process all the different properties */
	for (prop_node = object_node->children; prop_node; prop_node = prop_node->next) {
		ni_dbus_variant_t dict = NI_DBUS_VARIANT_INIT;
		const char *interface_name;
		const ni_dbus_service_t *service;
		dbus_bool_t rv;

		interface_name = prop_node->name;

		if (prefix_list) {
			ni_bool_t match = FALSE;
			unsigned int i;

			for (i = 0; prefix_list[i] && !match; ++i) {
				const char *pfx = prefix_list[i];
				unsigned int len;

				len = strlen(pfx);
				match = !strncmp(pfx, interface_name, len)
					&& (interface_name[len] == '.' || interface_name[len] == '\0');
			}
			if (!match)
				continue;
		}

		/* Parse the XML properties and store in a dbus dict. */
		if (ni_dbus_xml_serialize_properties(__ni_objectmodel_schema, &dict, prop_node) < 0) {
			ni_error("%s: unable to parse xml properties", xml_node_location(prop_node));
			ni_dbus_variant_destroy(&dict);
			return FALSE;
		}

		/* If ni_dbus_xml_serialize_properties succeeded, the following call cannot fail. */
		service = ni_objectmodel_service_by_name(interface_name);

		/* Now set the object properties from the dbus dict */
		rv = ni_dbus_object_set_properties_from_dict(object, service, &dict, NULL);
		ni_dbus_variant_destroy(&dict);

		if (!rv) {
			ni_error("%s: unable to assign properties", xml_node_location(prop_node));
			return FALSE;
		}
	}

	return TRUE;
}
Ejemplo n.º 2
0
/*
 * Filesystem.getInfo(path)
 *
 */
static dbus_bool_t
__ni_Testbus_Agent_Filesystem_getInfo(ni_dbus_object_t *object, const ni_dbus_method_t *method,
		unsigned int argc, const ni_dbus_variant_t *argv,
		ni_dbus_message_t *reply, DBusError *error)
{
	ni_dbus_variant_t res = NI_DBUS_VARIANT_INIT;
	struct stat stb;
	const char *path;
	dbus_bool_t rv;

	if (argc != 1 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/')
		return ni_dbus_error_invalid_args(error, object->path, method->name);

	if (stat(path, &stb) < 0) {
		ni_dbus_set_error_from_errno(error, errno, "unable to stat file \"%s\"", path);
		return FALSE;
	}
	if (!S_ISREG(stb.st_mode)) {
		dbus_set_error(error, DBUS_ERROR_FAILED, "not a regular file");
		return FALSE;
	}

	ni_dbus_variant_init_dict(&res);
	ni_dbus_dict_add_uint64(&res, "size", stb.st_size);

	rv = ni_dbus_message_serialize_variants(reply, 1, &res, error);
	ni_dbus_variant_destroy(&res);
	return rv;
}
Ejemplo n.º 3
0
/*
 * Get the state of a dbus object as XML.
 * We do this by going via the dbus representation, which is a bit of a waste of
 * time but at least that saves me from writing lots of code, and it makes sure
 * that we have one canonical mapping.
 * In fact, this is a lot like doing a Properties.GetAll call...
 */
static ni_bool_t
ni_objectmodel_save_object_state_xml(const ni_dbus_object_t *object, xml_node_t *parent)
{
	const ni_dbus_service_t *service;
	xml_node_t *object_node;
	unsigned int i;
	int rv = TRUE;

	object_node = xml_node_new("object", parent);
	xml_node_add_attr(object_node, "path", object->path);

	for (i = 0; rv && (service = object->interfaces[i]) != NULL; ++i) {
		ni_dbus_variant_t dict = NI_DBUS_VARIANT_INIT;
		xml_node_t *prop_node;

		ni_dbus_variant_init_dict(&dict);
		rv = ni_dbus_object_get_properties_as_dict(object, service, &dict, NULL);
		if (rv && dict.array.len != 0) {
			/* serialize as XML */
			prop_node = ni_dbus_xml_deserialize_properties(__ni_objectmodel_schema, service->name, &dict, object_node);
			if (!prop_node)
				rv = FALSE;
		}
		ni_dbus_variant_destroy(&dict);
	}

	return rv;
}
Ejemplo n.º 4
0
/*
 * Filesystem.download(path, offset, count)
 *
 */
static dbus_bool_t
__ni_Testbus_Agent_Filesystem_download(ni_dbus_object_t *object, const ni_dbus_method_t *method,
		unsigned int argc, const ni_dbus_variant_t *argv,
		ni_dbus_message_t *reply, DBusError *error)
{
	ni_dbus_variant_t res = NI_DBUS_VARIANT_INIT;
	const char *path;
	uint64_t offset;
	uint32_t count;
	dbus_bool_t rv;
	ni_buffer_t *bp = NULL;
	int fd = -1;

	if (argc != 3
	 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/'
	 || !ni_dbus_variant_get_uint64(&argv[1], &offset)
	 || !ni_dbus_variant_get_uint32(&argv[2], &count)
	 || count > 1024 * 1024
	 || offset + count < offset)
		return ni_dbus_error_invalid_args(error, object->path, method->name);

	if ((fd = open(path, O_RDONLY)) < 0) {
		ni_dbus_set_error_from_errno(error, errno, "unable to open file \"%s\"", path);
		return FALSE;
	}
	if (lseek(fd, offset, SEEK_SET) < 0) {
		ni_dbus_set_error_from_errno(error, errno, "seek faile");
		goto out_fail;
	}

	bp = ni_buffer_new(count);
	while (count) {
		int n;

		n = read(fd, ni_buffer_tail(bp), ni_buffer_tailroom(bp));
		if (n < 0) {
			ni_dbus_set_error_from_errno(error, errno, "read failed");
			goto out_fail;
		}
		if (n == 0)
			break;
		ni_buffer_push_tail(bp, n);
	}

	ni_dbus_variant_init_dict(&res);
	ni_dbus_variant_set_byte_array(&res, ni_buffer_head(bp), ni_buffer_count(bp));

	rv = ni_dbus_message_serialize_variants(reply, 1, &res, error);

	ni_dbus_variant_destroy(&res);
	ni_buffer_free(bp);
	close(fd);
	return rv;

out_fail:
	if (fd >= 0)
		close(fd);
	return FALSE;
}
Ejemplo n.º 5
0
/*
 * Create client handle for addrconf forwarder
 */
static dbus_bool_t
ni_objectmodel_addrconf_forwarder_call(ni_dbus_addrconf_forwarder_t *forwarder,
				ni_netdev_t *dev, const char *method_name,
				const ni_uuid_t *uuid, const ni_dbus_variant_t *dict,
				DBusError *error)
{
	ni_dbus_object_t *object;
	char object_path[256];
	ni_dbus_variant_t argv[2];
	int argc = 0;
	dbus_bool_t rv;

	if (forwarder->supplicant.client == NULL) {
		forwarder->supplicant.client = ni_create_dbus_client(forwarder->supplicant.bus_name);
		if (forwarder->supplicant.client == NULL) {
			dbus_set_error(error, "unable to create call forwarder for %s",
					forwarder->supplicant.bus_name);
			return FALSE;
		}

		ni_dbus_client_add_signal_handler(forwarder->supplicant.client,
				forwarder->supplicant.bus_name,		/* sender must be the supplicant */
				NULL,					/* any object */
				NI_OBJECTMODEL_ADDRCONF_INTERFACE,	/* interface */
				ni_objectmodel_addrconf_signal_handler,
				forwarder);
	}

	/* Build the path of the object to talk to in the supplicant service */
	snprintf(object_path, sizeof(object_path), "%s/%u",
			forwarder->supplicant.object_path, dev->link.ifindex);

	object = ni_dbus_client_object_new(forwarder->supplicant.client,
				&forwarder->class, object_path,
				forwarder->supplicant.interface, NULL);

	/* Build the arguments. Note that we don't clone the dict, we just assign it
	 * to argv[1]. Thus, we must make sure we never call ni_dbus_variant_destroy on argv[1] */
	memset(argv, 0, sizeof(argv));
	ni_dbus_variant_set_uuid(&argv[argc++], uuid);
	if (dict)
		argv[argc++] = *dict;

	/* Call the supplicant's method */
	rv = ni_dbus_object_call_variant(object, forwarder->supplicant.interface, method_name, argc, argv, 0, NULL, error);

	ni_dbus_object_free(object);
	ni_dbus_variant_destroy(&argv[0]);

	return rv;
}
Ejemplo n.º 6
0
/*
 * Wickedd is sending us a signal indicating internal device state change.
 * We want to wait for this signal and when it is >= device-up return TRUE.
 * After timeout we fail...
 */
void
ni_state_change_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data)
{
	const char *signal_name = dbus_message_get_member(msg);
	const char *object_path = dbus_message_get_path(msg);
	ni_dbus_variant_t argv = NI_DBUS_VARIANT_INIT;
	ni_ifworker_array_t *ifworkers = user_data;
	ni_fsm_state_t cur_state, target_state;
	const char *ifname;
	unsigned int i;

	if (ni_string_empty(object_path))
		return;

	/* Deserialize dbus message */
	if (ni_dbus_message_get_args_variants(msg, &argv, 1) < 0 ||
	    !ni_dbus_variant_is_dict(&argv)) {
		ni_error("Unable to retrieve dict from signal %s,  object_path=%s",
			signal_name, object_path);
		return;
	}

	if (!ni_dbus_dict_get_uint32(&argv, "current-state", &cur_state) ||
	    !ni_dbus_dict_get_uint32(&argv, "target-state", &target_state) ||
	    !ni_dbus_dict_get_string(&argv, "ifname", &ifname)) {
		ni_error("Unable to retrieve dict's values from signal %s,  object_path=%s",
			signal_name, object_path);
		return;
	}

	ni_debug_application("received signal %s; object_path=%s; target_state=%s, state_name=%s",
		signal_name, object_path,  ni_ifworker_state_name(target_state),
		ni_ifworker_state_name(cur_state));

	for (i = 0; i < ifworkers->count; ++i) {
		ni_ifworker_t *w = ifworkers->data[i];

		if (cur_state != NI_FSM_STATE_NONE && cur_state != target_state)
			continue;

		if (!ni_string_eq(w->name, ifname))
			continue;

		ni_warn("%s: Device %s", ifname, cur_state == target_state ? "succeeded" : "failed");
		ni_ifworker_array_remove_with_children(ifworkers, w);

	}

	ni_dbus_variant_destroy(&argv);
}
Ejemplo n.º 7
0
Archivo: calls.c Proyecto: mijos/wicked
/*
 * Identify an interface by name
 */
char *
ni_call_device_by_name(ni_dbus_object_t *list_object, const char *name)
{
	DBusError error = DBUS_ERROR_INIT;
	ni_dbus_variant_t arg = NI_DBUS_VARIANT_INIT;
	ni_dbus_variant_t res = NI_DBUS_VARIANT_INIT;
	char *result = NULL;

	ni_dbus_variant_set_string(&arg, name);
	if (ni_dbus_object_call_variant(list_object, NULL, "deviceByName", 1, &arg, 1, &res, &error)) {
		const char *value;

		if (ni_dbus_variant_get_string(&res, &value))
			result = strdup(value);
	} else {
		ni_dbus_print_error(&error, "%s.deviceByName(%s): failed",
				list_object->path, name);
		dbus_error_free(&error);
	}

	ni_dbus_variant_destroy(&arg);
	ni_dbus_variant_destroy(&res);
	return result;
}
Ejemplo n.º 8
0
/*
 * Send Eventlog.connected() signal
 */
static void
ni_testbus_eventlog_signal_eventsAdded(ni_dbus_object_t *eventlog_object, uint32_t last_seq)
{
	ni_dbus_variant_t arg = NI_DBUS_VARIANT_INIT;

	ni_dbus_variant_set_uint32(&arg, last_seq);

	/* Send the signal */
	ni_dbus_server_send_signal(ni_dbus_object_get_server(eventlog_object), eventlog_object,
			NI_TESTBUS_EVENTLOG_INTERFACE,
			"eventsAdded",
			1, &arg);

	ni_dbus_variant_destroy(&arg);
}
Ejemplo n.º 9
0
/*
 * 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);
}