/* * * Wireless daemon for Linux * * Copyright (C) 2019 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "linux/nl80211.h" #include "src/nl80211util.h" #include "src/iwd.h" #include "src/module.h" #include "src/netdev.h" #include "src/wiphy.h" #include "src/util.h" #include "src/common.h" #include "src/nl80211cmd.h" #include "src/p2p.h" static struct l_genl_family *nl80211 = NULL; static char **whitelist_filter; static char **blacklist_filter; static bool randomize; static bool use_default; struct wiphy_setup_state { uint32_t id; struct wiphy *wiphy; unsigned int pending_cmd_count; bool aborted; bool retry; /* * Data we may need if the driver does not seem to support interface * manipulation and we fall back to using the driver-created default * interface. */ bool use_default; struct l_genl_msg *default_if_msg; }; static struct l_queue *pending_wiphys; /* With these drivers don't even try creating our interfaces */ static const char *default_if_driver_list[] = { /* * The out-of-tree rtl88x2bu crashes the kernel hard. Seemingly * many other drivers are built from the same source code so * blacklist all of them. Unfortunately there are in-tree drivers * that also match these names and may be fine. Use * UseDefaultInterface to override. */ "rtl81*", "rtl87*", "rtl88*", "rtw_*", "brcmfmac", "bcmsdh_sdmmc", NULL, }; static void wiphy_setup_state_free(void *data) { struct wiphy_setup_state *state = data; if (state->default_if_msg) l_genl_msg_unref(state->default_if_msg); L_WARN_ON(state->pending_cmd_count); l_free(state); } static void wiphy_setup_state_destroy(struct wiphy_setup_state *state) { l_queue_remove(pending_wiphys, state); wiphy_setup_state_free(state); } static bool manager_use_default(struct wiphy_setup_state *state) { uint8_t addr_buf[6]; uint8_t *addr = NULL; l_debug(""); if (!state->default_if_msg) { l_error("No default interface for wiphy %u", (unsigned int) state->id); state->retry = true; return false; } if (randomize) { wiphy_generate_random_address(state->wiphy, addr_buf); addr = addr_buf; } netdev_create_from_genl(state->default_if_msg, addr); return true; } static void manager_new_station_interface_cb(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state = user_data; uint8_t addr_buf[6]; uint8_t *addr = NULL; int error; l_debug(""); if (state->aborted) return; error = l_genl_msg_get_error(msg); if (error < 0) { l_error("NEW_INTERFACE failed: %s", strerror(-l_genl_msg_get_error(msg))); /* * If we receive an EBUSY most likely the wiphy is still * initializing, the default interface has not been created * yet and the wiphy needs some time. Retry when we * receive a NEW_INTERFACE event. */ if (error == -EBUSY) { state->retry = true; return; } /* * Nothing we can do to use this wiphy since by now we * will have successfully deleted any default interface * there may have been. */ return; } if (randomize && !wiphy_has_feature(state->wiphy, NL80211_FEATURE_MAC_ON_CREATE)) { wiphy_generate_random_address(state->wiphy, addr_buf); addr = addr_buf; } netdev_create_from_genl(msg, addr); } static void manager_new_p2p_interface_cb(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state = user_data; l_debug(""); if (state->aborted) return; if (l_genl_msg_get_error(msg) < 0) { l_error("NEW_INTERFACE failed for p2p-device: %s", strerror(-l_genl_msg_get_error(msg))); return; } p2p_device_update_from_genl(msg, true); } static void manager_new_interface_done(void *user_data) { struct wiphy_setup_state *state = user_data; state->pending_cmd_count--; if (!state->pending_cmd_count && !state->retry) wiphy_setup_state_destroy(state); } static void manager_create_interfaces(struct wiphy_setup_state *state) { struct l_genl_msg *msg; char ifname[10]; uint32_t iftype; unsigned cmd_id; if (state->aborted) return; if (state->use_default) { manager_use_default(state); /* * Some drivers don't let us touch the default interface * but still allow us to create/destroy P2P interfaces, so * give it a chance. */ goto try_create_p2p; } /* * Current policy: we maintain one netdev per wiphy for station, * AP and Ad-Hoc modes, one optional p2p-device and zero or more * p2p-GOs or p2p-clients. The P2P-client/GO interfaces will be * created on request. */ /* To be improved */ snprintf(ifname, sizeof(ifname), "wlan%i", (int) state->id); l_debug("creating %s", ifname); iftype = NL80211_IFTYPE_STATION; msg = l_genl_msg_new(NL80211_CMD_NEW_INTERFACE); l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY, 4, &state->id); l_genl_msg_append_attr(msg, NL80211_ATTR_IFTYPE, 4, &iftype); l_genl_msg_append_attr(msg, NL80211_ATTR_IFNAME, strlen(ifname) + 1, ifname); l_genl_msg_append_attr(msg, NL80211_ATTR_4ADDR, 1, "\0"); l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, ""); if (randomize && wiphy_has_feature(state->wiphy, NL80211_FEATURE_MAC_ON_CREATE)) { uint8_t random_addr[6]; wiphy_generate_random_address(state->wiphy, random_addr); l_debug("Creating interface on phy: %s with random addr: "MAC, wiphy_get_name(state->wiphy), MAC_STR(random_addr)); l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, 6, random_addr); } cmd_id = l_genl_family_send(nl80211, msg, manager_new_station_interface_cb, state, manager_new_interface_done); if (!cmd_id) { l_error("Error sending NEW_INTERFACE for %s", ifname); return; } state->pending_cmd_count++; try_create_p2p: /* * Require the MAC on create feature so we can send our desired * interface address during GO Negotiation before actually creating * the local Client/GO interface. Could be worked around if needed. */ if (!wiphy_supports_iftype(state->wiphy, NL80211_IFTYPE_P2P_DEVICE) || !wiphy_supports_iftype(state->wiphy, NL80211_IFTYPE_P2P_CLIENT) || !wiphy_has_feature(state->wiphy, NL80211_FEATURE_MAC_ON_CREATE)) return; /* * Use wlan%i-p2p for now. We might want to use * -p2p here (in case state->use_default * is true) but the risk is that we'd go over the interface name * length limit. */ snprintf(ifname, sizeof(ifname), "wlan%i-p2p", (int) state->id); l_debug("creating %s", ifname); iftype = NL80211_IFTYPE_P2P_DEVICE; msg = l_genl_msg_new(NL80211_CMD_NEW_INTERFACE); l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY, 4, &state->id); l_genl_msg_append_attr(msg, NL80211_ATTR_IFTYPE, 4, &iftype); l_genl_msg_append_attr(msg, NL80211_ATTR_IFNAME, strlen(ifname) + 1, ifname); l_genl_msg_append_attr(msg, NL80211_ATTR_4ADDR, 1, "\0"); l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, ""); cmd_id = l_genl_family_send(nl80211, msg, manager_new_p2p_interface_cb, state, manager_new_interface_done); if (!cmd_id) { l_error("Error sending NEW_INTERFACE for %s", ifname); return; } state->pending_cmd_count++; } static bool manager_wiphy_check_setup_done(struct wiphy_setup_state *state) { if (state->pending_cmd_count || state->retry) return false; manager_create_interfaces(state); return !state->pending_cmd_count && !state->retry; } static void manager_setup_cmd_done(void *user_data) { struct wiphy_setup_state *state = user_data; state->pending_cmd_count--; if (manager_wiphy_check_setup_done(state)) wiphy_setup_state_destroy(state); } static void manager_del_interface_cb(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state = user_data; l_debug(""); if (state->aborted) return; if (l_genl_msg_get_error(msg) < 0) { l_error("DEL_INTERFACE failed: %s", strerror(-l_genl_msg_get_error(msg))); state->use_default = true; } } static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state = user_data; uint32_t wiphy; uint32_t ifindex; uint32_t iftype; uint64_t wdev; const char *ifname; struct l_genl_msg *del_msg; unsigned cmd_id; char *pattern; unsigned int i; bool whitelisted = false, blacklisted = false; l_debug(""); if (state->aborted) return; if (nl80211_parse_attrs(msg, NL80211_ATTR_WDEV, &wdev, NL80211_ATTR_WIPHY, &wiphy, NL80211_ATTR_IFTYPE, &iftype, NL80211_ATTR_UNSPEC) < 0) return; if (wiphy != state->id) { l_debug("Wiphy attribute mismatch, wanted: %u, got %u", state->id, wiphy); return; } if (nl80211_parse_attrs(msg, NL80211_ATTR_IFINDEX, &ifindex, NL80211_ATTR_IFNAME, &ifname, NL80211_ATTR_UNSPEC) < 0) goto delete_interface; if (whitelist_filter) { for (i = 0; (pattern = whitelist_filter[i]); i++) { if (fnmatch(pattern, ifname, 0) != 0) continue; whitelisted = true; break; } } if (blacklist_filter) { for (i = 0; (pattern = blacklist_filter[i]); i++) { if (fnmatch(pattern, ifname, 0) != 0) continue; blacklisted = true; break; } } /* * If this interface is usable as our default netdev in case the * driver does not support interface manipulation, save the message * just in case. */ if ((iftype == NL80211_IFTYPE_ADHOC || iftype == NL80211_IFTYPE_STATION || iftype == NL80211_IFTYPE_AP) && !state->default_if_msg && (!whitelist_filter || whitelisted) && !blacklisted) state->default_if_msg = l_genl_msg_ref(msg); delete_interface: if (state->use_default) return; del_msg = l_genl_msg_new(NL80211_CMD_DEL_INTERFACE); l_genl_msg_append_attr(del_msg, NL80211_ATTR_WDEV, 8, &wdev); l_genl_msg_append_attr(del_msg, NL80211_ATTR_WIPHY, 4, &state->id); cmd_id = l_genl_family_send(nl80211, del_msg, manager_del_interface_cb, state, manager_setup_cmd_done); if (!cmd_id) { l_error("Sending DEL_INTERFACE for wdev: %" PRIu64" failed", wdev); state->use_default = true; return; } l_debug(""); state->pending_cmd_count++; } static bool manager_wiphy_state_match(const void *a, const void *b) { const struct wiphy_setup_state *state = a; uint32_t id = L_PTR_TO_UINT(b); return (state->id == id); } static struct wiphy_setup_state *manager_find_pending(uint32_t id) { return l_queue_find(pending_wiphys, manager_wiphy_state_match, L_UINT_TO_PTR(id)); } static uint32_t manager_parse_wiphy_id(struct l_genl_msg *msg) { uint32_t wiphy; if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &wiphy, NL80211_ATTR_UNSPEC) < 0) return -1; return wiphy; } static void manager_del_wiphy_event(struct l_genl_msg *msg) { struct wiphy_setup_state *state; struct wiphy *wiphy; uint32_t id; id = manager_parse_wiphy_id(msg); state = manager_find_pending(id); if (state) { if (state->pending_cmd_count) state->aborted = true; else wiphy_setup_state_destroy(state); } wiphy = wiphy_find(id); if (wiphy) wiphy_destroy(wiphy); } static void manager_interface_dump_callback(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state; l_debug(""); state = manager_find_pending(manager_parse_wiphy_id(msg)); if (!state) return; manager_get_interface_cb(msg, state); } static bool manager_check_create_interfaces(void *data, void *user_data) { struct wiphy_setup_state *state = data; if (!manager_wiphy_check_setup_done(state)) return false; /* If we are here, there were no interfaces for this phy */ wiphy_setup_state_free(state); return true; } static void manager_interface_dump_done(void *user_data) { l_queue_foreach_remove(pending_wiphys, manager_check_create_interfaces, NULL); } /* We are dumping multiple wiphys for the very first time */ static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data) { uint32_t id; const char *name; struct wiphy *wiphy; struct wiphy_setup_state *state; if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &id, NL80211_ATTR_WIPHY_NAME, &name, NL80211_ATTR_UNSPEC) < 0) return; /* * A Wiphy split dump can generate many (6+) NEW_WIPHY messages * We need to parse attributes from all of them, but only perform * initialization steps once for each new wiphy detected */ wiphy = wiphy_find(id); if (wiphy) goto done; wiphy = wiphy_create(id, name); if (!wiphy || wiphy_is_blacklisted(wiphy)) return; state = l_new(struct wiphy_setup_state, 1); state->id = id; state->wiphy = wiphy; l_debug("New wiphy %s added (%d)", name, id); l_queue_push_tail(pending_wiphys, state); done: wiphy_update_from_genl(wiphy, msg); } /* We are dumping a single wiphy, due to a NEW_WIPHY event */ static void manager_wiphy_filtered_dump_callback(struct l_genl_msg *msg, void *user_data) { struct wiphy_setup_state *state = user_data; wiphy_update_from_genl(state->wiphy, msg); } static void manager_wiphy_dump_done(void *user_data) { const struct l_queue_entry *e; for (e = l_queue_get_entries(pending_wiphys); e; e = e->next) { struct wiphy_setup_state *state = e->data; wiphy_create_complete(state->wiphy); state->use_default = use_default; /* If whitelist/blacklist were given only try to use existing * interfaces same as when the driver does not support * NEW_INTERFACE or DEL_INTERFACE, otherwise the interface * names will become meaningless after we've created our own * interface(s). Optimally phy name white/blacklists should * be used. */ if (whitelist_filter || blacklist_filter) state->use_default = true; if (!state->use_default) { const char *driver = wiphy_get_driver(state->wiphy); const char **e; for (e = default_if_driver_list; *e; e++) if (fnmatch(*e, driver, 0) == 0) state->use_default = true; } if (state->use_default) l_info("Wiphy %s will only use the default interface", wiphy_get_name(state->wiphy)); } } static int manager_wiphy_filtered_dump(uint32_t wiphy_id, l_genl_msg_func_t cb, void *user_data) { struct l_genl_msg *msg; unsigned int wiphy_cmd_id; unsigned int iface_cmd_id; /* * Until fixed, a NEW_WIPHY event will not include all the information * that may be available, but a dump will. Because of this we do both * GET_WIPHY/GET_INTERFACE, same as we would during initialization. */ msg = l_genl_msg_new_sized(NL80211_CMD_GET_WIPHY, 128); l_genl_msg_append_attr(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP, 0, NULL); l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY, 4, &wiphy_id); wiphy_cmd_id = l_genl_family_dump(nl80211, msg, cb, user_data, manager_wiphy_dump_done); if (!wiphy_cmd_id) { l_error("Could not dump wiphy %u", wiphy_id); l_genl_msg_unref(msg); return -EIO; } /* * As the first step after new wiphy is detected we will query * the initial interface setup, delete the default interfaces * and create interfaces for our own use with NL80211_ATTR_SOCKET_OWNER * on them. After that if new interfaces are created outside of * IWD, or removed outside of IWD, we don't touch them and will * try to minimally adapt to handle the removals correctly. It's * a very unlikely situation in any case but it wouldn't make * sense to try to continually enforce our setup fighting against * some other process, and it wouldn't make sense to try to * manage and use additional interfaces beyond the one or two * we need for our operations. */ msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE); l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY, 4, &wiphy_id); iface_cmd_id = l_genl_family_dump(nl80211, msg, manager_interface_dump_callback, NULL, manager_interface_dump_done); if (!iface_cmd_id) { l_error("Could not dump interface for wiphy %u", wiphy_id); l_genl_family_cancel(nl80211, wiphy_cmd_id); l_genl_msg_unref(msg); return -EIO; } return 0; } static void manager_config_notify(struct l_genl_msg *msg, void *user_data) { uint8_t cmd; uint32_t wiphy_id; struct wiphy_setup_state *state; if (!pending_wiphys) return; cmd = l_genl_msg_get_command(msg); l_debug("Notification of command %s(%u)", nl80211cmd_to_string(cmd), cmd); switch (cmd) { case NL80211_CMD_NEW_WIPHY: { const char *name; struct wiphy *wiphy; if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &wiphy_id, NL80211_ATTR_WIPHY_NAME, &name, NL80211_ATTR_UNSPEC) < 0) return; /* * NEW_WIPHY events are sent in three cases: * 1. New wiphy is detected * 2. Wiphy is moved to a new namespace * 3. Wiphy is renamed * * Take care of case 3 here without re-parsing the entire * wiphy structure, potentially causing leaks, etc. */ wiphy = wiphy_find(wiphy_id); if (wiphy) { wiphy_update_name(wiphy, name); return; } wiphy = wiphy_create(wiphy_id, name); if (!wiphy || wiphy_is_blacklisted(wiphy)) return; state = l_new(struct wiphy_setup_state, 1); state->id = wiphy_id; state->wiphy = wiphy; if (manager_wiphy_filtered_dump(wiphy_id, manager_wiphy_filtered_dump_callback, state) < 0) { wiphy_setup_state_free(state); return; } l_queue_push_tail(pending_wiphys, state); return; } case NL80211_CMD_DEL_WIPHY: manager_del_wiphy_event(msg); return; case NL80211_CMD_NEW_INTERFACE: /* * Interfaces are normally dumped on the NEW_WIPHY events and * and we have nothing to do here. But check if by any chance * we've queried this wiphy and it was still busy initialising, * in that case retry the setup now that an interface, likely * the initial default one, has been added. */ wiphy_id = manager_parse_wiphy_id(msg); state = manager_find_pending(wiphy_id); if (state && state->retry) { state->retry = false; l_debug("Retrying setup of wiphy %u", state->id); manager_get_interface_cb(msg, state); if (manager_wiphy_check_setup_done(state)) wiphy_setup_state_destroy(state); return; } if (!wiphy_find(wiphy_id)) { l_warn("Received a NEW_INTERFACE for a wiphy id" " that isn't tracked. This is most ikely a" " kernel bug where NEW_WIPHY events that are" " too large are dropped on the floor." " Attempting a workaround..."); manager_wiphy_filtered_dump(wiphy_id, manager_wiphy_dump_callback, NULL); return; } return; case NL80211_CMD_DEL_INTERFACE: { uint32_t ifindex; if (nl80211_parse_attrs(msg, NL80211_ATTR_IFINDEX, &ifindex, NL80211_ATTR_UNSPEC) < 0) { uint64_t wdev_id; struct p2p_device *p2p_device; if (nl80211_parse_attrs(msg, NL80211_ATTR_WDEV, &wdev_id, NL80211_ATTR_UNSPEC) < 0) return; p2p_device = p2p_device_find(wdev_id); if (!p2p_device) return; p2p_device_destroy(p2p_device); } else { struct netdev *netdev = netdev_find(ifindex); if (!netdev) return; netdev_destroy(netdev); } return; } } } static int manager_init(void) { struct l_genl *genl = iwd_get_genl(); const struct l_settings *config = iwd_get_config(); struct l_genl_msg *msg; unsigned int wiphy_dump; unsigned int interface_dump; const char *randomize_str; const char *if_whitelist = iwd_get_iface_whitelist(); const char *if_blacklist = iwd_get_iface_blacklist(); nl80211 = l_genl_family_new(genl, NL80211_GENL_NAME); if (if_whitelist) whitelist_filter = l_strsplit(if_whitelist, ','); if (if_blacklist) blacklist_filter = l_strsplit(if_blacklist, ','); pending_wiphys = l_queue_new(); if (!l_genl_family_register(nl80211, "config", manager_config_notify, NULL, NULL)) { l_error("Registering for config notifications failed"); goto error; } msg = l_genl_msg_new_sized(NL80211_CMD_GET_WIPHY, 128); l_genl_msg_append_attr(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP, 0, NULL); wiphy_dump = l_genl_family_dump(nl80211, msg, manager_wiphy_dump_callback, NULL, manager_wiphy_dump_done); if (!wiphy_dump) { l_error("Initial wiphy information dump failed"); l_genl_msg_unref(msg); goto error; } msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE); interface_dump = l_genl_family_dump(nl80211, msg, manager_interface_dump_callback, NULL, manager_interface_dump_done); if (!interface_dump) { l_error("Initial interface information dump failed"); l_genl_msg_unref(msg); l_genl_family_cancel(nl80211, wiphy_dump); goto error; } randomize_str = l_settings_get_value(config, "General", "AddressRandomization"); if (randomize_str) { if (!strcmp(randomize_str, "once")) randomize = true; else if (!strcmp(randomize_str, "disabled")) randomize = false; } if (!l_settings_get_bool(config, "General", "UseDefaultInterface", &use_default)) { if (!l_settings_get_bool(config, "General", "use_default_interface", &use_default)) use_default = false; else l_warn("[General].use_default_interface is deprecated" ", please use UseDefaultInterface"); } return 0; error: l_queue_destroy(pending_wiphys, NULL); pending_wiphys = NULL; l_genl_family_free(nl80211); nl80211 = NULL; return -EIO; } static void manager_exit(void) { l_strfreev(whitelist_filter); l_strfreev(blacklist_filter); l_queue_destroy(pending_wiphys, wiphy_setup_state_free); pending_wiphys = NULL; l_genl_family_free(nl80211); nl80211 = NULL; randomize = false; } IWD_MODULE(manager, manager_init, manager_exit);