[pkg-wpa-devel] r1377 - in /iw/trunk: Makefile debian/changelog event.c ibss.c info.c interface.c iw.c iw.h mesh.c mpath.c phy.c reason.c reg.c scan.c station.c status.c version.sh

kelmo-guest at users.alioth.debian.org kelmo-guest at users.alioth.debian.org
Wed May 13 18:51:40 UTC 2009


Author: kelmo-guest
Date: Wed May 13 18:51:40 2009
New Revision: 1377

URL: http://svn.debian.org/wsvn/pkg-wpa/?sc=1&rev=1377
Log:
New upstream release.

Added:
    iw/trunk/event.c
      - copied unchanged from r1376, iw/branches/upstream/current/event.c
    iw/trunk/reason.c
      - copied unchanged from r1376, iw/branches/upstream/current/reason.c
    iw/trunk/status.c
      - copied unchanged from r1376, iw/branches/upstream/current/status.c
Modified:
    iw/trunk/Makefile
    iw/trunk/debian/changelog
    iw/trunk/ibss.c
    iw/trunk/info.c
    iw/trunk/interface.c
    iw/trunk/iw.c
    iw/trunk/iw.h
    iw/trunk/mesh.c
    iw/trunk/mpath.c
    iw/trunk/phy.c
    iw/trunk/reg.c
    iw/trunk/scan.c
    iw/trunk/station.c
    iw/trunk/version.sh

Modified: iw/trunk/Makefile
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/Makefile?rev=1377&op=diff
==============================================================================
--- iw/trunk/Makefile (original)
+++ iw/trunk/Makefile Wed May 13 18:51:40 2009
@@ -13,7 +13,7 @@
 CFLAGS ?= -O2 -g
 CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration
 
-OBJS = iw.o genl.o info.o phy.o interface.o ibss.o station.o util.o mesh.o mpath.o scan.o reg.o version.o
+OBJS = iw.o genl.o event.o info.o phy.o interface.o ibss.o station.o util.o mesh.o mpath.o scan.o reg.o version.o reason.o status.o
 ALL = iw
 
 NL1FOUND := $(shell pkg-config --atleast-version=1 libnl-1 && echo Y)

Modified: iw/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/debian/changelog?rev=1377&op=diff
==============================================================================
--- iw/trunk/debian/changelog (original)
+++ iw/trunk/debian/changelog Wed May 13 18:51:40 2009
@@ -1,4 +1,4 @@
-iw (0.9.13-1) unstable; urgency=low
+iw (0.9.14-1) UNRELEASED; urgency=low
 
   * New upstream release.
   * Use minimal dh-centric debian/rules.

Modified: iw/trunk/ibss.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/ibss.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/ibss.c (original)
+++ iw/trunk/ibss.c Wed May 13 18:51:40 2009
@@ -63,6 +63,12 @@
 	return 0;
 }
 COMMAND(ibss, leave, NULL,
-	NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss);
+	NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
+	"Leave the current IBSS cell.");
 COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>]",
-	NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss);
+	NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
+	"Join the IBSS cell with the given SSID, if it doesn't exist create\n"
+	"it on the given frequency. When fixed frequency is requested, don't\n"
+	"join/create a cell on a different frequency. When a fixed BSSID is\n"
+	"requested use that BSSID and do not adopt another cell's BSSID even\n"
+	"if it has higher TSF and the same SSID.");

Modified: iw/trunk/info.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/info.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/info.c (original)
+++ iw/trunk/info.c Wed May 13 18:51:40 2009
@@ -266,6 +266,8 @@
 
 	return 0;
 }
-TOPLEVEL(info, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_info);
-TOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info);
-TOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info);
+TOPLEVEL(info, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_info,
+	 "Show capabilities for the specified wireless device.");
+TOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info,
+	 "List all wireless devices and their capabilities.");
+TOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL);

Modified: iw/trunk/interface.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/interface.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/interface.c (original)
+++ iw/trunk/interface.c Wed May 13 18:51:40 2009
@@ -11,6 +11,12 @@
 
 #include "nl80211.h"
 #include "iw.h"
+
+#define VALID_FLAGS	"none:     no special flags\n"\
+			"fcsfail:  show frames with FCS errors\n"\
+			"control:  show control frames\n"\
+			"otherbss: show frames from other BSSes\n"\
+			"cook:     use cooked mode"
 
 static char *mntr_flags[NL80211_MNTR_FLAG_MAX + 1] = {
 	"none",
@@ -71,6 +77,9 @@
 	return err;
 }
 
+/* for help */
+#define IFACE_TYPES "Valid interface types are: managed, ibss, monitor, mesh, wds."
+
 /* return 0 if ok, internal error otherwise */
 static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type,
 		       bool need_type)
@@ -181,10 +190,15 @@
  nla_put_failure:
 	return -ENOBUFS;
 }
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags ...]",
-	NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add);
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags ...]",
-	NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add);
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
+	NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
+	"Add a new virtual interface with the given configuration.\n"
+	IFACE_TYPES "\n\n"
+	"The flags are only used for monitor interfaces, valid flags are:\n"
+	VALID_FLAGS "\n\n"
+	"The mesh_id is used only for mesh mode.");
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
+	NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
 
 static int handle_interface_del(struct nl80211_state *state,
 				struct nl_cb *cb,
@@ -193,7 +207,8 @@
 {
 	return 0;
 }
-TOPLEVEL(del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del);
+TOPLEVEL(del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del,
+	 "Remove this virtual interface");
 HIDDEN(interface, del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del);
 
 static int print_iface_handler(struct nl_msg *msg, void *arg)
@@ -232,7 +247,8 @@
 	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_iface_handler, NULL);
 	return 0;
 }
-TOPLEVEL(info, NULL, NL80211_CMD_GET_INTERFACE, 0, CIB_NETDEV, handle_interface_info);
+TOPLEVEL(info, NULL, NL80211_CMD_GET_INTERFACE, 0, CIB_NETDEV, handle_interface_info,
+	 "Show information for this interface.");
 
 static int handle_interface_set(struct nl80211_state *state,
 				struct nl_cb *cb,
@@ -259,8 +275,10 @@
  nla_put_failure:
 	return -ENOBUFS;
 }
-COMMAND(set, monitor, "<flag> [...]",
-	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_set);
+COMMAND(set, monitor, "<flag>*",
+	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_set,
+	"Set monitor flags. Valid flags are:\n"
+	VALID_FLAGS);
 
 static int handle_interface_meshid(struct nl80211_state *state,
 				   struct nl_cb *cb,
@@ -281,7 +299,7 @@
 	return -ENOBUFS;
 }
 COMMAND(set, meshid, "<meshid>",
-	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_meshid);
+	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_meshid, NULL);
 
 static unsigned int dev_dump_wiphy;
 
