Exemple #1
0
static void pan_create_nap(struct bluetooth_pan *pan)
{
	struct connman_device *device;
	const char* role;
	const char *adapter;

	role = proxy_get_role(pan->btdevice_proxy);
	if (!role) {
		pan_remove_nap(pan);
		return;
	}

	adapter = proxy_get_string(pan->btdevice_proxy, "Adapter");

	if (!adapter)
		return;

	device = g_hash_table_lookup(devices, adapter);

	if (!device || !connman_device_get_powered(device))
		return;

	if (!pan->network) {
		const char *address;
		char ident[BLUETOOTH_ADDR_LEN * 2 + 1];
		const char *name, *path;

		address = proxy_get_string(pan->btdevice_proxy, "Address");
		if (!address) {
			connman_warn("Bluetooth device address missing");
			return;
		}

		address2ident(address, ident);

		pan->network = connman_network_create(ident,
				CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN);

		name = proxy_get_string(pan->btdevice_proxy, "Alias");
		path = g_dbus_proxy_get_path(pan->btnetwork_proxy);

		DBG("network %p %s %s", pan->network, path, name);

		if (!pan->network) {
			connman_warn("Bluetooth network %s creation failed",
					path);
			return;
		}

		connman_network_set_data(pan->network, pan);
		connman_network_set_name(pan->network, name);
		connman_network_set_group(pan->network, ident);
	}

	pan->pan_role = role;
	connman_device_add_network(device, pan->network);

	if (pan_connect(pan, NULL))
		DBG("network %p already connected", pan->network);
}
Exemple #2
0
static int bluetooth_init(void)
{
	connection = connman_dbus_get_connection();
	if (!connection)
		goto out;

	if (connman_technology_driver_register(&tech_driver) < 0) {
		connman_warn("Failed to initialize technology for Bluez 5");
		goto out;
	}

	devices = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
			device_free);

	if (connman_device_driver_register(&device_driver) < 0) {
		connman_warn("Failed to initialize device driver for "
				BLUEZ_SERVICE);
		connman_technology_driver_unregister(&tech_driver);
		goto out;
	}

	if (connman_network_driver_register(&network_driver) < 0) {
		connman_technology_driver_unregister(&tech_driver);
		connman_device_driver_unregister(&device_driver);
		goto out;
	}

	networks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
			pan_free);

	client = g_dbus_client_new(connection, BLUEZ_SERVICE, BLUEZ_PATH);
	if (!client) {
		connman_warn("Failed to initialize D-Bus client for "
				BLUEZ_SERVICE);
		goto out;
	}

	g_dbus_client_set_proxy_handlers(client, object_added, object_removed,
			NULL, NULL);

	return 0;

out:
	if (networks)
		g_hash_table_destroy(networks);

	if (devices)
		g_hash_table_destroy(devices);

	if (client)
		g_dbus_client_unref(client);

	if (connection)
		dbus_connection_unref(connection);

	return -EIO;
}
Exemple #3
0
int __connman_device_disconnect(struct connman_device *device)
{
	GHashTableIter iter;
	gpointer key, value;

	DBG("device %p", device);

	connman_device_set_disconnected(device, TRUE);

	g_hash_table_iter_init(&iter, device->networks);

	while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
		struct connman_network *network = value;

		if (connman_network_get_connecting(network) == TRUE) {
			/*
			 * Skip network in the process of connecting.
			 * This is a workaround for WiFi networks serviced
			 * by the supplicant plugin that hold a reference
			 * to the network.  If we disconnect the network
			 * here then the referenced object will not be
			 * registered and usage (like launching DHCP client)
			 * will fail.  There is nothing to be gained by
			 * removing the network here anyway.
			 */
			connman_warn("Skipping disconnect of %s, network is connecting.",
				connman_network_get_identifier(network));
			continue;
		}

		__connman_network_disconnect(network);
	}

	return 0;
}
static void device_disable_cb(const DBusError *error, void *user_data)
{
	char *path = user_data;
	struct connman_device *device;
	GHashTableIter iter;
	gpointer key, value;

	device = g_hash_table_lookup(devices, path);
	if (device == NULL) {
		DBG("device already removed");
		goto out;
	}

	if (dbus_error_is_set(error) == TRUE) {
		connman_warn("Bluetooth device %s not disabled: %s",
				path, error->message);
		goto out;
	}

	DBG("device %p %s", device, path);
	connman_device_set_powered(device, FALSE);

	g_hash_table_iter_init(&iter, networks);
	while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
		struct bluetooth_pan *pan = value;

		if (connman_network_get_device(pan->network) == device) {
			DBG("disable network %p", pan->network);
			connman_device_remove_network(device, pan->network);
		}
	}

