Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package iwd for openSUSE:Factory checked in at 2022-12-25 15:14:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/iwd (Old) and /work/SRC/openSUSE:Factory/.iwd.new.1563 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "iwd" Sun Dec 25 15:14:48 2022 rev:34 rq:1045126 version:2.1 Changes: -------- --- /work/SRC/openSUSE:Factory/iwd/iwd.changes 2022-12-04 14:58:29.664318675 +0100 +++ /work/SRC/openSUSE:Factory/.iwd.new.1563/iwd.changes 2022-12-25 15:15:03.985445580 +0100 @@ -1,0 +2,9 @@ +Fri Dec 23 20:03:14 UTC 2022 - Dirk Müller <dmuel...@suse.com> + +- update to 2.1: + * Fix issue with handling FT-over-DS action. + * Fix issue with handling scan and 6 GHz support check. + * Fix issue with handling when periodic scans get aborted. + * Add support for using 5 GHz frequencies in AP mode. + +------------------------------------------------------------------- Old: ---- iwd-2.0.tar.sign iwd-2.0.tar.xz New: ---- iwd-2.1.tar.sign iwd-2.1.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ iwd.spec ++++++ --- /var/tmp/diff_new_pack.Qy6530/_old 2022-12-25 15:15:04.593449021 +0100 +++ /var/tmp/diff_new_pack.Qy6530/_new 2022-12-25 15:15:04.597449043 +0100 @@ -17,7 +17,7 @@ Name: iwd -Version: 2.0 +Version: 2.1 Release: 0 Summary: Wireless daemon for Linux License: LGPL-2.1-or-later ++++++ iwd-2.0.tar.xz -> iwd-2.1.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/ChangeLog new/iwd-2.1/ChangeLog --- old/iwd-2.0/ChangeLog 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/ChangeLog 2022-12-18 20:59:36.000000000 +0100 @@ -1,3 +1,9 @@ +ver 2.1: + Fix issue with handling FT-over-DS action. + Fix issue with handling scan and 6 GHz support check. + Fix issue with handling when periodic scans get aborted. + Add support for using 5 GHz frequencies in AP mode. + ver 2.0: Fix issue with handling P2P and limiting ciphers to CCMP. Fix issue with scanning before forced roaming action. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/client/command.c new/iwd-2.1/client/command.c --- old/iwd-2.0/client/command.c 2022-09-07 20:42:27.000000000 +0200 +++ new/iwd-2.1/client/command.c 2022-12-18 20:59:36.000000000 +0100 @@ -753,7 +753,7 @@ argv += optind; argc -= optind; - if (argc < 2) { + if (argc < 1) { interactive_mode = true; return false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/configure new/iwd-2.1/configure --- old/iwd-2.0/configure 2022-11-18 13:33:34.000000000 +0100 +++ new/iwd-2.1/configure 2022-12-18 21:01:21.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for iwd 2.0. +# Generated by GNU Autoconf 2.71 for iwd 2.1. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ # Identity of this package. PACKAGE_NAME='iwd' PACKAGE_TARNAME='iwd' -PACKAGE_VERSION='2.0' -PACKAGE_STRING='iwd 2.0' +PACKAGE_VERSION='2.1' +PACKAGE_STRING='iwd 2.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1421,7 +1421,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures iwd 2.0 to adapt to many kinds of systems. +\`configure' configures iwd 2.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1492,7 +1492,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of iwd 2.0:";; + short | recursive ) echo "Configuration of iwd 2.1:";; esac cat <<\_ACEOF @@ -1643,7 +1643,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -iwd configure 2.0 +iwd configure 2.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1861,7 +1861,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by iwd $as_me 2.0, which was +It was created by iwd $as_me 2.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3136,7 +3136,7 @@ # Define the identity of the package. PACKAGE='iwd' - VERSION='2.0' + VERSION='2.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -13986,7 +13986,7 @@ test "${enable_monitor}" != "no" || test "${enable_wired}" = "yes" || test "${enable_hwsim}" = "yes"); then - ell_min_version="0.54" + ell_min_version="0.55" else ell_min_version="0.5" fi @@ -14712,7 +14712,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by iwd $as_me 2.0, which was +This file was extended by iwd $as_me 2.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14780,7 +14780,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -iwd config.status 2.0 +iwd config.status 2.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/configure.ac new/iwd-2.1/configure.ac --- old/iwd-2.0/configure.ac 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/configure.ac 2022-12-18 20:59:36.000000000 +0100 @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([iwd],[2.0]) +AC_INIT([iwd],[2.1]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_AUX_DIR(build-aux) @@ -263,7 +263,7 @@ test "${enable_monitor}" != "no" || test "${enable_wired}" = "yes" || test "${enable_hwsim}" = "yes"); then - ell_min_version="0.54" + ell_min_version="0.55" else ell_min_version="0.5" fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/ell/checksum.c new/iwd-2.1/ell/checksum.c --- old/iwd-2.0/ell/checksum.c 2021-03-29 14:19:13.000000000 +0200 +++ new/iwd-2.1/ell/checksum.c 2022-12-18 20:40:29.000000000 +0100 @@ -146,55 +146,22 @@ return sk; } -/** - * l_checksum_new: - * @type: checksum type - * - * Creates new #l_checksum, using the checksum algorithm @type. - * - * Returns: a newly allocated #l_checksum object. - **/ -LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type) -{ - struct l_checksum *checksum; - int fd; - - if (!is_valid_index(checksum_algs, type) || !checksum_algs[type].name) - return NULL; - - checksum = l_new(struct l_checksum, 1); - checksum->alg_info = &checksum_algs[type]; - - fd = create_alg(checksum->alg_info->name); - if (fd < 0) - goto error; - - checksum->sk = accept4(fd, NULL, 0, SOCK_CLOEXEC); - close(fd); - - if (checksum->sk < 0) - goto error; - - return checksum; - -error: - l_free(checksum); - return NULL; -} - -LIB_EXPORT struct l_checksum *l_checksum_new_cmac_aes(const void *key, - size_t key_len) +static struct l_checksum *checksum_new_common(const char *alg, int sockopt, + const void *data, size_t len, + struct checksum_info *info) { struct l_checksum *checksum; int fd; - fd = create_alg("cmac(aes)"); + fd = create_alg(alg); if (fd < 0) return NULL; - if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) { - close(fd); - return NULL; + if (data) { + if (setsockopt(fd, SOL_ALG, sockopt, data, len) < 0) { + close(fd); + return NULL; + } } checksum = l_new(struct l_checksum, 1); @@ -206,40 +173,44 @@ return NULL; } - checksum->alg_info = &checksum_cmac_aes_alg; + checksum->alg_info = info; return checksum; } -LIB_EXPORT struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type, - const void *key, size_t key_len) +/** + * l_checksum_new: + * @type: checksum type + * + * Creates new #l_checksum, using the checksum algorithm @type. + * + * Returns: a newly allocated #l_checksum object. + **/ +LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type) { - struct l_checksum *checksum; - int fd; - - if (!is_valid_index(checksum_hmac_algs, type) || - !checksum_hmac_algs[type].name) - return NULL; - - fd = create_alg(checksum_hmac_algs[type].name); - if (fd < 0) + if (!is_valid_index(checksum_algs, type) || !checksum_algs[type].name) return NULL; - if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) { - close(fd); - return NULL; - } + return checksum_new_common(checksum_algs[type].name, 0, NULL, 0, + &checksum_algs[type]); +} - checksum = l_new(struct l_checksum, 1); - checksum->sk = accept4(fd, NULL, 0, SOCK_CLOEXEC); - close(fd); +LIB_EXPORT struct l_checksum *l_checksum_new_cmac_aes(const void *key, + size_t key_len) +{ + return checksum_new_common("cmac(aes)", ALG_SET_KEY, key, key_len, + &checksum_cmac_aes_alg); +} - if (checksum->sk < 0) { - l_free(checksum); +LIB_EXPORT struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type, + const void *key, size_t key_len) +{ + if (!is_valid_index(checksum_hmac_algs, type) || + !checksum_hmac_algs[type].name) return NULL; - } - checksum->alg_info = &checksum_hmac_algs[type]; - return checksum; + return checksum_new_common(checksum_hmac_algs[type].name, + ALG_SET_KEY, key, key_len, + &checksum_hmac_algs[type]); } /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/ell/dhcp.c new/iwd-2.1/ell/dhcp.c --- old/iwd-2.0/ell/dhcp.c 2022-11-18 10:08:38.000000000 +0100 +++ new/iwd-2.1/ell/dhcp.c 2022-12-18 20:40:29.000000000 +0100 @@ -365,12 +365,27 @@ unsigned int len) { struct sockaddr_in si; + int r; memset(&si, 0, sizeof(si)); si.sin_family = AF_INET; si.sin_port = L_CPU_TO_BE16(DHCP_PORT_SERVER); si.sin_addr.s_addr = client->lease->server_address; - return client->transport->send(client->transport, &si, request, len); + + /* + * sendto() might fail with an EPERM error, which most likely means + * that the unicast was prevented by netfilter. Ignore this case + * and assume that once the REBINDING timeout is hit, a broadcast + * will go through which will have a chance of renewing the lease + */ + r = client->transport->send(client->transport, &si, request, len); + if (r == -EPERM) { + CLIENT_DEBUG("transport->send() failed with EPERM -> ignore"); + CLIENT_DEBUG("Is a firewall denying unicast DHCP packets?"); + return 0; + } + + return r; } static int dhcp_client_send_request(struct l_dhcp_client *client) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/ap.c new/iwd-2.1/src/ap.c --- old/iwd-2.0/src/ap.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/ap.c 2022-12-18 20:59:36.000000000 +0100 @@ -70,6 +70,7 @@ char ssid[33]; char passphrase[64]; uint8_t psk[32]; + enum band_freq band; uint8_t channel; uint8_t *authorized_macs; unsigned int authorized_macs_num; @@ -985,7 +986,7 @@ frame_xchg_cb_t callback, void *user_data) { - uint32_t ch_freq = band_channel_to_freq(ap->channel, BAND_FREQ_2_4_GHZ); + uint32_t ch_freq = band_channel_to_freq(ap->channel, ap->band); uint64_t wdev_id = netdev_get_wdev_id(ap->netdev); struct iovec iov[2]; @@ -2408,7 +2409,7 @@ uint32_t nl_akm = CRYPTO_AKM_PSK; uint32_t wpa_version = NL80211_WPA_VERSION_2; uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - uint32_t ch_freq = band_channel_to_freq(ap->channel, BAND_FREQ_2_4_GHZ); + uint32_t ch_freq = band_channel_to_freq(ap->channel, ap->band); uint32_t ch_width = NL80211_CHAN_WIDTH_20; unsigned int i; @@ -3170,6 +3171,33 @@ return list; } +static bool ap_validate_band_channel(struct ap_state *ap) +{ + struct wiphy *wiphy = netdev_get_wiphy(ap->netdev); + uint32_t freq; + const struct band_freq_attrs *attr; + + if (!(wiphy_get_supported_bands(wiphy) & ap->band)) { + l_error("AP hardware does not support band"); + return -EINVAL; + } + + freq = band_channel_to_freq(ap->channel, ap->band); + if (!freq) { + l_error("AP invalid band (%s) and channel (%u) combination", + (ap->band & BAND_FREQ_5_GHZ) ? "5Ghz" : "2.4GHz", + ap->channel); + return false; + } + + attr = wiphy_get_frequency_info(wiphy, freq); + if (!attr || attr->disabled) { + l_error("AP frequency %u disabled or unsupported", freq); + return false; + } + return true; +} + static int ap_load_config(struct ap_state *ap, const struct l_settings *config, bool *out_cck_rates) { @@ -3214,17 +3242,31 @@ unsigned int uintval; if (!l_settings_get_uint(config, "General", "Channel", - &uintval) || - !band_channel_to_freq(uintval, - BAND_FREQ_2_4_GHZ)) { + &uintval)) { l_error("AP Channel value unsupported"); return -EINVAL; } ap->channel = uintval; - } else + + /* + * 6GHz is not supported so we can use only a channel number to + * distinguish between 2.4 and 5GHz. + */ + if (ap->channel >= 36) + ap->band = BAND_FREQ_5_GHZ; + else + ap->band = BAND_FREQ_2_4_GHZ; + } else { /* TODO: Start a Get Survey to decide the channel */ ap->channel = 6; + ap->band = BAND_FREQ_2_4_GHZ; + } + + if (!ap_validate_band_channel(ap)) { + l_error("AP Band and Channel combination invalid"); + return -EINVAL; + } strval = l_settings_get_string(config, "WSC", "DeviceName"); if (strval) { @@ -3290,7 +3332,13 @@ l_strfreev(strvval); } - if (l_settings_get_value(config, "General", "NoCCKRates")) { + /* + * Since 5GHz won't ever support only CCK rates we can ignore this + * setting on that band. + */ + if (ap->band & BAND_FREQ_5_GHZ) + *out_cck_rates = false; + else if (l_settings_get_value(config, "General", "NoCCKRates")) { bool boolval; if (!l_settings_get_bool(config, "General", "NoCCKRates", @@ -3381,6 +3429,9 @@ uint64_t wdev_id = netdev_get_wdev_id(netdev); int err; bool cck_rates = true; + const uint8_t *rates; + unsigned int num_rates; + unsigned int i; if (L_WARN_ON(!config)) { if (err_out) @@ -3406,22 +3457,17 @@ wsc_uuid_from_addr(netdev_get_address(netdev), ap->wsc_uuid_r); + rates = wiphy_get_supported_rates(wiphy, ap->band, &num_rates); + if (!rates) + goto error; + ap->rates = l_uintset_new(200); - /* TODO: Pick from actual supported rates */ - if (!cck_rates) { - l_uintset_put(ap->rates, 12); /* 6 Mbps*/ - l_uintset_put(ap->rates, 18); /* 9 Mbps*/ - l_uintset_put(ap->rates, 24); /* 12 Mbps*/ - l_uintset_put(ap->rates, 36); /* 18 Mbps*/ - l_uintset_put(ap->rates, 48); /* 24 Mbps*/ - l_uintset_put(ap->rates, 72); /* 36 Mbps*/ - l_uintset_put(ap->rates, 96); /* 48 Mbps*/ - l_uintset_put(ap->rates, 108); /* 54 Mbps*/ - } else { - l_uintset_put(ap->rates, 2); /* 1 Mbps*/ - l_uintset_put(ap->rates, 11); /* 5.5 Mbps*/ - l_uintset_put(ap->rates, 22); /* 11 Mbps*/ + for (i = 0; i < num_rates; i++) { + if (cck_rates && !L_IN_SET(rates[i], 2, 4, 11, 22)) + continue; + + l_uintset_put(ap->rates, rates[i]); } if (!frame_watch_add(wdev_id, 0, 0x0000 | @@ -4080,7 +4126,7 @@ if (!ap_if->ap || !ap_if->ap->started) return false; - freq = band_channel_to_freq(ap_if->ap->channel, BAND_FREQ_2_4_GHZ); + freq = band_channel_to_freq(ap_if->ap->channel, ap_if->ap->band); l_dbus_message_builder_append_basic(builder, 'u', &freq); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/band.c new/iwd-2.1/src/band.c --- old/iwd-2.0/src/band.c 2022-09-07 20:42:27.000000000 +0200 +++ new/iwd-2.1/src/band.c 2022-12-18 20:59:36.000000000 +0100 @@ -36,6 +36,8 @@ if (band->he_capabilities) l_queue_destroy(band->he_capabilities, l_free); + l_free(band->freq_attrs); + l_free(band); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/band.h new/iwd-2.1/src/band.h --- old/iwd-2.0/src/band.h 2022-09-07 20:42:27.000000000 +0200 +++ new/iwd-2.1/src/band.h 2022-12-18 20:59:36.000000000 +0100 @@ -55,8 +55,16 @@ uint8_t he_mcs_set[12]; }; +struct band_freq_attrs { + bool supported : 1; + bool disabled : 1; + bool no_ir : 1; +} __attribute__ ((packed)); + struct band { enum band_freq freq; + struct band_freq_attrs *freq_attrs; + size_t freqs_len; /* Each entry is type struct band_he_capabilities */ struct l_queue *he_capabilities; uint8_t vht_mcs_set[8]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/ft.c new/iwd-2.1/src/ft.c --- old/iwd-2.0/src/ft.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/ft.c 2022-12-18 20:59:36.000000000 +0100 @@ -54,8 +54,12 @@ uint8_t *authenticator_ie; uint8_t prev_bssid[6]; uint32_t frequency; + uint32_t ds_frequency; uint32_t offchannel_id; + struct l_timeout *timeout; + struct wiphy_radio_work_item work; + struct ie_ft_info ft_info; bool parsed : 1; @@ -830,6 +834,11 @@ info->parsed = true; + l_timeout_remove(info->timeout); + info->timeout = NULL; + + wiphy_radio_work_done(netdev_get_wiphy(netdev), info->work.id); + return; ft_error: @@ -868,6 +877,9 @@ if (info->authenticator_ie) l_free(info->authenticator_ie); + if (info->timeout) + l_timeout_remove(info->timeout); + l_free(info); } @@ -900,19 +912,17 @@ handshake_state_derive_ptk(hs); } -int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target) +static bool ft_send_action(struct wiphy_radio_work_item *work) { - struct netdev *netdev = netdev_find(ifindex); + struct ft_info *info = l_container_of(work, struct ft_info, work); + struct netdev *netdev = netdev_find(info->ifindex); struct handshake_state *hs = netdev_get_handshake(netdev); - struct ft_info *info; uint8_t ft_req[14]; struct iovec iov[5]; uint8_t ies[512]; size_t len; int ret = -EINVAL; - info = ft_info_new(hs, target); - ft_req[0] = 6; /* FT category */ ft_req[1] = 1; /* FT Request action */ memcpy(ft_req + 2, info->spa, 6); @@ -928,17 +938,47 @@ iov[1].iov_base = ies; iov[1].iov_len = len; - ret = tx_frame(hs->ifindex, 0x00d0, freq, hs->aa, iov, 2); + ret = tx_frame(hs->ifindex, 0x00d0, info->ds_frequency, hs->aa, iov, 2); if (ret < 0) goto failed; l_queue_push_tail(info_list, info); - return 0; + return false; failed: - l_free(info); - return ret; + l_debug("FT-over-DS action failed to "MAC, MAC_STR(hs->aa)); + + ft_info_destroy(info); + return true; +} + +struct wiphy_radio_work_item_ops ft_ops = { + .do_work = ft_send_action, +}; + +static void ft_ds_timeout(struct l_timeout *timeout, void *user_data) +{ + struct ft_info *info = user_data; + struct netdev *netdev = netdev_find(info->ifindex); + + wiphy_radio_work_done(netdev_get_wiphy(netdev), info->work.id); +} + +int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target) +{ + struct netdev *netdev = netdev_find(ifindex); + struct handshake_state *hs = netdev_get_handshake(netdev); + struct ft_info *info; + + info = ft_info_new(hs, target); + info->ds_frequency = freq; + info->timeout = l_timeout_create_ms(200, ft_ds_timeout, info, NULL); + + wiphy_radio_work_insert(netdev_get_wiphy(netdev), &info->work, + WIPHY_WORK_PRIORITY_FT, &ft_ops); + + return 0; } void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/iwd.ap.5 new/iwd-2.1/src/iwd.ap.5 --- old/iwd-2.0/src/iwd.ap.5 2022-11-18 13:35:29.000000000 +0100 +++ new/iwd-2.1/src/iwd.ap.5 2022-12-18 21:03:12.000000000 +0100 @@ -61,8 +61,17 @@ T} T{ Channel number .sp -Optional channel number for the access point to operate on. Only the -2.4GHz\-band channels are currently allowed. +Optional channel number for the access point to operate on. If omitted +the channel will be chosen automatically. Channels greater than or equal +to 36 will select the 5GHz band for the AP to operate on. +.sp +Note: Due to regulatory requirements the linux kernel does not allow or +strictly limits 5GHz use in AP mode while in world roaming. These +frequencies become available once the country is set, either via IWD\(aqs +main.conf option \fB[General].Country\fP (see \fBman iwd.config\fP) or +externally (e.g. iw reg set <CC>). If you are having trouble using 5GHz +ensure the country is set, and that the desired frequency/channel is +unrestricted. T} _ .TE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/iwd.ap.rst new/iwd-2.1/src/iwd.ap.rst --- old/iwd-2.0/src/iwd.ap.rst 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/iwd.ap.rst 2022-12-18 20:59:36.000000000 +0100 @@ -55,8 +55,17 @@ * - Channel - Channel number - Optional channel number for the access point to operate on. Only the - 2.4GHz-band channels are currently allowed. + Optional channel number for the access point to operate on. If omitted + the channel will be chosen automatically. Channels greater than or equal + to 36 will select the 5GHz band for the AP to operate on. + + Note: Due to regulatory requirements the linux kernel does not allow or + strictly limits 5GHz use in AP mode while in world roaming. These + frequencies become available once the country is set, either via IWD's + main.conf option ``[General].Country`` (see ``man iwd.config``) or + externally (e.g. iw reg set <CC>). If you are having trouble using 5GHz + ensure the country is set, and that the desired frequency/channel is + unrestricted. Network Authentication Settings ------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/iwd.config.5 new/iwd-2.1/src/iwd.config.5 --- old/iwd-2.0/src/iwd.config.5 2022-11-18 13:35:27.000000000 +0100 +++ new/iwd-2.1/src/iwd.config.5 2022-12-18 21:03:10.000000000 +0100 @@ -274,7 +274,7 @@ .sp Sets the global default that tells \fBiwd\fP whether it should configure IPv6 addresses and routes (either provided via static settings, -Router Advertisements or DHCPv6 protocol). This setting is disabled +Router Advertisements or DHCPv6 protocol). This setting is enabled by default. This setting can also be overridden on a per\-network basis. T} _ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/iwd.config.rst new/iwd-2.1/src/iwd.config.rst --- old/iwd-2.0/src/iwd.config.rst 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/iwd.config.rst 2022-12-18 20:59:36.000000000 +0100 @@ -232,7 +232,7 @@ Sets the global default that tells **iwd** whether it should configure IPv6 addresses and routes (either provided via static settings, - Router Advertisements or DHCPv6 protocol). This setting is disabled + Router Advertisements or DHCPv6 protocol). This setting is enabled by default. This setting can also be overridden on a per-network basis. * - NameResolvingService diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/nl80211util.c new/iwd-2.1/src/nl80211util.c --- old/iwd-2.0/src/nl80211util.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/nl80211util.c 2022-12-18 20:59:36.000000000 +0100 @@ -502,19 +502,21 @@ int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs, struct scan_freq_set *supported_list, - struct scan_freq_set *disabled_list) + struct band_freq_attrs *list, + size_t num_channels) { uint16_t type, len; const void *data; struct l_genl_attr attr; struct l_genl_attr nested; + uint8_t channel; if (!l_genl_attr_recurse(band_freqs, &nested)) return -EBADMSG; while (l_genl_attr_next(&nested, NULL, NULL, NULL)) { uint32_t freq = 0; - bool disabled = false; + struct band_freq_attrs freq_attr = { 0 }; if (!l_genl_attr_recurse(&nested, &attr)) continue; @@ -523,9 +525,13 @@ switch (type) { case NL80211_FREQUENCY_ATTR_FREQ: freq = *((uint32_t *) data); + freq_attr.supported = true; break; case NL80211_FREQUENCY_ATTR_DISABLED: - disabled = true; + freq_attr.disabled = true; + break; + case NL80211_FREQUENCY_ATTR_NO_IR: + freq_attr.no_ir = true; break; } } @@ -533,11 +539,17 @@ if (!freq) continue; + channel = band_freq_to_channel(freq, NULL); + if (!channel) + continue; + + if (L_WARN_ON(channel > num_channels)) + continue; + if (supported_list) scan_freq_set_add(supported_list, freq); - if (disabled && disabled_list) - scan_freq_set_add(disabled_list, freq); + list[channel] = freq_attr; } return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/nl80211util.h new/iwd-2.1/src/nl80211util.h --- old/iwd-2.0/src/nl80211util.h 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/nl80211util.h 2022-12-18 20:59:36.000000000 +0100 @@ -24,6 +24,7 @@ struct band_chandef; struct scan_freq_set; +struct band_freq_attrs; int nl80211_parse_attrs(struct l_genl_msg *msg, int tag, ...); @@ -58,5 +59,6 @@ int nl80211_parse_chandef(struct l_genl_msg *msg, struct band_chandef *out); int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs, - struct scan_freq_set *supported, - struct scan_freq_set *disabled); + struct scan_freq_set *supported_list, + struct band_freq_attrs *list, + size_t num_channels); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/scan.c new/iwd-2.1/src/scan.c --- old/iwd-2.0/src/scan.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/scan.c 2022-12-18 20:59:36.000000000 +0100 @@ -83,7 +83,6 @@ bool canceled : 1; /* Is scan_cancel being called on this request? */ bool passive:1; /* Active or Passive scan? */ bool started : 1; /* Has TRIGGER_SCAN succeeded at least once? */ - bool periodic : 1; /* Started as a periodic scan? */ /* * Set to true if the TRIGGER_SCAN command at the head of the 'cmds' * queue was acked by the kernel indicating that the scan request was @@ -426,7 +425,7 @@ * rates we don't want to advertise support for 802.11b rates. */ if (L_WARN_ON(!(supported = wiphy_get_supported_rates(sc->wiphy, - NL80211_BAND_2GHZ, + BAND_FREQ_2_4_GHZ, &num_supported)))) goto done; @@ -997,7 +996,6 @@ static bool scan_periodic_queue(struct scan_context *sc) { struct scan_parameters params = {}; - struct scan_request *sr; if (sc->sp.needs_active_scan && known_networks_has_hidden()) { params.randomize_mac_addr_hint = true; @@ -1015,13 +1013,7 @@ scan_periodic_notify, sc, scan_periodic_destroy); - if (!sc->sp.id) - return false; - - sr = l_queue_peek_tail(sc->requests); - sr->periodic = true; - - return true; + return sc->sp.id != 0; } static bool scan_periodic_is_disabled(void) @@ -1933,12 +1925,9 @@ struct scan_freq_set *freqs_6ghz; struct scan_freq_set *allowed; bool allow_6g; - const struct scan_freq_set *supported = - wiphy_get_supported_freqs(wiphy); - /* Only care about regulatory events, and if 6GHz capable */ - if (event != WIPHY_STATE_WATCH_EVENT_REGDOM_DONE || - !(scan_freq_set_get_bands(supported) & BAND_FREQ_6_GHZ)) + /* Only care about completed regulatory dumps */ + if (event != WIPHY_STATE_WATCH_EVENT_REGDOM_DONE) return; if (!sc->sp.id) @@ -2242,13 +2231,7 @@ if (sr->triggered) { sr->triggered = false; - - /* If periodic scan, don't report the abort */ - if (sr->periodic) { - l_queue_remove(sc->requests, sr); - wiphy_radio_work_done(sc->wiphy, sr->work.id); - } else - scan_finished(sc, -ECANCELED, NULL, NULL, sr); + scan_finished(sc, -ECANCELED, NULL, NULL, sr); } else if (wiphy_radio_work_is_running(sc->wiphy, sr->work.id)) { /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/station.c new/iwd-2.1/src/station.c --- old/iwd-2.0/src/station.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/station.c 2022-12-18 20:59:36.000000000 +0100 @@ -1407,8 +1407,6 @@ { _auto_(scan_freq_set_free) struct scan_freq_set *known_freq_set = NULL; bool known_6ghz; - const struct scan_freq_set *disabled = wiphy_get_disabled_freqs( - station->wiphy); if (wiphy_regdom_is_updating(station->wiphy)) { l_debug("regdom is updating, delaying quick scan"); @@ -1430,9 +1428,11 @@ * this since its so limited, so return an error which will fall back to * full autoconnect. */ - if ((scan_freq_set_get_bands(disabled) & BAND_FREQ_6_GHZ) && - wiphy_country_is_unknown(station->wiphy) && - known_6ghz) + if (wiphy_get_supported_bands(station->wiphy) & BAND_FREQ_6_GHZ && + wiphy_band_is_disabled(station->wiphy, + BAND_FREQ_6_GHZ) && + wiphy_country_is_unknown(station->wiphy) && + known_6ghz) return -ENOTSUP; if (!wiphy_constrain_freq_set(station->wiphy, known_freq_set)) { @@ -1812,10 +1812,6 @@ struct scan_freq_set *freq_set_md, *freq_set_no_md; uint32_t current_freq = 0; struct handshake_state *hs = netdev_get_handshake(station->netdev); - const struct scan_freq_set *supported = - wiphy_get_supported_freqs(station->wiphy); - const struct scan_freq_set *disabled = - wiphy_get_disabled_freqs(station->wiphy); freq_set_md = scan_freq_set_new(); freq_set_no_md = scan_freq_set_new(); @@ -1828,6 +1824,7 @@ uint32_t freq; enum band_freq band; const uint8_t *cc = NULL; + const struct band_freq_attrs *attr; if (ie_tlv_iter_get_tag(&iter) != IE_TYPE_NEIGHBOR_REPORT) continue; @@ -1853,8 +1850,8 @@ continue; /* Skip if frequency is not supported or disabled */ - if (!scan_freq_set_contains(supported, freq) || - scan_freq_set_contains(disabled, freq)) + attr = wiphy_get_frequency_info(station->wiphy, freq); + if (!attr || attr->disabled) continue; if (!memcmp(info.addr, @@ -1973,47 +1970,6 @@ return true; } -static void station_ft_ds_action_start(struct station *station) -{ - struct handshake_state *hs = netdev_get_handshake(station->netdev); - uint16_t mdid; - const struct l_queue_entry *entry; - struct scan_bss *bss; - struct ie_rsn_info rsn_info; - - if (!station_can_fast_transition(hs, station->connected_bss) || - !(hs->mde[4] & 1)) - return; - - if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, - &mdid, NULL, NULL) < 0) - return; - - for (entry = network_bss_list_get_entries(station->connected_network); - entry; entry = entry->next) { - bss = entry->data; - - if (bss == station->connected_bss) - continue; - - if (mdid != l_get_le16(bss->mde)) - continue; - - if (scan_bss_get_rsn_info(bss, &rsn_info) < 0) - continue; - - if (!IE_AKM_IS_FT(rsn_info.akm_suites)) - continue; - - /* - * Fire and forget. Netdev will maintain a cache of responses - * and when the time comes these can be referenced for a roam - */ - ft_action(netdev_get_ifindex(station->netdev), - station->connected_bss->frequency, bss); - } -} - static void station_roamed(struct station *station) { station->roam_scan_full = false; @@ -2042,8 +1998,6 @@ l_queue_clear(station->roam_bss_list, l_free); - station_ft_ds_action_start(station); - station_enter_state(station, STATION_STATE_CONNECTED); } @@ -2297,7 +2251,7 @@ ret = ft_associate(netdev_get_ifindex(station->netdev), bss->addr); if (ret == -ENOENT) { - station_debug_event(station, "ft-over-air-roam-failed"); + station_debug_event(station, "ft-roam-failed"); try_next: station_transition_start(station); return true; @@ -2327,7 +2281,6 @@ const struct network_info *info = network_get_info(connected); const struct iovec *vendor_ies; size_t iov_elems = 0; - int ret; /* Rebuild handshake RSN for target AP */ if (station_build_handshake_rsn(hs, station->wiphy, @@ -2338,34 +2291,17 @@ vendor_ies = network_info_get_extra_ies(info, bss, &iov_elems); handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems); - if ((hs->mde[4] & 1)) { - ret = ft_associate(netdev_get_ifindex(station->netdev), - bss->addr); - /* No action responses from this BSS, try over air */ - if (ret == -ENOENT) { - station_debug_event(station, "try-ft-over-air"); - goto try_over_air; - } else if (ret < 0) - return false; - - station->connected_bss = bss; - station->preparing_roam = false; - station_enter_state(station, STATION_STATE_FT_ROAMING); - - return true; - } else { -try_over_air: - /* - * Send FT-Authenticate and insert a work item which will be - * gated until authentication completes - */ + /* Both ft_action/ft_authenticate will gate the associate work item */ + if ((hs->mde[4] & 1)) + ft_action(netdev_get_ifindex(station->netdev), + station->connected_bss->frequency, bss); + else ft_authenticate(netdev_get_ifindex(station->netdev), bss); - wiphy_radio_work_insert(station->wiphy, &station->ft_work, + wiphy_radio_work_insert(station->wiphy, &station->ft_work, WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops); - return true; - } + return true; } static bool station_try_next_transition(struct station *station, @@ -3117,8 +3053,6 @@ l_warn("Could not request neighbor report"); } - station_ft_ds_action_start(station); - network_connected(station->connected_network); if (station->netconfig) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/util.c new/iwd-2.1/src/util.c --- old/iwd-2.0/src/util.c 2022-09-07 20:42:27.000000000 +0200 +++ new/iwd-2.1/src/util.c 2022-12-18 20:59:36.000000000 +0100 @@ -360,6 +360,28 @@ return false; } +bool scan_freq_set_remove(struct scan_freq_set *freqs, uint32_t freq) +{ + enum band_freq band; + uint8_t channel; + + channel = band_freq_to_channel(freq, &band); + if (!channel) + return false; + + switch (band) { + case BAND_FREQ_2_4_GHZ: + freqs->channels_2ghz &= ~(1 << (channel - 1)); + return true; + case BAND_FREQ_5_GHZ: + return l_uintset_take(freqs->channels_5ghz, channel); + case BAND_FREQ_6_GHZ: + return l_uintset_take(freqs->channels_6ghz, channel); + } + + return false; +} + bool scan_freq_set_contains(const struct scan_freq_set *freqs, uint32_t freq) { enum band_freq band; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/util.h new/iwd-2.1/src/util.h --- old/iwd-2.0/src/util.h 2022-09-07 20:42:27.000000000 +0200 +++ new/iwd-2.1/src/util.h 2022-12-18 20:59:36.000000000 +0100 @@ -111,6 +111,7 @@ struct scan_freq_set *scan_freq_set_new(void); void scan_freq_set_free(struct scan_freq_set *freqs); bool scan_freq_set_add(struct scan_freq_set *freqs, uint32_t freq); +bool scan_freq_set_remove(struct scan_freq_set *freqs, uint32_t freq); bool scan_freq_set_contains(const struct scan_freq_set *freqs, uint32_t freq); uint32_t scan_freq_set_get_bands(const struct scan_freq_set *freqs); void scan_freq_set_foreach(const struct scan_freq_set *freqs, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/wiphy.c new/iwd-2.1/src/wiphy.c --- old/iwd-2.0/src/wiphy.c 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/wiphy.c 2022-12-18 20:59:36.000000000 +0100 @@ -496,6 +496,67 @@ return wiphy->disabled_freqs; } +static struct band *wiphy_get_band(const struct wiphy *wiphy, enum band_freq band) +{ + switch (band) { + case BAND_FREQ_2_4_GHZ: + return wiphy->band_2g; + case BAND_FREQ_5_GHZ: + return wiphy->band_5g; + case BAND_FREQ_6_GHZ: + return wiphy->band_6g; + default: + return NULL; + } +} + +const struct band_freq_attrs *wiphy_get_frequency_info( + const struct wiphy *wiphy, + uint32_t freq) +{ + struct band_freq_attrs *attr; + enum band_freq band; + uint8_t channel; + struct band *bandp; + + channel = band_freq_to_channel(freq, &band); + if (!channel) + return NULL; + + bandp = wiphy_get_band(wiphy, band); + if (!bandp) + return NULL; + + attr = &bandp->freq_attrs[channel]; + if (!attr->supported) + return NULL; + + return attr; +} + +bool wiphy_band_is_disabled(const struct wiphy *wiphy, enum band_freq band) +{ + struct band_freq_attrs attr; + unsigned int i; + struct band *bandp; + + bandp = wiphy_get_band(wiphy, band); + if (!bandp) + return true; + + for (i = 0; i < bandp->freqs_len; i++) { + attr = bandp->freq_attrs[i]; + + if (!attr.supported) + continue; + + if (!attr.disabled) + return false; + } + + return true; +} + bool wiphy_supports_probe_resp_offload(struct wiphy *wiphy) { return wiphy->ap_probe_resp_offload; @@ -745,8 +806,35 @@ bool wiphy_constrain_freq_set(const struct wiphy *wiphy, struct scan_freq_set *set) { + struct band *bands[3] = { wiphy->band_2g, + wiphy->band_5g, wiphy->band_6g }; + unsigned int b; + unsigned int i; + scan_freq_set_constrain(set, wiphy->supported_freqs); - scan_freq_set_subtract(set, wiphy->disabled_freqs); + + for (b = 0; b < L_ARRAY_SIZE(bands); b++) { + struct band *band = bands[b]; + + if (!band) + continue; + + for (i = 0; i < band->freqs_len; i++) { + uint32_t freq; + + if (!band->freq_attrs[i].supported) + continue; + + if (!band->freq_attrs[i].disabled) + continue; + + freq = band_channel_to_freq(i, band->freq); + if (!freq) + continue; + + scan_freq_set_remove(set, freq); + } + } if (!scan_freq_set_get_bands(set)) /* The set is empty. */ @@ -788,24 +876,11 @@ return wiphy->supported_iftypes & (1 << (iftype - 1)); } -const uint8_t *wiphy_get_supported_rates(struct wiphy *wiphy, unsigned int band, +const uint8_t *wiphy_get_supported_rates(struct wiphy *wiphy, + enum band_freq band, unsigned int *out_num) { - struct band *bandp; - - switch (band) { - case NL80211_BAND_2GHZ: - bandp = wiphy->band_2g; - break; - case NL80211_BAND_5GHZ: - bandp = wiphy->band_5g; - break; - case NL80211_BAND_6GHZ: - bandp = wiphy->band_6g; - break; - default: - return NULL; - } + struct band *bandp = wiphy_get_band(wiphy, band); if (!bandp) return NULL; @@ -863,19 +938,9 @@ if (band_freq_to_channel(bss->frequency, &band) == 0) return -ENOTSUP; - switch (band) { - case BAND_FREQ_2_4_GHZ: - bandp = wiphy->band_2g; - break; - case BAND_FREQ_5_GHZ: - bandp = wiphy->band_5g; - break; - case BAND_FREQ_6_GHZ: - bandp = wiphy->band_6g; - break; - default: + bandp = wiphy_get_band(wiphy, band); + if (!bandp) return -ENOTSUP; - } ie_tlv_iter_init(&iter, ies, ies_len); @@ -951,7 +1016,7 @@ bool wiphy_regdom_is_updating(struct wiphy *wiphy) { - return wiphy->pending_freqs != NULL; + return wiphy->dump_id || (!wiphy->self_managed && wiphy_dump_id); } uint32_t wiphy_state_watch_add(struct wiphy *wiphy, @@ -1470,19 +1535,23 @@ struct band **bandp; struct band *band; enum band_freq freq; + size_t num_channels; switch (type) { case NL80211_BAND_2GHZ: bandp = &wiphy->band_2g; freq = BAND_FREQ_2_4_GHZ; + num_channels = 14; break; case NL80211_BAND_5GHZ: bandp = &wiphy->band_5g; freq = BAND_FREQ_5_GHZ; + num_channels = 196; break; case NL80211_BAND_6GHZ: bandp = &wiphy->band_6g; freq = BAND_FREQ_6_GHZ; + num_channels = 233; break; default: continue; @@ -1497,6 +1566,9 @@ continue; band->freq = freq; + band->freq_attrs = l_new(struct band_freq_attrs, + num_channels); + band->freqs_len = num_channels; /* Reset iter to beginning */ if (!l_genl_attr_recurse(bands, &attr)) { @@ -1506,7 +1578,6 @@ } else band = *bandp; - while (l_genl_attr_next(&attr, &type, &len, &data)) { struct l_genl_attr nested; @@ -1514,7 +1585,8 @@ case NL80211_BAND_ATTR_FREQS: nl80211_parse_supported_frequencies(&attr, wiphy->supported_freqs, - wiphy->disabled_freqs); + band->freq_attrs, + band->freqs_len); break; case NL80211_BAND_ATTR_RATES: @@ -1969,6 +2041,7 @@ struct l_genl_attr bands; struct l_genl_attr attr; uint16_t type; + struct band *band; if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &id, NL80211_ATTR_WIPHY_BANDS, &bands, @@ -1979,7 +2052,28 @@ if (L_WARN_ON(!wiphy)) return; - while (l_genl_attr_next(&bands, NULL, NULL, NULL)) { + /* Unregistered means the wiphy is blacklisted, don't bother parsing */ + if (!wiphy->registered) + return; + + while (l_genl_attr_next(&bands, &type, NULL, NULL)) { + switch (type) { + case NL80211_BAND_2GHZ: + band = wiphy->band_2g; + break; + case NL80211_BAND_5GHZ: + band = wiphy->band_5g; + break; + case NL80211_BAND_6GHZ: + band = wiphy->band_6g; + break; + default: + continue; + } + + if (L_WARN_ON(!band)) + continue; + if (!l_genl_attr_recurse(&bands, &attr)) return; @@ -1987,8 +2081,14 @@ if (type != NL80211_BAND_ATTR_FREQS) continue; + /* + * Just write over the old list for each frequency. In + * theory no new frequencies should be added so there + * should never be any stale values. + */ nl80211_parse_supported_frequencies(&attr, NULL, - wiphy->pending_freqs); + band->freq_attrs, + band->freqs_len); } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iwd-2.0/src/wiphy.h new/iwd-2.1/src/wiphy.h --- old/iwd-2.0/src/wiphy.h 2022-11-18 13:31:49.000000000 +0100 +++ new/iwd-2.1/src/wiphy.h 2022-12-18 20:59:36.000000000 +0100 @@ -28,7 +28,9 @@ struct scan_freq_set; struct wiphy_radio_work_item; struct ie_rsn_info; +struct band_freq_attrs; enum security; +enum band_freq; typedef bool (*wiphy_radio_work_func_t)(struct wiphy_radio_work_item *item); typedef void (*wiphy_radio_work_destroy_func_t)( @@ -99,6 +101,12 @@ const struct scan_freq_set *wiphy_get_supported_freqs( const struct wiphy *wiphy); const struct scan_freq_set *wiphy_get_disabled_freqs(const struct wiphy *wiphy); + +const struct band_freq_attrs *wiphy_get_frequency_info( + const struct wiphy *wiphy, + uint32_t freq); +bool wiphy_band_is_disabled(const struct wiphy *wiphy, enum band_freq band); + bool wiphy_supports_probe_resp_offload(struct wiphy *wiphy); bool wiphy_can_transition_disable(struct wiphy *wiphy); bool wiphy_can_offload(struct wiphy *wiphy); @@ -112,7 +120,8 @@ uint16_t wiphy_get_max_scan_ie_len(struct wiphy *wiphy); uint32_t wiphy_get_max_roc_duration(struct wiphy *wiphy); bool wiphy_supports_iftype(struct wiphy *wiphy, uint32_t iftype); -const uint8_t *wiphy_get_supported_rates(struct wiphy *wiphy, unsigned int band, +const uint8_t *wiphy_get_supported_rates(struct wiphy *wiphy, + enum band_freq band, unsigned int *out_num); bool wiphy_supports_adhoc_rsn(struct wiphy *wiphy); bool wiphy_can_offchannel_tx(struct wiphy *wiphy);