@@ -294,7 +312,8 @@
 	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_iface_handler, &dev_dump_wiphy);
 	return 0;
 }
-TOPLEVEL(dev, NULL, NL80211_CMD_GET_INTERFACE, NLM_F_DUMP, CIB_NONE, handle_dev_dump);
+TOPLEVEL(dev, NULL, NL80211_CMD_GET_INTERFACE, NLM_F_DUMP, CIB_NONE, handle_dev_dump,
+	 "List all network interfaces for wireless hardware.");
 
 static int handle_interface_type(struct nl80211_state *state,
 				 struct nl_cb *cb,
@@ -318,4 +337,6 @@
 	return -ENOBUFS;
 }
 COMMAND(set, type, "<type>",
-	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_type);
+	NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_type,
+	"Set interface type/mode.\n"
+	IFACE_TYPES);

Modified: iw/trunk/iw.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/iw.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/iw.c (original)
+++ iw/trunk/iw.c Wed May 13 18:51:40 2009
@@ -12,6 +12,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdbool.h>
                      
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
@@ -46,7 +47,7 @@
 #define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
 #endif /* CONFIG_LIBNL20 */
 
-static int debug = 0;
+int iw_debug = 0;
 
 static int nl80211_init(struct nl80211_state *state)
 {
@@ -93,44 +94,97 @@
 	nl_socket_free(state->nl_sock);
 }
 
-__COMMAND(NULL, NULL, "", NULL, 0, 0, 0, CIB_NONE, NULL);
-__COMMAND(NULL, NULL, "", NULL, 1, 0, 0, CIB_NONE, NULL);
+__COMMAND(NULL, NULL, "", NULL, 0, 0, 0, CIB_NONE, NULL, NULL);
+__COMMAND(NULL, NULL, "", NULL, 1, 0, 0, CIB_NONE, NULL, NULL);
 
 static int cmd_size;
 
-static void usage(const char *argv0)
-{
-	struct cmd *cmd;
-
-	fprintf(stderr, "Usage:\t%s [options] command\n", argv0);
+static void __usage_cmd(struct cmd *cmd, char *indent, bool full)
+{
+	const char *start, *lend, *end;
+
+	fprintf(stderr, "%s", indent);
+
+	switch (cmd->idby) {
+	case CIB_NONE:
+		break;
+	case CIB_PHY:
+		fprintf(stderr, "phy <phyname> ");
+		break;
+	case CIB_NETDEV:
+		fprintf(stderr, "dev <devname> ");
+		break;
+	}
+	if (cmd->section)
+		fprintf(stderr, "%s ", cmd->section);
+	fprintf(stderr, "%s", cmd->name);
+	if (cmd->args)
+		fprintf(stderr, " %s", cmd->args);
+	fprintf(stderr, "\n");
+
+	if (!full || !cmd->help)
+		return;
+
+	/* hack */
+	if (strlen(indent))
+		indent = "\t\t";
+	else
+		fprintf(stderr, "\n");
+
+	/* print line by line */
+	start = cmd->help;
+	end = strchr(start, '\0');
+	do {
+		lend = strchr(start, '\n');
+		if (!lend)
+			lend = end;
+		fprintf(stderr, "%s", indent);
+		fprintf(stderr, "%.*s\n", (int)(lend - start), start);
+		start = lend + 1;
+	} while (end != lend);
+
+	fprintf(stderr, "\n");
+}
+
+static void usage_options(void)
+{
 	fprintf(stderr, "Options:\n");
 	fprintf(stderr, "\t--debug\t\tenable netlink debugging\n");
-	fprintf(stderr, "\t--version\tshow version\n");
+}
+
+static const char *argv0;
+
+static void usage(bool full)
+{
+	struct cmd *cmd;
+
+	fprintf(stderr, "Usage:\t%s [options] command\n", argv0);
+	usage_options();
+	fprintf(stderr, "\t--version\tshow version (%s)\n", iw_version);
 	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)
 			continue;
-		switch (cmd->idby) {
-		case CIB_NONE:
-			fprintf(stderr, "\t");
-			break;
-		case CIB_PHY:
-			fprintf(stderr, "\tphy <phyname> ");
-			break;
-		case CIB_NETDEV:
-			fprintf(stderr, "\tdev <devname> ");
-			break;
-		}
-		if (cmd->section)
-			fprintf(stderr, "%s ", cmd->section);
-		fprintf(stderr, "%s", cmd->name);
-		if (cmd->args)
-			fprintf(stderr, " %s", cmd->args);
-		fprintf(stderr, "\n");
-	}
+		__usage_cmd(cmd, "\t", full);
+	}
+}
+
+static int print_help(struct nl80211_state *state,
+		      struct nl_cb *cb,
+		      struct nl_msg *msg,
+		      int argc, char **argv)
+{
+	exit(3);
+}
+TOPLEVEL(help, NULL, 0, 0, CIB_NONE, print_help,
+	 "Print usage for each command.");
+
+static void usage_cmd(struct cmd *cmd)
+{
+	fprintf(stderr, "Usage:\t%s [options] ", argv0);
+	__usage_cmd(cmd, "", true);
+	usage_options();
 }
 
 static void version(void)
@@ -177,8 +231,8 @@
 	return NL_STOP;
 }
 