out:
	g_free(path);
}
Exemple #5
0
static void object_removed(GDBusProxy *proxy, void *user_data)
{
	const char *interface, *path;

	interface = g_dbus_proxy_get_interface(proxy);
	if (!interface) {
		connman_warn("Interface or proxy missing when removing "
							"bluetooth object");
		return;
	}

	if (strcmp(interface, "org.bluez.Adapter1") == 0) {
		path = g_dbus_proxy_get_path(proxy);
		DBG("%s %s", interface, path);

		g_hash_table_remove(devices, path);
	}

	if (strcmp(interface, "org.bluez.Network1") == 0) {
		path = g_dbus_proxy_get_path(proxy);
		DBG("%s %s", interface, path);

		g_hash_table_remove(networks, path);
	}

}
Exemple #6
0
static void add_keys(struct vpn_config_provider *config_provider,
			GKeyFile *keyfile, const char *group)
{
	char **avail_keys;
	gsize nb_avail_keys, i;

	avail_keys = g_key_file_get_keys(keyfile, group, &nb_avail_keys, NULL);
	if (!avail_keys)
		return;

	for (i = 0 ; i < nb_avail_keys; i++) {
		char *value = g_key_file_get_value(keyfile, group,
						avail_keys[i], NULL);
		if (!value) {
			connman_warn("Cannot find value for %s",
							avail_keys[i]);
			continue;
		}

		set_string(config_provider, avail_keys[i], value);
		g_free(value);
	}

	g_strfreev(avail_keys);
}
Exemple #7
0
int __connman_firewall_init(void)
{
	int err;

	DBG("");

	if (getenv("CONNMAN_NFTABLES_DEBUG"))
		debug_enabled = true;

	/*
	 * EAFNOSUPPORT is return whenever the nf_tables_ipv4 hasn't been
	 * loaded yet. ENOENT is return in case the table is missing.
	 */
	err = cleanup_table_and_chains();
	if (err < 0 && (err != EAFNOSUPPORT && err != -ENOENT)) {
		connman_warn("initializing nftable failed with '%s' %d. Check if kernel module nf_tables_ipv4 is missing\n",
			strerror(-err), err);
		return err;
	}

	nft_info = g_new0(struct nftables_info, 1);
	err = create_table_and_chains(nft_info);
	if (err) {
		g_free(nft_info);
		nft_info = NULL;
	}

	return err;
}
Exemple #8
0
static gboolean set_connected(gpointer user_data)
{
	struct connman_network *network = user_data;
	struct connman_service *service;

	service = __connman_service_lookup_from_network(network);

	if (network->connected == TRUE) {
		struct connman_element *element;
		enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;

		switch (network->protocol) {
		case CONNMAN_NETWORK_PROTOCOL_UNKNOWN:
			connman_warn("%s: unknown protocol", __func__);
			return 0;
		case CONNMAN_NETWORK_PROTOCOL_IP:
			type = CONNMAN_ELEMENT_TYPE_DHCP;
			break;
		case CONNMAN_NETWORK_PROTOCOL_PPP:
			type = CONNMAN_ELEMENT_TYPE_PPP;
			break;
		}

		__connman_device_increase_connections(network->device);

		__connman_device_set_network(network->device, network);

		connman_device_set_disconnected(network->device, FALSE);

		element = connman_element_create(NULL);
		if (element != NULL) {
			element->type  = type;
			element->index = network->element.index;

			if (connman_element_register(element,
						&network->element) < 0)
				connman_element_unref(element);

			__connman_service_indicate_state(service,
					CONNMAN_SERVICE_STATE_CONFIGURATION);
		}
	} else {
		connman_element_unregister_children(&network->element);

		__connman_device_set_network(network->device, NULL);
		network->hidden = FALSE;

		__connman_device_decrease_connections(network->device);

		__connman_service_indicate_state(service,
						CONNMAN_SERVICE_STATE_IDLE);
	}

	network->connecting = FALSE;

	connman_network_set_associating(network, FALSE);

	return FALSE;
}
Exemple #9
0
static int jolla_gps_init()
{
    DBG("");

    connection = connman_dbus_get_connection();
    if (connection == NULL) {
        connman_warn("Failed to get dbus connection");
        return -EIO;
    }

    watch = g_dbus_add_service_watch(connection, JOLLA_SERVICE, jolla_gps_connect,
                                     jolla_gps_disconnect, NULL, NULL);
    if (watch == 0) {
        connman_warn("Failed to add jolla service watcher");
        dbus_connection_unref(connection);
        return -EIO;
    }

    device_watch = g_dbus_add_signal_watch(connection, JOLLA_SERVICE, JOLLA_DEVICE_PATH,
                                           JOLLA_DEVICE_INTERFACE, PROPERTY_CHANGED,
                                           device_changed, NULL, NULL);
    if (device_watch == 0) {
        connman_warn("Failed to add jolla device property changed signal watcher");
        g_dbus_remove_watch(connection, watch);
        dbus_connection_unref(connection);
        return -EIO;
    }

    if (connman_technology_driver_register(&tech_driver) < 0) {
        connman_warn("Failed to initialize technology for Jolla GPS");
        g_dbus_remove_watch(connection, device_watch);
        g_dbus_remove_watch(connection, watch);
        dbus_connection_unref(connection);
        return -EIO;
    }

    if (connman_device_driver_register(&device_driver) < 0) {
        connman_warn("Failed to initialize device driver for " JOLLA_SERVICE);
        connman_technology_driver_unregister(&tech_driver);
        g_dbus_remove_watch(connection, device_watch);
        g_dbus_remove_watch(connection, watch);
        dbus_connection_unref(connection);
        return -EIO;
    }

    jolla_gps_device = connman_device_create("gps", CONNMAN_DEVICE_TYPE_GPS);
    if (jolla_gps_device == NULL) {
        connman_warn("Failed to creat GPS device");
        return -ENODEV;
    }

    if (connman_device_register(jolla_gps_device) < 0) {
        connman_warn("Failed to register GPS device");
        connman_device_unref(jolla_gps_device);
        jolla_gps_device = NULL;
        return -EIO;
    }

    return 0;
}
Exemple #10
0
static gboolean force_kill_timeout(gpointer user_data)
{
	pid_t pid = GPOINTER_TO_INT(user_data);
	if (pid > 0) {
		if (kill(pid, SIGKILL) == 0)
			connman_warn("killing pid %d by force", pid);
	}

	return FALSE;
}
static gboolean valid_loopback(int sk, struct ifreq *ifr)
{
	struct sockaddr_in *addr;
	int err;
	char buf[INET_ADDRSTRLEN];

	/* It is possible to end up in situations in which the
	 * loopback interface is up but has no valid address. In that
	 * case, we expect EADDRNOTAVAIL and should return FALSE.
	 */

	err = ioctl(sk, SIOCGIFADDR, ifr);
	if (err < 0) {
		err = -errno;
		connman_error("Getting address failed (%s)", strerror(-err));
		return err != -EADDRNOTAVAIL ? TRUE : FALSE;
	}

	addr = (struct sockaddr_in *) &ifr->ifr_addr;
	if (addr->sin_addr.s_addr != loopback_address) {
		connman_warn("Invalid loopback address %s",
			inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)));
		return FALSE;
	}

	err = ioctl(sk, SIOCGIFNETMASK, ifr);
	if (err < 0) {
		err = -errno;
		connman_error("Getting netmask failed (%s)", strerror(-err));
		return TRUE;
	}

	addr = (struct sockaddr_in *) &ifr->ifr_netmask;
	if (addr->sin_addr.s_addr != loopback_netmask) {
		connman_warn("Invalid loopback netmask %s",
			inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)));
		return FALSE;
	}

	return TRUE;
}
Exemple #12
0
static int load_config(struct vpn_config *config, char *path, enum what action)
{
	GKeyFile *keyfile;
	gsize length;
	char **groups;
	char *str;
	bool found = false;
	int i;

	DBG("config %p", config);

	keyfile = __connman_storage_load_provider_config(config->ident);
	if (!keyfile)
		return -EIO;

	/* Verify keys validity of the global section */
	check_keys(keyfile, "global", config_possible_keys);

	str = __vpn_config_get_string(keyfile, "global", CONFIG_KEY_NAME, NULL);
	if (str) {
		g_free(config->name);
		config->name = str;
	}

	str = __vpn_config_get_string(keyfile, "global", CONFIG_KEY_DESC, NULL);
	if (str) {
		g_free(config->description);
		config->description = str;
	}

	groups = g_key_file_get_groups(keyfile, &length);

	for (i = 0; groups[i]; i++) {
		if (g_str_has_prefix(groups[i], "provider_")) {
			int ret = load_provider(keyfile, groups[i], config,
						action);
			if (ret == 0 || ret == -EALREADY)
				found = true;
		}
	}

	if (!found)
		connman_warn("Config file %s/%s.config does not contain any "
			"configuration that can be provisioned!",
			path, config->ident);

	g_strfreev(groups);

	g_key_file_free(keyfile);

	return 0;
}
Exemple #13
0
int supplicant_start(struct connman_device *device)
{
	struct supplicant_task *task;
	int err;

	_DBG_SUPPLICANT("device %p", device);

	task = g_try_new0(struct supplicant_task, 1);
	if (task == NULL)
		return -ENOMEM;

	task->ifindex = connman_device_get_index(device);
	task->ifname = connman_inet_ifname(task->ifindex);

	if (task->ifname == NULL) {
		err = -ENOMEM;
		goto failed;
	}

	task->mac80211 = connman_inet_is_mac80211(task->ifindex);
	if (task->mac80211 == FALSE)
		connman_warn("Enabling quirks for unsupported driver");

	task->range = g_try_malloc0(sizeof(struct iw_range));
	if (task->range == NULL) {
		err = -ENOMEM;
		goto failed;
	}

	err = get_range(task);
	if (err < 0)
		goto failed;

	task->device = connman_device_ref(device);

	task->created = FALSE;
	task->scanning = FALSE;
	task->state = WPA_INVALID;
	task->disconnecting = FALSE;
	task->pending_network = NULL;

	task_list = g_slist_append(task_list, task);

	return create_interface(task);

failed:
	g_free(task->range);
	g_free(task->ifname);
	g_free(task);

	return err;
}
Exemple #14
0
static void check_config(GKeyFile *config)
{
	char **keys;
	int j;

	if (!config)
		return;

	keys = g_key_file_get_groups(config, NULL);

	for (j = 0; keys && keys[j]; j++) {
		if (g_strcmp0(keys[j], "General") != 0)
			connman_warn("Unknown group %s in %s",
						keys[j], MAINFILE);
	}

	g_strfreev(keys);

	keys = g_key_file_get_keys(config, "General", NULL, NULL);

	for (j = 0; keys && keys[j]; j++) {
		bool found;
		int i;

		found = false;
		for (i = 0; supported_options[i]; i++) {
			if (g_strcmp0(keys[j], supported_options[i]) == 0) {
				found = true;
				break;
			}
		}
		if (!found && !supported_options[i])
			connman_warn("Unknown option %s in %s",
						keys[j], MAINFILE);
	}

	g_strfreev(keys);
}
Exemple #15
0
static void check_config(GKeyFile *config)
{
	char **keys;
	int j;

	if (config == NULL)
		return;

	keys = g_key_file_get_groups(config, NULL);

	for (j = 0; keys != NULL && keys[j] != NULL; j++) {
		if (g_strcmp0(keys[j], "General") != 0)
			connman_warn("Unknown group %s in %s",
						keys[j], MAINFILE);
	}

	g_strfreev(keys);

	keys = g_key_file_get_keys(config, "General", NULL, NULL);

	for (j = 0; keys != NULL && keys[j] != NULL; j++) {
		connman_bool_t found;
		int i;

		found = FALSE;
		for (i = 0; supported_options[i] != NULL; i++) {
			if (g_strcmp0(keys[j], supported_options[i]) == 0) {
				found = TRUE;
				break;
			}
		}
		if (found == FALSE && supported_options[i] == NULL)
			connman_warn("Unknown option %s in %s",
						keys[j], MAINFILE);
	}

	g_strfreev(keys);
}
Exemple #16
0
void __connman_firewall_cleanup(void)
{
	int err;

	DBG("");

	err = cleanup_table_and_chains();
	if (err < 0)
		connman_warn("cleanup table and chains failed with '%s' %d\n",
			strerror(-err), err);

	g_free(nft_info);
	nft_info = NULL;
}
Exemple #17
0
static int agent_send_cancel(struct connman_agent *agent)
{
	DBusMessage *message;

	if (agent_sender == NULL || agent == NULL || agent->driver == NULL)
		return 0;

	message = dbus_message_new_method_call(agent_sender, agent_path,
			agent->driver->interface, "Cancel");
	if (message != NULL) {
		dbus_message_set_no_reply(message, TRUE);
		g_dbus_send_message(connection, message);
		return 0;
	}

	connman_warn("Failed to send Cancel message to agent");
	return -ESRCH;
}
Exemple #18
0
static int vc_device_flags(struct vpn_provider *provider)
{
	const char *option;

	option = vpn_provider_get_string(provider, "VPNC.DeviceType");
	if (!option) {
		return IFF_TUN;
	}

	if (g_str_equal(option, "tap")) {
		return IFF_TAP;
	}

	if (!g_str_equal(option, "tun")) {
		connman_warn("bad VPNC.DeviceType value, falling back to tun");
	}

	return IFF_TUN;
}
Exemple #19
0
static bool check_reply_has_dict(DBusMessage *reply)
{
	const char *signature = 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;

	if (dbus_message_has_signature(reply, signature))
		return true;

	connman_warn("Reply %s to %s from %s has wrong signature %s",
			signature,
			dbus_message_get_interface(reply),
			dbus_message_get_sender(reply),
			dbus_message_get_signature(reply));

	return false;
}
Exemple #20
0
static void handle_service_state_offline(struct connman_service *service,
        struct connman_service_info *info)
{
    GSList *list;

