The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_netbsd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: ieee80211_netbsd.c,v 1.34 2018/12/22 14:28:56 maxv Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 #ifdef __FreeBSD__
   32 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.8 2005/08/08 18:46:35 sam Exp $");
   33 #else
   34 __KERNEL_RCSID(0, "$NetBSD: ieee80211_netbsd.c,v 1.34 2018/12/22 14:28:56 maxv Exp $");
   35 #endif
   36 
   37 /*
   38  * IEEE 802.11 support (NetBSD-specific code)
   39  */
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/systm.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/proc.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/once.h>
   47 
   48 #include <sys/socket.h>
   49 
   50 #include <sys/cprng.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_media.h>
   54 #include <net/if_ether.h>
   55 #include <net/route.h>
   56 
   57 #include <net80211/ieee80211_netbsd.h>
   58 #include <net80211/ieee80211_var.h>
   59 #include <net80211/ieee80211_sysctl.h>
   60 
   61 #define LOGICALLY_EQUAL(x, y)   (!(x) == !(y))
   62 
   63 static void ieee80211_sysctl_fill_node(struct ieee80211_node *,
   64     struct ieee80211_node_sysctl *, int, const struct ieee80211_channel *,
   65     uint32_t);
   66 static struct ieee80211_node *ieee80211_node_walknext(
   67     struct ieee80211_node_walk *);
   68 static struct ieee80211_node *ieee80211_node_walkfirst(
   69     struct ieee80211_node_walk *, u_short);
   70 static int ieee80211_sysctl_node(SYSCTLFN_ARGS);
   71 
   72 static void ieee80211_sysctl_setup(void);
   73 
   74 #ifdef IEEE80211_DEBUG
   75 int     ieee80211_debug = 0;
   76 #endif
   77 
   78 typedef void (*ieee80211_setup_func)(void);
   79 
   80 __link_set_decl(ieee80211_funcs, ieee80211_setup_func);
   81 
   82 static int
   83 ieee80211_init0(void)
   84 {
   85         ieee80211_setup_func * const *ieee80211_setup, f;
   86 
   87         ieee80211_sysctl_setup();
   88 
   89         if (max_linkhdr < ALIGN(sizeof(struct ieee80211_qosframe_addr4))) {
   90                 max_linkhdr = ALIGN(sizeof(struct ieee80211_qosframe_addr4));
   91         }
   92 
   93         __link_set_foreach(ieee80211_setup, ieee80211_funcs) {
   94                 f = (void*)*ieee80211_setup;
   95                 (*f)();
   96         }
   97 
   98         return 0;
   99 }
  100 
  101 void
  102 ieee80211_init(void)
  103 {
  104         static ONCE_DECL(ieee80211_init_once);
  105 
  106         RUN_ONCE(&ieee80211_init_once, ieee80211_init0);
  107 }
  108 
  109 static int
  110 ieee80211_sysctl_inact(SYSCTLFN_ARGS)
  111 {
  112         int error, t;
  113         struct sysctlnode node;
  114 
  115         node = *rnode;
  116 
  117         /*
  118          * sysctl_lookup copies the product from t.  Then, it
  119          * copies the new value onto t.
  120          */
  121         t = *(int*)rnode->sysctl_data * IEEE80211_INACT_WAIT;
  122         node.sysctl_data = &t;
  123         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  124         if (error || newp == NULL)
  125                 return error;
  126 
  127         /*
  128          * The new value was in seconds.  Convert to inactivity-wait
  129          * intervals.  There are IEEE80211_INACT_WAIT seconds per
  130          * interval.
  131          */
  132         *(int*)rnode->sysctl_data = t / IEEE80211_INACT_WAIT;
  133 
  134         return 0;
  135 }
  136 
  137 static int
  138 ieee80211_sysctl_parent(SYSCTLFN_ARGS)
  139 {
  140         struct ieee80211com *ic;
  141         char pname[IFNAMSIZ];
  142         struct sysctlnode node;
  143 
  144         node = *rnode;
  145         ic = node.sysctl_data;
  146         strlcpy(pname, ic->ic_ifp->if_xname, IFNAMSIZ);
  147         node.sysctl_data = pname;
  148         return sysctl_lookup(SYSCTLFN_CALL(&node));
  149 }
  150 
  151 /*
  152  * Create or get top of sysctl tree net.link.ieee80211.
  153  */
  154 static const struct sysctlnode *
  155 ieee80211_sysctl_treetop(struct sysctllog **log)
  156 {
  157         int rc;
  158         const struct sysctlnode *rnode;
  159 
  160         if ((rc = sysctl_createv(log, 0, NULL, &rnode,
  161             CTLFLAG_PERMANENT, CTLTYPE_NODE, "link",
  162             "link-layer statistics and controls",
  163             NULL, 0, NULL, 0, CTL_NET, PF_LINK, CTL_EOL)) != 0)
  164                 goto err;
  165 
  166         if ((rc = sysctl_createv(log, 0, &rnode, &rnode,
  167             CTLFLAG_PERMANENT, CTLTYPE_NODE, "ieee80211",
  168             "IEEE 802.11 WLAN statistics and controls",
  169             NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
  170                 goto err;
  171 
  172         return rnode;
  173 err:
  174         printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
  175         return NULL;
  176 }
  177 
  178 void
  179 ieee80211_sysctl_attach(struct ieee80211com *ic)
  180 {
  181         int rc;
  182         const struct sysctlnode *cnode, *rnode;
  183         char num[sizeof("vap") + 14];           /* sufficient for 32 bits */
  184 
  185         if ((rnode = ieee80211_sysctl_treetop(NULL)) == NULL)
  186                 return;
  187 
  188         snprintf(num, sizeof(num), "vap%u", ic->ic_vap);
  189 
  190         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &rnode,
  191             CTLFLAG_PERMANENT, CTLTYPE_NODE, num, SYSCTL_DESCR("virtual AP"),
  192             NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
  193                 goto err;
  194 
  195         /* control debugging printfs */
  196         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  197             CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING,
  198             "parent", SYSCTL_DESCR("parent device"),
  199             ieee80211_sysctl_parent, 0, (void *)ic, IFNAMSIZ, CTL_CREATE,
  200             CTL_EOL)) != 0)
  201                 goto err;
  202 
  203 #ifdef IEEE80211_DEBUG
  204         /* control debugging printfs */
  205         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  206             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  207             "debug", SYSCTL_DESCR("control debugging printfs"),
  208             NULL, ieee80211_debug, &ic->ic_debug, 0,
  209             CTL_CREATE, CTL_EOL)) != 0)
  210                 goto err;
  211 #endif
  212         /* XXX inherit from tunables */
  213         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  214             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  215             "inact_run", SYSCTL_DESCR("station inactivity timeout (sec)"),
  216             ieee80211_sysctl_inact, 0, &ic->ic_inact_run, 0,
  217             CTL_CREATE, CTL_EOL)) != 0)
  218                 goto err;
  219         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  220             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  221             "inact_probe",
  222             SYSCTL_DESCR("station inactivity probe timeout (sec)"),
  223             ieee80211_sysctl_inact, 0, &ic->ic_inact_probe, 0,
  224             CTL_CREATE, CTL_EOL)) != 0)
  225                 goto err;
  226         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  227             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  228             "inact_auth",
  229             SYSCTL_DESCR("station authentication timeout (sec)"),
  230             ieee80211_sysctl_inact, 0, &ic->ic_inact_auth, 0,
  231             CTL_CREATE, CTL_EOL)) != 0)
  232                 goto err;
  233         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  234             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  235             "inact_init",
  236             SYSCTL_DESCR("station initial state timeout (sec)"),
  237             ieee80211_sysctl_inact, 0, &ic->ic_inact_init, 0,
  238             CTL_CREATE, CTL_EOL)) != 0)
  239                 goto err;
  240         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  241             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  242             "driver_caps", SYSCTL_DESCR("driver capabilities"),
  243             NULL, 0, &ic->ic_caps, 0, CTL_CREATE, CTL_EOL)) != 0)
  244                 goto err;
  245         if ((rc = sysctl_createv(&ic->ic_sysctllog, 0, &rnode, &cnode,
  246             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  247             "bmiss_max", SYSCTL_DESCR("consecutive beacon misses before scanning"),
  248             NULL, 0, &ic->ic_bmiss_max, 0, CTL_CREATE, CTL_EOL)) != 0)
  249                 goto err;
  250 
  251         return;
  252 err:
  253         printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
  254 }
  255 
  256 void
  257 ieee80211_sysctl_detach(struct ieee80211com *ic)
  258 {
  259         sysctl_teardown(&ic->ic_sysctllog);
  260 }
  261 
  262 /*
  263  * Pointers for testing:
  264  *
  265  *      If there are no interfaces, or else no 802.11 interfaces,
  266  *      ieee80211_node_walkfirst must return NULL.
  267  *
  268  *      If there is any single 802.11 interface, ieee80211_node_walkfirst
  269  *      must not return NULL.
  270  */
  271 static struct ieee80211_node *
  272 ieee80211_node_walkfirst(struct ieee80211_node_walk *nw, u_short if_index)
  273 {
  274         memset(nw, 0, sizeof(*nw));
  275 
  276         nw->nw_ifindex = if_index;
  277 
  278         LIST_FOREACH(nw->nw_ic, &ieee80211com_head, ic_list) {
  279                 if (if_index != 0 && nw->nw_ic->ic_ifp->if_index != if_index)
  280                         continue;
  281                 if (!TAILQ_EMPTY(&nw->nw_ic->ic_sta.nt_node))
  282                         nw->nw_nt = &nw->nw_ic->ic_sta;
  283                 else if (!TAILQ_EMPTY(&nw->nw_ic->ic_scan.nt_node))
  284                         nw->nw_nt = &nw->nw_ic->ic_scan;
  285                 else if (nw->nw_ic->ic_bss == NULL)
  286                         continue;
  287                 break;
  288         }
  289 
  290         if (nw->nw_ic == NULL)
  291                 return NULL;
  292 
  293         if (nw->nw_nt == NULL)
  294                 nw->nw_ni = nw->nw_ic->ic_bss;
  295         else
  296                 nw->nw_ni = TAILQ_FIRST(&nw->nw_nt->nt_node);
  297 
  298         return nw->nw_ni;
  299 }
  300 
  301 static struct ieee80211_node *
  302 ieee80211_node_walknext(struct ieee80211_node_walk *nw)
  303 {
  304         if (nw->nw_nt != NULL)
  305                 nw->nw_ni = TAILQ_NEXT(nw->nw_ni, ni_list);
  306         else
  307                 nw->nw_ni = NULL;
  308 
  309         while (nw->nw_ni == NULL) {
  310                 if (nw->nw_nt == &nw->nw_ic->ic_sta) {
  311                         nw->nw_nt = &nw->nw_ic->ic_scan;
  312                         nw->nw_ni = TAILQ_FIRST(&nw->nw_nt->nt_node);
  313                         continue;
  314                 } else if (nw->nw_nt == &nw->nw_ic->ic_scan) {
  315                         nw->nw_nt = NULL;
  316                         nw->nw_ni = nw->nw_ic->ic_bss;
  317                         continue;
  318                 }
  319                 KASSERT(nw->nw_nt == NULL);
  320                 if (nw->nw_ifindex != 0)
  321                         return NULL;
  322 
  323                 nw->nw_ic = LIST_NEXT(nw->nw_ic, ic_list);
  324                 if (nw->nw_ic == NULL)
  325                         return NULL;
  326 
  327                 nw->nw_nt = &nw->nw_ic->ic_sta;
  328                 nw->nw_ni = TAILQ_FIRST(&nw->nw_nt->nt_node);
  329         }
  330 
  331         return nw->nw_ni;
  332 }
  333 
  334 static void
  335 ieee80211_sysctl_fill_node(struct ieee80211_node *ni,
  336     struct ieee80211_node_sysctl *ns, int ifindex,
  337     const struct ieee80211_channel *chan0, uint32_t flags)
  338 {
  339         memset(ns, 0, sizeof(*ns));
  340 
  341         ns->ns_ifindex = ifindex;
  342         ns->ns_capinfo = ni->ni_capinfo;
  343         ns->ns_flags = flags;
  344         memcpy(ns->ns_macaddr, ni->ni_macaddr, sizeof(ns->ns_macaddr));
  345         memcpy(ns->ns_bssid, ni->ni_bssid, sizeof(ns->ns_bssid));
  346         if (ni->ni_chan != IEEE80211_CHAN_ANYC) {
  347                 ns->ns_freq = ni->ni_chan->ic_freq;
  348                 ns->ns_chanflags = ni->ni_chan->ic_flags;
  349                 ns->ns_chanidx = ni->ni_chan - chan0;
  350         } else {
  351                 ns->ns_freq = ns->ns_chanflags = 0;
  352                 ns->ns_chanidx = 0;
  353         }
  354         ns->ns_rssi = ni->ni_rssi;
  355         ns->ns_esslen = ni->ni_esslen;
  356         memcpy(ns->ns_essid, ni->ni_essid, sizeof(ns->ns_essid));
  357         ns->ns_erp = ni->ni_erp;
  358         ns->ns_associd = ni->ni_associd;
  359         ns->ns_inact = ni->ni_inact * IEEE80211_INACT_WAIT;
  360         ns->ns_rstamp = ni->ni_rstamp;
  361         ns->ns_rates = ni->ni_rates;
  362         ns->ns_txrate = ni->ni_txrate;
  363         ns->ns_intval = ni->ni_intval;
  364         memcpy(ns->ns_tstamp, &ni->ni_tstamp, sizeof(ns->ns_tstamp));
  365         ns->ns_txseq = ni->ni_txseqs[0];
  366         ns->ns_rxseq = ni->ni_rxseqs[0];
  367         ns->ns_fhdwell = ni->ni_fhdwell;
  368         ns->ns_fhindex = ni->ni_fhindex;
  369         ns->ns_fails = ni->ni_fails;
  370 }
  371 
  372 /* Between two examinations of the sysctl tree, I expect each
  373  * interface to add no more than 5 nodes.
  374  */
  375 #define IEEE80211_SYSCTL_NODE_GROWTH    5
  376 
  377 static int
  378 ieee80211_sysctl_node(SYSCTLFN_ARGS)
  379 {
  380         struct ieee80211_node_walk nw;
  381         struct ieee80211_node *ni;
  382         struct ieee80211_node_sysctl ns;
  383         char *dp;
  384         u_int cur_ifindex, ifcount, ifindex, last_ifindex, op, arg, hdr_type;
  385         uint32_t flags;
  386         size_t len, needed, eltsize, out_size;
  387         int error, s, saw_bss = 0, nelt;
  388 
  389         if (namelen == 1 && name[0] == CTL_QUERY)
  390                 return (sysctl_query(SYSCTLFN_CALL(rnode)));
  391 
  392         if (namelen != IEEE80211_SYSCTL_NODENAMELEN)
  393                 return (EINVAL);
  394 
  395         /* ifindex.op.arg.header-type.eltsize.nelt */
  396         dp = oldp;
  397         len = (oldp != NULL) ? *oldlenp : 0;
  398         ifindex = name[IEEE80211_SYSCTL_NODENAME_IF];
  399         op = name[IEEE80211_SYSCTL_NODENAME_OP];
  400         arg = name[IEEE80211_SYSCTL_NODENAME_ARG];
  401         hdr_type = name[IEEE80211_SYSCTL_NODENAME_TYPE];
  402         eltsize = name[IEEE80211_SYSCTL_NODENAME_ELTSIZE];
  403         nelt = name[IEEE80211_SYSCTL_NODENAME_ELTCOUNT];
  404         out_size = MIN(sizeof(ns), eltsize);
  405 
  406         if (op != IEEE80211_SYSCTL_OP_ALL || arg != 0 ||
  407             hdr_type != IEEE80211_SYSCTL_T_NODE || eltsize < 1 || nelt < 0)
  408                 return (EINVAL);
  409 
  410         error = 0;
  411         needed = 0;
  412         ifcount = 0;
  413         last_ifindex = 0;
  414 
  415         s = splnet();
  416 
  417         for (ni = ieee80211_node_walkfirst(&nw, ifindex); ni != NULL;
  418              ni = ieee80211_node_walknext(&nw)) {
  419                 struct ieee80211com *ic;
  420 
  421                 ic = nw.nw_ic;
  422                 cur_ifindex = ic->ic_ifp->if_index;
  423 
  424                 if (cur_ifindex != last_ifindex) {
  425                         saw_bss = 0;
  426                         ifcount++;
  427                         last_ifindex = cur_ifindex;
  428                 }
  429 
  430                 if (nelt <= 0)
  431                         continue;
  432 
  433                 if (saw_bss && ni == ic->ic_bss)
  434                         continue;
  435                 else if (ni == ic->ic_bss) {
  436                         saw_bss = 1;
  437                         flags = IEEE80211_NODE_SYSCTL_F_BSS;
  438                 } else
  439                         flags = 0;
  440                 if (ni->ni_table == &ic->ic_scan)
  441                         flags |= IEEE80211_NODE_SYSCTL_F_SCAN;
  442                 else if (ni->ni_table == &ic->ic_sta)
  443                         flags |= IEEE80211_NODE_SYSCTL_F_STA;
  444                 if (len >= eltsize) {
  445                         ieee80211_sysctl_fill_node(ni, &ns, cur_ifindex,
  446                             &ic->ic_channels[0], flags);
  447                         error = copyout(&ns, dp, out_size);
  448                         if (error)
  449                                 goto cleanup;
  450                         dp += eltsize;
  451                         len -= eltsize;
  452                 }
  453                 needed += eltsize;
  454                 if (nelt != INT_MAX)
  455                         nelt--;
  456         }
  457 cleanup:
  458         splx(s);
  459 
  460         *oldlenp = needed;
  461         if (oldp == NULL)
  462                 *oldlenp += ifcount * IEEE80211_SYSCTL_NODE_GROWTH * eltsize;
  463 
  464         return (error);
  465 }
  466 
  467 /*
  468  * Setup sysctl(3) MIB, net.ieee80211.*
  469  *
  470  * TBD condition CTLFLAG_PERMANENT on being a module or not
  471  */
  472 static struct sysctllog *ieee80211_sysctllog;
  473 static void
  474 ieee80211_sysctl_setup(void)
  475 {
  476         int rc;
  477         const struct sysctlnode *rnode;
  478 
  479         if ((rnode = ieee80211_sysctl_treetop(&ieee80211_sysctllog)) == NULL)
  480                 return;
  481 
  482         if ((rc = sysctl_createv(&ieee80211_sysctllog, 0, &rnode, NULL,
  483             CTLFLAG_PERMANENT, CTLTYPE_NODE, "nodes", "client/peer stations",
  484             ieee80211_sysctl_node, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
  485                 goto err;
  486 
  487 #ifdef IEEE80211_DEBUG
  488         /* control debugging printfs */
  489         if ((rc = sysctl_createv(&ieee80211_sysctllog, 0, &rnode, NULL,
  490             CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
  491             "debug", SYSCTL_DESCR("control debugging printfs"),
  492             NULL, 0, &ieee80211_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
  493                 goto err;
  494 #endif
  495 
  496         ieee80211_rssadapt_sysctl_setup(&ieee80211_sysctllog);
  497 
  498         return;
  499 err:
  500         printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
  501 }
  502 
  503 int
  504 ieee80211_node_dectestref(struct ieee80211_node *ni)
  505 {
  506         if (atomic_dec_uint_nv(&ni->ni_refcnt) == 0) {
  507                 atomic_inc_uint(&ni->ni_refcnt);
  508                 return 1;
  509         } else
  510                 return 0;
  511 }
  512 
  513 void
  514 ieee80211_drain_ifq(struct ifqueue *ifq)
  515 {
  516         struct ieee80211_node *ni;
  517         struct mbuf *m;
  518 
  519         for (;;) {
  520                 IF_DEQUEUE(ifq, m);
  521                 if (m == NULL)
  522                         break;
  523 
  524                 ni = M_GETCTX(m, struct ieee80211_node *);
  525                 KASSERT(ni != NULL);
  526                 ieee80211_free_node(ni);
  527                 M_SETCTX(m, NULL);
  528 
  529                 m_freem(m);
  530         }
  531 }
  532 
  533 void
  534 if_printf(struct ifnet *ifp, const char *fmt, ...)
  535 {
  536         va_list ap;
  537         va_start(ap, fmt);
  538 
  539         printf("%s: ", ifp->if_xname);
  540         vprintf(fmt, ap);
  541 
  542         va_end(ap);
  543         return;
  544 }
  545 
  546 /*
  547  * Allocate and setup a management frame of the specified
  548  * size.  We return the mbuf and a pointer to the start
  549  * of the contiguous data area that's been reserved based
  550  * on the packet length.  The data area is forced to 32-bit
  551  * alignment and the buffer length to a multiple of 4 bytes.
  552  * This is done mainly so beacon frames (that require this)
  553  * can use this interface too.
  554  */
  555 struct mbuf *
  556 ieee80211_getmgtframe(u_int8_t **frm, u_int pktlen)
  557 {
  558         struct mbuf *m;
  559         u_int len;
  560 
  561         /*
  562          * NB: we know the mbuf routines will align the data area
  563          *     so we don't need to do anything special.
  564          */
  565         /* XXX 4-address frame? */
  566         len = roundup(sizeof(struct ieee80211_frame) + pktlen, 4);
  567         IASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len));
  568 
  569         if (len <= MHLEN) {
  570                 m = m_gethdr(M_NOWAIT, MT_HEADER);
  571                 /*
  572                  * Align the data in case additional headers are added.
  573                  * This should only happen when a WEP header is added
  574                  * which only happens for shared key authentication mgt
  575                  * frames which all fit in MHLEN.
  576                  */
  577                 if (m != NULL)
  578                         m_align(m, len);
  579         } else {
  580                 m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
  581         }
  582 
  583         if (m != NULL) {
  584                 m->m_data += sizeof(struct ieee80211_frame);
  585                 *frm = m->m_data;
  586                 IASSERT((uintptr_t)*frm % 4 == 0, ("bad beacon boundary"));
  587         }
  588 
  589         return m;
  590 }
  591 
  592 void
  593 get_random_bytes(void *p, size_t n)
  594 {
  595         cprng_fast(p, n);
  596 }
  597 
  598 void
  599 ieee80211_notify_node_join(struct ieee80211com *ic, struct ieee80211_node *ni,
  600     int newassoc)
  601 {
  602         struct ifnet *ifp = ic->ic_ifp;
  603         struct ieee80211_join_event iev;
  604 
  605         IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE, "%snode %s join\n",
  606             (ni == ic->ic_bss) ? "bss " : "",
  607             ether_sprintf(ni->ni_macaddr));
  608 
  609         memset(&iev, 0, sizeof(iev));
  610         if (ni == ic->ic_bss) {
  611                 IEEE80211_ADDR_COPY(iev.iev_addr, ni->ni_bssid);
  612                 rt_ieee80211msg(ifp, newassoc ?
  613                     RTM_IEEE80211_ASSOC : RTM_IEEE80211_REASSOC,
  614                     &iev, sizeof(iev));
  615                 if_link_state_change(ifp, LINK_STATE_UP);
  616         } else {
  617                 IEEE80211_ADDR_COPY(iev.iev_addr, ni->ni_macaddr);
  618                 rt_ieee80211msg(ifp, newassoc ?
  619                     RTM_IEEE80211_JOIN : RTM_IEEE80211_REJOIN,
  620                     &iev, sizeof(iev));
  621         }
  622 }
  623 
  624 void
  625 ieee80211_notify_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
  626 {
  627         struct ifnet *ifp = ic->ic_ifp;
  628         struct ieee80211_leave_event iev;
  629 
  630         IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE, "%snode %s leave\n",
  631             (ni == ic->ic_bss) ? "bss " : "",
  632             ether_sprintf(ni->ni_macaddr));
  633 
  634         if (ni == ic->ic_bss) {
  635                 rt_ieee80211msg(ifp, RTM_IEEE80211_DISASSOC, NULL, 0);
  636                 if_link_state_change(ifp, LINK_STATE_DOWN);
  637         } else {
  638                 /* fire off wireless event station leaving */
  639                 memset(&iev, 0, sizeof(iev));
  640                 IEEE80211_ADDR_COPY(iev.iev_addr, ni->ni_macaddr);
  641                 rt_ieee80211msg(ifp, RTM_IEEE80211_LEAVE, &iev, sizeof(iev));
  642         }
  643 }
  644 
  645 void
  646 ieee80211_notify_scan_done(struct ieee80211com *ic)
  647 {
  648         struct ifnet *ifp = ic->ic_ifp;
  649 
  650         IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
  651                 "%s", "notify scan done\n");
  652 
  653         /* dispatch wireless event indicating scan completed */
  654         rt_ieee80211msg(ifp, RTM_IEEE80211_SCAN, NULL, 0);
  655 }
  656 
  657 void
  658 ieee80211_notify_replay_failure(struct ieee80211com *ic,
  659         const struct ieee80211_frame *wh, const struct ieee80211_key *k,
  660         u_int64_t rsc)
  661 {
  662         struct ifnet *ifp = ic->ic_ifp;
  663 
  664         IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
  665             "[%s] %s replay detected <rsc %ju, csc %ju, keyix %u rxkeyix %u>\n",
  666             ether_sprintf(wh->i_addr2), k->wk_cipher->ic_name,
  667             (intmax_t) rsc, (intmax_t) k->wk_keyrsc,
  668             k->wk_keyix, k->wk_rxkeyix);
  669 
  670         if (ifp != NULL) {              /* NB: for cipher test modules */
  671                 struct ieee80211_replay_event iev;
  672 
  673                 IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1);
  674                 IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2);
  675                 iev.iev_cipher = k->wk_cipher->ic_cipher;
  676                 if (k->wk_rxkeyix != IEEE80211_KEYIX_NONE)
  677                         iev.iev_keyix = k->wk_rxkeyix;
  678                 else
  679                         iev.iev_keyix = k->wk_keyix;
  680                 iev.iev_keyrsc = k->wk_keyrsc;
  681                 iev.iev_rsc = rsc;
  682                 rt_ieee80211msg(ifp, RTM_IEEE80211_REPLAY, &iev, sizeof(iev));
  683         }
  684 }
  685 
  686 void
  687 ieee80211_notify_michael_failure(struct ieee80211com *ic,
  688         const struct ieee80211_frame *wh, u_int keyix)
  689 {
  690         struct ifnet *ifp = ic->ic_ifp;
  691 
  692         IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
  693             "[%s] michael MIC verification failed <keyix %u>\n",
  694             ether_sprintf(wh->i_addr2), keyix);
  695         ic->ic_stats.is_rx_tkipmic++;
  696 
  697         if (ifp != NULL) {              /* NB: for cipher test modules */
  698                 struct ieee80211_michael_event iev;
  699 
  700                 IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1);
  701                 IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2);
  702                 iev.iev_cipher = IEEE80211_CIPHER_TKIP;
  703                 iev.iev_keyix = keyix;
  704                 rt_ieee80211msg(ifp, RTM_IEEE80211_MICHAEL, &iev, sizeof(iev));
  705         }
  706 }
  707 
  708 void
  709 ieee80211_load_module(const char *modname)
  710 {
  711 #ifdef notyet
  712         struct thread *td = curthread;
  713 
  714         if (suser(td) == 0 && securelevel_gt(td->td_ucred, 0) == 0) {
  715                 mtx_lock(&Giant);
  716                 (void) linker_load_module(modname, NULL, NULL, NULL, NULL);
  717                 mtx_unlock(&Giant);
  718         }
  719 #else
  720         printf("%s: load the %s module by hand for now.\n", __func__, modname);
  721 #endif
  722 }
  723 
  724 /* -------------------------------------------------------------------------- */
  725 
  726 /*
  727  * Append the specified data to the indicated mbuf chain,
  728  * Extend the mbuf chain if the new data does not fit in
  729  * existing space.
  730  *
  731  * Return 1 if able to complete the job; otherwise 0.
  732  */
  733 int
  734 m_append(struct mbuf *m0, int len, const void *cpv)
  735 {
  736         struct mbuf *m, *n;
  737         int remainder, space;
  738         const char *cp = cpv;
  739 
  740         KASSERT(len != M_COPYALL);
  741         for (m = m0; m->m_next != NULL; m = m->m_next)
  742                 continue;
  743         remainder = len;
  744         space = M_TRAILINGSPACE(m);
  745         if (space > 0) {
  746                 /*
  747                  * Copy into available space.
  748                  */
  749                 if (space > remainder)
  750                         space = remainder;
  751                 memmove(mtod(m, char *) + m->m_len, cp, space);
  752                 m->m_len += space;
  753                 cp = cp + space, remainder -= space;
  754         }
  755         while (remainder > 0) {
  756                 /*
  757                  * Allocate a new mbuf; could check space
  758                  * and allocate a cluster instead.
  759                  */
  760                 n = m_get(M_DONTWAIT, m->m_type);
  761                 if (n == NULL)
  762                         break;
  763                 n->m_len = uimin(MLEN, remainder);
  764                 memmove(mtod(n, void *), cp, n->m_len);
  765                 cp += n->m_len, remainder -= n->m_len;
  766                 m->m_next = n;
  767                 m = n;
  768         }
  769         if (m0->m_flags & M_PKTHDR)
  770                 m0->m_pkthdr.len += len - remainder;
  771         return (remainder == 0);
  772 }

Cache object: b3deb597ac00bb6265e231295e947789


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.