示例#1
0
文件: service.c 项目: intgr/bluez
static void auth_cb(DBusError *derr, void *user_data)
{
	DBusConnection *conn = btd_get_dbus_connection();
	struct service_adapter *serv_adapter = user_data;
	DBusMessage *reply;
	struct pending_auth *auth;

	auth = next_pending(serv_adapter);
	if (auth == NULL) {
		info("Authorization cancelled: Client exited");
		return;
	}

	if (derr) {
		error("Access denied: %s", derr->message);

		reply = btd_error_not_authorized(auth->msg);
		g_dbus_send_message(conn, reply);
		goto done;
	}

	g_dbus_send_reply(conn, auth->msg, DBUS_TYPE_INVALID);

done:
	serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
									auth);
	dbus_message_unref(auth->msg);
	g_free(auth);

	auth = next_pending(serv_adapter);
	if (auth == NULL)
		return;

	auth->id = btd_request_authorization(get_address(serv_adapter),
							&auth->dst, auth->uuid,
							auth_cb, serv_adapter);
}
示例#2
0
static int send_cancel_request(struct connman_agent *agent,
			struct connman_agent_request *request)
{
	DBusMessage *message;
	const char *interface = NULL;

	if (request && request->driver)
		interface = request->driver->interface;

	DBG("send cancel req to %s %s iface %s", agent->owner, agent->path,
								interface);

	message = dbus_message_new_method_call(agent->owner,
					agent->path,
					interface,
					"Cancel");
	if (!message) {
		connman_error("Couldn't allocate D-Bus message");
		return -ENOMEM;
	}

	g_dbus_send_message(connection, message);
	return 0;
}
示例#3
0
static void properties_changed(dbus_uint32_t state)
{
	const char *key = "State";
	DBusMessageIter iter, dict, dict_entry, dict_val;
	DBusMessage *signal;

	signal = dbus_message_new_signal(NM_PATH, NM_INTERFACE,
						"PropertiesChanged");
	if (signal == NULL)
		return;

	dbus_message_iter_init_append(signal, &iter);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
					DBUS_TYPE_STRING_AS_STRING
					DBUS_TYPE_VARIANT_AS_STRING
					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
					&dict);

	dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
							NULL, &dict_entry);

	dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);

	dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT,
					DBUS_TYPE_UINT32_AS_STRING, &dict_val);

	dbus_message_iter_append_basic(&dict_val, DBUS_TYPE_UINT32, &state);

	dbus_message_iter_close_container(&dict_entry, &dict_val);
	dbus_message_iter_close_container(&dict, &dict_entry);
	dbus_message_iter_close_container(&iter, &dict);

	g_dbus_send_message(connection, signal);
}
static gboolean controlpoint_timeout(gpointer user_data)
{
	struct controlpoint_req *req = user_data;

	if (req->opcode == UPDATE_SENSOR_LOC) {
		g_dbus_pending_property_error(req->reply_id,
						ERROR_INTERFACE ".Failed",
						"Operation failed (timeout)");
	} else if (req->opcode == SET_CUMULATIVE_VALUE) {
		DBusMessage *reply;

		reply = btd_error_failed(req->msg,
						"Operation failed (timeout)");

		g_dbus_send_message(btd_get_dbus_connection(), reply);

		dbus_message_unref(req->msg);
	}

	req->csc->pending_req = NULL;
	g_free(req);

	return FALSE;
}
示例#5
0
文件: media.c 项目: BirdAndEarth/RPi
static int set_setting(const char *key, const char *value, void *user_data)
{
	struct media_player *mp = user_data;
	const char *iface = MEDIA_PLAYER_INTERFACE;
	DBusMessage *msg;
	DBusMessageIter iter;
	const char *curval;

	DBG("%s = %s", key, value);

	curval = g_hash_table_lookup(mp->settings, key);
	if (!curval)
		return -EINVAL;

	if (strcasecmp(curval, value) == 0)
		return 0;

	msg = dbus_message_new_method_call(mp->sender, mp->path,
					DBUS_INTERFACE_PROPERTIES, "Set");
	if (msg == NULL) {
		error("Couldn't allocate D-Bus message");
		return -ENOMEM;
	}

	dbus_message_iter_init_append(msg, &iter);
	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface);

	if (strcasecmp(key, "Shuffle") == 0)
		set_shuffle_setting(&iter, value);
	else if (strcasecmp(key, "Repeat") == 0)
		set_repeat_setting(&iter, value);

	g_dbus_send_message(btd_get_dbus_connection(), msg);

	return 0;
}
示例#6
0
static void release_session(gpointer key, gpointer value, gpointer user_data)
{
    struct connman_session *session = value;
    DBusMessage *message;

    DBG("owner %s path %s", session->owner, session->notify_path);

    if (session->notify_watch > 0)
        g_dbus_remove_watch(connection, session->notify_watch);

    g_dbus_unregister_interface(connection, session->session_path,
                                CONNMAN_SESSION_INTERFACE);

    message = dbus_message_new_method_call(session->owner,
                                           session->notify_path,
                                           CONNMAN_NOTIFICATION_INTERFACE,
                                           "Release");
    if (!message)
        return;

    dbus_message_set_no_reply(message, TRUE);

    g_dbus_send_message(connection, message);
}
示例#7
0
文件: server.c 项目: intgr/bluez
static int agent_ringer_set_ringer(const char *mode)
{
	struct alert_data *alert;
	DBusMessage *msg;

	alert = get_alert_data_by_category("ringer");
	if (!alert) {
		DBG("Category ringer is not registered");
		return -EINVAL;
	}

	msg = dbus_message_new_method_call(alert->srv, alert->path,
					ALERT_AGENT_INTERFACE, "SetRinger");
	if (!msg)
		return -ENOMEM;

	dbus_message_append_args(msg, DBUS_TYPE_STRING, &mode,
							DBUS_TYPE_INVALID);

	dbus_message_set_no_reply(msg, TRUE);
	g_dbus_send_message(btd_get_dbus_connection(), msg);

	return 0;
}
示例#8
0
static void emit_interfaces_added(struct generic_data *data)
{
	DBusMessage *signal;
	DBusMessageIter iter, array;

	if (root == NULL || data == root)
		return;

	signal = dbus_message_new_signal(root->path,
					DBUS_INTERFACE_OBJECT_MANAGER,
					"InterfacesAdded");
	if (signal == NULL)
		return;

	dbus_message_iter_init_append(signal, &iter);
	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
								&data->path);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
				DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
				DBUS_TYPE_STRING_AS_STRING
				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
				DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);

	g_slist_foreach(data->added, append_interface, &array);
	g_slist_free(data->added);
	data->added = NULL;

	dbus_message_iter_close_container(&iter, &array);

	g_dbus_send_message(data->conn, signal);
}
示例#9
0
static void update_watchers_read_complete(gpointer data, gpointer user_data)
{
	struct watcher *w = data;
	struct read_resp_op *op = user_data;
	struct characteristic *chr = op->chr;
	DBusConnection *conn = w->gatt->conn;
	DBusMessage *msg;
	uint8_t status = op->status;
	INFO("read_resp_watchers chr:%s data[0]:%02X len:%d",chr->path,op->data[0],op->len);

	msg = dbus_message_new_method_call(w->name, w->path,
				"org.bluez.Watcher", "ReadResponse");

	if (msg == NULL)
		return;

	dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &chr->path,
			DBUS_TYPE_BYTE, &status,
			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
			&op->data, op->len, DBUS_TYPE_INVALID);

	dbus_message_set_no_reply(msg, TRUE);
	g_dbus_send_message(conn, msg);
}
示例#10
0
static void hfp_connect_reply(DBusPendingCall *call, gpointer user_data)
{
	struct ofono_modem *modem = user_data;
	struct hfp_data *data = ofono_modem_get_data(modem);
	DBusError derr;
	DBusMessage *reply, *msg;

	reply = dbus_pending_call_steal_reply(call);

	if (ofono_modem_get_powered(modem))
		goto done;

	dbus_error_init(&derr);
	if (!dbus_set_error_from_message(&derr, reply))
		goto done;

	DBG("Connect reply: %s", derr.message);

	if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) {
		msg = dbus_message_new_method_call(BLUEZ_SERVICE,
				data->handsfree_path,
				BLUEZ_GATEWAY_INTERFACE, "Disconnect");
		if (msg == NULL)
			ofono_error("Disconnect failed");
		else
			g_dbus_send_message(connection, msg);
	}

	ofono_modem_set_powered(modem, FALSE);

	dbus_error_free(&derr);