-int handle_cmd(struct nl80211_state *state, enum id_input idby,
-	       int argc, char **argv)
+static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
+			int argc, char **argv, struct cmd **cmdout)
 {
 	struct cmd *cmd, *match = NULL;
 	struct nl_cb *cb;
@@ -264,6 +318,9 @@
 	if (!cmd)
 		return 1;
 
+	if (cmdout)
+		*cmdout = cmd;
+
 	if (!cmd->cmd) {
 		argc = o_argc;
 		argv = o_argv;
@@ -276,7 +333,7 @@
 		return 2;
 	}
 
-	cb = nl_cb_alloc(debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+	cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
 	if (!cb) {
 		fprintf(stderr, "failed to allocate netlink callbacks\n");
 		err = 2;
@@ -323,180 +380,17 @@
 	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];
-	char ifname[100];
-	char macbuf[6*3];
-	__u8 reg_type;
-
-	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;
-	case NL80211_CMD_NEW_SCAN_RESULTS:
-		if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
-		printf("scan finished on %s (phy #%d)\n",
-		       ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY]));
-		break;
-	case NL80211_CMD_SCAN_ABORTED:
-		if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
-		printf("scan aborted on %s (phy #%d)\n",
-		       ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY]));
-		break;
-	case NL80211_CMD_REG_CHANGE:
-
-		printf("regulatory domain change: ");
-
-		reg_type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
-
-		switch (reg_type) {
-		case NL80211_REGDOM_TYPE_COUNTRY:
-			printf("set to %s by %s request",
-			       nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
-			       reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
-			if (tb[NL80211_ATTR_WIPHY])
-				printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
-			break;
-		case NL80211_REGDOM_TYPE_WORLD:
-			printf("set to world roaming by %s request",
-			       reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
-			break;
-		case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
-			printf("custom world roaming rules in place on phy%d by %s request",
-			       nla_get_u32(tb[NL80211_ATTR_WIPHY]),
-			       reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
-			break;
-		case NL80211_REGDOM_TYPE_INTERSECTION:
-			printf("intersection used due to a request made by %s",
-			       reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
-			if (tb[NL80211_ATTR_WIPHY])
-				printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
-			break;
-		default:
-			printf("unknown source (upgrade this utility)");
-			break;
-		}
-
-		printf("\n");
-		break;
-	case NL80211_CMD_JOIN_IBSS:
-		if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
-		mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
-		printf("IBSS %s joined on %s (phy #%d)\n",
-		       macbuf, ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY]));
-		break;
-	default:
-		printf("unknown event: %d\n", gnlh->cmd);
-		break;
-	}
-
-	return NL_SKIP;
-}
-
-struct wait_event {
-	int n_cmds;
-	const __u32 *cmds;
-	__u32 cmd;
-};
-
-static int wait_event(struct nl_msg *msg, void *arg)
-{
-	struct wait_event *wait = arg;
-	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-	int i;
-
-	for (i = 0; i < wait->n_cmds; i++) {
-		if (gnlh->cmd == wait->cmds[i]) {
-			wait->cmd = gnlh->cmd;
-		}
-	}
-
-	return NL_SKIP;
-}
-
-__u32 listen_events(struct nl80211_state *state,
-		    const int n_waits, const __u32 *waits)
-{
-	int mcid, ret;
-	struct nl_cb *cb = nl_cb_alloc(debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
-	struct wait_event wait_ev;
-
-	if (!cb) {
-		fprintf(stderr, "failed to allocate netlink callbacks\n");
-		return -ENOMEM;
-	}
-
-	/* Configuration multicast group */
-	mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "config");
-	if (mcid < 0)
-		return mcid;
-
-	ret = nl_socket_add_membership(state->nl_sock, mcid);
-	if (ret)
-		return ret;
-
-	/* Scan multicast group */
-	mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
-	if (mcid >= 0) {
-		ret = nl_socket_add_membership(state->nl_sock, mcid);
-		if (ret)
-			return ret;
-	}
-
-	/* Regulatory multicast group */
-	mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "regulatory");
-	if (mcid >= 0) {
-		ret = nl_socket_add_membership(state->nl_sock, mcid);
-		if (ret)
-			return ret;
-	}
-
-	/* MLME multicast group */
-	mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "mlme");
-	if (mcid >= 0) {
-		ret = nl_socket_add_membership(state->nl_sock, 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);
-
-	if (n_waits && waits) {
-		wait_ev.cmds = waits;
-		wait_ev.n_cmds = n_waits;
-		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wait_event, &wait_ev);
-	} else {
-		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, NULL);
-	}
-
-	wait_ev.cmd = 0;
-
-	while (!wait_ev.cmd)
-		nl_recvmsgs(state->nl_sock, cb);
-
-	nl_cb_put(cb);
-
-	return wait_ev.cmd;
+int handle_cmd(struct nl80211_state *state, enum id_input idby,
+	       int argc, char **argv)
+{
+	return __handle_cmd(state, idby, argc, argv, NULL);
 }
 
 int main(int argc, char **argv)
 {
 	struct nl80211_state nlstate;
 	int err;
-	const char *argv0;
+	struct cmd *cmd = NULL;
 
 	/* calculate command size including padding */
 	cmd_size = abs((long)&__cmd_NULL_NULL_1_CIB_NONE_0
@@ -506,7 +400,7 @@
 	argv0 = *argv++;
 
 	if (argc > 0 && strcmp(*argv, "--debug") == 0) {
-		debug = 1;
+		iw_debug = 1;
 		argc--;
 		argv++;
 	}
@@ -516,8 +410,9 @@
 		return 0;
 	}
 
+	/* need to treat "help" command specially so it works w/o nl80211 */
 	if (argc == 0 || strcmp(*argv, "help") == 0) {
-		usage(argv0);
+		usage(argc != 0);
 		return 0;
 	}
 
@@ -525,30 +420,28 @@
 	if (err)
 		return 1;
 
-	if (strcmp(*argv, "event") == 0) {
-		if (argc != 1)
-			err = 1;
-		else
-			err = listen_events(&nlstate, 0, NULL);
-	} else if (strcmp(*argv, "dev") == 0 && argc > 1) {
+	if (strcmp(*argv, "dev") == 0 && argc > 1) {
 		argc--;
 		argv++;
-		err = handle_cmd(&nlstate, II_NETDEV, argc, argv);
+		err = __handle_cmd(&nlstate, II_NETDEV, argc, argv, &cmd);
 	} else if (strncmp(*argv, "phy", 3) == 0 && argc > 1) {
 		if (strlen(*argv) == 3) {
 			argc--;
 			argv++;
-			err = handle_cmd(&nlstate, II_PHY_NAME, argc, argv);
+			err = __handle_cmd(&nlstate, II_PHY_NAME, argc, argv, &cmd);
 		} else if (*(*argv + 3) == '#')
-			err = handle_cmd(&nlstate, II_PHY_IDX, argc, argv);
+			err = __handle_cmd(&nlstate, II_PHY_IDX, argc, argv, &cmd);
 		else
 			err = 1;
 	} else
-		err = handle_cmd(&nlstate, II_NONE, argc, argv);
-
-	if (err == 1)
-		usage(argv0);
-	if (err < 0)
+		err = __handle_cmd(&nlstate, II_NONE, argc, argv, &cmd);
+
+	if (err == 1) {
+		if (cmd)
+			usage_cmd(cmd);
+		else
+			usage(false);
+	} else if (err < 0)
 		fprintf(stderr, "command failed: %s (%d)\n", strerror(-err), err);
 
 	nl80211_cleanup(&nlstate);

Modified: iw/trunk/iw.h
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/iw.h?rev=1377&op=diff
==============================================================================
--- iw/trunk/iw.h (original)
+++ iw/trunk/iw.h Wed May 13 18:51:40 2009
@@ -37,6 +37,7 @@
 	const char *section;
 	const char *name;
 	const char *args;
+	const char *help;
 	const enum nl80211_commands cmd;
 	int nl_msg_flags;
 	int hidden;
@@ -54,21 +55,32 @@
 
 #define ARRAY_SIZE(ar) (sizeof(ar)/sizeof(ar[0]))
 
-#define __COMMAND(sect, symname, name, args, nlcmd, flags, hidden, idby, handler)\
+#define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help)\
 	static const struct cmd						\
-	__cmd ## _ ## symname ## _ ## handler ## _ ## nlcmd ## _ ## idby ## _ ## hidden\
-	__attribute__((used)) __attribute__((section("__cmd")))		\
-	= { sect, name, args, nlcmd, flags, hidden, idby, handler }
-#define COMMAND(section, name, args, cmd, flags, idby, handler)	\
-	__COMMAND(#section, name, #name, args, cmd, flags, 0, idby, handler)
-#define HIDDEN(section, name, args, cmd, flags, idby, handler)	\
-	__COMMAND(#section, name, #name, args, cmd, flags, 1, idby, handler)
-#define TOPLEVEL(name, args, cmd, flags, idby, handler)		\
-	__COMMAND(NULL, name, #name, args, cmd, flags, 0, idby, handler)
+	__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
+	__attribute__((used)) __attribute__((section("__cmd")))	= {	\
+		.section = (_section),					\
+		.name = (_name),					\
+		.args = (_args),					\
+		.cmd = (_nlcmd),					\
+		.nl_msg_flags = (_flags),				\
+		.hidden = (_hidden),					\
+		.idby = (_idby),					\
+		.handler = (_handler),					\
+		.help = (_help),					\
+	 }
+#define COMMAND(section, name, args, cmd, flags, idby, handler, help)	\
+	__COMMAND(#section, name, #name, args, cmd, flags, 0, idby, handler, help)
+#define HIDDEN(section, name, args, cmd, flags, idby, handler)		\
+	__COMMAND(#section, name, #name, args, cmd, flags, 1, idby, handler, NULL)
+#define TOPLEVEL(name, args, cmd, flags, idby, handler, help)		\
+	__COMMAND(NULL, name, #name, args, cmd, flags, 0, idby, handler, help)
 extern struct cmd __start___cmd;
 extern struct cmd __stop___cmd;
 
 extern const char iw_version[];
+
+extern int iw_debug;
 
 int handle_cmd(struct nl80211_state *state, enum id_input idby,
 	       int argc, char **argv);
@@ -87,4 +99,7 @@
 
 char *reg_initiator_to_string(__u8 initiator);
 
+const char *get_reason_str(uint16_t reason);
+const char *get_status_str(uint16_t status);
+
 #endif /* __IW_H */

Modified: iw/trunk/mesh.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/mesh.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/mesh.c (original)
+++ iw/trunk/mesh.c Wed May 13 18:51:40 2009
@@ -244,7 +244,8 @@
 }
 
 COMMAND(set, mesh_param, "<param> <value>",
-	NL80211_CMD_SET_MESH_PARAMS, 0, CIB_NETDEV, set_interface_meshparam);
+	NL80211_CMD_SET_MESH_PARAMS, 0, CIB_NETDEV, set_interface_meshparam,
+	"Set mesh parameter (run command without any to see available ones).");
 
 /* Getter */
 static int print_mesh_param_handler(struct nl_msg *msg, void *arg)
@@ -290,4 +291,5 @@
 }
 
 COMMAND(get, mesh_param, "<param>",
-	NL80211_CMD_GET_MESH_PARAMS, 0, CIB_NETDEV, get_interface_meshparam);
+	NL80211_CMD_GET_MESH_PARAMS, 0, CIB_NETDEV, get_interface_meshparam,
+	"Retrieve mesh parameter (run command without any to see available ones).");

Modified: iw/trunk/mpath.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/mpath.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/mpath.c (original)
+++ iw/trunk/mpath.c Wed May 13 18:51:40 2009
@@ -123,9 +123,11 @@
 	return -ENOBUFS;
 }
 COMMAND(mpath, get, "<MAC address>",
-	NL80211_CMD_GET_MPATH, 0, CIB_NETDEV, handle_mpath_get);
+	NL80211_CMD_GET_MPATH, 0, CIB_NETDEV, handle_mpath_get,
+	"Get information on mesh path to the given node.");
 COMMAND(mpath, del, "<MAC address>",
-	NL80211_CMD_DEL_MPATH, 0, CIB_NETDEV, handle_mpath_get);
+	NL80211_CMD_DEL_MPATH, 0, CIB_NETDEV, handle_mpath_get,
+	"Remove the mesh path to the given node.");
 
 static int handle_mpath_set(struct nl80211_state *state,
 			    struct nl_cb *cb,
@@ -169,9 +171,11 @@
 	return -ENOBUFS;
 }
 COMMAND(mpath, new, "<destination MAC address> next_hop <next hop MAC address>",
-	NL80211_CMD_NEW_MPATH, 0, CIB_NETDEV, handle_mpath_set);
+	NL80211_CMD_NEW_MPATH, 0, CIB_NETDEV, handle_mpath_set,
+	"Create a new mesh path (instead of relying on automatic discovery).");
 COMMAND(mpath, set, "<destination MAC address> next_hop <next hop MAC address>",
-	NL80211_CMD_SET_MPATH, 0, CIB_NETDEV, handle_mpath_set);
+	NL80211_CMD_SET_MPATH, 0, CIB_NETDEV, handle_mpath_set,
+	"Set an existing mesh path's next hop.");
 
 static int handle_mpath_dump(struct nl80211_state *state,
 			     struct nl_cb *cb,
@@ -182,4 +186,5 @@
 	return 0;
 }
 COMMAND(mpath, dump, NULL,
-	NL80211_CMD_GET_MPATH, NLM_F_DUMP, CIB_NETDEV, handle_mpath_dump);
+	NL80211_CMD_GET_MPATH, NLM_F_DUMP, CIB_NETDEV, handle_mpath_dump,
+	"List known mesh paths.");

