]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
Merge branch 'master' into scan-test
authorJohannes Berg <johannes@sipsolutions.net>
Mon, 8 Dec 2008 11:56:39 +0000 (12:56 +0100)
committerJohannes Berg <johannes@sipsolutions.net>
Mon, 8 Dec 2008 11:56:39 +0000 (12:56 +0100)
Conflicts:
Makefile
nl80211.h

COPYING
Makefile
README
genl.c [new file with mode: 0644]
info.c
iw.c
iw.h
nl80211.h
phy.c
util.c
version.sh

diff --git a/COPYING b/COPYING
index fc9a519b0fc14208b4b149e346856231b4882bd1..3ba767caef5035235325c86aa3caa2c786212602 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -3,27 +3,14 @@ Copyright (c) 2007            Andy Lutomirski
 Copyright (c) 2007             Mike Kershaw
 Copyright (c) 2008             Luis R. Rodriguez
 
-All rights reserved.
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer. 
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
index 0f3d427fb7e72f3b68faa6773097c6e3f9dd5c94..4a949643f767d36ddc02956157e89a530d17a37f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,16 +2,20 @@
 
 MAKEFLAGS += --no-print-directory
 
+PREFIX ?= /usr
+BINDIR ?= $(PREFIX)/bin
+MANDIR ?= $(PREFIX)/share/man
+
 MKDIR ?= mkdir -p
 INSTALL ?= install
-PREFIX ?= /usr
 CC ?= "gcc"
+
 CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration `pkg-config --cflags libnl-1`
 CFLAGS += -O2 -g
 LDFLAGS += `pkg-config --libs libnl-1`
 NLVERSION = 1.0
 
-OBJS = iw.o info.o phy.o interface.o station.o util.o mpath.o reg.o mesh.o scan.o
+OBJS = iw.o info.o phy.o interface.o station.o util.o mpath.o reg.o mesh.o genl.o scan.o
 ALL = iw
 
 ifeq ($(V),1)
@@ -49,11 +53,11 @@ check:
 
 install: iw iw.8.gz
        @$(NQ) ' INST iw'
-       $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)/bin/
-       $(Q)$(INSTALL) -m 755 -o root -g root -t $(DESTDIR)$(PREFIX)/bin/ iw
+       $(Q)$(MKDIR) $(DESTDIR)$(BINDIR)
+       $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(BINDIR) iw
        @$(NQ) ' INST iw.8'
-       $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)/share/man/man8/
-       $(Q)$(INSTALL) -m 644 -o root -g root -t $(DESTDIR)$(PREFIX)/share/man/man8/ iw.8.gz
+       $(Q)$(MKDIR) $(DESTDIR)$(MANDIR)/man8/
+       $(Q)$(INSTALL) -m 644 -t $(DESTDIR)$(MANDIR)/man8/ iw.8.gz
 
 clean:
        $(Q)rm -f iw *.o *~ *.gz version.h *-stamp
diff --git a/README b/README
index ee50c16efe233bb48eeac07b1cca6ff43250fe31..78dcccd9825a90056aa5f3f1e04001c29bd9822d 100644 (file)
--- a/README
+++ b/README
@@ -4,3 +4,11 @@ This is 'iw', a tool to use nl80211.
 
 To build iw, just enter 'make'. If that fails, copy the file
 defconfig to .config and adjust the settings in it.