done:
	dbus_message_unref(reply);
	data->call = NULL;
}
示例#11
0
文件: dbus.c 项目: Conjuror/ofono
int ofono_dbus_signal_property_changed(DBusConnection *conn,
					const char *path,
					const char *interface,
					const char *name,
					int type, void *value)
{
	DBusMessage *signal;
	DBusMessageIter iter;

	signal = dbus_message_new_signal(path, interface, "PropertyChanged");
	if (signal == NULL) {
		ofono_error("Unable to allocate new %s.PropertyChanged signal",
				interface);
		return -1;
	}

	dbus_message_iter_init_append(signal, &iter);

	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);

	append_variant(&iter, type, value);

	return g_dbus_send_message(conn, signal);
}
示例#12
0
static void slc_failed(gpointer userdata)
{
	struct ofono_modem *modem = userdata;
	struct hfp *hfp = ofono_modem_get_data(modem);
	struct hfp_slc_info *info = &hfp->info;
	DBusMessage *msg;

	msg = g_dbus_create_error(hfp->msg, BLUEZ_ERROR_INTERFACE
						".Failed",
						"HFP Handshake failed");

	g_dbus_send_message(ofono_dbus_get_connection(), msg);
	dbus_message_unref(hfp->msg);
	hfp->msg = NULL;

	ofono_error("Service level connection failed");
	ofono_modem_set_powered(modem, FALSE);

	ofono_handsfree_card_remove(hfp->card);
	hfp->card = NULL;

	g_at_chat_unref(info->chat);
	info->chat = NULL;
}
示例#13
0
文件: port.c 项目: BloodLiker/bluez
static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
							gpointer user_data)
{
	struct serial_port *port = user_data;
	struct serial_device *device = port->device;
	struct rfcomm_dev_req req;
	int sk, fd;
	DBusMessage *reply;

	/* Owner exited? */
	if (!port->listener_id)
		return;

	if (conn_err) {
		error("%s", conn_err->message);
		reply = btd_error_failed(port->msg, conn_err->message);
		goto fail;
	}

	sk = g_io_channel_unix_get_fd(chan);

	if (dbus_message_has_member(port->msg, "ConnectFD")) {
		reply = g_dbus_create_reply(port->msg, DBUS_TYPE_UNIX_FD, &sk,
							DBUS_TYPE_INVALID);
		g_dbus_send_message(device->conn, reply);

		close(sk);

		g_dbus_remove_watch(device->conn, port->listener_id);
		port->listener_id = 0;

		return;
	}

	memset(&req, 0, sizeof(req));
	req.dev_id = -1;
	req.flags = (1 << RFCOMM_REUSE_DLC);
	bacpy(&req.src, &device->src);
	bacpy(&req.dst, &device->dst);
	req.channel = port->channel;

	g_io_channel_unref(port->io);
	port->io = NULL;

	port->id = ioctl(sk, RFCOMMCREATEDEV, &req);
	if (port->id < 0) {
		int err = -errno;
		error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(-err), -err);
		reply = btd_error_failed(port->msg, strerror(-err));
		g_io_channel_shutdown(chan, TRUE, NULL);
		goto fail;
	}

	port->dev = g_strdup_printf("/dev/rfcomm%d", port->id);

	DBG("Serial port %s created", port->dev);

	g_io_channel_shutdown(chan, TRUE, NULL);

	/* Addressing connect port */
	fd = port_open(port);
	if (fd < 0)
		/* Open in progress: Wait the callback */
		return;

	open_notify(fd, 0, port);
	return;