Modified: iw/trunk/phy.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/phy.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/phy.c (original)
+++ iw/trunk/phy.c Wed May 13 18:51:40 2009
@@ -25,7 +25,8 @@
  nla_put_failure:
 	return -ENOBUFS;
 }
-COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name);
+COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
+	"Rename this wireless device.");
 
 static int handle_freqchan(struct nl_msg *msg, bool chan,
 			   int argc, char **argv)
@@ -75,9 +76,11 @@
 	return handle_freqchan(msg, false, argc, argv);
 }
 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
-	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq);
+	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
+	"Set frequency/channel the hardware is using, including HT\n"
+	"configuration.");
 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
-	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq);
+	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
 
 static int handle_chan(struct nl80211_state *state,
 		       struct nl_cb *cb, struct nl_msg *msg,
@@ -86,6 +89,6 @@
 	return handle_freqchan(msg, true, argc, argv);
 }
 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
-	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan);
+	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
-	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan);
+	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);

Modified: iw/trunk/reg.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/reg.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/reg.c (original)
+++ iw/trunk/reg.c Wed May 13 18:51:40 2009
@@ -91,7 +91,8 @@
 	return -ENOBUFS;
 }
 COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>",
-	NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set);
+	NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set,
+	"Notify the kernel about the current regulatory domain.");
 
 static int print_reg_handler(struct nl_msg *msg, void *arg)
 