    for (list = info->sessions; list; list = list->next) {
        struct connman_session *session = list->data;

        if (session->service != service) {
            connman_warn("session %p should have session %p assigned",
                         session, service);
            continue;
        }

        DBG("session %p remove service %p", session, service);

        session->service = NULL;
        update_session_state(session);
    }
}
Exemple #21
0
static void device_enable_cb(const DBusError *error, void *user_data)
{
	char *path = user_data;
	struct connman_device *device;

	device = g_hash_table_lookup(devices, path);
	if (!device) {
		DBG("device already removed");
		goto out;
	}

	if (dbus_error_is_set(error)) {
		connman_warn("Bluetooth device %s not enabled %s",
				path, error->message);
		goto out;
	}

	enable_device(device, path);
out:
	g_free(path);
}
Exemple #22
0
static void check_keys(GKeyFile *keyfile, const char *group,
			const char **possible_keys)
{
	char **avail_keys;
	gsize nb_avail_keys, i, j;

	avail_keys = g_key_file_get_keys(keyfile, group, &nb_avail_keys, NULL);
	if (!avail_keys)
		return;

	for (i = 0 ; i < nb_avail_keys; i++) {
		for (j = 0; possible_keys[j] ; j++)
			if (g_strcmp0(avail_keys[i], possible_keys[j]) == 0)
				break;

		if (!possible_keys[j])
			connman_warn("Unknown configuration key %s in [%s]",
					avail_keys[i], group);
	}

	g_strfreev(avail_keys);
}
static void device_enable_cb(const DBusError *error, void *user_data)
{
	char *path = user_data;
	struct connman_device *device;
	GHashTableIter iter;
	gpointer key, value;

	device = g_hash_table_lookup(devices, path);
	if (device == NULL) {
		DBG("device already removed");
		goto out;
	}

	if (dbus_error_is_set(error) == TRUE) {
		connman_warn("Bluetooth device %s not enabled %s",
				path, error->message);
		goto out;
	}

	DBG("device %p %s", device, path);

	connman_device_set_powered(device, TRUE);

	g_hash_table_iter_init(&iter, networks);
	while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
		struct bluetooth_pan *pan = value;

		if (g_strcmp0(proxy_get_string(pan->btdevice_proxy, "Adapter"),
						path) == 0) {

			DBG("enable network %p", pan->network);
			pan_create_nap(pan);
		}
	}