fail:
	g_dbus_send_message(device->conn, reply);
	g_dbus_remove_watch(device->conn, port->listener_id);
	port->listener_id = 0;
}
示例#14
0
int __connman_technology_enable(enum connman_service_type type, DBusMessage *msg)
{
	struct connman_technology *technology;
	GSList *list;
	int err = 0;
	int ret = -ENODEV;
	DBusMessage *reply;

	DBG("type %d enable", type);

	technology = technology_find(type);
	if (technology == NULL) {
		err = -ENXIO;
		goto done;
	}

	if (technology->pending_reply != NULL) {
		err = -EBUSY;
		goto done;
	}

	if (msg != NULL) {
		/*
		 * This is a bit of a trick. When msg is not NULL it means
		 * thats technology_enable was invoked from the manager API. Hence we save
		 * the state here.
		 */
		technology->enable_persistent = TRUE;
		save_state(technology);
	}

	__connman_rfkill_block(technology->type, FALSE);

	/*
	 * An empty device list means that devices in the technology
	 * were rfkill blocked. The unblock above will enable the devs.
	 */
	if (technology->device_list == NULL)
		return 0;

	for (list = technology->device_list; list; list = list->next) {
		struct connman_device *device = list->data;

		err = __connman_device_enable(device);
		/*
		 * err = 0 : Device was enabled right away.
		 * If atleast one device gets enabled, we consider
		 * the technology to be enabled.
		 */
		if (err == 0)
			ret = 0;
	}

done:
	if (ret == 0) {
		if (msg != NULL)
			g_dbus_send_reply(connection, msg, DBUS_TYPE_INVALID);
		return ret;
	}

	if (msg != NULL) {
		if (err == -EINPROGRESS) {
			technology->pending_reply = dbus_message_ref(msg);
			technology->pending_timeout = g_timeout_add_seconds(10,
					technology_pending_reply, technology);
		} else {
			reply = __connman_error_failed(msg, -err);
			if (reply != NULL)
				g_dbus_send_message(connection, reply);
		}
	}

	return err;
}
示例#15
0
static void process_properties_from_interface(struct generic_data *data,
						struct interface_data *iface)
{
	GSList *l;
	DBusMessage *signal;
	DBusMessageIter iter, dict, array;
	GSList *invalidated;

	if (iface->pending_prop == NULL)
		return;

	signal = dbus_message_new_signal(data->path,
			DBUS_INTERFACE_PROPERTIES, "PropertiesChanged");
	if (signal == NULL) {
		error("Unable to allocate new " DBUS_INTERFACE_PROPERTIES
						".PropertiesChanged signal");
		return;
	}

	iface->pending_prop = g_slist_reverse(iface->pending_prop);