@@ -184,4 +185,5 @@
 	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_reg_handler, NULL);
 	return 0;
 }
-COMMAND(reg, get, NULL, NL80211_CMD_GET_REG, 0, CIB_NONE, handle_reg_get);
+COMMAND(reg, get, NULL, NL80211_CMD_GET_REG, 0, CIB_NONE, handle_reg_get,
+	"Print out the kernel's current regulatory domain information.");

Modified: iw/trunk/scan.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/scan.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/scan.c (original)
+++ iw/trunk/scan.c Wed May 13 18:51:40 2009
@@ -13,6 +13,23 @@
 #include "nl80211.h"
 #include "iw.h"
 
+#define WLAN_CAPABILITY_ESS		(1<<0)
+#define WLAN_CAPABILITY_IBSS		(1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE	(1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST	(1<<3)
+#define WLAN_CAPABILITY_PRIVACY		(1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE	(1<<5)
+#define WLAN_CAPABILITY_PBCC		(1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY	(1<<7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT	(1<<8)
+#define WLAN_CAPABILITY_QOS		(1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME	(1<<10)
+#define WLAN_CAPABILITY_APSD		(1<<11)
+#define WLAN_CAPABILITY_DSSS_OFDM	(1<<13)
+
+static unsigned char wifi_oui[3]      = { 0x00, 0x50, 0xf2 };
+static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
+
 struct scan_params {
 	bool unknown;
 };
@@ -22,30 +39,94 @@
 		       struct nl_msg *msg,
 		       int argc, char **argv)
 {
-	struct nl_msg *ssids = NULL;
+	struct nl_msg *ssids = NULL, *freqs = NULL;
+	char *eptr;
 	int err = -ENOBUFS;
+	int i;
+	enum {
+		NONE,
+		FREQ,
+		SSID,
+		DONE,
+	} parse = NONE;
+	int freq;
+	bool passive = false, have_ssids = false, have_freqs = false;
 
 	ssids = nlmsg_alloc();
 	if (!ssids)
 		return -ENOMEM;
-	NLA_PUT(ssids, 1, 0, "");
-	nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+
+	freqs = nlmsg_alloc();
+	if (!freqs) {
+		nlmsg_free(ssids);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < argc; i++) {
+		if (parse == NONE && strcmp(argv[i], "freq") == 0) {
+			parse = FREQ;
+			have_freqs = true;
+			continue;
+		} else if (parse < SSID && strcmp(argv[i], "ssid") == 0) {
+			parse = SSID;
+			have_ssids = true;
+			continue;
+		} else if (parse < SSID && strcmp(argv[i], "passive") == 0) {
+			parse = DONE;
+			passive = true;
+			continue;
+		}
+
+		switch (parse) {
+		case NONE:
+		case DONE:
+			return 1;
+		case FREQ:
+			freq = strtoul(argv[i], &eptr, 10);
+			if (eptr != argv[i] + strlen(argv[i]))
+				return 1;
+			NLA_PUT_U32(freqs, i, freq);
+			break;
+		case SSID:
+			NLA_PUT(ssids, i, strlen(argv[i]), argv[i]);
+			break;
+		}
+	}
+
+	if (!have_ssids)
+		NLA_PUT(ssids, 1, 0, "");
+	if (!passive)
+		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+
+	if (have_freqs)
+		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
 
 	err = 0;
  nla_put_failure:
 	nlmsg_free(ssids);
+	nlmsg_free(freqs);
 	return err;
 }