out:
	g_free(path);
}
Exemple #24
0
static void object_added(GDBusProxy *proxy, void *user_data)
{
	const char *interface;

	interface = g_dbus_proxy_get_interface(proxy);
	if (!interface) {
		connman_warn("Interface or proxy missing when adding "
							"bluetooth object");
		return;
	}

	if (strcmp(interface, "org.bluez.Adapter1") == 0) {
		DBG("%s %s", interface, g_dbus_proxy_get_path(proxy));
		device_create(proxy);
		return;
	}

	if (strcmp(interface, "org.bluez.Network1") == 0) {
		DBG("%s %s", interface, g_dbus_proxy_get_path(proxy));
		pan_create(proxy);
		return;
	}
}
Exemple #25
0
static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
{
	struct connman_dhcp *dhcp = user_data;
	GList *option = NULL;
	char *address, *netmask = NULL, *gateway = NULL;
	const char *c_address, *c_gateway;
	unsigned char prefixlen, c_prefixlen;
	bool ip_change = false;

	DBG("Lease available");

	if (dhcp->ipv4ll_client) {
		ipv4ll_stop_client(dhcp);
		dhcp_invalidate(dhcp, false);
	}

	c_address = __connman_ipconfig_get_local(dhcp->ipconfig);
	c_gateway = __connman_ipconfig_get_gateway(dhcp->ipconfig);
	c_prefixlen = __connman_ipconfig_get_prefixlen(dhcp->ipconfig);

	address = g_dhcp_client_get_address(dhcp_client);

	__connman_ipconfig_set_dhcp_address(dhcp->ipconfig, address);
	DBG("last address %s", address);

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
	if (option)
		netmask = g_strdup(option->data);

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_ROUTER);
	if (option)
		gateway = g_strdup(option->data);

	prefixlen = connman_ipaddress_calc_netmask_len(netmask);
	if (prefixlen == 255)
		connman_warn("netmask: %s is invalid", netmask);

	DBG("c_address %s", c_address);

	if (g_strcmp0(address, c_address)) {
		ip_change = true;
		if (c_address) {
			/* Remove old ip address */
			__connman_ipconfig_address_remove(dhcp->ipconfig);
		}
	}
	if (g_strcmp0(gateway, c_gateway)) {
		ip_change = true;
		if (c_gateway) {
			/* Remove gateway ip address */
			__connman_ipconfig_gateway_remove(dhcp->ipconfig);
		}
	} else if (prefixlen != c_prefixlen)
		ip_change = true;

	__connman_ipconfig_set_method(dhcp->ipconfig,
						CONNMAN_IPCONFIG_METHOD_DHCP);
	if (ip_change) {
		__connman_ipconfig_set_local(dhcp->ipconfig, address);
		__connman_ipconfig_set_prefixlen(dhcp->ipconfig, prefixlen);
		__connman_ipconfig_set_gateway(dhcp->ipconfig, gateway);
	}

	if (!apply_lease_available_on_network(dhcp_client, dhcp))
		goto done;

	if (ip_change)
		dhcp_valid(dhcp);