	dbus_message_iter_init_append(signal, &iter);
	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,	&iface->name);
	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);

	invalidated = NULL;

	for (l = iface->pending_prop; l != NULL; l = l->next) {
		GDBusPropertyTable *p = l->data;

		if (p->get == NULL)
			continue;

		if (p->exists != NULL && !p->exists(p, iface->user_data)) {
			invalidated = g_slist_prepend(invalidated, p);
			continue;
		}

		append_property(iface, p, &dict);
	}

	dbus_message_iter_close_container(&iter, &dict);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
				DBUS_TYPE_STRING_AS_STRING, &array);
	for (l = invalidated; l != NULL; l = g_slist_next(l)) {
		GDBusPropertyTable *p = l->data;

		dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
								&p->name);
	}
	g_slist_free(invalidated);
	dbus_message_iter_close_container(&iter, &array);

	g_dbus_send_message(data->conn, signal);

	g_slist_free(iface->pending_prop);
	iface->pending_prop = NULL;
}
static void stream_state_changed(struct avdtp_stream *stream,
					avdtp_state_t old_state,
					avdtp_state_t new_state,
					struct avdtp_error *err,
					void *user_data)
{
	struct audio_device *dev = user_data;
	struct sink *sink = dev->sink;
	gboolean value;

	if (err)
		return;

	switch (new_state) {
	case AVDTP_STATE_IDLE:
		if (sink->disconnect) {
			DBusMessage *reply;
			struct pending_request *p;

			p = sink->disconnect;
			sink->disconnect = NULL;

			reply = dbus_message_new_method_return(p->msg);
			g_dbus_send_message(p->conn, reply);
			pending_request_free(dev, p);
		}

		if (sink->session) {
			avdtp_unref(sink->session);
			sink->session = NULL;
		}
		sink->stream = NULL;
		sink->cb_id = 0;
		break;
	case AVDTP_STATE_OPEN:
		if (old_state == AVDTP_STATE_CONFIGURED &&
				sink->state == SINK_STATE_CONNECTING) {
			value = TRUE;
			g_dbus_emit_signal(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Connected",
						DBUS_TYPE_INVALID);
			emit_property_changed(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Connected",
						DBUS_TYPE_BOOLEAN, &value);
		} else if (old_state == AVDTP_STATE_STREAMING) {
			value = FALSE;
			g_dbus_emit_signal(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Stopped",
						DBUS_TYPE_INVALID);
			emit_property_changed(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Playing",
						DBUS_TYPE_BOOLEAN, &value);
		}
		sink_set_state(dev, SINK_STATE_CONNECTED);
		break;
	case AVDTP_STATE_STREAMING:
		value = TRUE;
		g_dbus_emit_signal(dev->conn, dev->path, AUDIO_SINK_INTERFACE,
					"Playing", DBUS_TYPE_INVALID);
		emit_property_changed(dev->conn, dev->path,
					AUDIO_SINK_INTERFACE, "Playing",
					DBUS_TYPE_BOOLEAN, &value);
		sink_set_state(dev, SINK_STATE_PLAYING);
		break;
	case AVDTP_STATE_CONFIGURED:
	case AVDTP_STATE_CLOSING:
	case AVDTP_STATE_ABORTING:
	default:
		break;
	}

	sink->stream_state = new_state;
}
示例#17
0
static int session_policy_config_cb(struct connman_session *session,
                                    struct connman_session_config *config,
                                    void *user_data, int err)
{
    struct creation_data *creation_data = user_data;
    struct session_info *info, *info_last;
    DBusMessage *reply;

    DBG("session %p config %p", session, config);

    if (err < 0)
        goto err;

    session->policy_config = config;

    session->mark = session_mark++;
    session->index = -1;

    err = init_firewall_session(session);
    if (err < 0)
        goto err;

    err = init_routing_table(session);
    if (err < 0)
        goto err;

    info = session->info;
    info_last = session->info_last;

    if (session->policy_config->ecall)
        ecall_session = session;

    info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
    info->config.type = apply_policy_on_type(
                            session->policy_config->type,
                            creation_data->type);
    info->config.priority = session->policy_config->priority;
    info->config.roaming_policy = session->policy_config->roaming_policy;

    session->user_allowed_bearers = creation_data->allowed_bearers;
    creation_data->allowed_bearers = NULL;

    apply_policy_on_bearers(
        session->policy_config->allowed_bearers,
        session->user_allowed_bearers,
        &info->config.allowed_bearers);

    g_hash_table_replace(session_hash, session->session_path, session);

    DBG("add %s", session->session_path);

    if (!g_dbus_register_interface(connection, session->session_path,
                                   CONNMAN_SESSION_INTERFACE,
                                   session_methods, NULL, NULL,
                                   session, NULL)) {
        connman_error("Failed to register %s", session->session_path);
        g_hash_table_remove(session_hash, session->session_path);
        err = -EINVAL;
        goto err;
    }

    reply = g_dbus_create_reply(creation_data->pending,
                                DBUS_TYPE_OBJECT_PATH, &session->session_path,
                                DBUS_TYPE_INVALID);
    g_dbus_send_message(connection, reply);
    creation_data->pending = NULL;

    info_last->state = info->state;
    info_last->config.priority = info->config.priority;
    info_last->config.roaming_policy = info->config.roaming_policy;
    info_last->config.allowed_bearers = info->config.allowed_bearers;

    session->append_all = true;

    cleanup_creation_data(creation_data);

    session_activate(session);

    return 0;

err:
    reply = __connman_error_failed(creation_data->pending, -err);
    g_dbus_send_message(connection, reply);
    creation_data->pending = NULL;

    cleanup_session(session);
    cleanup_creation_data(creation_data);

    return err;
}
示例#18
0
static int session_create_cb(struct connman_session *session,
				struct connman_session_config *config,
				void *user_data, int err)
{
	DBusMessage *reply;
	struct user_config *user_config = user_data;
	struct session_info *info, *info_last;

	DBG("session %p config %p", session, config);

	if (err != 0)
		goto out;

	session->policy_config = config;

	info = session->info;
	info_last = session->info_last;

	if (session->policy_config->ecall == TRUE)
		ecall_session = session;

	info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
	info->config.type = apply_policy_on_type(
				session->policy_config->type,
				user_config->type);
	info->config.priority = session->policy_config->priority;
	info->config.roaming_policy = session->policy_config->roaming_policy;
	info->entry = NULL;

	session->user_allowed_bearers = user_config->allowed_bearers;
	user_config->allowed_bearers = NULL;

	err = apply_policy_on_bearers(
			session->policy_config->allowed_bearers,
			session->user_allowed_bearers,
			&info->config.allowed_bearers);
	if (err < 0)
		goto out;

	g_hash_table_replace(session_hash, session->session_path, session);

	DBG("add %s", session->session_path);

	if (g_dbus_register_interface(connection, session->session_path,
					CONNMAN_SESSION_INTERFACE,
					session_methods, NULL,
					NULL, session, NULL) == FALSE) {
		connman_error("Failed to register %s", session->session_path);
		g_hash_table_remove(session_hash, session->session_path);
		err = -EINVAL;
		goto out;
	}

	reply = g_dbus_create_reply(user_config->pending,
				DBUS_TYPE_OBJECT_PATH, &session->session_path,
				DBUS_TYPE_INVALID);
	g_dbus_send_message(connection, reply);
	user_config->pending = NULL;

	populate_service_list(session);

	info_last->state = info->state;
	info_last->config.priority = info->config.priority;
	info_last->config.roaming_policy = info->config.roaming_policy;
	info_last->entry = info->entry;
	info_last->config.allowed_bearers = info->config.allowed_bearers;

	session->append_all = TRUE;

	session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING);

