Ejemplo n.º 1
0
Archivo: dbus.c Proyecto: rzr/connman
void connman_dbus_property_append_dict(DBusMessageIter *iter, const char *key,
			connman_dbus_append_cb_t function, void *user_data)
{
	DBusMessageIter value, dict;

	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);

	dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
			DBUS_TYPE_ARRAY_AS_STRING
			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &value);

	connman_dbus_dict_open(&value, &dict);
	if (function)
		function(&dict, user_data);
	connman_dbus_dict_close(&value, &dict);

	dbus_message_iter_close_container(iter, &value);
}
Ejemplo n.º 2
0
static void append_peer_service(DBusMessageIter *iter,
					struct _peer_service *service)
{
	DBusMessageIter dict;

	connman_dbus_dict_open(iter, &dict);

	switch (service->type) {
	case CONNMAN_PEER_SERVICE_UNKNOWN:
		/* Should never happen */
		break;
	case CONNMAN_PEER_SERVICE_WIFI_DISPLAY:
		connman_dbus_dict_append_fixed_array(&dict,
				"WiFiDisplayIEs", DBUS_TYPE_BYTE,
				&service->data, service->length);
		break;
	}

	connman_dbus_dict_close(iter, &dict);
}
Ejemplo n.º 3
0
static void append_peer_services(DBusMessageIter *iter, void *user_data)
{
	struct connman_peer *peer = user_data;
	DBusMessageIter container;
	GSList *list;

	dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
							NULL, &container);

	if (!peer->services) {
		DBusMessageIter dict;

		connman_dbus_dict_open(&container, &dict);
		connman_dbus_dict_close(&container, &dict);
	} else {
		for (list = peer->services; list; list = list->next)
			append_peer_service(&container, list->data);
	}

	dbus_message_iter_close_container(iter, &container);
}
Ejemplo n.º 4
0
static int request_input(struct vpn_provider *provider,
			request_cb_t callback, const char *dbus_sender,
			void *user_data)
{
	DBusMessage *message;
	const char *path, *agent_sender, *agent_path;
	DBusMessageIter iter;
	DBusMessageIter dict;
	struct request_input_reply *l2tp_reply;
	int err;
	void *agent;

	agent = connman_agent_get_info(dbus_sender, &agent_sender,
							&agent_path);
	if (!provider || !agent || !agent_path || !callback)
		return -ESRCH;

	message = dbus_message_new_method_call(agent_sender, agent_path,
					VPN_AGENT_INTERFACE,
					"RequestInput");
	if (!message)
		return -ENOMEM;

	dbus_message_iter_init_append(message, &iter);

	path = vpn_provider_get_path(provider);
	dbus_message_iter_append_basic(&iter,
				DBUS_TYPE_OBJECT_PATH, &path);

	connman_dbus_dict_open(&iter, &dict);

	vpn_agent_append_user_info(&dict, provider, "L2TP.User");

	vpn_agent_append_host_and_name(&dict, provider);

	connman_dbus_dict_close(&iter, &dict);

	l2tp_reply = g_try_new0(struct request_input_reply, 1);
	if (!l2tp_reply) {
		dbus_message_unref(message);
		return -ENOMEM;
	}

	l2tp_reply->provider = provider;
	l2tp_reply->callback = callback;
	l2tp_reply->user_data = user_data;

	err = connman_agent_queue_message(provider, message,
			connman_timeout_input_request(),
			request_input_reply, l2tp_reply, agent);
	if (err < 0 && err != -EBUSY) {
		DBG("error %d sending agent request", err);
		dbus_message_unref(message);
		g_free(l2tp_reply);
		return err;
	}

	dbus_message_unref(message);

	return -EINPROGRESS;
}
Ejemplo n.º 5
0
static void setup_tun_interface(unsigned int flags, unsigned change,
		void *data)
{
	struct connman_private_network *pn = data;
	unsigned char prefixlen;
	DBusMessageIter array, dict;
	int err;

	DBG("index %d flags %d change %d", pn->index,  flags, change);

	if (flags & IFF_UP)
		return;

	prefixlen =
		__connman_ipconfig_netmask_prefix_len(PRIVATE_NETWORK_NETMASK);

	if ((__connman_inet_modify_address(RTM_NEWADDR,
				NLM_F_REPLACE | NLM_F_ACK, pn->index, AF_INET,
				pn->server_ip, pn->peer_ip,
				prefixlen, NULL)) < 0) {
		DBG("address setting failed");
		return;
	}

	connman_inet_ifup(pn->index);

	err = enable_nat(default_interface);
	if (err < 0) {
		connman_error("failed to enable NAT on %s", default_interface);
		goto error;
	}

	dbus_message_iter_init_append(pn->reply, &array);

	dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
						&pn->path);

	connman_dbus_dict_open(&array, &dict);

	connman_dbus_dict_append_basic(&dict, "ServerIPv4",
					DBUS_TYPE_STRING, &pn->server_ip);
	connman_dbus_dict_append_basic(&dict, "PeerIPv4",
					DBUS_TYPE_STRING, &pn->peer_ip);
	connman_dbus_dict_append_basic(&dict, "PrimaryDNS",
					DBUS_TYPE_STRING, &pn->primary_dns);
	connman_dbus_dict_append_basic(&dict, "SecondaryDNS",
					DBUS_TYPE_STRING, &pn->secondary_dns);

	connman_dbus_dict_close(&array, &dict);

	dbus_message_iter_append_basic(&array, DBUS_TYPE_UNIX_FD, &pn->fd);

	g_dbus_send_message(connection, pn->reply);

	return;

