Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src-draft/trunk]: src/sbin/ifconfig Add support for cloning wlan devices



details:   https://anonhg.NetBSD.org/src-all/rev/8398dfd86061
branches:  trunk
changeset: 952569:8398dfd86061
user:      Martin Husemann <martin%NetBSD.org@localhost>
date:      Fri Sep 25 19:42:03 2020 +0200

description:
Add support for cloning wlan devices

diffstat:

 sbin/ifconfig/Makefile.common |    1 +
 sbin/ifconfig/ieee80211.c     |  132 +++++++++++++++++++++++++++++++++++++++--
 sbin/ifconfig/ifconfig.c      |   39 ++++++++---
 sbin/ifconfig/parse.c         |   28 +++++++-
 sbin/ifconfig/parse.h         |   31 +++++++++
 5 files changed, 209 insertions(+), 22 deletions(-)

diffs (truncated from 433 to 300 lines):

diff -r 7cb1558aefc7 -r 8398dfd86061 sbin/ifconfig/Makefile.common
--- a/sbin/ifconfig/Makefile.common     Fri Sep 25 19:40:03 2020 +0200
+++ b/sbin/ifconfig/Makefile.common     Fri Sep 25 19:42:03 2020 +0200
@@ -13,6 +13,7 @@
 INCS+=         af_inetany.h env.h extern.h media.h parse.h util.h
 SRCS+=         af_inet.c af_inetany.c env.c ether.c ieee80211.c \
                ifconfig.c media.c parse.c tunnel.c util.c vlan.c
+
 .ifndef SMALLPROG
 SRCS+=         agr.c l2tp.c
 .endif
diff -r 7cb1558aefc7 -r 8398dfd86061 sbin/ifconfig/ieee80211.c
--- a/sbin/ifconfig/ieee80211.c Fri Sep 25 19:40:03 2020 +0200
+++ b/sbin/ifconfig/ieee80211.c Fri Sep 25 19:42:03 2020 +0200
@@ -78,6 +78,9 @@
 static void list_scan(prop_dictionary_t);
 static int mappsb(u_int , u_int);
 static int mapgsm(u_int , u_int);
+int clone_command(prop_dictionary_t env, prop_dictionary_t oenv);
+int wlan_clone_command(prop_dictionary_t env, prop_dictionary_t oenv);
+static int wlan_clone_fixup(struct match*, int, int);
 
 static int sethidessid(prop_dictionary_t, prop_dictionary_t);
 static int setapbridge(prop_dictionary_t, prop_dictionary_t);
@@ -111,8 +114,10 @@
 static const char * iename(int);
 
 extern struct pinteger parse_chan, parse_frag, parse_rts;
-extern struct pstr parse_bssid, parse_ssid, parse_nwkey;
+extern struct pstr parse_bssid, parse_ssid, parse_nwkey, wlan_device;
 extern struct pinteger parse_powersavesleep;