out:
	if (err < 0) {
		reply = __connman_error_failed(user_config->pending, -err);
		g_dbus_send_message(connection, reply);

		free_session(session);
	}

	cleanup_user_config(user_config);

	return err;
}
示例#19
0
static gboolean cf_ss_control(int type, const char *sc,
				const char *sia, const char *sib,
				const char *sic, const char *dn,
				DBusMessage *msg, void *data)
{
	struct ofono_call_forwarding *cf = data;
	DBusConnection *conn = ofono_dbus_get_connection();
	int cls = BEARER_CLASS_SS_DEFAULT;
	int timeout = DEFAULT_NO_REPLY_TIMEOUT;
	int cf_type;
	DBusMessage *reply;
	struct ofono_phone_number ph;
	void *operation = NULL;

	/* Before we do anything, make sure we're actually initialized */
	if (cf == NULL)
		return FALSE;

	if (__ofono_call_forwarding_is_busy(cf)) {
		reply = __ofono_error_busy(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	DBG("Received call forwarding ss control request");

	DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
		type, sc, sia, sib, sic, dn);

	if (!strcmp(sc, "21"))
		cf_type = CALL_FORWARDING_TYPE_UNCONDITIONAL;
	else if (!strcmp(sc, "67"))
		cf_type = CALL_FORWARDING_TYPE_BUSY;
	else if (!strcmp(sc, "61"))
		cf_type = CALL_FORWARDING_TYPE_NO_REPLY;
	else if (!strcmp(sc, "62"))
		cf_type = CALL_FORWARDING_TYPE_NOT_REACHABLE;
	else if (!strcmp(sc, "002"))
		cf_type = CALL_FORWARDING_TYPE_ALL;
	else if (!strcmp(sc, "004"))
		cf_type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
	else
		return FALSE;

	if (strlen(sia) &&
		(type == SS_CONTROL_TYPE_QUERY ||
		type == SS_CONTROL_TYPE_ERASURE ||
		type == SS_CONTROL_TYPE_DEACTIVATION))
		goto error;

	/*
	 * Activation / Registration is figured context specific according to
	 * 22.030 Section 6.5.2 "The UE shall determine from the context
	 * whether, an entry of a single *, activation or registration
	 * was intended."
	 */
	if (type == SS_CONTROL_TYPE_ACTIVATION && strlen(sia) > 0)
		type = SS_CONTROL_TYPE_REGISTRATION;

	if (type == SS_CONTROL_TYPE_REGISTRATION &&
		!valid_phone_number_format(sia))
		goto error;

	if (strlen(sib) > 0) {
		long service_code;
		char *end;

		service_code = strtoul(sib, &end, 10);

		if (end == sib || *end != '\0')
			goto error;

		cls = mmi_service_code_to_bearer_class(service_code);

		if (cls == 0)
			goto error;
	}

	if (strlen(sic) > 0) {
		char *end;

		if  (type != SS_CONTROL_TYPE_REGISTRATION)
			goto error;

		if (cf_type != CALL_FORWARDING_TYPE_ALL &&
			cf_type != CALL_FORWARDING_TYPE_ALL_CONDITIONAL &&
			cf_type != CALL_FORWARDING_TYPE_NO_REPLY)
			goto error;

		timeout = strtoul(sic, &end, 10);

		if (end == sic || *end != '\0')
			goto error;

		if (timeout < 1 || timeout > 30)
			goto error;
	}

	switch (type) {
	case SS_CONTROL_TYPE_REGISTRATION:
		operation = cf->driver->registration;
		break;
	case SS_CONTROL_TYPE_ACTIVATION:
		operation = cf->driver->activation;
		break;
	case SS_CONTROL_TYPE_DEACTIVATION:
		operation = cf->driver->deactivation;
		break;
	case SS_CONTROL_TYPE_ERASURE:
		operation = cf->driver->erasure;
		break;
	case SS_CONTROL_TYPE_QUERY:
		operation = cf->driver->query;
		break;
	}

	if (operation == NULL) {
		reply = __ofono_error_not_implemented(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	cf->ss_req = g_try_new0(struct cf_ss_request, 1);

	if (cf->ss_req == NULL) {
		reply = __ofono_error_failed(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	cf->ss_req->ss_type = type;
	cf->ss_req->cf_type = cf_type;
	cf->ss_req->cls = cls;

	cf->pending = dbus_message_ref(msg);

	switch (cf->ss_req->cf_type) {
	case CALL_FORWARDING_TYPE_ALL:
		cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
		cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
		break;
	case CALL_FORWARDING_TYPE_ALL_CONDITIONAL:
		cf->query_next = CALL_FORWARDING_TYPE_BUSY;
		cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
		break;
	default:
		cf->query_next = cf->ss_req->cf_type;
		cf->query_end = cf->ss_req->cf_type;
		break;
	}

	/*
	 * Some modems don't understand all classes very well, particularly
	 * the older models.  So if the bearer class is the default, we
	 * just use the more commonly understood value of 7 since BEARER_SMS
	 * is not applicable to CallForwarding conditions according to 22.004
	 * Annex A
	 */
	if (cls == BEARER_CLASS_SS_DEFAULT)
		cls = BEARER_CLASS_DEFAULT;

	switch (cf->ss_req->ss_type) {
	case SS_CONTROL_TYPE_REGISTRATION:
		string_to_phone_number(sia, &ph);
		cf->driver->registration(cf, cf_type, cls, &ph, timeout,
					cf_ss_control_callback, cf);
		break;
	case SS_CONTROL_TYPE_ACTIVATION:
		cf->driver->activation(cf, cf_type, cls, cf_ss_control_callback,
					cf);
		break;
	case SS_CONTROL_TYPE_DEACTIVATION:
		cf->driver->deactivation(cf, cf_type, cls,
					cf_ss_control_callback, cf);
		break;
	case SS_CONTROL_TYPE_ERASURE:
		cf->driver->erasure(cf, cf_type, cls, cf_ss_control_callback,
					cf);
		break;
	case SS_CONTROL_TYPE_QUERY:
		ss_set_query_next_cf_cond(cf);
		break;
	}

	return TRUE;

error:
	reply = __ofono_error_invalid_format(msg);
	g_dbus_send_message(conn, reply);
	return TRUE;
}
示例#20
0
文件: ussd.c 项目: endocode/ofono
void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
			const unsigned char *data, int data_len)
{
	DBusConnection *conn = ofono_dbus_get_connection();
	const char *ussdstr = "USSD";
	char *utf8_str = NULL;
	const char *str;
	const char sig[] = { DBUS_TYPE_STRING, 0 };
	DBusMessage *reply;
	DBusMessageIter iter;
	DBusMessageIter variant;

	DBG("status: %d %s, state: %d %s",
		status, ussd_status_name(status),
		ussd->state, ussd_state_name(ussd->state));

	if (ussd->req &&
			(status == OFONO_USSD_STATUS_NOTIFY ||
			status == OFONO_USSD_STATUS_TERMINATED ||
			status == OFONO_USSD_STATUS_TIMED_OUT ||
			status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
					dcs, data, data_len);

		ussd_change_state(ussd, USSD_STATE_IDLE);
		return;
	}

	if (status == OFONO_USSD_STATUS_TERMINATED) {
		ussd_change_state(ussd, USSD_STATE_IDLE);

		if (ussd->pending == NULL)
			return;

		reply = __ofono_error_network_terminated(ussd->pending);
		goto out;
	}

	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
		ussd_change_state(ussd, USSD_STATE_IDLE);

		if (ussd->pending == NULL)
			return;

		reply = __ofono_error_not_supported(ussd->pending);
		goto out;
	}

	if (status == OFONO_USSD_STATUS_TIMED_OUT) {
		ussd_change_state(ussd, USSD_STATE_IDLE);

		if (ussd->pending == NULL)
			return;

		reply = __ofono_error_timed_out(ussd->pending);
		goto out;
	}

	if (data && data_len > 0)
		utf8_str = ussd_decode(dcs, data_len, data);

	str = utf8_str;

	/* TODO: Rework this in the Agent framework */
	if (ussd->state == USSD_STATE_ACTIVE) {

		reply = dbus_message_new_method_return(ussd->pending);

		if (str == NULL)
			str = "";

		dbus_message_iter_init_append(reply, &iter);

		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
						&ussdstr);

		dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig,
							&variant);

		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
						&str);

		dbus_message_iter_close_container(&iter, &variant);

		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
			ussd_change_state(ussd, USSD_STATE_USER_ACTION);
		else
			ussd_change_state(ussd, USSD_STATE_IDLE);

	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
		reply = dbus_message_new_method_return(ussd->pending);

		if (str == NULL)
			str = "";

		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
						DBUS_TYPE_INVALID);

		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
			ussd_change_state(ussd, USSD_STATE_USER_ACTION);
		else
			ussd_change_state(ussd, USSD_STATE_IDLE);
	} else if (ussd->state == USSD_STATE_IDLE) {
		const char *signal_name;
		const char *path = __ofono_atom_get_path(ussd->atom);
		int new_state;

		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED) {
			new_state = USSD_STATE_USER_ACTION;
			signal_name = "RequestReceived";
		} else {
			new_state = USSD_STATE_IDLE;
			signal_name = "NotificationReceived";
		}

		if (str == NULL)
			str = "";

		g_dbus_emit_signal(conn, path,
			OFONO_SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);

		ussd_change_state(ussd, new_state);
		goto free;
	} else {
		ofono_error("Received an unsolicited USSD but can't handle.");
		DBG("USSD is: status: %d, %s", status, str);

		goto free;
	}

