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); }
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; }
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); }
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); } }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
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; }
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; }
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; }
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); } }
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); }
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); }
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; } }
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); }
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; }
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; }
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; }