error:
	pn->reply = __connman_error_failed(pn->msg, -err);
	g_dbus_send_message(connection, pn->reply);

	g_hash_table_remove(pn_hash, pn->path);
}
Ejemplo n.º 6
0
int __connman_agent_request_passphrase_input(struct connman_service *service,
				authentication_cb_t callback,
				const char *dbus_sender, void *user_data)
{
	DBusMessage *message;
	const char *path, *agent_sender, *agent_path;
	DBusMessageIter iter;
	DBusMessageIter dict;
	struct request_input_reply *passphrase_reply;
	int err;
	void *agent;

	agent = connman_agent_get_info(dbus_sender, &agent_sender,
							&agent_path);

	DBG("agent %p service %p path %s", agent, service, agent_path);

	if (!service || !agent || !agent_path || !callback)
		return -ESRCH;

	message = dbus_message_new_method_call(agent_sender, agent_path,
					CONNMAN_AGENT_INTERFACE,
					"RequestInput");
	if (!message)
		return -ENOMEM;

	dbus_message_iter_init_append(message, &iter);

	path = __connman_service_get_path(service);
	dbus_message_iter_append_basic(&iter,
				DBUS_TYPE_OBJECT_PATH, &path);

	connman_dbus_dict_open(&iter, &dict);

	if (__connman_service_is_hidden(service)) {
		connman_dbus_dict_append_dict(&dict, "Name",
					request_input_append_name, NULL);
		connman_dbus_dict_append_dict(&dict, "SSID",
					request_input_append_ssid, NULL);
	}

	if (__connman_service_get_security(service) ==
			CONNMAN_SERVICE_SECURITY_8021X) {
		connman_dbus_dict_append_dict(&dict, "Identity",
					request_input_append_identity, service);
	}

	if (__connman_service_get_security(service) !=
			CONNMAN_SERVICE_SECURITY_NONE) {
		connman_dbus_dict_append_dict(&dict, "Passphrase",
				request_input_append_passphrase, service);

		previous_passphrase_handler(&dict, service);
	}

	if (__connman_service_wps_enabled(service))
		connman_dbus_dict_append_dict(&dict, "WPS",
				request_input_append_wps, NULL);

	connman_dbus_dict_close(&iter, &dict);

	passphrase_reply = g_try_new0(struct request_input_reply, 1);
	if (!passphrase_reply) {
		dbus_message_unref(message);
		return -ENOMEM;
	}

	passphrase_reply->service = service;
	passphrase_reply->callback = callback;
	passphrase_reply->user_data = user_data;

	err = connman_agent_queue_message(service, message,
			connman_timeout_input_request(),
			request_input_passphrase_reply,
			passphrase_reply, agent);

	if (err < 0 && err != -EBUSY) {
		DBG("error %d sending agent message", err);
		dbus_message_unref(message);
		g_free(passphrase_reply);
		return err;
	}

	dbus_message_unref(message);

	return -EINPROGRESS;
}
Ejemplo n.º 7
0
int __connman_agent_request_login_input(struct connman_service *service,
				authentication_cb_t callback, void *user_data)
{
	DBusMessage *message;
	const char *path, *agent_sender, *agent_path;
	DBusMessageIter iter;
	DBusMessageIter dict;
	struct request_input_reply *username_password_reply;
	int err;
	void *agent;

	agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);

	if (!service || !agent || !agent_path || !callback)
		return -ESRCH;

	message = dbus_message_new_method_call(agent_sender, agent_path,
					CONNMAN_AGENT_INTERFACE,
					"RequestInput");
	if (!message)
		return -ENOMEM;

	dbus_message_iter_init_append(message, &iter);

	path = __connman_service_get_path(service);
	dbus_message_iter_append_basic(&iter,
				DBUS_TYPE_OBJECT_PATH, &path);

	connman_dbus_dict_open(&iter, &dict);

	connman_dbus_dict_append_dict(&dict, "Username",
				request_input_append_identity, service);

	connman_dbus_dict_append_dict(&dict, "Password",
				request_input_append_password, service);

	connman_dbus_dict_close(&iter, &dict);

	username_password_reply = g_try_new0(struct request_input_reply, 1);
	if (!username_password_reply) {
		dbus_message_unref(message);
		return -ENOMEM;
	}

	username_password_reply->service = service;
	username_password_reply->callback = callback;
	username_password_reply->user_data = user_data;

	err = connman_agent_queue_message(service, message,
			connman_timeout_input_request(),
			request_input_login_reply, username_password_reply,
			agent);
	if (err < 0 && err != -EBUSY) {
		DBG("error %d sending agent request", err);
		dbus_message_unref(message);
		g_free(username_password_reply);
		return err;
	}

	dbus_message_unref(message);

	return -EINPROGRESS;
}
Ejemplo n.º 8
0
static int create_configuration(DBusMessage *msg, connection_ready_cb callback)
{
	DBusMessage *new_msg = NULL;
	DBusPendingCall *call;
	DBusMessageIter iter, array, new_iter, new_dict;
	const char *type = NULL, *name = NULL;
	const char *host = NULL, *domain = NULL;
	char *ident, *me = NULL;
	int err = 0;
	dbus_bool_t result;
	struct connection_data *data;
	struct config_create_data *user_data = NULL;
	GSList *networks = NULL;

	/*
	 * We copy the old message data into new message. We cannot
	 * just use the old message as is because the user route
	 * information is not in the same format in vpnd.
	 */
	new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
	dbus_message_iter_init_append(new_msg, &new_iter);
	connman_dbus_dict_open(&new_iter, &new_dict);

	dbus_message_iter_init(msg, &iter);
	dbus_message_iter_recurse(&iter, &array);

	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
		DBusMessageIter entry, value;
		void *item_value;
		const char *key;
		int value_type;

		dbus_message_iter_recurse(&array, &entry);
		dbus_message_iter_get_basic(&entry, &key);

		dbus_message_iter_next(&entry);
		dbus_message_iter_recurse(&entry, &value);

		value_type = dbus_message_iter_get_arg_type(&value);
		item_value = NULL;

		switch (value_type) {
		case DBUS_TYPE_STRING:
			dbus_message_iter_get_basic(&value, &item_value);

			if (g_str_equal(key, "Type") == TRUE) {
				type = (const char *)item_value;
			} else if (g_str_equal(key, "Name") == TRUE) {
				name = (const char *)item_value;
			} else if (g_str_equal(key, "Host") == TRUE) {
				host = (const char *)item_value;
			} else if (g_str_equal(key, "VPN.Domain") == TRUE) {
				domain = (const char *)item_value;
			}

			DBG("%s %s", key, (char *)item_value);

			if (item_value != NULL)
				connman_dbus_dict_append_basic(&new_dict, key,
						value_type, &item_value);
			break;
		case DBUS_TYPE_ARRAY:
			if (g_str_equal(key, "Networks") == TRUE) {
				networks = get_user_networks(&value);
				connman_dbus_dict_append_array(&new_dict,
							"UserRoutes",
							DBUS_TYPE_DICT_ENTRY,
							append_routes,
							networks);
			}
			break;
		}

		dbus_message_iter_next(&array);
	}

	connman_dbus_dict_close(&new_iter, &new_dict);

	DBG("VPN type %s name %s host %s domain %s networks %p",
		type, name, host, domain, networks);

	if (host == NULL || domain == NULL) {
		err = -EINVAL;
		goto done;
	}

	if (type == NULL || name == NULL) {
		err = -EOPNOTSUPP;
		goto done;
	}

	ident = g_strdup_printf("%s_%s", host, domain);
	set_dbus_ident(ident);

	DBG("ident %s", ident);

	data = g_hash_table_lookup(vpn_connections, ident);
	if (data != NULL) {
		if (data->call != NULL || data->cb_data != NULL) {
			DBG("create configuration call already pending");
			err = -EINPROGRESS;
			goto done;
		}
	} else {
		char *path = g_strdup_printf("%s/connection/%s", VPN_PATH,
								ident);
		data = create_connection_data(path);
		g_free(path);

		if (data == NULL) {
			err = -ENOMEM;
			goto done;
		}

		g_hash_table_insert(vpn_connections, g_strdup(ident), data);
	}

	/*
	 * User called net.connman.Manager.ConnectProvider if we are here.
	 * So use the data from original message in the new msg.
	 */
	me = g_strdup(dbus_message_get_destination(msg));

	dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
	dbus_message_set_path(new_msg, "/");
	dbus_message_set_destination(new_msg, VPN_SERVICE);
	dbus_message_set_sender(new_msg, me);
	dbus_message_set_member(new_msg, "Create");

	user_data = g_try_new0(struct config_create_data, 1);
	if (user_data == NULL) {
		err = -ENOMEM;
		goto done;
	}

	user_data->callback = callback;
	user_data->message = dbus_message_ref(msg);
	user_data->path = NULL;

	DBG("cb %p msg %p", user_data, msg);

	result = dbus_connection_send_with_reply(connection, new_msg,
						&call, DBUS_TIMEOUT);
	if (result == FALSE || call == NULL) {
		err = -EIO;
		goto done;
	}

	dbus_pending_call_set_notify(call, configuration_create_reply,
							user_data, NULL);
	data->call = call;