out:
	g_dbus_send_message(conn, reply);

	dbus_message_unref(ussd->pending);
	ussd->pending = NULL;

free:
	g_free(utf8_str);
}
示例#21
0
static void sms_history_sms_send_status(
					struct ofono_history_context *context,
					const struct ofono_uuid *uuid,
					time_t when,
					enum ofono_history_sms_status s)
{
	if ((s == OFONO_HISTORY_SMS_STATUS_DELIVERED)
			|| (s == OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED)) {

		DBusMessage *signal;
		DBusMessageIter iter;
		DBusMessageIter dict;
		const char *uuid_str;
		char *msg_uuid_str;
		size_t msg_len;
		struct ofono_atom *atom;
		const char *path;
		DBusConnection *conn;
		int delivered;

		atom = __ofono_modem_find_atom(context->modem,
						OFONO_ATOM_TYPE_SMS);
		if (atom == NULL)
			return;

		path = __ofono_atom_get_path(atom);
		if (path == NULL)
			return;

		conn = ofono_dbus_get_connection();
		if (conn == NULL)
			return;

		delivered = (s == OFONO_HISTORY_SMS_STATUS_DELIVERED);

		uuid_str = ofono_uuid_to_str(uuid);
		/* sizeof adds extra space for one '\0' */
		msg_len = strlen(path) + sizeof(msg_prefix)
				+ strlen(uuid_str);

		msg_uuid_str = g_try_malloc(msg_len);
		if (msg_uuid_str == NULL)
			return;

		/* modem path + msg_prefix + UUID as string */
		snprintf(msg_uuid_str, msg_len, "%s%s%s", path,
				msg_prefix, uuid_str);

		DBG("SMS %s delivery success: %d", msg_uuid_str, delivered);

		signal = dbus_message_new_signal(path,
					OFONO_MESSAGE_MANAGER_INTERFACE,
					"StatusReport");
		if (signal != NULL) {
			dbus_message_iter_init_append(signal, &iter);
			dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
							&msg_uuid_str);

			dbus_message_iter_open_container(
					&iter,
					DBUS_TYPE_ARRAY,
					OFONO_PROPERTIES_ARRAY_SIGNATURE,
					&dict);
			ofono_dbus_dict_append(&dict, "Delivered",
						DBUS_TYPE_BOOLEAN,
						&delivered);
			dbus_message_iter_close_container(&iter, &dict);

			g_dbus_send_message(conn, signal);
		}