done:
	g_free(address);
	g_free(netmask);
	g_free(gateway);
}
Exemple #26
0
static int load_provider(GKeyFile *keyfile, const char *group,
				struct vpn_config *config, enum what action)
{
	struct vpn_config_provider *config_provider;
	const char *ident, *host, *domain;
	int err;

	/* Strip off "provider_" prefix */
	ident = group + 9;

	if (strlen(ident) < 1)
		return -EINVAL;

	config_provider = g_hash_table_lookup(config->provider_table, ident);
	if (config_provider)
		return -EALREADY;

	config_provider = g_try_new0(struct vpn_config_provider, 1);
	if (!config_provider)
		return -ENOMEM;

	config_provider->ident = g_strdup(ident);

	config_provider->setting_strings = g_hash_table_new_full(g_str_hash,
						g_str_equal, g_free, g_free);

	add_keys(config_provider, keyfile, group);

	host = get_string(config_provider, "Host");
	domain = get_string(config_provider, "Domain");
	if (host && domain) {
		char *id = __vpn_provider_create_identifier(host, domain);

		struct vpn_provider *provider;
		provider = __vpn_provider_lookup(id);
		if (provider) {
			if (action == REMOVE) {
				__vpn_provider_delete(provider);
				err = 0;
			} else {
				connman_warn("Provider configuration %s "
						"already exist", id);
				err = -EALREADY;
			}

			g_free(id);
			goto err;
		}

		config_provider->provider_identifier = id;

		DBG("provider identifier %s", id);
	} else {
		DBG("invalid values host %s domain %s", host, domain);
		err = -EINVAL;
		goto err;
	}