+extern struct pbranch wlan_or_opt_silent_family;
+extern struct pkw wlan_mode;
 
 static const struct kwinst ieee80211boolkw[] = {
          {.k_word = "hidessid", .k_key = "hidessid", .k_neg = true,
@@ -133,6 +138,34 @@
 static struct pkw lists = PKW_INITIALIZER(&lists, "ieee80211 lists", NULL,
     "list", listskw, __arraycount(listskw), &command_root.pb_parser);
 
+static const struct kwinst kw80211modes[] = {
+         {.k_word = "sta", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_STA },
+         {.k_word = "ahdemo", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_AHDEMO },
+         {.k_word = "adhoc-demo", .k_key = "mode",     // alias for previous
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_AHDEMO },
+         {.k_word = "ibss", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_IBSS },
+         {.k_word = "adhoc", .k_key = "mode",          // alias for previous
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_IBSS },
+         {.k_word = "ap", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_HOSTAP },
+         {.k_word = "hostap", .k_key = "mode",         // alias for previous
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_HOSTAP },
+         {.k_word = "wds", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_WDS },
+         {.k_word = "tdma", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = -1 },   /* XXX ??? */
+         {.k_word = "mesh", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_MBSS },
+         {.k_word = "monitor", .k_key = "mode",
+          .k_type = KW_T_INT, .k_int = IEEE80211_M_MONITOR },
+};
+
+struct pkw wlan_mode = PKW_INITIALIZER1(&wlan_mode, "802.11 modes", NULL, NULL,
+    kw80211modes, __arraycount(kw80211modes), NULL, wlan_clone_fixup);
+
 static const struct kwinst kw80211kw[] = {
          {.k_word = "bssid", .k_nextparser = &parse_bssid.ps_parser}
        , {.k_word = "-bssid", .k_exec = unsetifbssid,
@@ -191,6 +224,73 @@
 struct pstr parse_bssid = PSTR_INITIALIZER1(&parse_bssid, "bssid", setifbssid,
     "bssid", false, &command_root.pb_parser);
 
+struct pstr wlan_device = PSTR_INITIALIZER2(&wlan_device, "wlandev", NULL,
+     "wlandev", false, &wlan_or_opt_silent_family.pb_parser, wlan_clone_fixup,
+     true);
+
+/*
+ * We accumlute various changes originally directed at clone_command()
+ * into a single extended call redirected to wlan_clone_command
+ * (but with the environment gathered by all previous matches).
+ */
+static int
+wlan_clone_fixup(struct match *matches, int index, int max_index)
+{
+       int i;
+
+       /*
+        * Make every match trying to exec clone_command or
+        * wlan_clone_command do nothing.
+        */
+       for (i = 0; i < index; i++) {
+               if (matches[i].m_exec == clone_command ||
+                   matches[i].m_exec == wlan_clone_command) {
+                       matches[i].m_exec = NULL;
+                       matches[i].m_override_parser_exec = true;
+               }
+       }
+
+       /*
+        * Now make myself exec wlan_clone_command.
+        */
+       matches[index].m_exec = wlan_clone_command;
+       matches[index].m_override_parser_exec = true;
+
+       return 0;
+}
+
+int
+wlan_clone_command(prop_dictionary_t env, prop_dictionary_t oenv)
+{
+       struct if_cclonearg carg;
+       struct ieee80211_clone_params req;
+       const char *parent;
+       int mode;
+
+       if (!prop_dictionary_get_cstring_nocopy(env, "wlandev", &parent)) {
+               warn("wlandev required");
+               return -1;
+       }
+
+       memset(&carg, 0, sizeof carg);
+       memset(&req, 0, sizeof req);
+       /* set some defaults */
+       req.icp_opmode = IEEE80211_M_STA;
+
+       carg.ifc_arg_size = sizeof req;
+       carg.ifc_args = &req;
+       strlcpy(req.icp_parent, parent, sizeof req.icp_parent);
+       if (prop_dictionary_get_int(env, "mode", &mode))
+               req.icp_opmode = mode;
+
+       if (direct_ioctl(env, SIOCIFCREATEARGS, &carg) == -1) {
+               warn("%s", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
 static int
 set80211(prop_dictionary_t env, uint16_t type, int16_t val, int16_t len,
     u_int8_t *data)
@@ -235,14 +335,22 @@
        struct ifmediareq ifmr;
 
        memset(&ifmr, 0, sizeof(ifmr));
-       if (direct_ioctl(env, SIOCGIFMEDIA, &ifmr) == -1)
+       if (direct_ioctl(env, SIOCGIFMEDIA, &ifmr) == -1) {
                ;
-       else if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
-               return IEEE80211_M_IBSS;        /* XXX ahdemo */
-       else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
+       } else if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
+               if (ifmr.ifm_current & IFM_FLAG0)
+                       return IEEE80211_M_AHDEMO;
+               else
+                       return IEEE80211_M_IBSS;
+       } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) {
                return IEEE80211_M_HOSTAP;
-       else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
+       } else if (ifmr.ifm_current & IFM_IEEE80211_IBSS) {
+               return IEEE80211_M_IBSS;
+       } else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) {
                return IEEE80211_M_MONITOR;
+       } else if (ifmr.ifm_current & IFM_IEEE80211_MBSS) {
+               return IEEE80211_M_MBSS;
+       }
 
        return IEEE80211_M_STA;
 }
@@ -737,15 +845,24 @@
 static void
 scan_and_wait(prop_dictionary_t env)
 {
+       struct ieee80211_scan_req sr;
        int sroute;
 
+       memset(&sr, 0, sizeof sr);
+       sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE
+                       | IEEE80211_IOC_SCAN_BGSCAN
+                       | IEEE80211_IOC_SCAN_NOPICK
+                       | IEEE80211_IOC_SCAN_ONCE;
+       sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
+
        sroute = prog_socket(PF_ROUTE, SOCK_RAW, 0);
        if (sroute < 0) {
                warn("socket(PF_ROUTE,SOCK_RAW)");
                return;
        }
        /* NB: only root can trigger a scan so ignore errors */
-       if (set80211(env, IEEE80211_IOC_SCAN_REQ, 0, 0, NULL) >= 0) {
+       if (set80211(env, IEEE80211_IOC_SCAN_REQ, 0, sizeof sr,
+           (uint8_t*)&sr) >= 0) {
                char buf[2048];
                struct if_announcemsghdr *ifan;
                struct rt_msghdr *rtm;
@@ -1398,3 +1515,4 @@
        register_statistics(&statistics);
        register_usage(&usage);
 }
+
diff -r 7cb1558aefc7 -r 8398dfd86061 sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c  Fri Sep 25 19:40:03 2020 +0200
+++ b/sbin/ifconfig/ifconfig.c  Fri Sep 25 19:42:03 2020 +0200
@@ -112,7 +112,8 @@
 bool gflagset[10 + 26 * 2];
 
 static int carrier(prop_dictionary_t);
-static int clone_command(prop_dictionary_t, prop_dictionary_t);
+int clone_command(prop_dictionary_t, prop_dictionary_t);
+int wlan_clone_command(prop_dictionary_t, prop_dictionary_t);
 static void do_setifpreference(prop_dictionary_t);
 static int flag_index(int);
 static void init_afs(void);
@@ -170,9 +171,10 @@
 
 extern struct pbranch command_root;
 extern struct pbranch opt_command;
-extern struct pbranch opt_family, opt_silent_family;
-extern struct pkw cloning, silent_family, family, ifcaps, ifflags, misc;
-extern struct pstr parse_linkstr;
+extern struct pbranch opt_family, wlan_or_opt_silent_family;
+extern struct pkw cloning, silent_family, family, ifcaps, ifflags, misc,
+                wlan_create;
+extern struct pstr parse_linkstr, wlan_device, wlan_mode;
 
 struct pinteger parse_metric = PINTEGER_INITIALIZER(&parse_metric, "metric", 10,
     setifmetric, "metric", &command_root.pb_parser);
@@ -225,10 +227,17 @@
           .k_nextparser = &command_root.pb_parser}
 };
 
+static const struct kwinst wlan_createkw[] = {
+         {.k_word = "wlandev", .k_key = "wlandev",
+          .k_nextparser = &wlan_device.ps_parser}
+       , {.k_word = "wlanmode", .k_key = "wlanmode",
+          .k_nextparser = &wlan_mode.ps_parser}
+};
+
 /* key: clonecmd */
 static const struct kwinst clonekw[] = {
        {.k_word = "create", .k_type = KW_T_INT, .k_int = SIOCIFCREATE,
-        .k_nextparser = &opt_silent_family.pb_parser},
+        .k_nextparser = &wlan_or_opt_silent_family.pb_parser},
        {.k_word = "destroy", .k_type = KW_T_INT, .k_int = SIOCIFDESTROY}
 };
 
@@ -243,6 +252,11 @@
 struct pterm no_cmds = PTERM_INITIALIZER(&no_cmds, "no commands", no_cmds_exec,
     "none");
 
+struct pkw wlan_create =
+    PKW_INITIALIZER(&wlan_create, "wlan-create", NULL, "wlan-create",
+       wlan_createkw, __arraycount(wlan_createkw),
+       &wlan_or_opt_silent_family.pb_parser);
+
 struct pkw family_only =
     PKW_INITIALIZER(&family_only, "family-only", NULL, "af", familykw,
        __arraycount(familykw), &no_cmds.pt_parser);
@@ -278,8 +292,9 @@
 struct branch opt_clone_brs[] = {
          {.b_nextparser = &cloning.pk_parser}
        , {.b_nextparser = &opt_family.pb_parser}
-}, opt_silent_family_brs[] = {
-         {.b_nextparser = &silent_family.pk_parser}
+}, wlan_or_opt_silent_family_brs[] = {
+         {.b_nextparser = &wlan_create.pk_parser }
+       , {.b_nextparser = &silent_family.pk_parser}
        , {.b_nextparser = &command_root.pb_parser}
 }, opt_family_brs[] = {
          {.b_nextparser = &family.pk_parser}
@@ -339,9 +354,10 @@
 struct pbranch opt_clone = PBRANCH_INITIALIZER(&opt_clone,
     "opt-clone", opt_clone_brs, __arraycount(opt_clone_brs), true);
 
-struct pbranch opt_silent_family = PBRANCH_INITIALIZER(&opt_silent_family,
-    "optional silent family", opt_silent_family_brs,
-    __arraycount(opt_silent_family_brs), true);
+struct pbranch wlan_or_opt_silent_family = PBRANCH_INITIALIZER(
+    &wlan_or_opt_silent_family,
+    "wlan config or optional silent family", wlan_or_opt_silent_family_brs,
+    __arraycount(wlan_or_opt_silent_family_brs), true);
 
 struct pbranch opt_family = PBRANCH_INITIALIZER(&opt_family,
     "opt-family", opt_family_brs, __arraycount(opt_family_brs), true);
@@ -946,7 +962,7 @@
        exit(EXIT_SUCCESS);
 }
 
-static int
+int
 clone_command(prop_dictionary_t env, prop_dictionary_t oenv)
 {
        int64_t cmd;
@@ -955,7 +971,6 @@
                errno = ENOENT;
                return -1;



Home | Main Index | Thread Index | Old Index