		g_free(msg_uuid_str);
	}
}
示例#22
0
文件: gateway.c 项目: intgr/bluez
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	int ch;
	sdp_list_t *protos, *classes;
	uuid_t uuid;
	GIOChannel *io;
	GError *gerr = NULL;

	if (err < 0) {
		error("Unable to get service record: %s (%d)", strerror(-err),
					-err);
		goto fail;
	}

	if (!recs || !recs->data) {
		error("No records found");
		err = -EIO;
		goto fail;
	}

	if (sdp_get_service_classes(recs->data, &classes) < 0) {
		error("Unable to get service classes from record");
		err = -EINVAL;
		goto fail;
	}

	if (sdp_get_access_protos(recs->data, &protos) < 0) {
		error("Unable to get access protocols from record");
		err = -ENODATA;
		goto fail;
	}

	gw->version = get_remote_profile_version(recs->data);
	if (gw->version == 0) {
		error("Unable to get profile version from record");
		err = -EINVAL;
		goto fail;
	}

	memcpy(&uuid, classes->data, sizeof(uuid));
	sdp_list_free(classes, free);

	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
			uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
		sdp_list_free(protos, NULL);
		error("Invalid service record or not HFP");
		err = -EIO;
		goto fail;
	}

	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
	sdp_list_free(protos, NULL);
	if (ch <= 0) {
		error("Unable to extract RFCOMM channel from service record");
		err = -EIO;
		goto fail;
	}

	io = bt_io_connect(rfcomm_connect_cb, dev, NULL, &gerr,
				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
				BT_IO_OPT_DEST_BDADDR, &dev->dst,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_CHANNEL, ch,
				BT_IO_OPT_INVALID);
	if (!io) {
		error("Unable to connect: %s", gerr->message);
		goto fail;
	}

	g_io_channel_unref(io);
	return;

