]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
some work for making command more dynamic
authorJohannes Berg <johannes@sipsolutions.net>
Tue, 16 Sep 2008 14:56:09 +0000 (16:56 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Tue, 16 Sep 2008 14:56:09 +0000 (16:56 +0200)
interface.c
iw.c
iw.h
reg.c
station.c

index a9c1731ad078a6a9d35b8ffe079764aa2fc6a590..68039042f10c799eadd6d22934f2cbc91801c4dc 100644 (file)
@@ -57,18 +57,16 @@ static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type)
 }
 
 static int handle_interface_add(struct nl80211_state *state,
-                               char *phy, char *dev, int argc, char **argv)
+                               struct nl_msg *msg,
+                               int argc, char **argv)
 {
        char *name;
        char *mesh_id = NULL;
        enum nl80211_iftype type;
        int tpset, err = -ENOBUFS;
-       struct nl_msg *msg;
 
-       if (argc < 1) {
-               fprintf(stderr, "not enough arguments\n");
+       if (argc < 1)
                return -1;
-       }
 
        name = argv[0];
        argc--;
@@ -102,18 +100,6 @@ static int handle_interface_add(struct nl80211_state *state,
                return -1;
        }
 
-       msg = nlmsg_alloc();
-       if (!msg) {
-               fprintf(stderr, "failed to allocate netlink msg\n");
-               return -1;
-       }
-
-       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
-                   0, NL80211_CMD_NEW_INTERFACE, 0);
-       if (dev)
-               NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
-       if (phy)
-               return -1; /* XXX TODO */
        NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
        if (tpset)
                NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
@@ -124,51 +110,30 @@ static int handle_interface_add(struct nl80211_state *state,
            (err = nl_wait_for_ack(state->nl_handle)) < 0) {
  nla_put_failure:
                fprintf(stderr, "failed to create interface: %d\n", err);
-               nlmsg_free(msg);
-               return -1;
+               return 1;
        }
 
-       nlmsg_free(msg);
-
        return 0;
 }
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>]",
+       NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add);
 
 static int handle_interface_del(struct nl80211_state *state,
-                               char *phy, char *dev, int argc, char **argv)
+                               struct nl_msg *msg,
+                               int argc, char **argv)
 {
        int err = -ENOBUFS;
-       struct nl_msg *msg;
-
-       if (argc) {
-               fprintf(stderr, "too many arguments\n");
-               return -1;
-       }
-
-        msg = nlmsg_alloc();
-       if (!msg)
-               return -1;
-
-       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
-                   0, NL80211_CMD_DEL_INTERFACE, 0);
-       if (!dev) {
-               fprintf(stderr, "need device\n");
-               nlmsg_free(msg);
-               return -1;
-       }
-       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
 
        if ((err = nl_send_auto_complete(state->nl_handle, msg)) < 0 ||
            (err = nl_wait_for_ack(state->nl_handle)) < 0) {
- nla_put_failure:
                fprintf(stderr, "failed to remove interface: %d\n", err);
                nlmsg_free(msg);
-               return -1;
+               return 1;
        }
 
-       nlmsg_free(msg);
-
        return 0;
 }
+TOPLEVEL(del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del);
 
 static int print_iface_handler(struct nl_msg *msg, void *arg)
 {
@@ -197,32 +162,13 @@ static int ack_wait_handler(struct nl_msg *msg, void *arg)
 }
 
 static int handle_interface_info(struct nl80211_state *state,
-                                char *phy, char *dev,
-                                int argc, char **argv, int flags)
+                                struct nl_msg *msg,
+                                int argc, char **argv)
 {
        int err = -ENOBUFS;
-       struct nl_msg *msg;
        struct nl_cb *cb = NULL;
        int finished = 0;
 
-       if (argc) {
-               fprintf(stderr, "too many arguments\n");
-               return -1;
-       }
-
-        msg = nlmsg_alloc();
-       if (!msg)
-               return -1;
-
-       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
-                   flags, NL80211_CMD_GET_INTERFACE, 0);
-       if (!dev) {
-               fprintf(stderr, "need device\n");
-               nlmsg_free(msg);
-               return -1;
-       }
-       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
-
        cb = nl_cb_alloc(NL_CB_CUSTOM);
        if (!cb)
                goto out;