	config_provider->config_ident = g_strdup(config->ident);
	config_provider->config_entry = g_strdup_printf("provider_%s",
						config_provider->ident);

	g_hash_table_insert(config->provider_table,
				config_provider->ident,	config_provider);

	err = __vpn_provider_create_from_config(
					config_provider->setting_strings,
					config_provider->config_ident,
					config_provider->config_entry);
	if (err != 0) {
		DBG("Cannot create provider from config file (%d/%s)",
			-err, strerror(-err));
		goto err;
	}

	DBG("Added provider configuration %s",
						config_provider->ident);
	return 0;

err:
	g_free(config_provider->ident);
	g_free(config_provider->type);
	g_free(config_provider->name);
	g_free(config_provider->host);
	g_free(config_provider->domain);
	g_free(config_provider->networks);
	g_hash_table_destroy(config_provider->setting_strings);
	g_free(config_provider);

	return err;
}
Exemple #27
0
static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
{
	struct connman_dhcp *dhcp = user_data;
	GList *list, *option = NULL;
	char *address, *netmask = NULL, *gateway = NULL;
	const char *c_address, *c_gateway;
	char *domainname = NULL, *hostname = NULL;
	char **nameservers, **timeservers, *pac = NULL;
	int ns_entries;
	struct connman_ipconfig *ipconfig;
	struct connman_service *service;
	unsigned char prefixlen, c_prefixlen;
	gboolean ip_change;
	int i;

	DBG("Lease available");

	service = connman_service_lookup_from_network(dhcp->network);
	if (service == NULL) {
		connman_error("Can not lookup service");
		return;
	}

	ipconfig = __connman_service_get_ip4config(service);
	if (ipconfig == NULL) {
		connman_error("Could not lookup ipconfig");
		return;
	}

	c_address = __connman_ipconfig_get_local(ipconfig);
	c_gateway = __connman_ipconfig_get_gateway(ipconfig);
	c_prefixlen = __connman_ipconfig_get_prefixlen(ipconfig);

	address = g_dhcp_client_get_address(dhcp_client);

	__connman_ipconfig_set_dhcp_address(ipconfig, address);
	DBG("last address %s", address);

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
	if (option != NULL)
		netmask = g_strdup(option->data);

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_ROUTER);
	if (option != NULL)
		gateway = g_strdup(option->data);

	prefixlen = __connman_ipaddress_netmask_prefix_len(netmask);
	if (prefixlen == 255)
		connman_warn("netmask: %s is invalid", netmask);

	DBG("c_address %s", c_address);

	if (address != NULL && c_address != NULL &&
					g_strcmp0(address, c_address) != 0)
		ip_change = TRUE;
	else if (gateway != NULL && c_gateway != NULL &&
					g_strcmp0(gateway, c_gateway) != 0)
		ip_change = TRUE;
	else if (prefixlen != c_prefixlen)
		ip_change = TRUE;
	else if (c_address == NULL || c_gateway == NULL)
		ip_change = TRUE;
	else
		ip_change = FALSE;

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DNS_SERVER);
	ns_entries = g_list_length(option);
	nameservers = g_try_new0(char *, ns_entries + 1);
	if (nameservers != NULL) {
		for (i = 0, list = option; list; list = list->next, i++)
			nameservers[i] = g_strdup(list->data);
		nameservers[ns_entries] = NULL;
	}

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DOMAIN_NAME);
	if (option != NULL)
		domainname = g_strdup(option->data);

	if (connman_setting_get_bool("AllowHostnameUpdates") == TRUE) {
		option = g_dhcp_client_get_option(dhcp_client,
						G_DHCP_HOST_NAME);
		if (option != NULL)
			hostname = g_strdup(option->data);
	}

	option = g_dhcp_client_get_option(dhcp_client, G_DHCP_NTP_SERVER);
	ns_entries = g_list_length(option);
	timeservers = g_try_new0(char *, ns_entries + 1);
	if (timeservers != NULL) {
		for (i = 0, list = option; list; list = list->next, i++)
			timeservers[i] = g_strdup(list->data);
		timeservers[ns_entries] = NULL;
	}

	option = g_dhcp_client_get_option(dhcp_client, 252);
	if (option != NULL)
		pac = g_strdup(option->data);

	__connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP);

	if (ip_change == TRUE) {
		__connman_ipconfig_set_local(ipconfig, address);
		__connman_ipconfig_set_prefixlen(ipconfig, prefixlen);
		__connman_ipconfig_set_gateway(ipconfig, gateway);
	}

	if (compare_string_arrays(nameservers, dhcp->nameservers) == FALSE) {
		if (dhcp->nameservers != NULL) {
			for (i = 0; dhcp->nameservers[i] != NULL; i++) {
				__connman_service_nameserver_remove(service,
						dhcp->nameservers[i], FALSE);
			}
			g_strfreev(dhcp->nameservers);
		}

		dhcp->nameservers = nameservers;

		for (i = 0; dhcp->nameservers != NULL &&
					dhcp->nameservers[i] != NULL; i++) {
			__connman_service_nameserver_append(service,
						dhcp->nameservers[i], FALSE);
		}
	} else {
		g_strfreev(nameservers);
	}

	if (compare_string_arrays(timeservers, dhcp->timeservers) == FALSE) {
		if (dhcp->timeservers != NULL) {
			for (i = 0; dhcp->timeservers[i] != NULL; i++) {
				__connman_service_timeserver_remove(service,
							dhcp->timeservers[i]);
			}
			g_strfreev(dhcp->timeservers);
		}

		dhcp->timeservers = timeservers;

		for (i = 0; dhcp->timeservers != NULL &&
					 dhcp->timeservers[i] != NULL; i++) {
			__connman_service_timeserver_append(service,
							dhcp->timeservers[i]);
		}
	} else {
		g_strfreev(timeservers);
	}

	if (g_strcmp0(pac, dhcp->pac) != 0) {
		g_free(dhcp->pac);
		dhcp->pac = pac;

		__connman_service_set_pac(service, dhcp->pac);
	}

	__connman_service_set_domainname(service, domainname);

	if (domainname != NULL)
		__connman_utsname_set_domainname(domainname);

	if (hostname != NULL)
		__connman_utsname_set_hostname(hostname);

	if (ip_change == TRUE)
		dhcp_valid(dhcp);

	__connman_6to4_probe(service);

	g_free(address);
	g_free(netmask);
	g_free(gateway);
	g_free(domainname);
	g_free(hostname);
}
static int setup_loopback(void)
{
	struct ifreq ifr;
	struct sockaddr_in addr;
	int sk, err;

	sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
	if (sk < 0)
		return -errno;

	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_name, "lo");

	if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
		err = -errno;
		goto done;
	}

	if (ifr.ifr_flags & IFF_UP) {
		connman_info("Checking loopback interface settings");
		if (valid_loopback(sk, &ifr) == TRUE) {
			err = -EALREADY;
			goto done;
		}

		connman_warn("Correcting wrong lookback settings");
	}

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = loopback_address;
	memcpy(&ifr.ifr_addr, &addr, sizeof(ifr.ifr_addr));

	err = ioctl(sk, SIOCSIFADDR, &ifr);
	if (err < 0) {
		err = -errno;
		connman_error("Setting address failed (%s)", strerror(-err));
		goto done;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = loopback_netmask;
	memcpy(&ifr.ifr_netmask, &addr, sizeof(ifr.ifr_netmask));

	err = ioctl(sk, SIOCSIFNETMASK, &ifr);
	if (err < 0) {
		err = -errno;
		connman_error("Setting netmask failed (%s)", strerror(-err));
		goto done;
	}

	if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
		err = -errno;
		goto done;
	}

	ifr.ifr_flags |= IFF_UP;

	if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
		err = -errno;
		connman_error("Activating loopback interface failed (%s)",
							strerror(-err));
		goto done;
	}