fail:
	if (gw->msg) {
		DBusMessage *reply = btd_error_failed(gw->msg,
					gerr ? gerr->message : strerror(-err));
		g_dbus_send_message(btd_get_dbus_connection(), reply);
	}

	gateway_close(dev);

	if (gerr)
		g_error_free(gerr);
}
示例#23
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);
}
示例#24
0
文件: sms.c 项目: AndriusA/ofono
static void dispatch_text_message(struct ofono_sms *sms,
					const struct ofono_uuid *uuid,
					const char *message,
					enum sms_class cls,
					const struct sms_address *addr,
					const struct sms_scts *scts)
{
	struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
	DBusConnection *conn = ofono_dbus_get_connection();
	const char *path = __ofono_atom_get_path(sms->atom);
	DBusMessage *signal;
	DBusMessageIter iter;
	DBusMessageIter dict;
	char buf[128];
	const char *signal_name;
	time_t ts;
	struct tm remote;
	struct tm local;
	const char *str = buf;
	ofono_sms_text_notify_cb_t notify;
	struct sms_handler *h;
	GSList *l;

	if (message == NULL)
		return;

	if (cls == SMS_CLASS_0)
		signal_name = "ImmediateMessage";
	else
		signal_name = "IncomingMessage";

	signal = dbus_message_new_signal(path, OFONO_MESSAGE_MANAGER_INTERFACE,
						signal_name);

	if (signal == NULL)
		return;

	dbus_message_iter_init_append(signal, &iter);

	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &message);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
					OFONO_PROPERTIES_ARRAY_SIGNATURE,
						&dict);

	ts = sms_scts_to_time(scts, &remote);
	localtime_r(&ts, &local);

	strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", &local);
	buf[127] = '\0';
	ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING, &str);

	strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", &remote);
	buf[127] = '\0';
	ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING, &str);

	str = sms_address_to_string(addr);
	ofono_dbus_dict_append(&dict, "Sender", DBUS_TYPE_STRING, &str);

	dbus_message_iter_close_container(&iter, &dict);

	g_dbus_send_message(conn, signal);

	if (cls == SMS_CLASS_0)
		return;

	for (l = sms->text_handlers->items; l; l = l->next) {
		h = l->data;
		notify = h->item.notify;

		notify(str, &remote, &local, message, h->item.notify_data);
	}

	__ofono_history_sms_received(modem, uuid, str, &remote, &local,
					message);
}
示例#25
0
static gboolean cb_ss_control(int type, const char *sc,
				const char *sia, const char *sib,
				const char *sic, const char *dn,
				DBusMessage *msg, void *data)
{
	struct ofono_call_barring *cb = data;
	DBusConnection *conn = ofono_dbus_get_connection();
	int cls = BEARER_CLASS_DEFAULT;
	const char *fac;
	DBusMessage *reply;
	void *operation = NULL;
	int i;

	if (cb->pending) {
		reply = __ofono_error_busy(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	DBG("Received call barring ss control request");

	DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
		type, sc, sia, sib, sic, dn);

	fac = cb_ss_service_to_fac(sc);
	if (!fac)
		return FALSE;

	cb_set_query_bounds(cb, fac, type == SS_CONTROL_TYPE_QUERY);

	i = 0;
	while (cb_locks[i].name && strcmp(cb_locks[i].fac, fac))
		i++;

	cb->ss_req_lock = i;

	if (strlen(sic) > 0)
		goto bad_format;

	if (strlen(dn) > 0)
		goto bad_format;

	if (type != SS_CONTROL_TYPE_QUERY && !is_valid_pin(sia, PIN_TYPE_NET))
		goto bad_format;

	switch (type) {
	case SS_CONTROL_TYPE_ACTIVATION:
	case SS_CONTROL_TYPE_DEACTIVATION:
	case SS_CONTROL_TYPE_REGISTRATION:
	case SS_CONTROL_TYPE_ERASURE:
		operation = cb->driver->set;
		break;
	case SS_CONTROL_TYPE_QUERY:
		operation = cb->driver->query;
		break;
	default:
		break;
	}

	if (!operation) {
		reply = __ofono_error_not_implemented(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	/* According to 27.007, AG, AC and AB only work with mode = 0
	 * We support query by querying all relevant types, since we must
	 * do this for the deactivation case anyway
	 */
	if ((!strcmp(fac, "AG") || !strcmp(fac, "AC") || !strcmp(fac, "AB")) &&
		(type == SS_CONTROL_TYPE_ACTIVATION ||
			type == SS_CONTROL_TYPE_REGISTRATION))
		goto bad_format;

	if (strlen(sib) > 0) {
		long service_code;
		char *end;

		service_code = strtoul(sib, &end, 10);

		if (end == sib || *end != '\0')
			goto bad_format;

		cls = mmi_service_code_to_bearer_class(service_code);

		if (cls == 0)
			goto bad_format;
	}

	cb->ss_req_cls = cls;
	cb->pending = dbus_message_ref(msg);

	switch (type) {
	case SS_CONTROL_TYPE_ACTIVATION:
	case SS_CONTROL_TYPE_REGISTRATION:
		cb->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
		cb->driver->set(cb, fac, 1, sia, cls,
				cb_ss_set_lock_callback, cb);
		break;
	case SS_CONTROL_TYPE_ERASURE:
	case SS_CONTROL_TYPE_DEACTIVATION:
		cb->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
		cb->driver->set(cb, fac, 0, sia, cls,
				cb_ss_set_lock_callback, cb);
		break;
	case SS_CONTROL_TYPE_QUERY:
		cb->ss_req_type = SS_CONTROL_TYPE_QUERY;
		cb_ss_query_next_lock(cb);
		break;
	}

	return TRUE;

bad_format:
	reply = __ofono_error_invalid_format(msg);
	g_dbus_send_message(conn, reply);
	return TRUE;
}
static void error_failed(DBusConnection *conn, DBusMessage *msg,
							const char *desc)
{
	DBusMessage *reply = btd_error_failed(msg, desc);
	g_dbus_send_message(conn, reply);
}
示例#27
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);
}