done:
	if (new_msg != NULL)
		dbus_message_unref(new_msg);

	if (networks != NULL)
		g_slist_free_full(networks, destroy_route);

	g_free(me);
	return err;
}
Ejemplo n.º 9
0
int __connman_agent_request_input(struct connman_service *service,
				authentication_cb_t callback, void *user_data)
{
	DBusMessage *message;
	const char *path;
	DBusMessageIter iter;
	DBusMessageIter dict;
	DBusPendingCall *call;
	struct request_input_reply *passphrase_reply;

	if (service == NULL || agent_path == NULL || callback == NULL)
		return -ESRCH;

	message = dbus_message_new_method_call(agent_sender, agent_path,
					CONNMAN_AGENT_INTERFACE,
					"RequestInput");
	if (message == NULL)
		return -ENOMEM;

	dbus_message_iter_init_append(message, &iter);

	path = __connman_service_get_path(service);
	dbus_message_iter_append_basic(&iter,
				DBUS_TYPE_OBJECT_PATH, &path);

	connman_dbus_dict_open(&iter, &dict);

	if (__connman_service_get_security(service) ==
			CONNMAN_SERVICE_SECURITY_8021X) {
		connman_dbus_dict_append_dict(&dict, "Identity",
					request_input_append_identity, service);
	}

	connman_dbus_dict_append_dict(&dict, "Passphrase",
				request_input_append_passphrase, service);

	if (__connman_service_wps_enabled(service) == TRUE) {
	    connman_dbus_dict_append_dict(&dict, "WPS",
				request_input_append_wps, NULL);
	}

	connman_dbus_dict_close(&iter, &dict);

	passphrase_reply = g_try_new0(struct request_input_reply, 1);
	if (passphrase_reply == NULL) {
		dbus_message_unref(message);
		return -ENOMEM;
	}

	if (dbus_connection_send_with_reply(connection, message,
						&call, -1) == FALSE) {
		dbus_message_unref(message);
		g_free(passphrase_reply);
		return -ESRCH;
	}

	if (call == NULL) {
		dbus_message_unref(message);
		g_free(passphrase_reply);
		return -ESRCH;
	}

	passphrase_reply->service = connman_service_ref(service);
	passphrase_reply->callback = callback;
	passphrase_reply->user_data = user_data;

	dbus_pending_call_set_notify(call, request_input_passphrase_reply,
				passphrase_reply, NULL);

	dbus_message_unref(message);

	return -EIO;
}
Ejemplo n.º 10
0
static void create_proxy_configuration(void)
{
	DBusMessage *msg;
	DBusMessageIter iter, dict;
	DBusPendingCall *call;
	dbus_bool_t result;
	char *interface;
	const char *method;
	const char *str;
	char **str_list;

	if (default_service == NULL)
		return;

	DBG("");

	msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
			PACRUNNER_INTERFACE, "CreateProxyConfiguration");
	if (msg == NULL)
		return;

	dbus_message_set_auto_start(msg, FALSE);

	dbus_message_iter_init_append(msg, &iter);
	connman_dbus_dict_open(&iter, &dict);

	switch(connman_service_get_proxy_method(default_service)) {
	case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
		goto done;
	case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
		method= "direct";
		break;
	case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
		method = "manual";

		str_list = connman_service_get_proxy_servers(default_service);
		if (str_list == NULL)
			goto done;

		connman_dbus_dict_append_array(&dict, "Servers",
					DBUS_TYPE_STRING, append_string_list,
					str_list);
		g_strfreev(str_list);

		str_list = connman_service_get_proxy_excludes(default_service);
		if (str_list == NULL)
			break;

		connman_dbus_dict_append_array(&dict, "Excludes",
					DBUS_TYPE_STRING, append_string_list,
					str_list);
		g_strfreev(str_list);

		break;
	case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
		method = "auto";

		str = connman_service_get_proxy_url(default_service);
		if (str == NULL) {
			str = connman_service_get_proxy_autoconfig(
							default_service);
			if (str == NULL)
				goto done;
		}

		connman_dbus_dict_append_basic(&dict, "URL",
					DBUS_TYPE_STRING, &str);
		break;
	}

	connman_dbus_dict_append_basic(&dict, "Method",
				DBUS_TYPE_STRING, &method);

	interface = connman_service_get_interface(default_service);
	if (interface != NULL) {
		connman_dbus_dict_append_basic(&dict, "Interface",
						DBUS_TYPE_STRING, &interface);
		g_free(interface);
	}

	str = connman_service_get_domainname(default_service);
	if (str != NULL)
		connman_dbus_dict_append_array(&dict, "Domains",
					DBUS_TYPE_STRING, append_string, &str);

	str_list = connman_service_get_nameservers(default_service);
	if (str_list != NULL)
		connman_dbus_dict_append_array(&dict, "Nameservers",
					DBUS_TYPE_STRING, append_string_list,
					str_list);

	connman_dbus_dict_close(&iter, &dict);

	result = dbus_connection_send_with_reply(connection, msg,
							&call, DBUS_TIMEOUT);

	if (result == FALSE || call == NULL)
		goto done;

	dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);

	dbus_pending_call_unref(call);