-COMMAND(scan, trigger, NULL,
-	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan);
-
-typedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data);
-
-static void print_ssid(unsigned char type, unsigned char len, unsigned char *data)
+COMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
+	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
+	 "Trigger a scan on the given frequencies with probing for the given\n"
+	 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
+
+static void tab_on_first(bool *first)
+{
+	if (!*first)
+		printf("\t");
+	else
+		*first = false;
+}
+
+static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data)
 {
 	int i;
-	printf("\tSSID: ");
-	for (i=0; i<len; i++) {
+
+	printf(" ");
+
+	for (i = 0; i < len; i++) {
 		if (isprint(data[i]))
 			printf("%c", data[i]);
 		else
@@ -54,38 +135,512 @@
 	printf("\n");
 }
 
-static void print_supprates(unsigned char type, unsigned char len, unsigned char *data)
+static void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data)
 {
 	int i;
 
-	if (type == 1)
-		printf("\tSupported rates: ");
-	else
-		printf("\tExtended supported rates: ");
-
-	for (i=0; i<len; i++) {
+	printf(" ");
+
+	for (i = 0; i < len; i++) {
 		int r = data[i] & 0x7f;
 		printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":"");
 	}
 	printf("\n");
 }
 
-static void print_ds(unsigned char type, unsigned char len, unsigned char *data)
-{
-	printf("\tDS Parameter set: channel %d\n", data[0]);
-}
-
-static void print_ign(unsigned char type, unsigned char len, unsigned char *data)
-{
-	/* ignore for now, not too useful */
-}
-
-static const printfn ieprinters[] = {
-	[0] = print_ssid,
-	[1] = print_supprates,
-	[3] = print_ds,
-	[5] = print_ign,
-	[50] = print_supprates,
+static void print_ds(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	printf(" channel %d\n", data[0]);
+}
+
+static void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	int i;
+
+	printf(" %.*s", 2, data);
+	switch (data[2]) {
+	case 'I':
+		printf(" (indoor)");
+		break;
+	case 'O':
+		printf(" (outdoor)");
+		break;
+	case ' ':
+		printf(" (in/outdoor)");
+		break;
+	default:
+		printf(" (invalid environment)");
+		break;
+	}
+	printf(", data:");
+	for(i=0; i<len-3; i++)
+		printf(" %.02x", data[i + 3]);
+	printf("\n");
+}
+
+static void print_powerconstraint(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	printf(" %d dB\n", data[0]);
+}
+
+static void print_erp(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	if (data[0] == 0x00)
+		printf(" <no flags>");
+	if (data[0] & 0x01)
+		printf(" NonERP_Present");
+	if (data[0] & 0x02)
+		printf(" Use_Protection");
+	if (data[0] & 0x04)
+		printf(" Barker_Preamble_Mode");
+	printf("\n");
+}
+
+static void print_cipher(const uint8_t *data)
+{
+	if (memcmp(data, wifi_oui, 3) == 0) {
+		switch (data[3]) {
+		case 0:
+			printf("Use group cipher suite");
+			break;
+		case 1:
+			printf("WEP-40");
+			break;
+		case 2:
+			printf("TKIP");
+			break;
+		case 4:
+			printf("CCMP");
+			break;
+		case 5:
+			printf("WEP-104");
+			break;
+		default:
+			printf("%.02x-%.02x-%.02x:%d",
+				data[0], data[1] ,data[2], data[3]);
+			break;
+		}
+	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
+		switch (data[3]) {
+		case 0:
+			printf("Use group cipher suite");
+			break;
+		case 1:
+			printf("WEP-40");
+			break;
+		case 2:
+			printf("TKIP");
+			break;
+		case 4:
+			printf("CCMP");
+			break;
+		case 5:
+			printf("WEP-104");
+			break;
+		case 6:
+			printf("AES-128-CMAC");
+			break;
+		default:
+			printf("%.02x-%.02x-%.02x:%d",
+				data[0], data[1] ,data[2], data[3]);
+			break;
+		}
+	} else
+		printf("%.02x-%.02x-%.02x:%d",
+			data[0], data[1] ,data[2], data[3]);
+}
+
+static void print_auth(const uint8_t *data)
+{
+	if (memcmp(data, wifi_oui, 3) == 0) {
+		switch (data[3]) {
+		case 1:
+			printf("IEEE 802.1X");
+			break;
+		case 2:
+			printf("PSK");
+			break;
+		default:
+			printf("%.02x-%.02x-%.02x:%d",
+				data[0], data[1] ,data[2], data[3]);
+			break;
+		}
+	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
+		switch (data[3]) {
+		case 1:
+			printf("IEEE 802.1X");
+			break;
+		case 2:
+			printf("PSK");
+			break;
+		case 3:
+			printf("FT/IEEE 802.1X");
+			break;
+		case 4:
+			printf("FT/PSK");
+			break;
+		case 5:
+			printf("IEEE 802.1X/SHA-256");
+			break;
+		case 6:
+			printf("PSK/SHA-256");
+			break;
+		default:
+			printf("%.02x-%.02x-%.02x:%d",
+				data[0], data[1] ,data[2], data[3]);
+			break;
+		}
+	} else
+		printf("%.02x-%.02x-%.02x:%d",
+			data[0], data[1] ,data[2], data[3]);
+}
+
+static void print_rsn_ie(const char *defcipher, const char *defauth,
+			 uint8_t len, const uint8_t *data)
+{
+	bool first = true;
+	__u16 version, count, capa;
+	int i;
+
+	version = data[0] + (data[1] << 8);
+	tab_on_first(&first);
+	printf("\t * Version: %d\n", version);
+
+	data += 2;
+	len -= 2;
+
+	if (len < 4) {
+		tab_on_first(&first);
+		printf("\t * Group cipher: %s\n", defcipher);
+		printf("\t * Pairwise ciphers: %s\n", defcipher);
+		return;
+	}
+
+	tab_on_first(&first);
+	printf("\t * Group cipher: ");
+	print_cipher(data);
+	printf("\n");
+
+	data += 4;
+	len -= 4;
+
+	if (len < 2) {
+		tab_on_first(&first);
+		printf("\t * Pairwise ciphers: %s\n", defcipher);
+		return;
+	}
+
+	count = data[0] | (data[1] << 8);
+	if (2 + (count * 4) > len)
+		goto invalid;
+
+	tab_on_first(&first);
+	printf("\t * Pairwise ciphers:");
+	for (i = 0; i < count; i++) {
+		printf(" ");
+		print_cipher(data + 2 + (i * 4));
+	}
+	printf("\n");
+
+	data += 2 + (count * 4);
+	len -= 2 + (count * 4);
+
+	if (len < 2) {
+		tab_on_first(&first);
+		printf("\t * Authentication suites: %s\n", defauth);
+		return;
+	}
+
+	count = data[0] | (data[1] << 8);
+	if (2 + (count * 4) > len)
+		goto invalid;
+
+	tab_on_first(&first);
+	printf("\t * Authentication suites:");
+	for (i = 0; i < count; i++) {
+		printf(" ");
+		print_auth(data + 2 + (i * 4));
+	}
+	printf("\n");
+
+	data += 2 + (count * 4);
+	len -= 2 + (count * 4);
+
+	if (len >= 2) {
+		capa = data[0] | (data[1] << 8);
+		tab_on_first(&first);
+		printf("\t * Capabilities:");
+		if (capa & 0x0001)
+			printf(" PreAuth");
+		if (capa & 0x0002)
+			printf(" NoPairwise");
+		switch ((capa & 0x000c) >> 2) {
+		case 0:
+			break;
+		case 1:
+			printf(" 2-PTKSA-RC");
+			break;
+		case 2:
+			printf(" 4-PTKSA-RC");
+			break;
+		case 3:
+			printf(" 16-PTKSA-RC");
+			break;
+		}
+		switch ((capa & 0x0030) >> 4) {
+		case 0:
+			break;
+		case 1:
+			printf(" 2-GTKSA-RC");
+			break;
+		case 2:
+			printf(" 4-GTKSA-RC");
+			break;
+		case 3:
+			printf(" 16-GTKSA-RC");
+			break;
+		}
+		if (capa & 0x0040)
+			printf(" MFP-required");
+		if (capa & 0x0080)
+			printf(" MFP-capable");
+		if (capa & 0x0200)
+			printf(" Peerkey-enabled");
+		if (capa & 0x0400)
+			printf(" SPP-AMSDU-capable");
+		if (capa & 0x0800)
+			printf(" SPP-AMSDU-required");
+		printf(" (0x%.4x)\n", capa);
+		data += 2;
+		len -= 2;
+	}
+
+ invalid:
+	if (len != 0) {
+		printf("\t\t * bogus tail data (%d):", len);
+		while (len) {
+			printf(" %.2x", *data);
+			data++;
+			len--;
+		}
+		printf("\n");
+	}
+}
+
+static void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	print_rsn_ie("CCMP", "IEEE 802.1X", len, data);
+}
+
+static void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	int i, base, bit;
+	bool first = true;
+
+
+	for (i = 0; i < len; i++) {
+		base = i * 8;
+
+		for (bit = 0; bit < 8; bit++) {
+			if (!(data[i] & (1 << bit)))
+				continue;
+
+			if (!first)
+				printf(",");
+			else
+				first = false;
+
+			switch (bit + base) {
+			case 0:
+				printf(" HT Information Exchange Supported");
+				break;
+			case 1:
+				printf(" On-demand Beacon");
+				break;
+			case 2:
+				printf(" Extended Channel Switching");
+				break;
+			case 3:
+				printf(" Wave Indication");
+				break;
+			case 4:
+				printf(" PSMP Capability");
+				break;
+			case 5:
+				printf(" Service Interval Granularity");
+				break;
+			case 6:
+				printf(" S-PSMP Capability");
+				break;
+			default:
+				printf(" %d", bit);
+				break;
+			}
+		}
+	}
+
+	printf("\n");
+}
+
+struct ie_print {
+	const char *name;
+	void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
+	uint8_t minlen, maxlen;
+};
+
+static void print_ie(const struct ie_print *p, const uint8_t type,
+		     uint8_t len, const uint8_t *data)
+{
+	int i;
+
+	if (!p->print)
+		return;
+
+	printf("\t%s:", p->name);
+	if (len < p->minlen || len > p->maxlen) {
+		if (len > 1) {
+			printf(" <invalid: %d bytes:", len);
+			for (i = 0; i < len; i++)
+				printf(" %.02x", data[i]);
+			printf(">\n");
+		} else if (len)
+			printf(" <invalid: 1 byte: %.02x>\n", data[0]);
+		else
+			printf(" <invalid: no data>\n");
+		return;
+	}
+
+	p->print(type, len, data);
+}
+
+#define PRINT_IGN {		\
+	.name = "IGNORE",	\
+	.print = NULL,		\
+	.minlen = 0,		\
+	.maxlen = 255,		\
+}
+
+static const struct ie_print ieprinters[] = {
+	[0] = { "SSID", print_ssid, 0, 32, },
+	[1] = { "Supported rates", print_supprates, 0, 255, },
+	[3] = { "DS Paramater set", print_ds, 1, 1, },
+	[5] = PRINT_IGN,
+	[7] = { "Country", print_country, 3, 255, },
+	[32] = { "Power constraint", print_powerconstraint, 1, 1, },
+	[42] = { "ERP", print_erp, 1, 255, },
+	[48] = { "RSN", print_rsn, 2, 255, },
+	[50] = { "Extended supported rates", print_supprates, 0, 255, },
+	[127] = { "Extended capabilities", print_capabilities, 0, 255, },
+};
+
+static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	print_rsn_ie("TKIP", "IEEE 802.1X", len, data);
+}
+
+static void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	int i;
+
+	switch (data[0]) {
+	case 0x00:
+		printf(" information:");
+		break;
+	case 0x01:
+		printf(" parameter:");
+		break;
+	default:
+		printf(" type %d:", data[0]);
+		break;
+	}
+
+	for(i = 0; i < len - 1; i++)
+		printf(" %.02x", data[i + 1]);
+	printf("\n");
+}
+
+static void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+	bool first = true;
+	__u16 subtype, sublen;
+
+	while (len >= 4) {
+		subtype = (data[0] << 8) + data[1];
+		sublen = (data[2] << 8) + data[3];
+		if (sublen > len)
+			break;
+
+		switch (subtype) {
+		case 0x104a:
+			tab_on_first(&first);
+			printf("\t * Version: %d.%d\n", data[4] >> 4, data[4] & 0xF);
+			break;
+		case 0x1011:
+			tab_on_first(&first);
+			printf("\t * Device name: %.*s\n", sublen, data + 4);
+			break;
+		case 0x1021:
+			tab_on_first(&first);
+			printf("\t * Manufacturer: %.*s\n", sublen, data + 4);
+			break;
+		case 0x1023:
+			tab_on_first(&first);
+			printf("\t * Model: %.*s\n", sublen, data + 4);
+			break;
+		case 0x1057: {
+			__u16 val = (data[4] << 8) | data[5];
+			tab_on_first(&first);
+			printf("\t * AP setup locked: 0x%.4x\n", val);
+			break;
+		}
+		case 0x1008: {
+			__u16 meth = (data[4] << 8) + data[5];
+			bool comma = false;
+			tab_on_first(&first);
+			printf("\t * Config methods:");
+#define T(bit, name) do {		\
+	if (meth & (1<<bit)) {		\
+		if (comma)		\
+			printf(",");	\
+		comma = true;		\
+		printf(" " name);	\
+	} } while (0)
+			T(0, "USB");
+			T(1, "Ethernet");
+			T(2, "Label");
+			T(3, "Display");
+			T(4, "Ext. NFC");
+			T(5, "Int. NFC");
+			T(6, "NFC Intf.");
+			T(7, "PBC");
+			T(8, "Keypad");
+			printf("\n");
+			break;
+#undef T
+		}
+		default:
+			break;
+		}
+
+		data += sublen + 4;
+		len -= sublen + 4;
+	}
+
+	if (len != 0) {
+		printf("\t\t * bogus tail data (%d):", len);
+		while (len) {
+			printf(" %.2x", *data);
+			data++;
+			len--;
+		}
+		printf("\n");
+	}
+}
+
+static const struct ie_print wifiprinters[] = {
+	[1] = { "WPA", print_wifi_wpa, 2, 255, },
+	[2] = { "WMM", print_wifi_wmm, 1, 255, },
+	[4] = { "WPS", print_wifi_wps, 0, 255, },
 };
 
 static void print_vendor(unsigned char len, unsigned char *data,
@@ -93,30 +648,51 @@
 {
 	int i;
 
-	/* currently _all_ vendor IEs are unknown (not parsed) */
+	if (len < 3) {
+		printf("\tVendor specific: <too short> data:");
+		for(i = 0; i < len; i++)
+			printf(" %.02x", data[i]);
+		printf("\n");
+		return;
+	}
+
+	if (len >= 4 && memcmp(data, wifi_oui, 3) == 0) {
+		if (data[3] < ARRAY_SIZE(wifiprinters) && wifiprinters[data[3]].name) {
+			print_ie(&wifiprinters[data[3]], data[3], len - 4, data + 4);
+			return;
+		}
+		if (!params->unknown)
+			return;
+		printf("\tWiFi OUI %#.2x, data:", data[3]);
+		for(i = 0; i < len - 4; i++)
+			printf(" %.02x", data[i + 4]);
+		printf("\n");
+		return;
+	}
+
 	if (!params->unknown)
 		return;
 
-	printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ",
+	printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:",
 		data[0], data[1], data[2]);
-	for (i=3; i<len; i++)
-		printf("\\x%.2x", data[i]);
+	for (i = 3; i < len; i++)
+		printf(" %.2x", data[i]);
 	printf("\n");
 }
 
 static void print_ies(unsigned char *ie, int ielen, struct scan_params *params)
 {
 	while (ielen >= 2 && ielen >= ie[1]) {
-		if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) {
-			ieprinters[ie[0]](ie[0], ie[1], ie + 2);
+		if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]].name) {
+			print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2);
 		} else if (ie[0] == 221 /* vendor */) {
 			print_vendor(ie[1], ie + 2, params);
 		} else if (params->unknown) {
 			int i;
 
-			printf("\tUnknown IE (%d): ", ie[0]);
+			printf("\tUnknown IE (%d):", ie[0]);
 			for (i=0; i<ie[1]; i++)
-				printf("\\x%.2x", ie[2+i]);
+				printf(" %.2x", ie[2+i]);
 			printf("\n");
 		}
 		ielen -= ie[1] + 2;