+
+
+'iw' is currently maintained at http://git.sipsolutions.net/iw.git/,
+some more documentation is available at
+http://wireless.kernel.org/en/users/Documentation/iw.
+
+Please send all patches to Johannes Berg <johannes@sipsolutions.net>
+and CC linux-wireless@vger.kernel.org for community review.
diff --git a/genl.c b/genl.c
new file mode 100644 (file)
index 0000000..8f83d13
--- /dev/null
+++ b/genl.c
@@ -0,0 +1,114 @@
+/*
+ * This ought to be provided by libnl
+ */
+
+#include <asm/errno.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>  
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+                        void *arg)
+{
+       int *ret = arg;
+       *ret = err->error;
+       return NL_STOP;
+}
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+       int *ret = arg;
+       *ret = 0;
+       return NL_STOP;
+}
+
+struct handler_args {
+       const char *group;
+       int id;
+};
+
+static int family_handler(struct nl_msg *msg, void *arg)
+{
+       struct handler_args *grp = arg;
+       struct nlattr *tb[CTRL_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *mcgrp;
+       int rem_mcgrp;
+
+       nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+        if (!tb[CTRL_ATTR_MCAST_GROUPS])
+               return NL_SKIP;
+
+       nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
+               struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+               nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
+                         nla_data(mcgrp), nla_len(mcgrp), NULL);
+
+               if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
+                   !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
+                       continue;
+               if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
+                           grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
+                       continue;
+               grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
+               break;
+       }
+       
+       return NL_SKIP;
+}
+
+int nl_get_multicast_id(struct nl_handle *handle, const char *family, const char *group)
+{
+       struct nl_msg *msg;
+       struct nl_cb *cb;
+       int ret, ctrlid;
+       struct handler_args grp = {
+               .group = group,
+               .id = -ENOENT,
+       };
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return -ENOMEM;
+
+       cb = nl_cb_alloc(NL_CB_DEFAULT);
+       if (!cb) {
+               ret = -ENOMEM;
+               goto out_fail_cb;
+       }
+
+       ctrlid = genl_ctrl_resolve(handle, "nlctrl");
+
+        genlmsg_put(msg, 0, 0, ctrlid, 0,
+                   0, CTRL_CMD_GETFAMILY, 0);
+
+       ret = -ENOBUFS;
+       NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
+
+       ret = nl_send_auto_complete(handle, msg);
+       if (ret < 0)
+               goto out;
+
+       ret = 1;
+
+       nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
+       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &grp);
+
+       while (ret > 0)
+               nl_recvmsgs(handle, cb);
+
+       if (ret == 0)
+               ret = grp.id;
+ nla_put_failure:
+ out:
+       nl_cb_put(cb);
+ out_fail_cb:
+       nlmsg_free(msg);
+       return ret;
+}
diff --git a/info.c b/info.c
index 1079d2f0738b5563d2ca770f605e7f55e522577f..7fb96ac76c5689e6020bc7082604bc7af74648f1 100644 (file)
--- a/info.c
+++ b/info.c
@@ -16,7 +16,7 @@ static void print_flag(const char *name, int *open)
                printf(" (");
        else
                printf(", ");
-       printf(name);
+       printf("%s", name);
        *open = 1;
 }
 
@@ -34,6 +34,7 @@ static int print_phy_handler(struct nl_msg *msg, void *arg)
                [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
                [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
                [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
+               [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
        };
 
        struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
@@ -137,11 +138,18 @@ static int print_phy_handler(struct nl_msg *msg, void *arg)
                printf("\t\tFrequencies:\n");
 
                nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
+                       uint32_t freq;
                        nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
                                  nla_len(nl_freq), freq_policy);
                        if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
                                continue;
-                       printf("\t\t\t* %d MHz", nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]));
+                       freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
+                       printf("\t\t\t* %d MHz [%d]", freq, ieee80211_frequency_to_channel(freq));
+
+                       if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&
+                           !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
+                               printf(" (%.1f dBm)", 0.01 * nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]));
+
                        open = 0;
                        if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
                                print_flag("disabled", &open);
diff --git a/iw.c b/iw.c
index e6d7232abccb37c38cf648fcdccf14e2e9c4dbb9..5859180768db448fbe5511301d5d0c96f7db601c 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -85,6 +85,8 @@ static void usage(const char *argv0)
        fprintf(stderr, "\t--debug\t\tenable netlink debugging\n");
        fprintf(stderr, "\t--version\tshow version\n");
        fprintf(stderr, "Commands:\n");