done:
	dbus_message_unref(msg);
}
Ejemplo n.º 11
0
static int request_cookie_input(struct vpn_provider *provider,
		struct oc_private_data *data)
{
	DBusMessage *message;
	const char *path, *agent_sender, *agent_path;
	DBusMessageIter iter;
	DBusMessageIter dict;
	const char *str;
	int err;

	connman_agent_get_info(&agent_sender, &agent_path);

	if (provider == NULL || agent_path == NULL)
		return -ESRCH;

	message = dbus_message_new_method_call(agent_sender, agent_path,
					VPN_AGENT_INTERFACE,
					"RequestInput");
	if (message == NULL)
		return -ENOMEM;

	dbus_message_iter_init_append(message, &iter);

	path = vpn_provider_get_path(provider);
	dbus_message_iter_append_basic(&iter,
				DBUS_TYPE_OBJECT_PATH, &path);

	connman_dbus_dict_open(&iter, &dict);

	str = vpn_provider_get_string(provider, "OpenConnect.CACert");
	if (str != NULL)
		connman_dbus_dict_append_dict(&dict, "OpenConnect.CACert",
				request_input_append_informational,
				(void *)str);

	str = vpn_provider_get_string(provider, "OpenConnect.ClientCert");
	if (str != NULL)
		connman_dbus_dict_append_dict(&dict, "OpenConnect.ClientCert",
				request_input_append_informational,
				(void *)str);