@@ -242,34 +188,7 @@ static int handle_interface_info(struct nl80211_state *state,
                fprintf(stderr, "failed to get information: %d\n", err);
 
  out:
- nla_put_failure:
-       nlmsg_free(msg);
        nl_cb_put(cb);
        return 0;
 }
-
-int handle_interface(struct nl80211_state *state,
-                    char *phy, char *dev, int argc, char **argv)
-{
-       char *cmd = argv[0];
-
-       if (argc < 1) {
-               fprintf(stderr, "you must specify an interface command\n");
-               return -1;
-       }
-
-       argc--;
-       argv++;
-
-       if (strcmp(cmd, "add") == 0)
-               return handle_interface_add(state, phy, dev, argc, argv);
-       else if (strcmp(cmd, "del") == 0)
-               return handle_interface_del(state, phy, dev, argc, argv);
-       else if (strcmp(cmd, "get") == 0)
-               return handle_interface_info(state, phy, dev, argc, argv, 0);
-       else if (strcmp(cmd, "dump") == 0)
-               return handle_interface_info(state, phy, dev, argc, argv, NLM_F_DUMP);
-
-       printf("invalid interface command %s\n", cmd);
-       return -1;
-}
+TOPLEVEL(info, NULL, NL80211_CMD_GET_INTERFACE, 0, CIB_NETDEV, handle_interface_info);
diff --git a/iw.c b/iw.c
index 09a04cbeb36abbd41aebd910ef8610ee4b234411..35cb306d3f5025c3ef395dd758b8633c936d7347 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -7,7 +7,12 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
-
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+                     
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
 #include <netlink/genl/ctrl.h>  
@@ -64,48 +69,142 @@ static void nl80211_cleanup(struct nl80211_state *state)
        nl_handle_destroy(state->nl_handle);
 }
 
-/*
- * return
- *     0 - error
- *     1 - phy
- *     2 - dev
- */
-static int get_phy_or_dev(int *argc, char ***argv, char **name)
+static void usage(const char *argv0)
+{
+       struct cmd *cmd;
+
+       fprintf(stderr, "Usage:\t%s help\n", argv0);
+       for (cmd = &__start___cmd; cmd < &__stop___cmd; cmd++) {
+               switch (cmd->idby) {
+               case CIB_NONE:
+                       fprintf(stderr, "\t%s %s %s\n", argv0, cmd->section, cmd->name);
+                       break;
+               case CIB_PHY:
+                       fprintf(stderr, "\t%s phy <phyname> ", argv0);
+                       /* fall through */
+               case CIB_NETDEV:
+                       if (cmd->idby == CIB_NETDEV)
+                               fprintf(stderr, "\t%s dev <devname> ", argv0);
+                       if (cmd->section)
+                               fprintf(stderr, "%s ", cmd->section);
+                       fprintf(stderr, "%s", cmd->name);
+                       if (cmd->args)
+                               fprintf(stderr, " %s", cmd->args);
+                       fprintf(stderr, "\n");
+                       break;
+               }
+       }
+}
+
+static int phy_lookup(char *name)
+{
+       char buf[200];
+       int fd, pos;
+
+       snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", name);
+
+       fd = open(buf, O_RDONLY);
+       pos = read(fd, buf, sizeof(buf) - 1);
+       if (pos < 0)
+               return -1;
+       buf[pos] = '\0';
+       return atoi(buf);
+}
+
+static int handle_phydev_cmd(struct nl80211_state *state,
+                            enum command_identify_by idby,
+                            int argc, char **argv)
 {
-       char *type = (*argv)[0];
+       struct cmd *cmd;
+       struct nl_msg *msg;
+       int devidx = 0;
+       const char *command, *section;
 
-       if (*argc < 2)
-               return 0;
+       if (argc <= 1)
+               return -1;
 
-       *name = (*argv)[1];
+       switch (idby) {
+       case CIB_PHY:
+               devidx = phy_lookup(*argv);
+               argc--;
+               argv++;
+               break;
+       case CIB_NETDEV:
+               devidx = if_nametoindex(*argv);
+               argc--;
+               argv++;
+               break;
+       default:
+               break;
+       }
+
+       section = command = *argv;
+       argc--;
+       argv++;
+
+       for (cmd = &__start___cmd; cmd < &__stop___cmd; cmd++) {
+               if (cmd->idby != idby)
+                       continue;
+               if (cmd->section) {
+                       if (strcmp(cmd->section, section))
+                               continue;
+                       /* this is a bit icky ... */
+                       if (command == section) {
+                               if (argc <= 0)
+                                       return -1;
+                               command = *argv;
+                               argc--;
+                               argv++;
+                       }
+               } else if (section != command)
+                       continue;
+               if (strcmp(cmd->name, command))
+                       continue;
+               if (argc && !cmd->args)
+                       continue;
+               break;
+       }
 
-       *argc -= 2;
-       *argv += 2;
+       /* XXX: handle dev for phy */
+       if (cmd == &__stop___cmd)
+               return -1;
 
-       if (strcmp(type, "phy") == 0)
+       msg = nlmsg_alloc();
+       if (!msg) {
+               fprintf(stderr, "out of memory\n");
                return 1;
-       if (strcmp(type, "dev") == 0)
-               return 2;
+       }
 
-       return 0;
+       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+                   cmd->nl_msg_flags, cmd->cmd, 0);
+
+       switch (idby) {
+       case CIB_PHY:
+               NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx);
+               break;
+       case CIB_NETDEV:
+               NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
+               break;
+       default:
+               break;
+       }
+
+       return cmd->handler(state, msg, argc, argv);
+ nla_put_failure:
+       fprintf(stderr, "building message failed\n");
+       return 1;
 }
 
-static void usage(char *argv0)
+static int handle_other_cmd(struct nl80211_state *state, int argc, char **argv)
 {
-       fprintf(stderr, "Usage: %1$s dev <phydev> <OBJECT> <COMMAND> [OPTIONS]"
-                       "\n     %1$s dev <phydev> info"
-                       "\n     %1$s reg set <ISO/IEC 3166-1 alpha2>\n"
-                       "\n"
-                       "where OBJECT := { interface | station | mpath | info }\n"
-                       "and COMMAND := { add | del | set | get | dump }\n",
-                       argv0);
+       return -1;
 }
 
 int main(int argc, char **argv)
 {
        struct nl80211_state nlstate;
-       int err = 0, pod;
-       char *ifname = NULL, *phyname = NULL, *type, *argv0;
+       int err;
+       const char *argv0;
 
        err = nl80211_init(&nlstate);
        if (err)
@@ -115,50 +214,24 @@ int main(int argc, char **argv)
        argc--;
        argv0 = *argv++;
 
-       if (argc == 0 || (argc == 1 && strcmp(*argv, "help") == 0)) {
+       if (argc == 0 || strcmp(*argv, "help") == 0) {
                usage(argv0);
                goto out;
        }
 
-       if (strcmp(argv[0], "reg") == 0) {
+       if (strcmp(*argv, "dev") == 0) {
                argc--;
                argv++;
-               err = handle_reg(&nlstate, argc, argv);
-               goto out;
-       }
-
-       pod = get_phy_or_dev(&argc, &argv, &ifname);
-       if (pod == 0) {
-               err = 1;
-               goto out;
-       }
-
-       if (pod == 1) {
-               phyname = ifname;
-               ifname = NULL;
-       }
-
-       if (argc <= 0) {
-               err = 1;
-               goto out;
-       }
-
-       type = argv[0];
-       argc--;
-       argv++;
+               err = handle_phydev_cmd(&nlstate, CIB_NETDEV, argc, argv);
+       } else if (strcmp(*argv, "phy") == 0) {
+               argc--;
+               argv++;
+               err = handle_phydev_cmd(&nlstate, CIB_PHY, argc, argv);
+       } else
+               err = handle_other_cmd(&nlstate, argc, argv);
 
-       if (strcmp(type, "interface") == 0)
-               err = handle_interface(&nlstate, phyname, ifname, argc, argv);
-       else if (strcmp(type, "info") == 0)
-               err = handle_info(&nlstate, phyname, ifname);
-       else if (strcmp(type, "station") == 0)
-               err = handle_station(&nlstate, ifname, argc, argv);
-       else if (strcmp(type, "mpath") == 0)
-               err = handle_mpath(&nlstate, ifname, argc, argv);
-       else {
-               fprintf(stderr, "No such object type %s\n", type);
-               err = 1;
-       }
+       if (err < 0)
+               usage(argv0);
 
  out:
        nl80211_cleanup(&nlstate);
diff --git a/iw.h b/iw.h
index f4f5b3e930a26c71bfa04230058d08b362eff860..3d12175c54a382060c7a6f28e6c8a962c8b136b2 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -14,20 +14,34 @@ struct nl80211_state {
        struct genl_family *nl80211;
 };
 
+enum command_identify_by {
+       CIB_NONE,
+       CIB_PHY,
+       CIB_NETDEV,
+};
 
-int handle_interface(struct nl80211_state *state,
-                    char *phy, char *dev, int argc, char **argv);
-
-int handle_info(struct nl80211_state *state, char *phy, char *dev);
-
-int handle_station(struct nl80211_state *state,
-                  char *dev, int argc, char **argv);
-
-int handle_mpath(struct nl80211_state *state,
-                  char *dev, int argc, char **argv);
+struct cmd {
+       const char *section;
+       const char *name;
+       const char *args;
+       const enum nl80211_commands cmd;
+       int nl_msg_flags;
+       const enum command_identify_by idby;
+       int (*handler)(struct nl80211_state *state,
+                      struct nl_msg *msg,
+                      int argc, char **argv);
+};
 
-int handle_reg(struct nl80211_state *state,
-                  int argc, char **argv);
+#define __COMMAND(sect, name, args, nlcmd, flags, idby, handler)\
+       static const struct cmd __cmd_ ## handler ## idby       \
+       __attribute__((used)) __attribute__((section("__cmd"))) \
+       = { sect, name, args, nlcmd, flags, idby, handler }
+#define COMMAND(section, name, args, cmd, flags, idby, handler)        \
+       __COMMAND(#section, #name, args, cmd, flags, idby, handler)
+#define TOPLEVEL(name, args, cmd, flags, idby, handler)                \
+       __COMMAND(NULL, #name, args, cmd, flags, idby, handler)
+extern struct cmd __start___cmd;
+extern struct cmd __stop___cmd;
 
 int mac_addr_a2n(unsigned char *mac_addr, char *arg);
 int mac_addr_n2a(char *mac_addr, unsigned char *arg);
diff --git a/reg.c b/reg.c
index 37d198dcfac44e0ef6b98eed41d9930dd70f2574..0e6363a5ed06f359e0b75b80554834909135e437 100644 (file)
--- a/reg.c
+++ b/reg.c
@@ -128,28 +128,3 @@ static int handle_reg_set(struct nl80211_state *state,
        nlmsg_free(msg);
        return ret;
 }
-
-int handle_reg(struct nl80211_state *state,
-                  int argc, char **argv)
-{
-       char *cmd = argv[0];
-
-       if (argc < 1) {
-               fprintf(stderr, "you must specify an station command\n");
-               return -1;
-       }
-
-       argc--;
-       argv++;
-
-       /* XXX: write support for getting the currently set regdomain
-       if (strcmp(cmd, "get") == 0)
-               return handle_reg_get(state, argc, argv);
-       */
-
-       if (strcmp(cmd, "set") == 0)
-               return handle_reg_set(state, argc, argv);
-
-       printf("invalid regulatory command %s\n", cmd);
-       return -1;
-}
index f5d67569212585e0f3d9fadef0db998dfc07cca0..e729641d8a75ceb83ca234c63f8f36a538019373 100644 (file)
--- a/station.c
+++ b/station.c
@@ -386,29 +386,3 @@ static int handle_station_del(struct nl80211_state *state,
        nlmsg_free(msg);
        return ret;
 }
-
-int handle_station(struct nl80211_state *state,
-                  char *dev, int argc, char **argv)
-{
-       char *cmd = argv[0];
-
-       if (argc < 1) {
-               fprintf(stderr, "you must specify an station command\n");
-               return -1;
-       }
-
-       argc--;
-       argv++;
-
-       if (strcmp(cmd, "del") == 0)
-               return handle_station_del(state, dev, argc, argv);
-       if (strcmp(cmd, "get") == 0)
-               return handle_station_get(state, dev, argc, argv);
-       if (strcmp(cmd, "set") == 0)
-               return handle_station_set(state, dev, argc, argv);
-       if (strcmp(cmd, "dump") == 0)
-               return handle_station_dump(state, dev, argc, argv);
-
-       printf("invalid interface command %s\n", cmd);
-       return -1;
-}