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