]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
make it possible to pass WEP keys to connect/join
authorJohannes Berg <johannes@sipsolutions.net>
Tue, 7 Jul 2009 22:44:25 +0000 (00:44 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Tue, 7 Jul 2009 22:44:25 +0000 (00:44 +0200)
connect.c
ibss.c
iw.h
util.c

index 1fb2892c387f618923151e86badb17891a42d0ad..678d22181b5ab4dae7a7b07a0d08ee77ec424107 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -15,7 +15,7 @@ static int iw_connect(struct nl80211_state *state,
                      int argc, char **argv)
 {
        char *end;
-       unsigned char abssid[6];
+       unsigned char bssid[6];
        int freq;
 
        if (argc < 1)
@@ -38,17 +38,23 @@ static int iw_connect(struct nl80211_state *state,
 
        /* bssid */
        if (argc) {
-               if (mac_addr_a2n(abssid, argv[0]))
-                       return 1;
-               NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
-               argv++;
-               argc--;
+               if (mac_addr_a2n(bssid, argv[0]) == 0) {
+                       NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid);
+                       argv++;
+                       argc--;
+               }
        }
 
-       if (argc)
+       if (!argc)
+               return 0;
+
+       if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
                return 1;
 
-       return 0;
+       argv++;
+       argc--;
+
+       return parse_keys(msg, argv, argc);
  nla_put_failure:
        return -ENOSPC;
 }
@@ -63,6 +69,6 @@ static int disconnect(struct nl80211_state *state,
 TOPLEVEL(disconnect, NULL,
        NL80211_CMD_DISCONNECT, 0, CIB_NETDEV, disconnect,
        "Disconnect from the current network.");
-TOPLEVEL(connect, "<SSID> [<freq in MHz>] [<bssid>]",
+TOPLEVEL(connect, "<SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1:6162636465]",
        NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_connect,
        "Join the network with the given SSID (and frequency, BSSID).");
diff --git a/ibss.c b/ibss.c
index 63226275d8b4f58f1567e3c8a71966bd25e15067..8785e7acaffd68fa0767f00e48f2cb500ae74b53 100644 (file)
--- a/ibss.c
+++ b/ibss.c
@@ -40,17 +40,23 @@ static int join_ibss(struct nl80211_state *state,
        }
 
        if (argc) {
-               if (mac_addr_a2n(abssid, argv[0]))
-                       return 1;
-               NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
-               argv++;
-               argc--;
+               if (mac_addr_a2n(abssid, argv[0]) == 0) {
+                       NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
+                       argv++;
+                       argc--;
+               }
        }
 
-       if (argc)
+       if (!argc)
+               return 0;
+
+       if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
                return 1;
 
-       return 0;
+       argv++;
+       argc--;
+
+       return parse_keys(msg, argv, argc);
  nla_put_failure:
        return -ENOSPC;
 }
@@ -65,7 +71,7 @@ static int leave_ibss(struct nl80211_state *state,
 COMMAND(ibss, leave, NULL,
        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>]",
+COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
        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"
diff --git a/iw.h b/iw.h
index 339ebc1eec46ed3243c35b80196cc41303bf971b..69bb17c4b62e024dba43941a4d4271da3797a841 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -91,6 +91,8 @@ __u32 listen_events(struct nl80211_state *state,
 int mac_addr_a2n(unsigned char *mac_addr, char *arg);
 int mac_addr_n2a(char *mac_addr, unsigned char *arg);
 
+int parse_keys(struct nl_msg *msg, char **argv, int argc);
+
 const char *iftype_name(enum nl80211_iftype iftype);
 int ieee80211_channel_to_frequency(int chan);
 int ieee80211_frequency_to_channel(int freq);
diff --git a/util.c b/util.c
index 1750de26c1379c237b4aec9bed10966528b6992c..6251defcc8580441baa37141574672e9a782ebe0 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,4 +1,7 @@
 #include <ctype.h>
+#include <netlink/attr.h>
+#include <errno.h>
+#include <stdbool.h>
 #include "iw.h"
 #include "nl80211.h"
 
@@ -102,3 +105,121 @@ void print_ssid_escaped(const uint8_t len, const uint8_t *data)
                        printf("\\x%.2x", data[i]);
        }
 }
+
+static int hex2num(char digit)
+{
+       if (!isxdigit(digit))
+               return -1;
+       if (isdigit(digit))
+               return digit - '0';
+       return tolower(digit) - 'a' + 10;
+}
+
+static int hex2byte(char *hex)
+{
+       int d1, d2;
+
+       d1 = hex2num(hex[0]);
+       if (d1 < 0)
+               return -1;
+       d2 = hex2num(hex[1]);
+       if (d2 < 0)
+               return -1;
+       return (d1 << 4) | d2;
+}
+
+static char *hex2bin(char *hex, char *buf)
+{
+       char *result = buf;
+       int d;
+
+       while (hex[0]) {
+               d = hex2byte(hex);
+               if (d < 0)
+                       return NULL;
+               buf[0] = d;
+               buf++;
+               hex += 2;
+       }
+
+       return result;
+}
+
+int parse_keys(struct nl_msg *msg, char **argv, int argc)
+{
+       struct nlattr *keys;
+       int i = 0;
+       char keybuf[13];
+
+       if (!argc)
+               return 1;
+
+       NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
+
+       keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
+       if (!keys)
+               return -ENOBUFS;
+
+       do {
+               char *arg = *argv;
+               int pos = 0, keylen;
+               struct nlattr *key = nla_nest_start(msg, ++i);
+               char *keydata;
+
+               if (!key)
+                       return -ENOBUFS;
+
+               if (arg[pos] == 'd') {
+                       NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
+                       pos++;
+                       if (arg[pos] == ':')
+                               pos++;
+               }
+
+               if (!isdigit(arg[pos]))
+                       goto explain;
+               NLA_PUT_U8(msg, NL80211_KEY_IDX, arg[pos++] - '0');
+               if (arg[pos++] != ':')
+                       goto explain;
+               keydata = arg + pos;
+               switch (strlen(keydata)) {
+               case 10:
+                       keydata = hex2bin(keydata, keybuf);
+               case 5:
+                       NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC01);
+                       keylen = 5;
+                       break;
+               case 26:
+                       keydata = hex2bin(keydata, keybuf);
+               case 13:
+                       NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC05);
+                       keylen = 13;
+                       break;
+               default:
+                       goto explain;
+               }
+
+               if (!keydata)
+                       goto explain;
+
+               NLA_PUT(msg, NL80211_KEY_DATA, keylen, keydata);
+
+               nla_nest_end(msg, key);
+               argv++;
+               argc--;
+       } while (argc);
+
+       nla_nest_end(msg, keys);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+ explain:
+       fprintf(stderr, "key must be [d:]index:data where\n"
+                       "  'd:'     means default (transmit) key\n"
+                       "  'index:' is a single digit (0-3)\n"
+                       "  'data'   must be 5 or 13 ascii chars\n"
+                       "           or 10 or 26 hex digits\n"
+                       "for example: d:2:6162636465 is the same as d:2:abcde\n");
+       return 2;
+}