+       fprintf(stderr, "\thelp\n");
+       fprintf(stderr, "\tevent\n");
        for (cmd = &__start___cmd; cmd < &__stop___cmd;
             cmd = (struct cmd *)((char *)cmd + cmd_size)) {
                if (!cmd->handler || cmd->hidden)
@@ -141,6 +143,8 @@ static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
 
 static int finish_handler(struct nl_msg *msg, void *arg)
 {
+       int *ret = arg;
+       *ret = 0;
        return NL_SKIP;
 }
 
@@ -251,7 +255,7 @@ static int handle_cmd(struct nl80211_state *state,
        err = 1;
 
        nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
-       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, NULL);
+       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
        nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
 
        while (err > 0)
@@ -266,6 +270,62 @@ static int handle_cmd(struct nl80211_state *state,
        return 2;
 }
 
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+       return NL_OK;
+}
+
+static int print_event(struct nl_msg *msg, void *arg)
+{
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+                          
+       switch (gnlh->cmd) {
+       case NL80211_CMD_NEW_WIPHY: {
+               printf("wiphy rename: phy #%d to %s\n",
+                      nla_get_u32(tb[NL80211_ATTR_WIPHY]),
+                      nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]));
+               break;
+       }
+       }
+
+       return NL_SKIP;
+}
+
+static int listen_events(struct nl80211_state *state,
+                        int argc, char **argv)
+{
+       int mcid, ret;
+       struct nl_cb *cb = nl_cb_alloc(debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+
+       if (!cb) {
+               fprintf(stderr, "failed to allocate netlink callbacks\n");
+               return -ENOMEM;
+       }
+
+       mcid = nl_get_multicast_id(state->nl_handle, "nl80211", "config");
+       if (mcid < 0)
+               return mcid;
+
+       ret = nl_socket_add_membership(state->nl_handle, mcid);
+       if (ret)
+               return ret;
+       
+       /* no sequence checking for multicast messages */
+       nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, NULL);
+
+       while (1)
+               nl_recvmsgs(state->nl_handle, cb);
+
+       nl_cb_put(cb);
+
+       return 0;
+}
+
 int main(int argc, char **argv)
 {
        struct nl80211_state nlstate;
@@ -299,7 +359,9 @@ int main(int argc, char **argv)
        if (err)
                return 1;
 
-       if (strcmp(*argv, "dev") == 0) {
+       if (strcmp(*argv, "event") == 0) {
+               err = listen_events(&nlstate, argc, argv);
+       } else if (strcmp(*argv, "dev") == 0) {
                argc--;
                argv++;
                err = handle_cmd(&nlstate, CIB_NETDEV, argc, argv);
diff --git a/iw.h b/iw.h
index 2a5be6f2ae768b54a422c016cdfff6b60d4dcc43..3967368ef05422e8de7012cfbd122cb43523f094 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -57,5 +57,9 @@ int mac_addr_a2n(unsigned char *mac_addr, char *arg);
 int mac_addr_n2a(char *mac_addr, unsigned char *arg);
 
 const char *iftype_name(enum nl80211_iftype iftype);
+int ieee80211_channel_to_frequency(int chan);
+int ieee80211_frequency_to_channel(int freq);
+
+int nl_get_multicast_id(struct nl_handle *handle, const char *family, const char *group);
 
 #endif /* __IW_H */
index 2929d46033487874bb5e5afdb5ce2de0b64578e5..1f60a24ea4dd1b9f7ab60318bcfee5403057f2e8 100644 (file)
--- a/nl80211.h
+++ b/nl80211.h
@@ -3,7 +3,26 @@
 /*
  * 802.11 netlink interface public header
  *
- * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006, 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com>
+ * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
+ * Copyright 2008 Colin McCabe <colin@cozybit.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
  */
 
 /**
  *
  * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
  *     to get a list of all present wiphys.
- * @NL80211_CMD_SET_WIPHY: set wiphy name, needs %NL80211_ATTR_WIPHY and
- *     %NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
+ *     %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
+ *     %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or
+ *     %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET.
  * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
  *     or rename notification. Has attributes %NL80211_ATTR_WIPHY and
  *     %NL80211_ATTR_WIPHY_NAME.
@@ -187,6 +208,15 @@ enum nl80211_commands {
  * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
  *     /sys/class/ieee80211/<phyname>/index
  * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
+ * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
+ * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
+ * @NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET: included with NL80211_ATTR_WIPHY_FREQ
+ *     if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
+ *     NL80211_SEC_CHAN_NO_HT = HT not allowed (i.e., same as not including
+ *             this attribute)
+ *     NL80211_SEC_CHAN_DISABLED = HT20 only
+ *     NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel
+ *     NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel
  *
  * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
  * @NL80211_ATTR_IFNAME: network interface name
@@ -252,6 +282,9 @@ enum nl80211_commands {
  *     (u8, 0 or 1)
  * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
  *     (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic
+ *     rates in format defined by IEEE 802.11 7.3.2.2 but without the length
+ *     restriction (at most %NL80211_MAX_SUPP_RATES).
  *
  * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
  *     association request when used with NL80211_CMD_NEW_STATION)
@@ -323,6 +356,12 @@ enum nl80211_attrs {
 
        NL80211_ATTR_MESH_PARAMS,
 
+       NL80211_ATTR_BSS_BASIC_RATES,
+
+       NL80211_ATTR_WIPHY_TXQ_PARAMS,
+       NL80211_ATTR_WIPHY_FREQ,
+       NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET,
+
        NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
 
        NL80211_ATTR_SCAN_FREQUENCIES,
@@ -341,6 +380,10 @@ enum nl80211_attrs {
  * here
  */
 #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
+#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
+#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
+#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
+#define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET
 
 #define NL80211_MAX_SUPP_RATES                 32
 #define NL80211_MAX_SUPP_REG_RULES             32
@@ -520,6 +563,8 @@ enum nl80211_band_attr {
  *     on this channel in current regulatory domain.
  * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
  *     on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
+ *     (100 * dBm).
  */
 enum nl80211_frequency_attr {
        __NL80211_FREQUENCY_ATTR_INVALID,
@@ -528,12 +573,15 @@ enum nl80211_frequency_attr {
        NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
        NL80211_FREQUENCY_ATTR_NO_IBSS,
        NL80211_FREQUENCY_ATTR_RADAR,
+       NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
 
        /* keep last */
        __NL80211_FREQUENCY_ATTR_AFTER_LAST,
        NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
 };
 
+#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
+
 /**
  * enum nl80211_bitrate_attr - bitrate attributes
  * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
@@ -715,6 +763,47 @@ enum nl80211_meshconf_params {
        NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
 };
 
+/**
+ * enum nl80211_txq_attr - TX queue parameter attributes
+ * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
+ * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
+ * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning
+ *     disabled
+ * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form
+ *     2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form
+ *     2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255]
+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
+ * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number
+ */
+enum nl80211_txq_attr {
+       __NL80211_TXQ_ATTR_INVALID,
+       NL80211_TXQ_ATTR_QUEUE,
+       NL80211_TXQ_ATTR_TXOP,
+       NL80211_TXQ_ATTR_CWMIN,
+       NL80211_TXQ_ATTR_CWMAX,
+       NL80211_TXQ_ATTR_AIFS,
+
+       /* keep last */
+       __NL80211_TXQ_ATTR_AFTER_LAST,
+       NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1
+};
+
+enum nl80211_txq_q {
+       NL80211_TXQ_Q_VO,
+       NL80211_TXQ_Q_VI,
+       NL80211_TXQ_Q_BE,
+       NL80211_TXQ_Q_BK
+};
+
+enum nl80211_sec_chan_offset {
+       NL80211_SEC_CHAN_NO_HT /* No HT */,
+       NL80211_SEC_CHAN_DISABLED /* HT20 only */,
+       NL80211_SEC_CHAN_BELOW /* HT40- */,
+       NL80211_SEC_CHAN_ABOVE /* HT40+ */
+};
+
 enum nl80211_bss {
        __NL80211_BSS_INVALID,
        NL80211_BSS_BSSID,
diff --git a/phy.c b/phy.c
index 50d6a2e755ee7f7b4ee15d55f5fd5c5cf82e16ef..45d4e78fefd28b95aed3954bc0df6a60c2ffa62d 100644 (file)
--- a/phy.c
+++ b/phy.c
@@ -1,3 +1,4 @@
+#include <stdbool.h>
 #include <errno.h>
 #include <net/if.h>
 
@@ -24,3 +25,64 @@ static int handle_name(struct nl_cb *cb,
        return -ENOBUFS;
 }
 COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name);
+
+static int handle_freqchan(struct nl_msg *msg, bool chan,
+                          int argc, char **argv)
+{
+       static const struct {
+               const char *name;
+               unsigned int val;
+       } htmap[] = {
+               { .name = "HT20", .val = NL80211_SEC_CHAN_DISABLED, },
+               { .name = "HT40+", .val = NL80211_SEC_CHAN_ABOVE, },
+               { .name = "HT40-", .val = NL80211_SEC_CHAN_BELOW, },
+       };
+       unsigned int htval = NL80211_SEC_CHAN_NO_HT;
+       unsigned int freq;
+       int i;
+
+       if (!argc || argc > 2)
+               return 1;
+
+       if (argc == 2) {
+               for (i = 0; i < sizeof(htmap)/sizeof(htmap[0]); i++) {
+                       if (strcasecmp(htmap[i].name, argv[1]) == 0) {
+                               htval = htmap[i].val;
+                               break;
+                       }
+               }
+               if (htval == NL80211_SEC_CHAN_NO_HT)
+                       return 1;
+       }
+
+       freq = strtoul(argv[0], NULL, 10);
+       if (chan)
+               freq = ieee80211_channel_to_frequency(freq);
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET, htval);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+
+static int handle_freq(struct nl_cb *cb, struct nl_msg *msg,
+                      int argc, char **argv)
+{
+       return handle_freqchan(msg, false, argc, argv);
+}
+COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq);
+COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq);
+
+static int handle_chan(struct nl_cb *cb, struct nl_msg *msg,
+                      int argc, char **argv)
+{
+       return handle_freqchan(msg, true, argc, argv);
+}
+COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan);
+COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan);
diff --git a/util.c b/util.c
index 4d1c1a69a844beaed2bd964378294066cd0f9e95..40a9568c02486fe65102f5de8df51df0c0764a7e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -65,3 +65,27 @@ const char *iftype_name(enum nl80211_iftype iftype)
        sprintf(modebuf, "Unknown mode (%d)", iftype);
        return modebuf;
 }