@@ -175,9 +751,33 @@
 	if (bss[NL80211_BSS_BEACON_INTERVAL])
 		printf("\tbeacon interval: %d\n",
 			nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
-	if (bss[NL80211_BSS_CAPABILITY])
-		printf("\tcapability: 0x%.4x\n",
-			nla_get_u16(bss[NL80211_BSS_CAPABILITY]));
+	if (bss[NL80211_BSS_CAPABILITY]) {
+		__u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
+		printf("\tcapability:");
+		if (capa & WLAN_CAPABILITY_ESS)
+			printf(" ESS");
+		if (capa & WLAN_CAPABILITY_IBSS)
+			printf(" IBSS");
+		if (capa & WLAN_CAPABILITY_PRIVACY)
+			printf(" Privacy");
+		if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE)
+			printf(" ShortPreamble");
+		if (capa & WLAN_CAPABILITY_PBCC)
+			printf(" PBCC");
+		if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY)
+			printf(" ChannelAgility");
+		if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT)
+			printf(" SpectrumMgmt");
+		if (capa & WLAN_CAPABILITY_QOS)
+			printf(" QoS");
+		if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+			printf(" ShortSlotTime");
+		if (capa & WLAN_CAPABILITY_APSD)
+			printf(" APSD");
+		if (capa & WLAN_CAPABILITY_DSSS_OFDM)
+			printf(" DSSS-OFDM");
+		printf(" (0x%.4x)\n", capa);
+	}
 	if (bss[NL80211_BSS_SIGNAL_MBM]) {
 		int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
 		printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
@@ -213,33 +813,72 @@
 	return 0;
 }
 COMMAND(scan, dump, "[-u]",
-	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump);
+	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
+	"Dump the current scan results. If -u is specified, print unknown\n"
+	"data in scan results.");
 
 static int handle_scan_combined(struct nl80211_state *state,
 				struct nl_cb *cb,
 				struct nl_msg *msg,
 				int argc, char **argv)
 {
-	static char *trig_argv[] = {
-		NULL,
-		"scan",
-		"trigger",
-	};
+	char **trig_argv;
 	static char *dump_argv[] = {
 		NULL,
 		"scan",
 		"dump",
+		NULL,
 	};
 	static const __u32 cmds[] = {
 		NL80211_CMD_NEW_SCAN_RESULTS,
 		NL80211_CMD_SCAN_ABORTED,
 	};
-	int err;
-
+	int trig_argc, dump_argc, err;
+
+	if (argc >= 3 && !strcmp(argv[2], "-u")) {
+		dump_argc = 4;
+		dump_argv[3] = "-u";
+	} else
+		dump_argc = 3;
+
+	trig_argc = 3 + (argc - 2) + (3 - dump_argc);
+	trig_argv = calloc(trig_argc, sizeof(*trig_argv));
+	if (!trig_argv)
+		return -ENOMEM;
 	trig_argv[0] = argv[0];
-	err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(trig_argv), trig_argv);
+	trig_argv[1] = "scan";
+	trig_argv[2] = "trigger";
+	int i;
+	for (i = 0; i < argc - 2 - (dump_argc - 3); i++)
+		trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)];
+	err = handle_cmd(state, II_NETDEV, trig_argc, trig_argv);
+	free(trig_argv);
 	if (err)
 		return err;
