Hello community, here is the log from the commit of package iw for openSUSE:Factory checked in at 2019-08-16 15:31:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/iw (Old) and /work/SRC/openSUSE:Factory/.iw.new.22127 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "iw" Fri Aug 16 15:31:07 2019 rev:33 rq:723182 version:5.3 Changes: -------- --- /work/SRC/openSUSE:Factory/iw/iw.changes 2019-02-27 15:05:12.478463922 +0100 +++ /work/SRC/openSUSE:Factory/.iw.new.22127/iw.changes 2019-08-16 15:31:09.533952081 +0200 @@ -1,0 +2,32 @@ +Mon Aug 12 14:42:54 UTC 2019 - Xaver Hellauer <[email protected]> + +- Update to version 5.3 + * info: update extended feature list + * info: macro-ify ext_feat_print() + * util: update command list + * iw: print HE capabilities + * iw: really fix build + * iw: add HE support to station dump call + * cac: fix error handling in channel parsing + * nan: fix memory leak + * mesh: initialize err in set_interface_meshparam() + * iw: fix fp handling inside handle_vendor + * iw: fix memory leaks inside handle_scan + * iw: fix memory leak inside parse_sched_scan + * iw: fix fd leak inside handle_netns + * iw: fix memory leak inside handle_cac + * iw: fix endless loop inside handle_mgmt_dump + * iw: fix memory leak inside register_mgmt_frame + * iw: add version.o to objects + * iw: include all C files into the binary + * iw: change __cmd section scheme to fit gcc/clang + * iw: Add support for controlling tx power for per station + * iw: add command to inject a frame via direct mesh link to mesh peer + * iw: print 4ADDR attribute when dumping interface + * iw: small cleanup for the sizer code + * iw: fix cmd_size determination with LTO + * iw: Print airtime fairness feature + * iw: Add command to set airtime weight + * iw: Add printing of station tx duration and airtim + +------------------------------------------------------------------- Old: ---- iw-5.0.1.tar.xz New: ---- iw-5.3.tar.sign iw-5.3.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ iw.spec ++++++ --- /var/tmp/diff_new_pack.PmfO2a/_old 2019-08-16 15:31:10.077951924 +0200 +++ /var/tmp/diff_new_pack.PmfO2a/_new 2019-08-16 15:31:10.081951922 +0200 @@ -17,13 +17,14 @@ Name: iw -Version: 5.0.1 +Version: 5.3 Release: 0 Summary: Configuration utility for nl80211 based wireless drivers License: ISC Group: Hardware/Wifi Url: https://wireless.wiki.kernel.org/en/users/documentation/iw Source: https://kernel.org/pub/software/network/iw/iw-%{version}.tar.xz +Source2: https://kernel.org/pub/software/network/iw/iw-%{version}.tar.sign BuildRequires: pkgconfig BuildRequires: pkgconfig(libnl-3.0) BuildRoot: %{_tmppath}/%{name}-%{version}-build ++++++ iw-5.0.1.tar.xz -> iw-5.3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/Makefile new/iw-5.3/Makefile --- old/iw-5.0.1/Makefile 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/Makefile 2019-08-05 22:33:56.000000000 +0200 @@ -18,18 +18,9 @@ -Werror-implicit-function-declaration -Wsign-compare -Wno-unused-parameter \ $(CFLAGS_EVAL) -OBJS = iw.o genl.o event.o info.o phy.o \ - interface.o ibss.o station.o survey.o util.o ocb.o \ - mesh.o mpath.o mpp.o scan.o reg.o version.o \ - reason.o status.o connect.o link.o offch.o ps.o cqm.o \ - bitrate.o wowlan.o coalesce.o roc.o p2p.o vendor.o mgmt.o \ - ap.o sha256.o nan.o bloom.o \ - measurements.o ftm.o -OBJS += sections.o - -OBJS-$(HWSIM) += hwsim.o - -OBJS += $(OBJS-y) $(OBJS-Y) +_OBJS := $(sort $(patsubst %.c,%.o,$(wildcard *.c))) +VERSION_OBJS := $(filter-out version.o, $(_OBJS)) +OBJS := $(VERSION_OBJS) version.o ALL = iw @@ -98,8 +89,6 @@ all: $(ALL) -VERSION_OBJS := $(filter-out version.o, $(OBJS)) - version.c: version.sh $(patsubst %.o,%.c,$(VERSION_OBJS)) nl80211.h iw.h Makefile \ $(wildcard .git/index .git/refs/tags) @$(NQ) ' GEN ' $@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/info.c new/iw-5.3/info.c --- old/iw-5.0.1/info.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/info.c 2019-08-05 22:33:56.000000000 +0200 @@ -69,13 +69,15 @@ return (ft_byte & BIT(ftidx % 8)) != 0; } -static void ext_feat_print(const struct nlattr *tb, - enum nl80211_ext_feature_index idx, - const char *feature_name, const char *feature_desc) +static void _ext_feat_print(const struct nlattr *tb, + enum nl80211_ext_feature_index idx, + const char *feature_name, const char *feature_desc) { if (ext_feature_isset(nla_data(tb), nla_len(tb),idx)) printf("\t\t* [ %s ]: %s\n", feature_name, feature_desc); } +#define ext_feat_print(tb, name, desc) \ + _ext_feat_print(tb, NL80211_EXT_FEATURE_##name, #name, desc) static int print_phy_handler(struct nl_msg *msg, void *arg) { @@ -162,7 +164,13 @@ tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]) print_vht_info(nla_get_u32(tb_band[NL80211_BAND_ATTR_VHT_CAPA]), nla_data(tb_band[NL80211_BAND_ATTR_VHT_MCS_SET])); + if (tb_band[NL80211_BAND_ATTR_IFTYPE_DATA]) { + struct nlattr *nl_iftype; + int rem_band; + nla_for_each_nested(nl_iftype, tb_band[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) + print_he_info(nl_iftype); + } if (tb_band[NL80211_BAND_ATTR_FREQS]) { if (!band_had_freq) { printf("\t\tFrequencies:\n"); @@ -625,75 +633,59 @@ printf("\tSupported extended features:\n"); - ext_feat_print(tb, NL80211_EXT_FEATURE_VHT_IBSS, - "VHT_IBSS", "VHT-IBSS"); - ext_feat_print(tb, NL80211_EXT_FEATURE_RRM, - "RRM", "RRM"); - ext_feat_print(tb, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER, - "MU_MIMO_AIR_SNIFFER", "MU-MIMO sniffer"); - ext_feat_print(tb, NL80211_EXT_FEATURE_SCAN_START_TIME, - "SCAN_START_TIME", "scan start timestamp"); - ext_feat_print(tb, NL80211_EXT_FEATURE_BSS_PARENT_TSF, - "BSS_PARENT_TSF", "BSS last beacon/probe TSF"); - ext_feat_print(tb, NL80211_EXT_FEATURE_SET_SCAN_DWELL, - "SET_SCAN_DWELL", "scan dwell setting"); - ext_feat_print(tb, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, - "BEACON_RATE_LEGACY", "legacy beacon rate setting"); - ext_feat_print(tb, NL80211_EXT_FEATURE_BEACON_RATE_HT, - "BEACON_RATE_HT", "HT beacon rate setting"); - ext_feat_print(tb, NL80211_EXT_FEATURE_BEACON_RATE_VHT, - "BEACON_RATE_VHT", "VHT beacon rate setting"); - ext_feat_print(tb, NL80211_EXT_FEATURE_FILS_STA, - "FILS_STA", "STA FILS (Fast Initial Link Setup)"); - ext_feat_print(tb, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA, - "MGMT_TX_RANDOM_TA", + ext_feat_print(tb, VHT_IBSS, "VHT-IBSS"); + ext_feat_print(tb, RRM, "RRM"); + ext_feat_print(tb, MU_MIMO_AIR_SNIFFER, "MU-MIMO sniffer"); + ext_feat_print(tb, SCAN_START_TIME, "scan start timestamp"); + ext_feat_print(tb, BSS_PARENT_TSF, + "BSS last beacon/probe TSF"); + ext_feat_print(tb, SET_SCAN_DWELL, "scan dwell setting"); + ext_feat_print(tb, BEACON_RATE_LEGACY, + "legacy beacon rate setting"); + ext_feat_print(tb, BEACON_RATE_HT, "HT beacon rate setting"); + ext_feat_print(tb, BEACON_RATE_VHT, "VHT beacon rate setting"); + ext_feat_print(tb, FILS_STA, + "STA FILS (Fast Initial Link Setup)"); + ext_feat_print(tb, MGMT_TX_RANDOM_TA, "randomized TA while not associated"); - ext_feat_print(tb, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED, - "MGMT_TX_RANDOM_TA_CONNECTED", + ext_feat_print(tb, MGMT_TX_RANDOM_TA_CONNECTED, "randomized TA while associated"); - ext_feat_print(tb, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI, - "SCHED_SCAN_RELATIVE_RSSI", + ext_feat_print(tb, SCHED_SCAN_RELATIVE_RSSI, "sched_scan for BSS with better RSSI report"); - ext_feat_print(tb, NL80211_EXT_FEATURE_CQM_RSSI_LIST, - "CQM_RSSI_LIST", + ext_feat_print(tb, CQM_RSSI_LIST, "multiple CQM_RSSI_THOLD records"); - ext_feat_print(tb, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, - "FILS_SK_OFFLOAD", + ext_feat_print(tb, FILS_SK_OFFLOAD, "FILS shared key authentication offload"); - ext_feat_print(tb, NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, - "4WAY_HANDSHAKE_STA_PSK", + ext_feat_print(tb, 4WAY_HANDSHAKE_STA_PSK, "4-way handshake with PSK in station mode"); - ext_feat_print(tb, NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, - "4WAY_HANDSHAKE_STA_1X", + ext_feat_print(tb, 4WAY_HANDSHAKE_STA_1X, "4-way handshake with 802.1X in station mode"); - ext_feat_print(tb, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME, - "FILS_MAX_CHANNEL_TIME", + ext_feat_print(tb, FILS_MAX_CHANNEL_TIME, "FILS max channel attribute override with dwell time"); - ext_feat_print(tb, NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP, - "ACCEPT_BCAST_PROBE_RESP", + ext_feat_print(tb, ACCEPT_BCAST_PROBE_RESP, "accepts broadcast probe response"); - ext_feat_print(tb, NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE, - "OCE_PROBE_REQ_HIGH_TX_RATE", + ext_feat_print(tb, OCE_PROBE_REQ_HIGH_TX_RATE, "probe request TX at high rate (at least 5.5Mbps)"); - ext_feat_print(tb, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, - "OCE_PROBE_REQ_DEFERRAL_SUPPRESSION", + ext_feat_print(tb, OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, "probe request tx deferral and suppression"); - ext_feat_print(tb, NL80211_EXT_FEATURE_MFP_OPTIONAL, - "MFP_OPTIONAL", + ext_feat_print(tb, MFP_OPTIONAL, "MFP_OPTIONAL value in ATTR_USE_MFP"); - ext_feat_print(tb, NL80211_EXT_FEATURE_LOW_SPAN_SCAN, - "LOW_SPAN_SCAN", "low span scan"); - ext_feat_print(tb, NL80211_EXT_FEATURE_LOW_POWER_SCAN, - "LOW_POWER_SCAN", "low power scan"); - ext_feat_print(tb, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, - "HIGH_ACCURACY_SCAN", "high accuracy scan"); - ext_feat_print(tb, NL80211_EXT_FEATURE_DFS_OFFLOAD, - "DFS_OFFLOAD", "DFS offload"); - ext_feat_print(tb, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, - "CONTROL_PORT_OVER_NL80211", + ext_feat_print(tb, LOW_SPAN_SCAN, "low span scan"); + ext_feat_print(tb, LOW_POWER_SCAN, "low power scan"); + ext_feat_print(tb, HIGH_ACCURACY_SCAN, "high accuracy scan"); + ext_feat_print(tb, DFS_OFFLOAD, "DFS offload"); + ext_feat_print(tb, CONTROL_PORT_OVER_NL80211, "control port over nl80211"); - ext_feat_print(tb, NL80211_EXT_FEATURE_TXQS, - "TXQS", "FQ-CoDel-enabled intermediate TXQs"); + ext_feat_print(tb, TXQS, "FQ-CoDel-enabled intermediate TXQs"); + ext_feat_print(tb, AIRTIME_FAIRNESS, + "airtime fairness scheduling"); + ext_feat_print(tb, AP_PMKSA_CACHING, + "PMKSA caching supported in AP mode"); + ext_feat_print(tb, SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, + "band specific RSSI thresholds for scheduled scan"); + ext_feat_print(tb, EXT_KEY_ID, "extended key ID support"); + ext_feat_print(tb, STA_TX_PWR, "TX power control per station"); + ext_feat_print(tb, SAE_OFFLOAD, "SAE offload support"); } if (tb_msg[NL80211_ATTR_COALESCE_RULE]) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/interface.c new/iw-5.3/interface.c --- old/iw-5.0.1/interface.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/interface.c 2019-08-05 22:33:56.000000000 +0200 @@ -447,6 +447,12 @@ printf("%s\tmulticast TXQ:%s\n", indent, buf); } + if (tb_msg[NL80211_ATTR_4ADDR]) { + uint8_t use_4addr = nla_get_u8(tb_msg[NL80211_ATTR_4ADDR]); + if (use_4addr) + printf("%s\t4addr: on\n", indent); + } + return NL_SKIP; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/iw.c new/iw-5.3/iw.c --- old/iw-5.0.1/iw.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/iw.c 2019-08-05 22:33:56.000000000 +0200 @@ -89,12 +89,12 @@ static int cmd_size; -extern struct cmd __start___cmd; -extern struct cmd __stop___cmd; +extern struct cmd *__start___cmd[]; +extern struct cmd *__stop___cmd; -#define for_each_cmd(_cmd) \ - for (_cmd = &__start___cmd; _cmd < &__stop___cmd; \ - _cmd = (const struct cmd *)((char *)_cmd + cmd_size)) +#define for_each_cmd(_cmd, i) \ + for (i = 0; i < &__stop___cmd - __start___cmd; i++) \ + if ((_cmd = __start___cmd[i])) static void __usage_cmd(const struct cmd *cmd, char *indent, bool full) @@ -192,6 +192,7 @@ bool full = argc >= 0; const char *sect_filt = NULL; const char *cmd_filt = NULL; + unsigned int i, j; if (argc > 0) sect_filt = argv[0]; @@ -203,7 +204,7 @@ usage_options(); printf("\t--version\tshow version (%s)\n", iw_version); printf("Commands:\n"); - for_each_cmd(section) { + for_each_cmd(section, i) { if (section->parent) continue; @@ -213,7 +214,7 @@ if (section->handler && !section->hidden) __usage_cmd(section, "\t", full); - for_each_cmd(cmd) { + for_each_cmd(cmd, j) { if (section != cmd->parent) continue; if (!cmd->handler || cmd->hidden) @@ -350,7 +351,7 @@ struct nl_cb *s_cb; struct nl_msg *msg; signed long long devidx = 0; - int err, o_argc; + int err, o_argc, i; const char *command, *section; char *tmp, **o_argv; enum command_identify_by command_idby = CIB_NONE; @@ -402,7 +403,7 @@ argc--; argv++; - for_each_cmd(sectcmd) { + for_each_cmd(sectcmd, i) { if (sectcmd->parent) continue; /* ok ... bit of a hack for the dupe 'info' section */ @@ -420,7 +421,7 @@ if (argc > 0) { command = *argv; - for_each_cmd(cmd) { + for_each_cmd(cmd, i) { if (!cmd->handler) continue; if (cmd->parent != sectcmd) @@ -542,6 +543,25 @@ return __handle_cmd(state, idby, argc, argv, NULL); } +/* + * Unfortunately, I don't know how densely the linker packs the struct cmd. + * For example, if you have a 72-byte struct cmd, the linker will pad each + * out to 96 bytes before putting them together in the section. There must + * be some algorithm, but I haven't found it yet. + * + * We used to calculate this by taking the (abs value of) the difference + * between __section_get and __section_set, but if LTO is enabled then this + * stops working because the entries of the "__cmd" section get rearranged + * freely by the compiler/linker. + * + * Fix this by using yet another "__sizer" section that only contains these + * two entries - then the (abs value of) the difference between them will + * be how they get packed and that can be used to iterate the __cmd section + * as well. + */ +static struct cmd sizer1 __attribute__((section("__sizer"))) = {}; +static struct cmd sizer2 __attribute__((section("__sizer"))) = {}; + int main(int argc, char **argv) { struct nl80211_state nlstate; @@ -549,7 +569,7 @@ const struct cmd *cmd = NULL; /* calculate command size including padding */ - cmd_size = labs((long)&__section_set - (long)&__section_get); + cmd_size = labs((long)&sizer2 - (long)&sizer1); /* strip off self */ argc--; argv0 = *argv++; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/iw.h new/iw-5.3/iw.h --- old/iw-5.0.1/iw.h 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/iw.h 2019-08-05 22:33:56.000000000 +0200 @@ -106,8 +106,7 @@ #define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel)\ static struct cmd \ - __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\ - __attribute__((used)) __attribute__((section("__cmd"))) = { \ + __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden = {\ .name = (_name), \ .args = (_args), \ .cmd = (_nlcmd), \ @@ -118,7 +117,10 @@ .help = (_help), \ .parent = _section, \ .selector = (_sel), \ - } + }; \ + static struct cmd *__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden ## _p \ + __attribute__((used,section("__cmd"))) = \ + &__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden #define __ACMD(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel, _alias)\ __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel);\ static const struct cmd *_alias = &__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden @@ -130,10 +132,7 @@ __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 1, idby, handler, NULL, NULL) #define TOPLEVEL(_name, _args, _nlcmd, _flags, _idby, _handler, _help) \ - extern struct cmd __section ## _ ## _name; /* sparse */ \ - struct cmd \ - __section ## _ ## _name \ - __attribute__((used)) __attribute__((section("__cmd"))) = { \ + struct cmd __section ## _ ## _name = { \ .name = (#_name), \ .args = (_args), \ .cmd = (_nlcmd), \ @@ -141,14 +140,17 @@ .idby = (_idby), \ .handler = (_handler), \ .help = (_help), \ - } + }; \ + static struct cmd *__section ## _ ## _name ## _p \ + __attribute__((used,section("__cmd"))) = &__section ## _ ## _name + #define SECTION(_name) \ - extern struct cmd __section ## _ ## _name; /* sparse */ \ - struct cmd __section ## _ ## _name \ - __attribute__((used)) __attribute__((section("__cmd"))) = { \ + struct cmd __section ## _ ## _name = { \ .name = (#_name), \ .hidden = 1, \ - } + }; \ + static struct cmd *__section ## _ ## _name ## _p \ + __attribute__((used,section("__cmd"))) = &__section ## _ ## _name #define DECLARE_SECTION(_name) \ extern struct cmd __section ## _ ## _name; @@ -195,6 +197,7 @@ void print_ampdu_spacing(__u8 spacing); void print_ht_capability(__u16 cap); void print_vht_info(__u32 capa, const __u8 *mcs); +void print_he_info(struct nlattr *nl_iftype); char *channel_width_name(enum nl80211_chan_width width); const char *iftype_name(enum nl80211_iftype iftype); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/mesh.c new/iw-5.3/mesh.c --- old/iw-5.0.1/mesh.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/mesh.c 2019-08-05 22:33:56.000000000 +0200 @@ -298,7 +298,7 @@ const struct mesh_param_descr *mdescr; struct nlattr *container; uint32_t ret; - int err; + int err = 2; container = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); if (!container) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/mgmt.c new/iw-5.3/mgmt.c --- old/iw-5.0.1/mgmt.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/mgmt.c 2019-08-05 22:33:56.000000000 +0200 @@ -69,9 +69,11 @@ NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type); NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match); + free(match); return 0; nla_put_failure: + free(match); return -ENOBUFS; } @@ -107,6 +109,8 @@ for (i = 3; i < argc; i += 3) { if (strcmp(argv[i], "count") == 0) { count = 1 + atoi(argv[i + 1]); + if (count < 1) + count = 1; break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/mpath.c new/iw-5.3/mpath.c --- old/iw-5.0.1/mpath.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/mpath.c 2019-08-05 22:33:56.000000000 +0200 @@ -90,6 +90,45 @@ return NL_SKIP; } +static int handle_mpath_probe(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +{ + unsigned char dst[ETH_ALEN]; + unsigned char *frame; + size_t frame_len; + + if (argc < 3) + return 1; + + if (mac_addr_a2n(dst, argv[0])) { + fprintf(stderr, "invalid mac address\n"); + return 2; + } + + if (strcmp("frame", argv[1]) != 0) + return 1; + + frame = parse_hex(argv[2], &frame_len); + if (!frame) { + fprintf(stderr, "invalid frame pattern: %p\n", frame); + return 2; + } + + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); + NLA_PUT(msg, NL80211_ATTR_FRAME, frame_len, frame); + + return 0; + nla_put_failure: + return -ENOBUFS; +} +COMMAND(mpath, probe, "<destination MAC address> frame <frame>", + NL80211_CMD_PROBE_MESH_LINK, 0, CIB_NETDEV, handle_mpath_probe, + "Inject ethernet frame to given peer overriding the next hop\n" + "lookup from mpath table.\n." + "Example: iw dev wlan0 mpath probe xx:xx:xx:xx:xx:xx frame 01:xx:xx:00\n"); + static int handle_mpath_get(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/nan.c new/iw-5.3/nan.c --- old/iw-5.0.1/nan.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/nan.c 2019-08-05 22:33:56.000000000 +0200 @@ -204,6 +204,7 @@ unsigned char *srf; size_t srf_len; __u8 bf_idx; + int err; argc--; argv++; @@ -231,6 +232,7 @@ while (cur_mac) { if (mac_addr_a2n(mac_addr, cur_mac)) { printf("mac format error %s\n", cur_mac); + free(srf); return -EINVAL; } @@ -238,7 +240,10 @@ cur_mac = strtok_r(NULL, ";", &sptr); } - NLA_PUT(srf_attrs, NL80211_NAN_SRF_BF, srf_len, srf); + err = nla_put(srf_attrs, NL80211_NAN_SRF_BF, srf_len, srf); + free(srf); + if (err) + goto nla_put_failure; argv++; argc--; } else if (strcmp(argv[0], "list") == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/nl80211.h new/iw-5.3/nl80211.h --- old/iw-5.0.1/nl80211.h 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/nl80211.h 2019-08-05 22:33:56.000000000 +0200 @@ -11,7 +11,7 @@ * Copyright 2008 Jouni Malinen <[email protected]> * Copyright 2008 Colin McCabe <[email protected]> * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -235,6 +235,15 @@ */ /** + * DOC: SAE authentication offload + * + * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they + * support offloading SAE authentication for WPA3-Personal networks. In + * %NL80211_CMD_CONNECT the password for SAE should be specified using + * %NL80211_ATTR_SAE_PASSWORD. + */ + +/** * enum nl80211_commands - supported nl80211 commands * * @NL80211_CMD_UNSPEC: unspecified command to catch errors @@ -648,7 +657,9 @@ * is used during CSA period. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. + * time if it is known that it is no longer necessary. This command is + * also sent as an event whenever the driver has completed the off-channel + * wait time. * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies @@ -1065,6 +1076,26 @@ * indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes * determining the width and type. * + * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to + * offload OWE processing to user space. This intends to support + * OWE AKM by the host drivers that implement SME but rely + * on the user space for the cryptographic/DH IE processing in AP mode. + * + * @NL80211_CMD_PROBE_MESH_LINK: The requirement for mesh link metric + * refreshing, is that from one mesh point we be able to send some data + * frames to other mesh points which are not currently selected as a + * primary traffic path, but which are only 1 hop away. The absence of + * the primary path to the chosen node makes it necessary to apply some + * form of marking on a chosen packet stream so that the packets can be + * properly steered to the selected node for testing, and not by the + * regular mesh path lookup. Further, the packets must be of type data + * so that the rate control (often embedded in firmware) is used for + * rate selection. + * + * Here attribute %NL80211_ATTR_MAC is used to specify connected mesh + * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame + * content. The frame is ethernet data. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1285,6 +1316,10 @@ NL80211_CMD_NOTIFY_RADAR, + NL80211_CMD_UPDATE_OWE_INFO, + + NL80211_CMD_PROBE_MESH_LINK, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1565,6 +1600,12 @@ * (a u32 with flags from &enum nl80211_wpa_versions). * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to * indicate which key management algorithm(s) to use (an array of u32). + * This attribute is also sent in response to @NL80211_CMD_GET_WIPHY, + * indicating the supported AKM suites, intended for specific drivers which + * implement SME and have constraints on which AKMs are supported and also + * the cases where an AKM support is offloaded to the driver/firmware. + * If there is no such notification from the driver, user space should + * assume the driver supports all the AKM suites. * * @NL80211_ATTR_REQ_IE: (Re)association request information elements as * sent out by the card, for ROAM and successful CONNECT events. @@ -2260,10 +2301,10 @@ * &enum nl80211_external_auth_action value). This is used with the * %NL80211_CMD_EXTERNAL_AUTH request event. * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user - * space supports external authentication. This attribute shall be used - * only with %NL80211_CMD_CONNECT request. The driver may offload - * authentication processing to user space if this capability is indicated - * in NL80211_CMD_CONNECT requests from the user space. + * space supports external authentication. This attribute shall be used + * with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver + * may offload authentication processing to user space if this capability + * is indicated in the respective requests from the user space. * * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. @@ -2299,6 +2340,27 @@ * This is also used for capability advertisement in the wiphy information, * with the appropriate sub-attributes. * + * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime + * scheduler. + * + * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for + * station associated with the AP. See &enum nl80211_tx_power_setting for + * possible values. + * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This + * allows to set Tx power for a station. If this attribute is not included, + * the default per-interface tx power setting will be overriding. Driver + * should be picking up the lowest tx power, either tx power per-interface + * or per-station. + * + * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It + * is used with %NL80211_CMD_CONNECT to provide password for offloading + * SAE authentication for WPA3-Personal networks. + * + * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. + * + * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection + * functionality. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2748,6 +2810,16 @@ NL80211_ATTR_PEER_MEASUREMENTS, + NL80211_ATTR_AIRTIME_WEIGHT, + NL80211_ATTR_STA_TX_POWER_SETTING, + NL80211_ATTR_STA_TX_POWER, + + NL80211_ATTR_SAE_PASSWORD, + + NL80211_ATTR_TWT_RESPONDER, + + NL80211_ATTR_HE_OBSS_PD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2791,14 +2863,14 @@ #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_HT_RATES 77 -#define NL80211_MAX_SUPP_REG_RULES 64 +#define NL80211_MAX_SUPP_REG_RULES 128 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 #define NL80211_HT_CAPABILITY_LEN 26 #define NL80211_VHT_CAPABILITY_LEN 12 #define NL80211_HE_MIN_CAPABILITY_LEN 16 -#define NL80211_HE_MAX_CAPABILITY_LEN 51 +#define NL80211_HE_MAX_CAPABILITY_LEN 54 #define NL80211_MAX_NR_CIPHER_SUITES 5 #define NL80211_MAX_NR_AKM_SUITES 2 @@ -3125,6 +3197,10 @@ * might not be fully accurate. * @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a * mesh gate (u8, 0 or 1) + * @NL80211_STA_INFO_TX_DURATION: aggregate PPDU duration for all frames + * sent to the station (u64, usec) + * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16) + * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3168,6 +3244,9 @@ NL80211_STA_INFO_RX_MPDUS, NL80211_STA_INFO_FCS_ERROR_COUNT, NL80211_STA_INFO_CONNECTED_TO_GATE, + NL80211_STA_INFO_TX_DURATION, + NL80211_STA_INFO_AIRTIME_WEIGHT, + NL80211_STA_INFO_AIRTIME_LINK_METRIC, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -3277,8 +3356,10 @@ * &enum nl80211_mpath_flags; * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination + * @NL80211_MPATH_INFO_PATH_CHANGE: total number of path changes to destination * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number - * currently defind + * currently defined * @__NL80211_MPATH_INFO_AFTER_LAST: internal use */ enum nl80211_mpath_info { @@ -3290,6 +3371,8 @@ NL80211_MPATH_INFO_FLAGS, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, NL80211_MPATH_INFO_DISCOVERY_RETRIES, + NL80211_MPATH_INFO_HOP_COUNT, + NL80211_MPATH_INFO_PATH_CHANGE, /* keep last */ __NL80211_MPATH_INFO_AFTER_LAST, @@ -3618,6 +3701,14 @@ * value as specified by &struct nl80211_bss_select_rssi_adjust. * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching * (this cannot be used together with SSID). + * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the + * band specific minimum rssi thresholds for the bands defined in + * enum nl80211_band. The minimum rssi threshold value(s32) specific to a + * band shall be encapsulated in attribute with type value equals to one + * of the NL80211_BAND_* defined in enum nl80211_band. For example, the + * minimum rssi threshold value for 2.4GHZ band shall be encapsulated + * within an attribute of type NL80211_BAND_2GHZ. And one or more of such + * attributes will be nested within this attribute. * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter * attribute number currently defined * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use @@ -3630,6 +3721,7 @@ NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST, NL80211_SCHED_SCAN_MATCH_ATTR_BSSID, + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, /* keep last */ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, @@ -4115,6 +4207,27 @@ }; /** + * enum nl80211_key_mode - Key mode + * + * @NL80211_KEY_RX_TX: (Default) + * Key can be used for Rx and Tx immediately + * + * The following modes can only be selected for unicast keys and when the + * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID: + * + * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY: + * Unicast key can only be used for Rx, Tx not allowed, yet + * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY: + * The unicast key identified by idx and mac is cleared for Tx and becomes + * the preferred Tx key for the station. + */ +enum nl80211_key_mode { + NL80211_KEY_RX_TX, + NL80211_KEY_NO_TX, + NL80211_KEY_SET_TX +}; + +/** * enum nl80211_chan_width - channel width definitions * * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH @@ -4319,6 +4432,7 @@ enum nl80211_wpa_versions { NL80211_WPA_VERSION_1 = 1 << 0, NL80211_WPA_VERSION_2 = 1 << 1, + NL80211_WPA_VERSION_3 = 1 << 2, }; /** @@ -4357,6 +4471,9 @@ * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags * attributes, specifying what a key should be set as default as. * See &enum nl80211_key_default_types. + * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. + * Defaults to @NL80211_KEY_RX_TX. + * * @__NL80211_KEY_AFTER_LAST: internal * @NL80211_KEY_MAX: highest key attribute */ @@ -4370,6 +4487,7 @@ NL80211_KEY_DEFAULT_MGMT, NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, + NL80211_KEY_MODE, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -5223,7 +5341,7 @@ NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28, NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29, NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30, - NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31, + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1U << 31, }; /** @@ -5315,6 +5433,24 @@ * able to rekey an in-use key correctly. Userspace must not rekey PTK keys * if this flag is not set. Ignoring this can leak clear text packets and/or * freeze the connection. + * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for + * Individually Addressed Frames" from IEEE802.11-2016. + * + * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime + * fairness for transmitted packets and has enabled airtime fairness + * scheduling. + * + * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching + * (set/del PMKSA operations) in AP mode. + * + * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports + * filtering of sched scan results using band specific RSSI thresholds. + * + * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power + * to a station. + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in + * station mode (SAE password is passed as part of the connect command). * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -5355,6 +5491,12 @@ NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, + NL80211_EXT_FEATURE_AP_PMKSA_CACHING, + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, + NL80211_EXT_FEATURE_EXT_KEY_ID, + NL80211_EXT_FEATURE_STA_TX_PWR, + NL80211_EXT_FEATURE_SAE_OFFLOAD, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -5606,9 +5748,14 @@ * Used by cfg80211_rx_mgmt() * * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver. + * @NL80211_RXMGMT_FLAG_EXTERNAL_AUTH: Host driver intends to offload + * the authentication. Exclusively defined for host drivers that + * advertises the SME functionality but would like the userspace + * to handle certain authentication algorithms (e.g. SAE). */ enum nl80211_rxmgmt_flags { NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1, }; /* @@ -6348,4 +6495,26 @@ NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1 }; +/** + * enum nl80211_obss_pd_attributes - OBSS packet detection attributes + * @__NL80211_HE_OBSS_PD_ATTR_INVALID: Invalid + * + * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * + * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal + * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. + */ +enum nl80211_obss_pd_attributes { + __NL80211_HE_OBSS_PD_ATTR_INVALID, + + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + + /* keep last */ + __NL80211_HE_OBSS_PD_ATTR_LAST, + NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, +}; + + #endif /* __LINUX_NL80211_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/phy.c new/iw-5.3/phy.c --- old/iw-5.0.1/phy.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/phy.c 2019-08-05 22:33:56.000000000 +0200 @@ -1,6 +1,7 @@ #include <stdbool.h> #include <errno.h> #include <strings.h> +#include <unistd.h> #include <sys/param.h> #include <sys/stat.h> #include <fcntl.h> @@ -328,12 +329,16 @@ } else if (strcmp(argv[2], "freq") == 0) { err = parse_freqchan(&chandef, false, argc - 3, argv + 3, NULL); } else { - return 1; + err = 1; } + if (err) + goto err_out; cac_trigger_argv = calloc(argc + 1, sizeof(char*)); - if (!cac_trigger_argv) - return -ENOMEM; + if (!cac_trigger_argv) { + err = -ENOMEM; + goto err_out; + } cac_trigger_argv[0] = argv[0]; cac_trigger_argv[1] = "cac"; @@ -341,9 +346,8 @@ memcpy(&cac_trigger_argv[3], &argv[2], (argc - 2) * sizeof(char*)); err = handle_cmd(state, id, argc + 1, cac_trigger_argv); - free(cac_trigger_argv); if (err) - return err; + goto err_out; cac_event.ret = 1; cac_event.freq = chandef.control_freq; @@ -357,7 +361,13 @@ while (cac_event.ret > 0) nl_recvmsgs(state->nl_sock, radar_cb); - return 0; + err = 0; +err_out: + if (radar_cb) + nl_cb_put(radar_cb); + if (cac_trigger_argv) + free(cac_trigger_argv); + return err; } TOPLEVEL(cac, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" @@ -523,7 +533,7 @@ enum id_input id) { char *end; - int fd; + int fd = -1; if (argc < 1 || !*argv[0]) return 1; @@ -551,6 +561,8 @@ return 1; nla_put_failure: + if (fd >= 0) + close(fd); return -ENOBUFS; } COMMAND(set, netns, "{ <pid> | name <nsname> }", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/scan.c new/iw-5.3/scan.c --- old/iw-5.0.1/scan.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/scan.c 2019-08-05 22:33:56.000000000 +0200 @@ -355,11 +355,12 @@ nla_put_failure: if (match) nla_nest_end(msg, match); +out: nlmsg_free(freqs); nlmsg_free(matchset); nlmsg_free(scan_plans); + nlmsg_free(ssids); -out: *argc = c; *argv = v; return err; @@ -388,7 +389,7 @@ bool passive = false, have_ssids = false, have_freqs = false; bool duration_mandatory = false; size_t ies_len = 0, meshid_len = 0; - unsigned char *ies = NULL, *meshid = NULL, *tmpies; + unsigned char *ies = NULL, *meshid = NULL, *tmpies = NULL; unsigned int flags = 0; ssids = nlmsg_alloc(); @@ -449,7 +450,8 @@ case DONE: nlmsg_free(ssids); nlmsg_free(freqs); - return 1; + err = 1; + goto nla_put_failure; case FREQ: freq = strtoul(argv[i], &eptr, 10); if (eptr != argv[i] + strlen(argv[i])) { @@ -461,6 +463,8 @@ NLA_PUT_U32(freqs, i, freq); break; case IES: + if (ies) + free(ies); ies = parse_hex(argv[i], &ies_len); if (!ies) goto nla_put_failure; @@ -489,24 +493,14 @@ if (ies || meshid) { tmpies = (unsigned char *) malloc(ies_len + meshid_len); - if (!tmpies) { - free(ies); - free(meshid); + if (!tmpies) goto nla_put_failure; - } - if (ies) { + if (ies) memcpy(tmpies, ies, ies_len); - free(ies); - } - if (meshid) { + if (meshid) memcpy(&tmpies[ies_len], meshid, meshid_len); - free(meshid); - } - if (nla_put(msg, NL80211_ATTR_IE, ies_len + meshid_len, tmpies) < 0) { - free(tmpies); + if (nla_put(msg, NL80211_ATTR_IE, ies_len + meshid_len, tmpies) < 0) goto nla_put_failure; - } - free(tmpies); } if (!have_ssids) @@ -534,6 +528,12 @@ nla_put_failure: nlmsg_free(ssids); nlmsg_free(freqs); + if (meshid) + free(meshid); + if (ies) + free(ies); + if (tmpies) + free(tmpies); return err; } @@ -1384,7 +1384,7 @@ static void print_ibssatim(const uint8_t type, uint8_t len, const uint8_t *data, const struct print_ies_data *ie_buffer) { - printf(" %d TUs", (data[1] << 8) + data[0]); + printf(" %d TUs\n", (data[1] << 8) + data[0]); } static void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/station.c new/iw-5.3/station.c --- old/iw-5.0.1/station.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/station.c 2019-08-05 22:33:56.000000000 +0200 @@ -243,6 +243,18 @@ if (rinfo[NL80211_RATE_INFO_VHT_NSS]) pos += snprintf(pos, buflen - (pos - buf), " VHT-NSS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS])); + if (rinfo[NL80211_RATE_INFO_HE_MCS]) + pos += snprintf(pos, buflen - (pos - buf), + " HE-MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_HE_MCS])); + if (rinfo[NL80211_RATE_INFO_HE_NSS]) + pos += snprintf(pos, buflen - (pos - buf), + " HE-NSS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_HE_NSS])); + if (rinfo[NL80211_RATE_INFO_HE_GI]) + pos += snprintf(pos, buflen - (pos - buf), + " HE-GI %d", nla_get_u8(rinfo[NL80211_RATE_INFO_HE_GI])); + if (rinfo[NL80211_RATE_INFO_HE_DCM]) + pos += snprintf(pos, buflen - (pos - buf), + " HE-DCM %d", nla_get_u8(rinfo[NL80211_RATE_INFO_HE_DCM])); } static char *get_chain_signal(struct nlattr *attr_list) @@ -309,6 +321,7 @@ [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }, [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED }, [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 }, + [NL80211_STA_INFO_TX_DURATION] = { .type = NLA_U64 }, [NL80211_STA_INFO_ACK_SIGNAL] = {.type = NLA_U8 }, [NL80211_STA_INFO_ACK_SIGNAL_AVG] = { .type = NLA_U8 }, }; @@ -401,6 +414,10 @@ printf("\n\ttx bitrate:\t%s", buf); } + if (sinfo[NL80211_STA_INFO_TX_DURATION]) + printf("\n\ttx duration:\t%lld us", + (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_TX_DURATION])); + if (sinfo[NL80211_STA_INFO_RX_BITRATE]) { char buf[100]; @@ -420,6 +437,10 @@ printf("\n\tavg ack signal:\t%d dBm", (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_ACK_SIGNAL_AVG])); + if (sinfo[NL80211_STA_INFO_AIRTIME_WEIGHT]) { + printf("\n\tairtime weight: %d", nla_get_u16(sinfo[NL80211_STA_INFO_AIRTIME_WEIGHT])); + } + if (sinfo[NL80211_STA_INFO_EXPECTED_THROUGHPUT]) { uint32_t thr; @@ -651,6 +672,8 @@ static const struct cmd *station_set_plink; static const struct cmd *station_set_vlan; static const struct cmd *station_set_mesh_power_mode; +static const struct cmd *station_set_airtime_weight; +static const struct cmd *station_set_txpwr; static const struct cmd *select_station_cmd(int argc, char **argv) { @@ -662,6 +685,10 @@ return station_set_vlan; if (strcmp(argv[1], "mesh_power_mode") == 0) return station_set_mesh_power_mode; + if (strcmp(argv[1], "airtime_weight") == 0) + return station_set_airtime_weight; + if (strcmp(argv[1], "txpwr") == 0) + return station_set_txpwr; return NULL; } @@ -813,6 +840,120 @@ "Set link-specific mesh power mode for this station", select_station_cmd, station_set_mesh_power_mode); +static int handle_station_set_airtime_weight(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +{ + unsigned char mac_addr[ETH_ALEN]; + unsigned long airtime_weight = 0; + char *err = NULL; + + if (argc < 3) + return 1; + + if (mac_addr_a2n(mac_addr, argv[0])) { + fprintf(stderr, "invalid mac address\n"); + return 2; + } + argc--; + argv++; + + if (strcmp("airtime_weight", argv[0]) != 0) + return 1; + argc--; + argv++; + + airtime_weight = strtoul(argv[0], &err, 0); + if (err && *err) { + fprintf(stderr, "invalid airtime weight\n"); + return 2; + } + argc--; + argv++; + + if (argc) + return 1; + + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + NLA_PUT_U16(msg, NL80211_ATTR_AIRTIME_WEIGHT, airtime_weight); + + return 0; + nla_put_failure: + return -ENOBUFS; + +} +COMMAND_ALIAS(station, set, "<MAC address> airtime_weight <weight>", + NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_airtime_weight, + "Set airtime weight for this station.", + select_station_cmd, station_set_airtime_weight); + +static int handle_station_set_txpwr(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +{ + enum nl80211_tx_power_setting type; + unsigned char mac_addr[ETH_ALEN]; + int sta_txpwr = 0; + char *err = NULL; + + if (argc != 3 && argc != 4) + return 1; + + if (mac_addr_a2n(mac_addr, argv[0])) { + fprintf(stderr, "invalid mac address\n"); + return 2; + } + + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + argc--; + argv++; + + if (strcmp("txpwr", argv[0]) != 0) + return 1; + argc--; + argv++; + + if (!strcmp(argv[0], "auto")) + type = NL80211_TX_POWER_AUTOMATIC; + else if (!strcmp(argv[0], "limit")) + type = NL80211_TX_POWER_LIMITED; + else { + printf("Invalid parameter: %s\n", argv[0]); + return 2; + } + + NLA_PUT_U8(msg, NL80211_ATTR_STA_TX_POWER_SETTING, type); + + if (type != NL80211_TX_POWER_AUTOMATIC) { + if (argc != 2) { + printf("Missing TX power level argument.\n"); + return 2; + } + + argc--; + argv++; + + sta_txpwr = strtoul(argv[0], &err, 0); + NLA_PUT_U16(msg, NL80211_ATTR_STA_TX_POWER, sta_txpwr); + } + + argc--; + argv++; + + if (argc) + return 1; + + return 0; + nla_put_failure: + return -ENOBUFS; +} +COMMAND_ALIAS(station, set, "<MAC address> txpwr <auto|limit> [<tx power dBm>]", + NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_txpwr, + "Set Tx power for this station.", + select_station_cmd, station_set_txpwr); + static int handle_station_dump(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/util.c new/iw-5.3/util.c --- old/iw-5.0.1/util.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/util.c 2019-08-05 22:33:56.000000000 +0200 @@ -285,6 +285,8 @@ [NL80211_CMD_PEER_MEASUREMENT_RESULT] = "peer_measurement_result", [NL80211_CMD_PEER_MEASUREMENT_COMPLETE] = "peer_measurement_complete", [NL80211_CMD_NOTIFY_RADAR] = "notify_radar", + [NL80211_CMD_UPDATE_OWE_INFO] = "update_owe_info", + [NL80211_CMD_PROBE_MESH_LINK] = "probe_mesh_link", }; static char cmdbuf[100]; @@ -1101,6 +1103,237 @@ printf("\t\tVHT TX highest supported: %d Mbps\n", tmp & 0x1fff); } +void print_he_info(struct nlattr *nl_iftype) +{ + struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1]; + struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1]; + char *iftypes[NUM_NL80211_IFTYPES] = { + "Unspec", "Adhoc", "Station", "AP", "AP/VLAN", "WDS", "Monitor", + "Mesh", "P2P/Client", "P2P/Go", "P2P/Device", "OCB", "NAN", + }; + __u16 mac_cap[3] = { 0 }; + __u16 phy_cap[6] = { 0 }; + __u16 mcs_set[6] = { 0 }; + __u8 ppet[25] = { 0 }; + size_t len; + int i; + + #define PRINT_HE_CAP(_var, _idx, _bit, _str) \ + do { \ + if (_var[_idx] & BIT(_bit)) \ + printf("\t\t\t\t" _str "\n"); \ + } while (0) + + #define PRINT_HE_CAP_MASK(_var, _idx, _shift, _mask, _str) \ + do { \ + if ((_var[_idx] >> _shift) & _mask) \ + printf("\t\t\t\t" _str ": %d\n", (_var[_idx] >> _shift) & _mask); \ + } while (0) + + #define PRINT_HE_MAC_CAP(...) PRINT_HE_CAP(mac_cap, __VA_ARGS__) + #define PRINT_HE_MAC_CAP_MASK(...) PRINT_HE_CAP_MASK(mac_cap, __VA_ARGS__) + #define PRINT_HE_PHY_CAP(...) PRINT_HE_CAP(phy_cap, __VA_ARGS__) + #define PRINT_HE_PHY_CAP0(_idx, _bit, ...) PRINT_HE_CAP(phy_cap, _idx, _bit + 8, __VA_ARGS__) + #define PRINT_HE_PHY_CAP_MASK(...) PRINT_HE_CAP_MASK(phy_cap, __VA_ARGS__) + + nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX, + nla_data(nl_iftype), nla_len(nl_iftype), NULL); + + if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES]) + return; + + if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX, + tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL)) + return; + + printf("\t\tHE Iftypes:"); + for (i = 0; i < NUM_NL80211_IFTYPES; i++) + if (nla_get_flag(tb_flags[i]) && iftypes[i]) + printf(" %s", iftypes[i]); + printf("\n"); + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]); + if (len > sizeof(mac_cap)) + len = sizeof(mac_cap); + memcpy(mac_cap, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]), + len); + } + printf("\t\t\tHE MAC Capabilities (0x"); + for (i = 0; i < 3; i++) + printf("%04x", mac_cap[i]); + printf("):\n"); + + PRINT_HE_MAC_CAP(0, 0, "+HTC HE Supported"); + PRINT_HE_MAC_CAP(0, 1, "TWT Requester"); + PRINT_HE_MAC_CAP(0, 2, "TWT Responder"); + PRINT_HE_MAC_CAP_MASK(0, 3, 0x3, "Dynamic BA Fragementation Level"); + PRINT_HE_MAC_CAP_MASK(0, 5, 0x7, "Maximum number of MSDUS Fragments"); + PRINT_HE_MAC_CAP_MASK(0, 8, 0x3, "Minimum Payload size of 128 bytes"); + PRINT_HE_MAC_CAP_MASK(0, 10, 0x3, "Trigger Frame MAC Padding Duration"); + PRINT_HE_MAC_CAP_MASK(0, 12, 0x7, "Multi-TID Aggregation Support"); + + PRINT_HE_MAC_CAP(1, 1, "All Ack"); + PRINT_HE_MAC_CAP(1, 2, "TRS"); + PRINT_HE_MAC_CAP(1, 3, "BSR"); + PRINT_HE_MAC_CAP(1, 4, "Broadcast TWT"); + PRINT_HE_MAC_CAP(1, 5, "32-bit BA Bitmap"); + PRINT_HE_MAC_CAP(1, 6, "MU Cascading"); + PRINT_HE_MAC_CAP(1, 7, "Ack-Enabled Aggregation"); + PRINT_HE_MAC_CAP(1, 9, "OM Control"); + PRINT_HE_MAC_CAP(1, 10, "OFDMA RA"); + PRINT_HE_MAC_CAP_MASK(1, 11, 0x3, "Maximum A-MPDU Length Exponent"); + PRINT_HE_MAC_CAP(1, 13, "A-MSDU Fragmentation"); + PRINT_HE_MAC_CAP(1, 14, "Flexible TWT Scheduling"); + PRINT_HE_MAC_CAP(1, 15, "RX Control Frame to MultiBSS"); + + PRINT_HE_MAC_CAP(2, 0, "BSRP BQRP A-MPDU Aggregation"); + PRINT_HE_MAC_CAP(2, 1, "QTP"); + PRINT_HE_MAC_CAP(2, 2, "BQR"); + PRINT_HE_MAC_CAP(2, 3, "SRP Responder Role"); + PRINT_HE_MAC_CAP(2, 4, "NDP Feedback Report"); + PRINT_HE_MAC_CAP(2, 5, "OPS"); + PRINT_HE_MAC_CAP(2, 6, "A-MSDU in A-MPDU"); + PRINT_HE_MAC_CAP_MASK(2, 7, 7, "Multi-TID Aggregation TX"); + PRINT_HE_MAC_CAP(2, 10, "HE Subchannel Selective Transmission"); + PRINT_HE_MAC_CAP(2, 11, "UL 2x996-Tone RU"); + PRINT_HE_MAC_CAP(2, 12, "OM Control UL MU Data Disable RX"); + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]); + + if (len > sizeof(phy_cap) - 1) + len = sizeof(phy_cap) - 1; + memcpy(&((__u8 *)phy_cap)[1], + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]), + len); + } + printf("\t\t\tHE PHY Capabilities: (0x"); + for (i = 0; i < 11; i++) + printf("%02x", ((__u8 *)phy_cap)[i + 1]); + printf("):\n"); + + PRINT_HE_PHY_CAP0(0, 1, "HE40/2.4GHz"); + PRINT_HE_PHY_CAP0(0, 2, "HE40/HE80/5GHz"); + PRINT_HE_PHY_CAP0(0, 3, "HE160/5GHz"); + PRINT_HE_PHY_CAP0(0, 4, "HE160/HE80+80/5GHz"); + PRINT_HE_PHY_CAP0(0, 5, "242 tone RUs/2.4GHz"); + PRINT_HE_PHY_CAP0(0, 6, "242 tone RUs/5GHz"); + + PRINT_HE_PHY_CAP_MASK(1, 0, 0xf, "Punctured Preamble RX"); + PRINT_HE_PHY_CAP_MASK(1, 4, 0x1, "Device Class"); + PRINT_HE_PHY_CAP(1, 5, "LDPC Coding in Payload"); + PRINT_HE_PHY_CAP(1, 6, "HE SU PPDU with 1x HE-LTF and 0.8us GI"); + PRINT_HE_PHY_CAP_MASK(1, 7, 0x3, "Midamble Rx Max NSTS"); + PRINT_HE_PHY_CAP(1, 9, "NDP with 4x HE-LTF and 3.2us GI"); + PRINT_HE_PHY_CAP(1, 10, "STBC Tx <= 80MHz"); + PRINT_HE_PHY_CAP(1, 11, "STBC Rx <= 80MHz"); + PRINT_HE_PHY_CAP(1, 12, "Doppler Tx"); + PRINT_HE_PHY_CAP(1, 13, "Doppler Rx"); + PRINT_HE_PHY_CAP(1, 14, "Full Bandwidth UL MU-MIMO"); + PRINT_HE_PHY_CAP(1, 15, "Partial Bandwidth UL MU-MIMO"); + + PRINT_HE_PHY_CAP_MASK(2, 0, 0x3, "DCM Max Constellation"); + PRINT_HE_PHY_CAP_MASK(2, 2, 0x1, "DCM Max NSS Tx"); + PRINT_HE_PHY_CAP_MASK(2, 3, 0x3, "DCM Max Constellation Rx"); + PRINT_HE_PHY_CAP_MASK(2, 5, 0x1, "DCM Max NSS Rx"); + PRINT_HE_PHY_CAP(2, 6, "Rx HE MU PPDU from Non-AP STA"); + PRINT_HE_PHY_CAP(2, 7, "SU Beamformer"); + PRINT_HE_PHY_CAP(2, 8, "SU Beamformee"); + PRINT_HE_PHY_CAP(2, 9, "MU Beamformer"); + PRINT_HE_PHY_CAP_MASK(2, 10, 0x7, "Beamformee STS <= 80Mhz"); + PRINT_HE_PHY_CAP_MASK(2, 13, 0x7, "Beamformee STS > 80Mhz"); + + PRINT_HE_PHY_CAP_MASK(3, 0, 0x7, "Sounding Dimensions <= 80Mhz"); + PRINT_HE_PHY_CAP_MASK(3, 3, 0x7, "Sounding Dimensions > 80Mhz"); + PRINT_HE_PHY_CAP(3, 6, "Ng = 16 SU Feedback"); + PRINT_HE_PHY_CAP(3, 7, "Ng = 16 MU Feedback"); + PRINT_HE_PHY_CAP(3, 8, "Codebook Size SU Feedback"); + PRINT_HE_PHY_CAP(3, 9, "Codebook Size MU Feedback"); + PRINT_HE_PHY_CAP(3, 10, "Triggered SU Beamforming Feedback"); + PRINT_HE_PHY_CAP(3, 11, "Triggered MU Beamforming Feedback"); + PRINT_HE_PHY_CAP(3, 12, "Triggered CQI Feedback"); + PRINT_HE_PHY_CAP(3, 13, "Partial Bandwidth Extended Range"); + PRINT_HE_PHY_CAP(3, 14, "Partial Bandwidth DL MU-MIMO"); + PRINT_HE_PHY_CAP(3, 15, "PPE Threshold Present"); + + PRINT_HE_PHY_CAP(4, 0, "SRP-based SR"); + PRINT_HE_PHY_CAP(4, 1, "Power Boost Factor ar"); + PRINT_HE_PHY_CAP(4, 2, "HE SU PPDU & HE PPDU 4x HE-LTF 0.8us GI"); + PRINT_HE_PHY_CAP_MASK(4, 3, 0x7, "Max NC"); + PRINT_HE_PHY_CAP(4, 6, "STBC Tx > 80MHz"); + PRINT_HE_PHY_CAP(4, 7, "STBC Rx > 80MHz"); + PRINT_HE_PHY_CAP(4, 8, "HE ER SU PPDU 4x HE-LTF 0.8us GI"); + PRINT_HE_PHY_CAP(4, 9, "20MHz in 40MHz HE PPDU 2.4GHz"); + PRINT_HE_PHY_CAP(4, 10, "20MHz in 160/80+80MHz HE PPDU"); + PRINT_HE_PHY_CAP(4, 11, "80MHz in 160/80+80MHz HE PPDU"); + PRINT_HE_PHY_CAP(4, 12, "HE ER SU PPDU 1x HE-LTF 0.8us GI"); + PRINT_HE_PHY_CAP(4, 13, "Midamble Rx 2x & 1x HE-LTF"); + PRINT_HE_PHY_CAP_MASK(4, 14, 0x3, "DCM Max BW"); + + PRINT_HE_PHY_CAP(5, 0, "Longer Than 16HE SIG-B OFDM Symbols"); + PRINT_HE_PHY_CAP(5, 1, "Non-Triggered CQI Feedback"); + PRINT_HE_PHY_CAP(5, 2, "TX 1024-QAM"); + PRINT_HE_PHY_CAP(5, 3, "RX 1024-QAM"); + PRINT_HE_PHY_CAP(5, 4, "RX Full BW SU Using HE MU PPDU with Compression SIGB"); + PRINT_HE_PHY_CAP(5, 5, "RX Full BW SU Using HE MU PPDU with Non-Compression SIGB"); + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]); + if (len > sizeof(mcs_set)) + len = sizeof(mcs_set); + memcpy(mcs_set, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]), + len); + } + + for (i = 0; i < 3; i++) { + __u8 phy_cap_support[] = { BIT(1) | BIT(2), BIT(3), BIT(4) }; + char *bw[] = { "<= 80", "160", "80+80" }; + int j; + + if ((phy_cap[0] & (phy_cap_support[i] << 8)) == 0) + continue; + + for (j = 0; j < 2; j++) { + int k; + printf("\t\t\tHE %s MCS and NSS set %s MHz\n", j ? "TX" : "RX", bw[i]); + for (k = 0; k < 8; k++) { + __u16 mcs = mcs_set[(i * 2) + j]; + mcs >>= k * 2; + mcs &= 0x3; + printf("\t\t\t\t\t %d streams: ", k + 1); + if (mcs == 3) + printf("not supported\n"); + else + printf("MCS 0-%d\n", 7 + (mcs * 2)); + } + + } + } + + len = 0; + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]); + if (len > sizeof(ppet)) + len = sizeof(ppet); + memcpy(ppet, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]), + len); + } + + if (len && (phy_cap[3] & BIT(15))) { + size_t i; + + printf("\t\t\tPPE Threshold "); + for (i = 0; i < len; i++) + if (ppet[i]) + printf("0x%02x ", ppet[i]); + printf("\n"); + } +} + void iw_hexdump(const char *prefix, const __u8 *buf, size_t size) { size_t i; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/vendor.c new/iw-5.3/vendor.c --- old/iw-5.0.1/vendor.c 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/vendor.c 2019-08-05 22:33:56.000000000 +0200 @@ -107,7 +107,8 @@ if (file) { count = read_file(file, buf, sizeof(buf)); - fclose(file); + if (file != stdin) + fclose(file); } else count = read_hex(argc - 2, &argv[2], buf, sizeof(buf)); @@ -120,6 +121,8 @@ return 0; nla_put_failure: + if (file && file != stdin) + fclose(file); return -ENOBUFS; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iw-5.0.1/version.sh new/iw-5.3/version.sh --- old/iw-5.0.1/version.sh 2019-02-04 14:37:44.000000000 +0100 +++ new/iw-5.3/version.sh 2019-08-05 22:33:56.000000000 +0200 @@ -1,6 +1,6 @@ #!/bin/sh -VERSION="5.0.1" +VERSION="5.3" OUT="$1" # get the absolute path for the OUT file