done:
	close(sk);

	return err;
}
Exemple #29
0
static int create_table_and_chains(struct nftables_info *nft_info)
{
	struct mnl_socket *nl;
	struct nftnl_table *table;
	struct nftnl_chain *chain;
	int err;


	DBG("");

        err = socket_open_and_bind(&nl);
        if (err < 0)
		return err;

	/*
	 * Add table
	 * http://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
	 */

	/*
	 * # nft add table connman
	 */
	table = build_table(CONNMAN_TABLE, NFPROTO_IPV4);
	if (!table) {
		err = -ENOMEM;
		goto out;
	}

        err = table_cmd(nl, table, NFT_MSG_NEWTABLE, NFPROTO_IPV4,
			NLM_F_CREATE|NLM_F_ACK);
        if (err < 0)
                goto out;

	/*
	 * Add basic chains
	 * http://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains
	 */

	/*
	 * # nft add chain connman nat-prerouting		\
	 *	{ type nat hook prerouting priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_NAT_PRE, CONNMAN_TABLE,
				"nat", NF_INET_PRE_ROUTING, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

	/*
	 * # nft add chain connman nat-postrouting		\
	 *	{ type nat hook postrouting priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_NAT_POST, CONNMAN_TABLE,
				"nat", NF_INET_POST_ROUTING, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

	/*
	 * # nft add chain connman route-output		\
	 *	{ type route hook output priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_ROUTE_OUTPUT, CONNMAN_TABLE,
				"route", NF_INET_LOCAL_OUT, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

out:
	if (err)
		connman_warn("Failed to create basic chains: %s",
				strerror(-err));
	mnl_socket_close(nl);
	return err;
}