On 4/24/19 9:03 PM, Matthias Schiffer wrote: > The new regrulelist operation returns the list of regulatory rules, similar > to the `iw reg get` command. The passed ifname must either refer to a PHY, > or be NULL to retrieve the rules for the global regdomain. > > The new operation is implemented for nl80211 only. > > Signed-off-by: Matthias Schiffer <mschif...@universe-factory.net> > --- > include/iwinfo.h | 27 ++++++++++ > iwinfo_nl80211.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 153 insertions(+) > > Usecase: In Gluon we would like to use the regulatory data to filter the > channel list for channels that are valid for indoor / outdoor use.
It seems we have found a simpler solution for Gluon (country3 option in hostapd.conf). So unless someone else considers this a useful feature for libiwinfo, this patch can be rejected. > > > diff --git a/include/iwinfo.h b/include/iwinfo.h > index 9b2ffd1ea111..f7e53c599e5f 100644 > --- a/include/iwinfo.h > +++ b/include/iwinfo.h > @@ -57,6 +57,22 @@ > #define IWINFO_FREQ_NO_160MHZ (1 << 5) > #define IWINFO_FREQ_NO_2160MHZ (1 << 6) > > +#define IWINFO_REGRULE_NO_OFDM (1 << 0) > +#define IWINFO_REGRULE_NO_CCK (1 << 1) > +#define IWINFO_REGRULE_NO_INDOOR (1 << 2) > +#define IWINFO_REGRULE_NO_OUTDOOR (1 << 3) > +#define IWINFO_REGRULE_DFS (1 << 4) > +#define IWINFO_REGRULE_PTP_ONLY (1 << 5) > +#define IWINFO_REGRULE_AUTO_BW (1 << 6) > +#define IWINFO_REGRULE_IR_CONCURRENT (1 << 7) > +#define IWINFO_REGRULE_NO_HT40MINUS (1 << 8) > +#define IWINFO_REGRULE_NO_HT40PLUS (1 << 9) > +#define IWINFO_REGRULE_NO_80MHZ (1 << 10) > +#define IWINFO_REGRULE_NO_160MHZ (1 << 11) > +#define IWINFO_REGRULE_NO_IR (1 << 12) > +#define IWINFO_REGRULE_PASSIVE_SCAN (1 << 13) > +#define IWINFO_REGRULE_NO_IBSS (1 << 14) > + > extern const char *IWINFO_CIPHER_NAMES[IWINFO_CIPHER_COUNT]; > extern const char *IWINFO_KMGMT_NAMES[IWINFO_KMGMT_COUNT]; > extern const char *IWINFO_AUTH_NAMES[IWINFO_AUTH_COUNT]; > @@ -183,6 +199,16 @@ struct iwinfo_country_entry { > char ccode[4]; > }; > > +struct iwinfo_regrule_entry { > + uint32_t start_freq_khz; > + uint32_t end_freq_khz; > + uint32_t max_bw_khz; > + uint32_t max_ant_gain_mbi; > + uint32_t max_eirp_mbm; > + uint32_t dfs_cac_time_ms; > + uint32_t flags; > +}; > + > struct iwinfo_iso3166_label { > uint16_t iso3166; > char name[28]; > @@ -242,6 +268,7 @@ struct iwinfo_ops { > int (*freqlist)(const char *, char *, int *); > int (*countrylist)(const char *, char *, int *); > int (*survey)(const char *, char *, int *); > + int (*regrulelist)(const char *, char *, int *); > int (*lookup_phy)(const char *, char *); > void (*close)(void); > }; > diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c > index 200be28d9a44..9b1efea2f4b5 100644 > --- a/iwinfo_nl80211.c > +++ b/iwinfo_nl80211.c > @@ -2732,6 +2732,131 @@ static int nl80211_get_countrylist(const char > *ifname, char *buf, int *len) > return 0; > } > > +static int nl80211_get_regrulelist_cb(struct nl_msg *msg, void *arg) { > + struct nl80211_array_buf *arr = arg; > + struct iwinfo_regrule_entry *e; > + const char *const end = (char *)arr->buf + IWINFO_BUFSIZE; > + > + uint32_t flags; > + int rule_rem; > + > + struct nlattr **attr = nl80211_parse(msg); > + struct nlattr *rule; > + struct nlattr *rule_attr[NL80211_REG_RULE_ATTR_MAX + 1]; > + > + e = arr->buf; > + e += arr->count; > + > + if (!attr[NL80211_ATTR_REG_RULES]) > + return NL_SKIP; > + > + nla_for_each_nested(rule, attr[NL80211_ATTR_REG_RULES], rule_rem) > + { > + if ((char *)(e+1) > end) > + break; // We're out of buffer space... > + > + nla_parse(rule_attr, NL80211_REG_RULE_ATTR_MAX, nla_data(rule), > nla_len(rule), NULL); > + > + if ( > + !rule_attr[NL80211_ATTR_REG_RULE_FLAGS] || > + !rule_attr[NL80211_ATTR_FREQ_RANGE_START] || > + !rule_attr[NL80211_ATTR_FREQ_RANGE_END] || > + !rule_attr[NL80211_ATTR_FREQ_RANGE_MAX_BW] || > + !rule_attr[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] || > + !rule_attr[NL80211_ATTR_POWER_RULE_MAX_EIRP] > + ) > + continue; > + > + flags = nla_get_u32(rule_attr[NL80211_ATTR_REG_RULE_FLAGS]); > + > + e->flags = 0; > + e->start_freq_khz = > nla_get_u32(rule_attr[NL80211_ATTR_FREQ_RANGE_START]); > + e->end_freq_khz = > nla_get_u32(rule_attr[NL80211_ATTR_FREQ_RANGE_END]); > + e->max_bw_khz = > nla_get_u32(rule_attr[NL80211_ATTR_FREQ_RANGE_MAX_BW]); > + e->max_ant_gain_mbi = > nla_get_u32(rule_attr[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); > + e->max_eirp_mbm = > nla_get_u32(rule_attr[NL80211_ATTR_POWER_RULE_MAX_EIRP]); > + > + if ((flags & NL80211_RRF_DFS) && > rule_attr[NL80211_ATTR_DFS_CAC_TIME]) { > + e->dfs_cac_time_ms = > nla_get_u32(rule_attr[NL80211_ATTR_DFS_CAC_TIME]); > + } > + > +#define HANDLE_FLAG(flag) \ > + do { \ > + if (flags & NL80211_RRF_##flag) \ > + e->flags |= IWINFO_REGRULE_##flag; \ > + } while (0) > + > + HANDLE_FLAG(NO_OFDM); > + HANDLE_FLAG(NO_CCK); > + HANDLE_FLAG(NO_INDOOR); > + HANDLE_FLAG(NO_OUTDOOR); > + HANDLE_FLAG(DFS); > + HANDLE_FLAG(PTP_ONLY); > + HANDLE_FLAG(AUTO_BW); > + HANDLE_FLAG(IR_CONCURRENT); > + HANDLE_FLAG(NO_HT40MINUS); > + HANDLE_FLAG(NO_HT40PLUS); > + HANDLE_FLAG(NO_80MHZ); > + HANDLE_FLAG(NO_160MHZ); > + > + /* Logic taken from iw */ > + if ((flags & NL80211_RRF_NO_IR) && (flags & > __NL80211_RRF_NO_IBSS)) { > + e->flags |= IWINFO_REGRULE_NO_IR; > + } else { > + HANDLE_FLAG(PASSIVE_SCAN); > + > + if (flags & __NL80211_RRF_NO_IBSS) > + e->flags |= IWINFO_REGRULE_NO_IBSS; > + } > + > +#undef HANDLE_FLAG > + > + e++; > + arr->count++; > + } > + > + return NL_SKIP; > +} > + > +static int nl80211_get_regrulelist(const char *ifname, char *buf, int *len) > +{ > + struct nl80211_msg_conveyor *cv; > + struct nl80211_array_buf arr = { .buf = buf, .count = 0 }; > + int phyidx = -1; > + > + if (nl80211_init() < 0) > + goto out; > + > + if (ifname) { > + if (!strncmp(ifname, "phy", 3)) > + phyidx = atoi(&ifname[3]); > + else if (!strncmp(ifname, "radio", 5)) > + phyidx = nl80211_phy_idx_from_uci(ifname); > + > + if (phyidx < 0) > + goto out; > + } > + > + cv = nl80211_new(nls->nl80211, NL80211_CMD_GET_REG, 0); > + if (!cv) > + goto out; > + > + if (ifname) > + NLA_PUT_U32(cv->msg, NL80211_ATTR_WIPHY, phyidx); > + > + if (nl80211_send(cv, nl80211_get_regrulelist_cb, &arr)) > + goto out; > + > + *len = arr.count * sizeof(struct iwinfo_regrule_entry); > + return 0; > + > +nla_put_failure: > + nl80211_free(cv); > +out: > + *len = 0; > + return -1; > +} > + > > struct nl80211_modes > { > @@ -3045,6 +3170,7 @@ const struct iwinfo_ops nl80211_ops = { > .freqlist = nl80211_get_freqlist, > .countrylist = nl80211_get_countrylist, > .survey = nl80211_get_survey, > + .regrulelist = nl80211_get_regrulelist, > .lookup_phy = nl80211_lookup_phyname, > .close = nl80211_close > }; >
signature.asc
Description: OpenPGP digital signature
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel