]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
"add interface" implementation
authorJohannes Berg <johannes@sipsolutions.net>
Fri, 28 Sep 2007 21:47:38 +0000 (23:47 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Fri, 28 Sep 2007 21:47:38 +0000 (23:47 +0200)
interface.c [new file with mode: 0644]
iw.c
iw.h

diff --git a/interface.c b/interface.c
new file mode 100644 (file)
index 0000000..9600543
--- /dev/null
@@ -0,0 +1,125 @@
+
+#include <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>
+#include <linux/nl80211.h>
+
+#include <net/if.h>
+
+#include "iw.h"
+
+/* return 0 if not found, 1 if ok, -1 on error */
+static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type)
+{
+       char *tpstr;
+
+       if (*argc < 2)
+               return 0;
+
+       if (strcmp((*argv)[0], "type"))
+               return 0;
+
+       tpstr = (*argv)[1];
+       *argc -= 2;
+       *argv += 2;
+
+       if (strcmp(tpstr, "adhoc") == 0 ||
+           strcmp(tpstr, "ibss") == 0) {
+               *type = NL80211_IFTYPE_ADHOC;
+               return 1;
+       } else if (strcmp(tpstr, "monitor") == 0) {
+               *type = NL80211_IFTYPE_MONITOR;
+               return 1;
+       } else if (strcmp(tpstr, "ap") == 0) {
+               *type = NL80211_IFTYPE_AP;
+               return 1;
+       } else if (strcmp(tpstr, "ap_vlan") == 0) {
+               *type = NL80211_IFTYPE_AP_VLAN;
+               return 1;
+       } else if (strcmp(tpstr, "wds") == 0) {
+               *type = NL80211_IFTYPE_WDS;
+               return 1;
+       } else if (strcmp(tpstr, "station") == 0) {
+               *type = NL80211_IFTYPE_STATION;
+               return 1;
+       }
+
+
+       fprintf(stderr, "invalid interface type %s\n", tpstr);
+       return -1;
+}
+
+static int handle_interface_add(struct nl80211_state *state,
+                               char *phy, char *dev, int argc, char **argv)
+{
+       char *name = argv[0];
+       enum nl80211_iftype type;
+       int tpset, err;
+       struct nl_msg *msg;
+
+       if (argc < 1) {
+               fprintf(stderr, "not enough arguments\n");
+               return -1;
+       }
+
+       argc--;
+       argv++;
+
+       if (argc) {
+               tpset = get_if_type(&argc, &argv, &type);
+               if (tpset < 0)
+                       return -1;
+       }
+
+       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_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);
+
+       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 create interface: %d\n", err);
+               nlmsg_free(msg);
+               return -1;
+       }
+
+       nlmsg_free(msg);
+
+       return 0;
+}
+
+int handle_interface(struct nl80211_state *state,
+                    char *phy, char *dev, int argc, char **argv)
+{
+       char *cmd = argv[0];
+
+       if (argc < 1)
+               return -1;
+
+       argc--;
+       argv++;
+
+       if (strcmp(cmd, "add") == 0)
+               return handle_interface_add(state, phy, dev, argc, argv);
+
+       printf("invalid interface command %s\n", cmd);
+       return -1;
+}
diff --git a/iw.c b/iw.c
index e973fea6bb8a96771366a25cbcd661b6c585c5c3..1d04d584a3a6122e6db7ff15c0765260fa8370c4 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -64,17 +64,75 @@ 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)
+{
+       char *type = (*argv)[0];
+
+       if (*argc < 2)
+               return 0;
+
+       *name = (*argv)[1];
+
+       *argc -= 2;
+       *argv += 2;
+
+       if (strcmp(type, "phy") == 0)
+               return 1;
+       if (strcmp(type, "dev") == 0)
+               return 2;
+
+       return 0;
+}
+
 int main(int argc, char **argv)
 {
        struct nl80211_state nlstate;
-       int err;
+       int err = 0, pod;
+       char *ifname, *phyname, *type;
 
        err = nl80211_init(&nlstate);
        if (err)
                return 1;
 
+       /* strip off self */
+       argc--;
+       argv++;
+
+       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++;
+
+       if (strcmp(type, "interface") == 0)
+               err = handle_interface(&nlstate, phyname, ifname, argc, argv);
+       else {
+               fprintf(stderr, "No such object type %s\n", type);
+               err = 1;
+       }
 
+ out:
        nl80211_cleanup(&nlstate);
 
-       return 0;
+       return err;
 }
diff --git a/iw.h b/iw.h
index 09faa879d01534da1c5872df5664ac26862b5f2f..a4db8f70932b3c0dd8a58ef032afe3eadc184165 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -11,4 +11,8 @@ struct nl80211_state {
        struct genl_family *nl80211;
 };
 
+
+int handle_interface(struct nl80211_state *state,
+                    char *phy, char *dev, int argc, char **argv);
+
 #endif /* __IW_H */