+
+int ieee80211_channel_to_frequency(int chan)
+{
+       if (chan < 14)
+               return 2407 + chan * 5;
+
+       if (chan == 14)
+               return 2484;
+
+       /* FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2) */
+       return (chan + 1000) * 5;
+}
+
+int ieee80211_frequency_to_channel(int freq)
+{
+       if (freq == 2484)
+               return 14;
+
+       if (freq < 2484)
+               return (freq - 2407) / 5;
+
+       /* FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2) */
+       return freq/5 - 1000;
+}
index 773486faacebaa63d2f980be67cde9ec00dd7de1..938a65d0ac3a51493e656104ebb77434a32566d4 100755 (executable)
@@ -1,8 +1,8 @@
 #!/bin/sh
 
-VERSION="0.9.5"
+VERSION="0.9.6"
+OUT="version.h"
 
-(
 if head=`git rev-parse --verify HEAD 2>/dev/null`; then
        git update-index --refresh --unmerged > /dev/null
        descr=$(git describe)
@@ -11,13 +11,12 @@ if head=`git rev-parse --verify HEAD 2>/dev/null`; then
        # is correct...
        [ "${descr%%-*}" = "v$VERSION" ] || exit 2
        
-       echo -n '#define IW_VERSION "'
-       echo -n "${descr#v}"
+       echo -n '#define IW_VERSION "' > "$OUT"
+       echo -n "${descr#v}" >> "$OUT"
        if git diff-index --name-only HEAD | read dummy ; then
-               echo -n "-dirty"
+               echo -n "-dirty" >> "$OUT"
        fi
-       echo '"'
+       echo '"' >> "$OUT"
 else
-echo "#define IW_VERSION \"$VERSION-nogit\""
+echo "#define IW_VERSION \"$VERSION-nogit\"" > "$OUT"
 fi
-) > version.h