	connman_dbus_dict_append_dict(&dict, "OpenConnect.ServerCert",
			request_input_append_mandatory, NULL);

	connman_dbus_dict_append_dict(&dict, "OpenConnect.VPNHost",
			request_input_append_mandatory, NULL);

	connman_dbus_dict_append_dict(&dict, "OpenConnect.Cookie",
			request_input_append_mandatory, NULL);

	vpn_agent_append_host_and_name(&dict, provider);

	connman_dbus_dict_close(&iter, &dict);

	err = connman_agent_queue_message(provider, message,
			connman_timeout_input_request(),
			request_input_cookie_reply, data);

	if (err < 0 && err != -EBUSY) {
		DBG("error %d sending agent request", err);
		dbus_message_unref(message);

		return err;
	}

	dbus_message_unref(message);

	return -EINPROGRESS;
}
Ejemplo n.º 12
0
static void setup_tun_interface(unsigned int flags, unsigned change,
		void *data)
{
	struct connman_private_network *pn = data;
	unsigned char prefixlen;
	DBusMessageIter array, dict;
	const char *server_ip;
	const char *peer_ip;
	const char *subnet_mask;
	int err;

	DBG("index %d flags %d change %d", pn->index,  flags, change);

	if (flags & IFF_UP)
		return;

	subnet_mask = __connman_ippool_get_subnet_mask(pn->pool);
	server_ip = __connman_ippool_get_start_ip(pn->pool);
	peer_ip = __connman_ippool_get_end_ip(pn->pool);
	prefixlen = connman_ipaddress_calc_netmask_len(subnet_mask);

	if ((__connman_inet_modify_address(RTM_NEWADDR,
				NLM_F_REPLACE | NLM_F_ACK, pn->index, AF_INET,
				server_ip, peer_ip, prefixlen, NULL)) < 0) {
		DBG("address setting failed");
		return;
	}

	connman_inet_ifup(pn->index);

	err = __connman_nat_enable(BRIDGE_NAME, server_ip, prefixlen);
	if (err < 0) {
		connman_error("failed to enable NAT");
		goto error;
	}

	dbus_message_iter_init_append(pn->reply, &array);

	dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
						&pn->path);

	connman_dbus_dict_open(&array, &dict);

	connman_dbus_dict_append_basic(&dict, "ServerIPv4",
					DBUS_TYPE_STRING, &server_ip);
	connman_dbus_dict_append_basic(&dict, "PeerIPv4",
					DBUS_TYPE_STRING, &peer_ip);
	if (pn->primary_dns)
		connman_dbus_dict_append_basic(&dict, "PrimaryDNS",
					DBUS_TYPE_STRING, &pn->primary_dns);

	if (pn->secondary_dns)
		connman_dbus_dict_append_basic(&dict, "SecondaryDNS",
					DBUS_TYPE_STRING, &pn->secondary_dns);

	connman_dbus_dict_close(&array, &dict);

	dbus_message_iter_append_basic(&array, DBUS_TYPE_UNIX_FD, &pn->fd);

	g_dbus_send_message(connection, pn->reply);

	return;

error:
	pn->reply = __connman_error_failed(pn->msg, -err);
	g_dbus_send_message(connection, pn->reply);

	g_hash_table_remove(pn_hash, pn->path);
}