+
+	/*
+	 * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION
+	 *
+	 * This code has a bug, which requires creating a separate
+	 * nl80211 socket to fix:
+	 * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or
+	 * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel
+	 * before (!) we listen to it, because we only start listening
+	 * after we send our scan request.
+	 *
+	 * Doing it the other way around has a race condition as well,
+	 * if you first open the events socket you may get a notification
+	 * for a previous scan.
+	 *
+	 * The only proper way to fix this would be to listen to events
+	 * before sending the command, and for the kernel to send the
+	 * scan request along with the event, so that you can match up
+	 * whether the scan you requested was finished or aborted (this
+	 * may result in processing a scan that another application
+	 * requested, but that doesn't seem to be a problem).
+	 *
+	 * Alas, the kernel doesn't do that (yet).
+	 */
 
 	if (listen_events(state, ARRAY_SIZE(cmds), cmds) ==
 					NL80211_CMD_SCAN_ABORTED) {
@@ -248,6 +887,10 @@
 	}
 
 	dump_argv[0] = argv[0];
-	return handle_cmd(state, II_NETDEV, ARRAY_SIZE(dump_argv), dump_argv);
-}
-TOPLEVEL(scan, NULL, 0, 0, CIB_NETDEV, handle_scan_combined);
+	return handle_cmd(state, II_NETDEV, dump_argc, dump_argv);
+}
+TOPLEVEL(scan, "[-u] [freq <freq>*] [ssid <ssid>*|passive]", 0, 0,
+	 CIB_NETDEV, handle_scan_combined,
+	 "Scan on the given frequencies and probe for the given SSIDs\n"
+	 "(or wildcard if not given) unless passive scanning is requested.\n"
+	 "If -u is specified print unknown data in the scan results.");

Modified: iw/trunk/station.c
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/station.c?rev=1377&op=diff
==============================================================================
--- iw/trunk/station.c (original)
+++ iw/trunk/station.c Wed May 13 18:51:40 2009
@@ -188,9 +188,11 @@
 	return -ENOBUFS;
 }
 COMMAND(station, get, "<MAC address>",
-	NL80211_CMD_GET_STATION, 0, CIB_NETDEV, handle_station_get);
+	NL80211_CMD_GET_STATION, 0, CIB_NETDEV, handle_station_get,
+	"Get information for a specific station.");
 COMMAND(station, del, "<MAC address>",
-	NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get);
+	NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get,
+	"Remove the given station entry (use with caution!)");
 
 static int handle_station_set(struct nl80211_state *state,
 			      struct nl_cb *cb,
@@ -237,7 +239,8 @@
 	return -ENOBUFS;
 }
 COMMAND(station, set, "<MAC address> plink_action <open|block>",
-	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set);
+	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set,
+	"Set mesh peer link action for this station (peer).");
 
 static int handle_station_dump(struct nl80211_state *state,
 			       struct nl_cb *cb,
@@ -248,4 +251,5 @@
 	return 0;
 }
 COMMAND(station, dump, NULL,
-	NL80211_CMD_GET_STATION, NLM_F_DUMP, CIB_NETDEV, handle_station_dump);
+	NL80211_CMD_GET_STATION, NLM_F_DUMP, CIB_NETDEV, handle_station_dump,
+	"List all stations known, e.g. the AP on managed interfaces");

Modified: iw/trunk/version.sh
URL: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/version.sh?rev=1377&op=diff
==============================================================================
--- iw/trunk/version.sh (original)
+++ iw/trunk/version.sh Wed May 13 18:51:40 2009
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-VERSION="0.9.13"
+VERSION="0.9.14"
 OUT="$1"
 
 if head=`git rev-parse --verify HEAD 2>/dev/null`; then




More information about the Pkg-wpa-devel mailing list