summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-06-28 06:09:39 +0000
committersam <sam@FreeBSD.org>2003-06-28 06:09:39 +0000
commit9b56e94b9579416e84551fdd705e5d64be3c11da (patch)
tree6267257f50dfff8cdb091e54032827295c06a64e /sys/net
parent4651aaa88dafc1e518057fd40e5d9fd1d66debc3 (diff)
downloadFreeBSD-src-9b56e94b9579416e84551fdd705e5d64be3c11da.zip
FreeBSD-src-9b56e94b9579416e84551fdd705e5d64be3c11da.tar.gz
remove old 802.11 support; replaced by new code in sys/net80211
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_ieee80211.h614
-rw-r--r--sys/net/if_ieee80211subr.c3413
2 files changed, 0 insertions, 4027 deletions
diff --git a/sys/net/if_ieee80211.h b/sys/net/if_ieee80211.h
deleted file mode 100644
index 7e5d04b..0000000
--- a/sys/net/if_ieee80211.h
+++ /dev/null
@@ -1,614 +0,0 @@
-/* $NetBSD: if_ieee80211.h,v 1.23 2002/10/15 08:51:50 onoe Exp $ */
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _NET_IF_IEEE80211_H_
-#define _NET_IF_IEEE80211_H_
-
-#include <net/ethernet.h>
-#include <net/if_arp.h>
-
-#define IEEE80211_ADDR_LEN ETHER_ADDR_LEN
-
-/*
- * generic definitions for IEEE 802.11 frames
- */
-struct ieee80211_frame {
- u_int8_t i_fc[2];
- u_int8_t i_dur[2];
- u_int8_t i_addr1[IEEE80211_ADDR_LEN];
- u_int8_t i_addr2[IEEE80211_ADDR_LEN];
- u_int8_t i_addr3[IEEE80211_ADDR_LEN];
- u_int8_t i_seq[2];
- /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
- /* see below */
-} __attribute__((__packed__));
-
-struct ieee80211_frame_addr4 {
- u_int8_t i_fc[2];
- u_int8_t i_dur[2];
- u_int8_t i_addr1[IEEE80211_ADDR_LEN];
- u_int8_t i_addr2[IEEE80211_ADDR_LEN];
- u_int8_t i_addr3[IEEE80211_ADDR_LEN];
- u_int8_t i_seq[2];
- u_int8_t i_addr4[IEEE80211_ADDR_LEN];
-} __attribute__((__packed__));
-
-#define IEEE80211_FC0_VERSION_MASK 0x03
-#define IEEE80211_FC0_VERSION_SHIFT 0
-#define IEEE80211_FC0_VERSION_0 0x00
-#define IEEE80211_FC0_TYPE_MASK 0x0c
-#define IEEE80211_FC0_TYPE_SHIFT 2
-#define IEEE80211_FC0_TYPE_MGT 0x00
-#define IEEE80211_FC0_TYPE_CTL 0x04
-#define IEEE80211_FC0_TYPE_DATA 0x08
-
-#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
-#define IEEE80211_FC0_SUBTYPE_SHIFT 4
-/* for TYPE_MGT */
-#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
-#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
-#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
-#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
-#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
-#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
-#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
-#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
-#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
-#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
-#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
-/* for TYPE_CTL */
-#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
-#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
-#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
-#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
-#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
-#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
-/* for TYPE_DATA (bit combination) */
-#define IEEE80211_FC0_SUBTYPE_DATA 0x00
-#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
-#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
-#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
-#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
-#define IEEE80211_FC0_SUBTYPE_CFACK 0x50
-#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60
-#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
-
-#define IEEE80211_FC1_DIR_MASK 0x03
-#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
-#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
-#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
-#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
-
-#define IEEE80211_FC1_MORE_FRAG 0x04
-#define IEEE80211_FC1_RETRY 0x08
-#define IEEE80211_FC1_PWR_MGT 0x10
-#define IEEE80211_FC1_MORE_DATA 0x20
-#define IEEE80211_FC1_WEP 0x40
-#define IEEE80211_FC1_ORDER 0x80
-
-#define IEEE80211_SEQ_FRAG_MASK 0x000f
-#define IEEE80211_SEQ_FRAG_SHIFT 0
-#define IEEE80211_SEQ_SEQ_MASK 0xfff0
-#define IEEE80211_SEQ_SEQ_SHIFT 4
-
-#define IEEE80211_NWID_LEN 32
-
-/*
- * BEACON management packets
- *
- * octet timestamp[8]
- * octet beacon interval[2]
- * octet capability information[2]
- * information element
- * octet elemid
- * octet length
- * octet information[length]
- */
-
-typedef uint8_t *ieee80211_mgt_beacon_t;
-
-#define IEEE80211_BEACON_INTERVAL(beacon) \
- ((beacon)[8] | ((beacon)[9] << 8))
-#define IEEE80211_BEACON_CAPABILITY(beacon) \
- ((beacon)[10] | ((beacon)[11] << 8))
-
-#define IEEE80211_CAPINFO_ESS 0x0001
-#define IEEE80211_CAPINFO_IBSS 0x0002
-#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004
-#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008
-#define IEEE80211_CAPINFO_PRIVACY 0x0010
-#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020
-#define IEEE80211_CAPINFO_PBCC 0x0040
-#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080
-
-#define IEEE80211_RATE_BASIC 0x80
-#define IEEE80211_RATE_VAL 0x7f
-
-/*
- * Management information elements
- */
-
-struct ieee80211_information {
- char ssid[IEEE80211_NWID_LEN+1];
- struct rates {
- u_int8_t *p;
- } rates;
- struct fh {
- u_int16_t dwell;
- u_int8_t set;
- u_int8_t pattern;
- u_int8_t index;
- } fh;
- struct ds {
- u_int8_t channel;
- } ds;
- struct cf {
- u_int8_t count;
- u_int8_t period;
- u_int8_t maxdur[2];
- u_int8_t dur[2];
- } cf;
- struct tim {
- u_int8_t count;
- u_int8_t period;
- u_int8_t bitctl;
- /* u_int8_t pvt[251]; The driver needs to use this. */
- } tim;
- struct ibss {
- u_int16_t atim;
- } ibss;
- struct challenge {
- u_int8_t *p;
- u_int8_t len;
- } challenge;
-};
-
-#define IEEE80211_ELEMID_SSID 0
-#define IEEE80211_ELEMID_RATES 1
-#define IEEE80211_ELEMID_FHPARMS 2
-#define IEEE80211_ELEMID_DSPARMS 3
-#define IEEE80211_ELEMID_CFPARMS 4
-#define IEEE80211_ELEMID_TIM 5
-#define IEEE80211_ELEMID_IBSSPARMS 6
-#define IEEE80211_ELEMID_CHALLENGE 16
-
-/*
- * AUTH management packets
- *
- * octet algo[2]
- * octet seq[2]
- * octet status[2]
- * octet chal.id
- * octet chal.length
- * octet chal.text[253]
- */
-
-typedef u_int8_t *ieee80211_mgt_auth_t;
-
-#define IEEE80211_AUTH_ALGORITHM(auth) \
- ((auth)[0] | ((auth)[1] << 8))
-#define IEEE80211_AUTH_TRANSACTION(auth) \
- ((auth)[2] | ((auth)[3] << 8))
-#define IEEE80211_AUTH_STATUS(auth) \
- ((auth)[4] | ((auth)[5] << 8))
-
-#define IEEE80211_AUTH_ALG_OPEN 0x0000
-#define IEEE80211_AUTH_ALG_SHARED 0x0001
-
-#define IEEE80211_AUTH_OPEN_REQUEST 1
-#define IEEE80211_AUTH_OPEN_RESPONSE 2
-
-#define IEEE80211_AUTH_SHARED_REQUEST 1
-#define IEEE80211_AUTH_SHARED_CHALLENGE 2
-#define IEEE80211_AUTH_SHARED_RESPONSE 3
-#define IEEE80211_AUTH_SHARED_PASS 4
-
-/*
- * Reason codes
- *
- * Unlisted codes are reserved
- */
-
-#define IEEE80211_REASON_UNSPECIFIED 1
-#define IEEE80211_REASON_AUTH_EXPIRE 2
-#define IEEE80211_REASON_AUTH_LEAVE 3
-#define IEEE80211_REASON_ASSOC_EXPIRE 4
-#define IEEE80211_REASON_ASSOC_TOOMANY 5
-#define IEEE80211_REASON_NOT_AUTHED 6
-#define IEEE80211_REASON_NOT_ASSOCED 7
-#define IEEE80211_REASON_ASSOC_LEAVE 8
-#define IEEE80211_REASON_ASSOC_NOT_AUTHED 9
-
-#define IEEE80211_STATUS_SUCCESS 0
-#define IEEE80211_STATUS_UNSPECIFIED 1
-#define IEEE80211_STATUS_CAPINFO 10
-#define IEEE80211_STATUS_NOT_ASSOCED 11
-#define IEEE80211_STATUS_OTHER 12
-#define IEEE80211_STATUS_ALG 13
-#define IEEE80211_STATUS_SEQUENCE 14
-#define IEEE80211_STATUS_CHALLENGE 15
-#define IEEE80211_STATUS_TIMEOUT 16
-#define IEEE80211_STATUS_TOOMANY 17
-#define IEEE80211_STATUS_BASIC_RATE 18
-#define IEEE80211_STATUS_SP_REQUIRED 19
-#define IEEE80211_STATUS_PBCC_REQUIRED 20
-#define IEEE80211_STATUS_CA_REQUIRED 21
-#define IEEE80211_STATUS_TOO_MANY_STATIONS 22
-#define IEEE80211_STATUS_RATES 23
-
-#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
-#define IEEE80211_WEP_IVLEN 3 /* 24bit */
-#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
-#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
-#define IEEE80211_WEP_NKID 4 /* number of key ids */
-
-#define IEEE80211_CRC_LEN 4
-
-#define IEEE80211_MTU 1500
-#define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \
- (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
-
-/*
- * ioctls
- */
-
-/* nwid is pointed at by ifr.ifr_data */
-struct ieee80211_nwid {
- u_int8_t i_len;
- u_int8_t i_nwid[IEEE80211_NWID_LEN];
-};
-
-#define SIOCS80211NWID _IOWR('i', 230, struct ifreq)
-#define SIOCG80211NWID _IOWR('i', 231, struct ifreq)
-
-/* the first member must be matched with struct ifreq */
-struct ieee80211_nwkey {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- int i_wepon; /* wep enabled flag */
- int i_defkid; /* default encrypt key id */
- struct {
- int i_keylen;
- u_int8_t *i_keydat;
- } i_key[IEEE80211_WEP_NKID];
-};
-#define SIOCS80211NWKEY _IOW('i', 232, struct ieee80211_nwkey)
-#define SIOCG80211NWKEY _IOWR('i', 233, struct ieee80211_nwkey)
-/* i_wepon */
-#define IEEE80211_NWKEY_OPEN 0 /* No privacy */
-#define IEEE80211_NWKEY_WEP 1 /* WEP enabled */
-#define IEEE80211_NWKEY_EAP 2 /* EAP enabled */
-#define IEEE80211_NWKEY_PERSIST 0x100 /* designate persist keyset */
-
-/* power management parameters */
-struct ieee80211_power {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- int i_enabled; /* 1 == on, 0 == off */
- int i_maxsleep; /* max sleep in ms */
-};
-#ifdef __NetBSD__
-#define SIOCS80211POWER _IOW('i', 234, struct ieee80211_power)
-#define SIOCG80211POWER _IOWR('i', 235, struct ieee80211_power)
-#else
-#define SIOCS80211POWER _IOW('i', 242, struct ieee80211_power)
-#define SIOCG80211POWER _IOWR('i', 243, struct ieee80211_power)
-#endif
-
-struct ieee80211_auth {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- int i_authtype;
-};
-
-#define IEEE80211_AUTH_NONE 0
-#define IEEE80211_AUTH_OPEN 1
-#define IEEE80211_AUTH_SHARED 2
-
-#define SIOCS80211AUTH _IOW('i', 236, struct ieee80211_auth)
-#define SIOCG80211AUTH _IOWR('i', 237, struct ieee80211_auth)
-
-struct ieee80211_channel {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- u_int16_t i_channel;
-};
-
-#define IEEE80211_CHAN_ANY 0xffff
-
-#define SIOCS80211CHANNEL _IOW('i', 238, struct ieee80211_channel)
-#define SIOCG80211CHANNEL _IOWR('i', 239, struct ieee80211_channel)
-
-struct ieee80211_bssid {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- u_int8_t i_bssid[IEEE80211_ADDR_LEN];
-};
-
-#define SIOCS80211BSSID _IOW('i', 240, struct ieee80211_bssid)
-#define SIOCG80211BSSID _IOWR('i', 241, struct ieee80211_bssid)
-
-/*
- * FreeBSD-style ioctls.
- */
-/* the first member must be matched with struct ifreq */
-struct ieee80211req {
- char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
- u_int16_t i_type; /* req type */
- int16_t i_val; /* Index or simple value */
- int16_t i_len; /* Index or simple value */
- void *i_data; /* Extra data */
-};
-#ifdef __FreeBSD__
-#define SIOCS80211 _IOW('i', 234, struct ieee80211req)
-#define SIOCG80211 _IOWR('i', 235, struct ieee80211req)
-#else
-#define SIOCS80211 _IOW('i', 242, struct ieee80211req)
-#define SIOCG80211 _IOWR('i', 243, struct ieee80211req)
-#endif
-
-#define IEEE80211_IOC_SSID 1
-#define IEEE80211_IOC_NUMSSIDS 2
-#define IEEE80211_IOC_WEP 3
-#define IEEE80211_WEP_NOSUP -1
-#define IEEE80211_WEP_OFF 0
-#define IEEE80211_WEP_ON 1
-#define IEEE80211_WEP_MIXED 2
-#define IEEE80211_IOC_WEPKEY 4
-#define IEEE80211_IOC_NUMWEPKEYS 5
-#define IEEE80211_IOC_WEPTXKEY 6
-#define IEEE80211_IOC_AUTHMODE 7
-#define IEEE80211_IOC_STATIONNAME 8
-#define IEEE80211_IOC_CHANNEL 9
-#define IEEE80211_IOC_POWERSAVE 10
-#define IEEE80211_POWERSAVE_NOSUP -1
-#define IEEE80211_POWERSAVE_OFF 0
-#define IEEE80211_POWERSAVE_CAM 1
-#define IEEE80211_POWERSAVE_PSP 2
-#define IEEE80211_POWERSAVE_PSP_CAM 3
-#define IEEE80211_POWERSAVE_ON IEEE80211_POWERSAVE_CAM
-#define IEEE80211_IOC_POWERSAVESLEEP 11
-
-#ifdef _KERNEL
-
-#define IEEE80211_ASCAN_WAIT 2 /* active scan wait */
-#define IEEE80211_PSCAN_WAIT 5 /* passive scan wait */
-#define IEEE80211_TRANS_WAIT 5 /* transition wait */
-#define IEEE80211_INACT_WAIT 5 /* inactivity timer interval */
-#define IEEE80211_INACT_MAX (300/IEEE80211_INACT_WAIT)
-
-/*
- * Structure for IEEE 802.11 drivers.
- */
-
-#define IEEE80211_CHAN_MAX 255
-#define IEEE80211_RATE_SIZE 12
-#define IEEE80211_KEYBUF_SIZE 16
-#define IEEE80211_NODE_HASHSIZE 32
-/* simple hash is enough for variation of macaddr */
-#define IEEE80211_NODE_HASH(addr) \
- (((u_int8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % IEEE80211_NODE_HASHSIZE)
-
-enum ieee80211_phytype {
- IEEE80211_T_DS, /* direct sequence spread spectrum */
- IEEE80211_T_FH, /* frequency hopping */
- IEEE80211_T_OFDM, /* frequency division multiplexing */
- IEEE80211_T_HRDS /* high rate DS */
-};
-
-enum ieee80211_opmode {
- IEEE80211_M_STA = 1, /* infrastructure station */
- IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
- IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
- IEEE80211_M_HOSTAP = 6 /* Software Access Point */
-};
-
-enum ieee80211_state {
- IEEE80211_S_INIT, /* default state */
- IEEE80211_S_SCAN, /* scanning */
- IEEE80211_S_AUTH, /* try to authenticate */
- IEEE80211_S_ASSOC, /* try to assoc */
- IEEE80211_S_RUN /* associated */
-};
-
-/*
- * Node specific information.
- */
-struct ieee80211_node {
- TAILQ_ENTRY(ieee80211_node) ni_list;
- LIST_ENTRY(ieee80211_node) ni_hash;
-
- /* hardware */
- u_int8_t ni_rssi;
- u_int32_t ni_rstamp;
-
- /* header */
- u_int8_t ni_macaddr[IEEE80211_ADDR_LEN];
- u_int8_t ni_bssid[IEEE80211_ADDR_LEN];
-
- /* beacon, probe response */
- u_int8_t ni_tstamp[8];
- u_int16_t ni_intval;
- u_int16_t ni_capinfo;
- u_int8_t ni_esslen;
- u_int8_t ni_essid[IEEE80211_NWID_LEN];
- int ni_nrate;
- u_int8_t ni_rates[IEEE80211_RATE_SIZE];
- u_int8_t ni_chan;
- u_int16_t ni_fhdwell; /* FH only */
- u_int8_t ni_fhindex; /* FH only */
-
- /* DTIM and contention free period (CFP) */
- u_int8_t ni_dtimperiod;
- u_int8_t ni_cfpperiod; /* # of DTIMs between CFPs */
- u_int16_t ni_cfpmaxduration;/* max CFP duration in TU */
- u_int16_t ni_cfpduremain; /* remaining duration */
- u_int16_t ni_timoffset;
-
- /* others */
- u_int16_t ni_associd; /* assoc response */
- u_int16_t ni_txseq; /* seq to be transmitted */
- u_int16_t ni_rxseq; /* seq previous received */
- int ni_fails; /* failure count to associate */
- int ni_inact; /* inactivity mark count */
- int ni_txrate; /* index to ni_rates[] */
- void *ni_private; /* driver private */
-};
-
-/* ni_chan encoding for FH phy */
-#define IEEE80211_FH_CHANMOD 80
-#define IEEE80211_FH_CHAN(set,pat) (((set)-1)*IEEE80211_FH_CHANMOD+(pat))
-#define IEEE80211_FH_CHANSET(chan) ((chan)/IEEE80211_FH_CHANMOD+1)
-#define IEEE80211_FH_CHANPAT(chan) ((chan)%IEEE80211_FH_CHANMOD)
-
-struct ieee80211_wepkey {
- int wk_len;
- u_int8_t wk_key[IEEE80211_KEYBUF_SIZE];
-};
-
-struct ieee80211com {
-#ifdef __NetBSD__
- struct ethercom ic_ec;
-#endif
-#ifdef __FreeBSD__
- struct arpcom ic_ac;
- struct mtx ic_mtx;
-#endif
- void (*ic_recv_mgmt[16])(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
- int (*ic_send_mgmt[16])(struct ieee80211com *,
- struct ieee80211_node *, int, int);
- int (*ic_newstate)(void *, enum ieee80211_state);
- int (*ic_chancheck)(void *, u_char *);
- u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
- u_int8_t ic_sup_rates[IEEE80211_RATE_SIZE];
- u_char ic_chan_avail[roundup(IEEE80211_CHAN_MAX,NBBY)];
- u_char ic_chan_active[roundup(IEEE80211_CHAN_MAX, NBBY)];
- struct ifqueue ic_mgtq;
- int ic_flags;
- enum ieee80211_phytype ic_phytype;
- enum ieee80211_opmode ic_opmode;
- enum ieee80211_state ic_state;
- struct bpf_if *ic_rawbpf; /* packet filter structure */
- struct ieee80211_node ic_bss; /* information for this node */
- int ic_node_privlen;/* size for ni_private */
- void (*ic_node_free)(struct ieee80211com *,
- struct ieee80211_node *); /* callback */
- u_int8_t ic_ibss_chan;
- int ic_fixed_rate; /* index to ic_sup_rates[] */
- TAILQ_HEAD(, ieee80211_node) ic_node; /* information of all nodes */
- LIST_HEAD(, ieee80211_node) ic_hash[IEEE80211_NODE_HASHSIZE];
- u_int16_t ic_lintval; /* listen interval */
- int ic_mgt_timer; /* mgmt timeout */
- int ic_scan_timer; /* scant wait */
- int ic_inact_timer; /* inactivity timer wait */
- int ic_des_esslen;
- u_int8_t ic_des_essid[IEEE80211_NWID_LEN];
- int ic_des_chan; /* desired channel */
- u_int8_t ic_des_bssid[IEEE80211_ADDR_LEN];
- struct ieee80211_wepkey ic_nw_keys[IEEE80211_WEP_NKID];
- int ic_wep_txkey; /* default tx key index */
- void *ic_wep_ctx; /* wep crypt context */
- u_int32_t ic_iv; /* initial vector for wep */
-};
-#ifdef __NetBSD__
-#define ic_if ic_ec.ec_if
-#define IEEE80211_LOCK(_ic) do { s = splnet(); } while (0)
-#define IEEE80211_UNLOCK(_ic) splx(s)
-#endif
-#ifdef __FreeBSD__
-#define ic_if ic_ac.ac_if
-#define IEEE80211_LOCK(_ic) mtx_lock(&(_ic)->ic_mtx)
-#define IEEE80211_UNLOCK(_ic) mtx_unlock(&(_ic)->ic_mtx)
-#endif
-#define ic_softc ic_if.if_softc
-
-#define IEEE80211_SEND_MGMT(ic,ni,type,arg) do { \
- if ((ic)->ic_send_mgmt[(type)>>IEEE80211_FC0_SUBTYPE_SHIFT] != NULL) \
- (*(ic)->ic_send_mgmt[(type)>>IEEE80211_FC0_SUBTYPE_SHIFT]) \
- (ic,ni,type,arg); \
-} while (0)
-
-#define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
-#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN)
-
-#define IEEE80211_IS_MULTICAST(a) ETHER_IS_MULTICAST(a)
-
-/* ic_flags */
-#define IEEE80211_F_ASCAN 0x00000001 /* STATUS: active scan */
-#define IEEE80211_F_SIBSS 0x00000002 /* STATUS: start IBSS */
-#define IEEE80211_F_WEPON 0x00000100 /* CONF: WEP enabled */
-#define IEEE80211_F_IBSSON 0x00000200 /* CONF: IBSS creation enable */
-#define IEEE80211_F_PMGTON 0x00000400 /* CONF: Power mgmt enable */
-#define IEEE80211_F_DESBSSID 0x00000800 /* CONF: des_bssid is set */
-#define IEEE80211_F_SCANAP 0x00001000 /* CONF: Scanning AP */
-#define IEEE80211_F_HASWEP 0x00010000 /* CAPABILITY: WEP available */
-#define IEEE80211_F_HASIBSS 0x00020000 /* CAPABILITY: IBSS available */
-#define IEEE80211_F_HASPMGT 0x00040000 /* CAPABILITY: Power mgmt */
-#define IEEE80211_F_HASHOSTAP 0x00080000 /* CAPABILITY: HOSTAP avail */
-#define IEEE80211_F_HASAHDEMO 0x00100000 /* CAPABILITY: Old Adhoc Demo */
-
-/* flags for ieee80211_fix_rate() */
-#define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */
-#define IEEE80211_F_DOFRATE 0x00000002 /* use fixed rate */
-#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
-#define IEEE80211_F_DODEL 0x00000008 /* delete ignore rate */
-
-void ieee80211_ifattach(struct ifnet *);
-void ieee80211_ifdetach(struct ifnet *);
-void ieee80211_input(struct ifnet *, struct mbuf *, int, u_int32_t);
-int ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *,
- struct mbuf *, int);
-struct mbuf *ieee80211_encap(struct ifnet *, struct mbuf *);
-struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *);
-int ieee80211_ioctl(struct ifnet *, u_long, caddr_t);
-void ieee80211_print_essid(u_int8_t *, int);
-void ieee80211_dump_pkt(u_int8_t *, int, int, int);
-void ieee80211_watchdog(struct ifnet *);
-void ieee80211_next_scan(struct ifnet *);
-void ieee80211_end_scan(struct ifnet *);
-struct ieee80211_node *ieee80211_alloc_node(struct ieee80211com *, u_int8_t *,
- int);
-struct ieee80211_node *ieee80211_find_node(struct ieee80211com *, u_int8_t *);
-void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *);
-void ieee80211_free_allnodes(struct ieee80211com *);
-int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int);
-int ieee80211_new_state(struct ifnet *, enum ieee80211_state, int);
-struct mbuf *ieee80211_wep_crypt(struct ifnet *, struct mbuf *, int);
-int ieee80211_rate2media(int, enum ieee80211_phytype);
-int ieee80211_media2rate(int, enum ieee80211_phytype);
-
-int ieee80211_cfgget(struct ifnet *, u_long, caddr_t);
-int ieee80211_cfgset(struct ifnet *, u_long, caddr_t);
-
-#endif /* _KERNEL */
-
-#endif /* _NET_IF_IEEE80211_H_ */
diff --git a/sys/net/if_ieee80211subr.c b/sys/net/if_ieee80211subr.c
deleted file mode 100644
index 9f2ec0a..0000000
--- a/sys/net/if_ieee80211subr.c
+++ /dev/null
@@ -1,3413 +0,0 @@
-/* $NetBSD: if_ieee80211subr.c,v 1.22 2002/10/16 11:29:30 onoe Exp $ */
-/* $FreeBSD$ */
-
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Atsushi Onoe.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * IEEE 802.11 generic handler
- */
-
-#include <sys/cdefs.h>
-
-#include "opt_inet.h"
-#define NBPFILTER 1
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/endian.h>
-#include <sys/errno.h>
-#include <sys/bus.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-
-#include <crypto/rc4/rc4.h>
-#define arc4_ctxlen() sizeof (struct rc4_state)
-#define arc4_setkey(_c,_k,_l) rc4_init(_c,_k,_l)
-#define arc4_encrypt(_c,_d,_s,_l) rc4_crypt(_c,_s,_d,_l)
-
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/ethernet.h>
-#include <net/if_llc.h>
-#include <net/if_ieee80211.h>
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#endif
-
-#include <dev/wi/if_wavelan_ieee.h>
-
-#define IEEE80211_DEBUG
-#ifdef IEEE80211_DEBUG
-int ieee80211_debug = 0;
-#define DPRINTF(X) if (ieee80211_debug) printf X
-#define DPRINTF2(X) if (ieee80211_debug>1) printf X
-
-SYSCTL_INT(_debug, OID_AUTO, ieee80211, CTLFLAG_RW, &ieee80211_debug,
- 0, "IEEE 802.11 media debugging printfs");
-#else
-#define DPRINTF(X)
-#define DPRINTF2(X)
-#endif
-
-/* XXX belongs elsewhere */
-#ifndef ALIGNED_POINTER
-/*
- * ALIGNED_POINTER is a boolean macro that checks whether an address
- * is valid to fetch data elements of type t from on this architecture.
- * This does not reflect the optimal alignment, just the possibility
- * (within reasonable limits).
- *
- */
-#define ALIGNED_POINTER(p,t) 1
-#endif
-
-static int ieee80211_send_prreq(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_prresp(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_auth(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_deauth(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_asreq(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_asresp(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-static int ieee80211_send_disassoc(struct ieee80211com *,
- struct ieee80211_node *, int, int);
-
-static void ieee80211_recv_beacon(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_prreq(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_auth(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_asreq(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_asresp(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_disassoc(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-static void ieee80211_recv_deauth(struct ieee80211com *,
- struct mbuf *, int, u_int32_t);
-
-static void ieee80211_crc_init(void);
-static u_int32_t ieee80211_crc_update(u_int32_t, u_int8_t *, int);
-
-static const char *ieee80211_mgt_subtype_name[] = {
- "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
- "probe_req", "probe_resp", "reserved#6", "reserved#7",
- "beacon", "atim", "disassoc", "auth",
- "deauth", "reserved#13", "reserved#14", "reserved#15"
-};
-
-void
-ieee80211_ifattach(struct ifnet *ifp)
-{
- struct ieee80211com *ic = (void *)ifp;
- int i, rate;
-
- /* XXX need unit */
- mtx_init(&ic->ic_mtx, ifp->if_name, "802.11 link layer", MTX_DEF);
-
- ether_ifattach(ifp, ic->ic_myaddr);
-#if NBPFILTER > 0
- bpfattach2(ifp, DLT_IEEE802_11,
- sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
-#endif
- ieee80211_crc_init();
- ic->ic_iv = arc4random();
- memcpy(ic->ic_chan_active, ic->ic_chan_avail,
- sizeof(ic->ic_chan_active));
- if (isclr(ic->ic_chan_active, ic->ic_ibss_chan)) {
- for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
- if (isset(ic->ic_chan_active, i)) {
- ic->ic_ibss_chan = i;
- break;
- }
- }
- }
- ic->ic_des_chan = IEEE80211_CHAN_ANY;
- ic->ic_fixed_rate = -1;
- if (ic->ic_lintval == 0)
- ic->ic_lintval = 100; /* default sleep */
- TAILQ_INIT(&ic->ic_node);
- mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_name, "mgmt send q", MTX_DEF);
-
- rate = 0;
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (ic->ic_sup_rates[i] != 0)
- rate = (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2;
- }
- if (rate)
- ifp->if_baudrate = IF_Mbps(rate);
- ifp->if_hdrlen = sizeof(struct ieee80211_frame);
-
- /* initialize management frame handler */
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_BEACON
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_prreq;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_auth;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_deauth;
- ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_disassoc;
-
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prreq;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prresp;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_auth;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_deauth;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
- ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
- >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_disassoc;
-}
-
-void
-ieee80211_ifdetach(struct ifnet *ifp)
-{
- struct ieee80211com *ic = (void *)ifp;
-
- IEEE80211_LOCK(ic);
- IF_DRAIN(&ic->ic_mgtq);
- mtx_destroy(&ic->ic_mgtq.ifq_mtx);
- if (ic->ic_wep_ctx != NULL) {
- free(ic->ic_wep_ctx, M_DEVBUF);
- ic->ic_wep_ctx = NULL;
- }
- ieee80211_free_allnodes(ic);
-#if NBPFILTER > 0
- bpfdetach(ifp);
-#endif
- ether_ifdetach(ifp);
- IEEE80211_UNLOCK(ic);
- mtx_destroy(&ic->ic_mtx);
-}
-
-void
-ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ieee80211_node *ni = NULL;
- struct ieee80211_frame *wh;
- struct ether_header *eh;
- void (*rh)(struct ieee80211com *, struct mbuf *, int, u_int);
- struct mbuf *m1;
- int len;
- u_int8_t dir, subtype;
- u_int8_t *bssid;
- u_int16_t rxseq;
-
- /* trim CRC here for WEP can find its own CRC at the end of packet. */
- if (m->m_flags & M_HASFCS) {
- m_adj(m, -IEEE80211_CRC_LEN);
- m->m_flags &= ~M_HASFCS;
- }
-
- wh = mtod(m, struct ieee80211_frame *);
- if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
- IEEE80211_FC0_VERSION_0) {
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "receive packet with wrong version: %x\n",
- wh->i_fc[0]);
- goto err;
- }
-
- dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
-
- if (ic->ic_state != IEEE80211_S_SCAN) {
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- ni = &ic->ic_bss;
- if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
- DPRINTF2(("ieee80211_input: other bss %s\n",
- ether_sprintf(wh->i_addr2)));
- /* not interested in */
- goto out;
- }
- break;
- case IEEE80211_M_IBSS:
- case IEEE80211_M_AHDEMO:
- case IEEE80211_M_HOSTAP:
- if (dir == IEEE80211_FC1_DIR_NODS)
- bssid = wh->i_addr3;
- else
- bssid = wh->i_addr1;
- if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss.ni_bssid) &&
- !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
- /* not interested in */
- DPRINTF2(("ieee80211_input: other bss %s\n",
- ether_sprintf(wh->i_addr3)));
- goto out;
- }
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni == NULL) {
- DPRINTF2(("ieee80211_input: unknown src %s\n",
- ether_sprintf(wh->i_addr2)));
- ni = &ic->ic_bss; /* XXX allocate? */
- }
- break;
- }
- ni->ni_rssi = rssi;
- ni->ni_rstamp = rstamp;
- rxseq = ni->ni_rxseq;
- ni->ni_rxseq =
- le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
- /* TODO: fragment */
- if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
- rxseq == ni->ni_rxseq) {
- /* duplicate, silently discarded */
- goto out;
- }
- ni->ni_inact = 0;
- }
-
- switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
- case IEEE80211_FC0_TYPE_DATA:
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- if (dir != IEEE80211_FC1_DIR_FROMDS)
- goto out;
- if ((ifp->if_flags & IFF_SIMPLEX) &&
- IEEE80211_IS_MULTICAST(wh->i_addr1) &&
- IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
- /*
- * In IEEE802.11 network, multicast packet
- * sent from me is broadcasted from AP.
- * It should be silently discarded for
- * SIMPLEX interface.
- */
- goto out;
- }
- break;
- case IEEE80211_M_IBSS:
- case IEEE80211_M_AHDEMO:
- if (dir != IEEE80211_FC1_DIR_NODS)
- goto out;
- break;
- case IEEE80211_M_HOSTAP:
- if (dir != IEEE80211_FC1_DIR_TODS)
- goto out;
- /* check if source STA is associated */
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni == NULL) {
- DPRINTF(("ieee80211_input: "
- "data from unknown src %s\n",
- ether_sprintf(wh->i_addr2)));
- if ((ni = ieee80211_alloc_node(ic, wh->i_addr2,
- 1)) != NULL) {
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_NOT_AUTHED);
- ieee80211_free_node(ic, ni);
- }
- goto err;
- }
- if (ni->ni_associd == 0) {
- DPRINTF(("ieee80211_input: "
- "data from unassoc src %s\n",
- ether_sprintf(wh->i_addr2)));
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DISASSOC,
- IEEE80211_REASON_NOT_ASSOCED);
- goto err;
- }
- break;
- }
- if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- m = ieee80211_wep_crypt(ifp, m, 0);
- if (m == NULL)
- goto err;
- wh = mtod(m, struct ieee80211_frame *);
- } else
- goto out;
- }
- /* copy to listener after decrypt */
-#if NBPFILTER > 0
- if (ic->ic_rawbpf)
- bpf_mtap(ic->ic_rawbpf, m);
-#endif
- m = ieee80211_decap(ifp, m);
- if (m == NULL)
- goto err;
- ifp->if_ipackets++;
-
- /* perform as a bridge within the AP */
- m1 = NULL;
- if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
- eh = mtod(m, struct ether_header *);
- if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
- m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
- if (m1 == NULL)
- ifp->if_oerrors++;
- else
- m1->m_flags |= M_MCAST;
- } else {
- ni = ieee80211_find_node(ic, eh->ether_dhost);
- if (ni != NULL && ni->ni_associd != 0) {
- m1 = m;
- m = NULL;
- }
- }
- if (m1 != NULL) {
-#ifdef ALTQ
- if (ALTQ_IS_ENABLED(&ifp->if_snd))
- altq_etherclassify(&ifp->if_snd, m1,
- &pktattr);
-#endif
- len = m1->m_pkthdr.len;
- IF_ENQUEUE(&ifp->if_snd, m1);
- if (m != NULL)
- ifp->if_omcasts++;
- ifp->if_obytes += len;
- }
- }
- if (m != NULL)
- (*ifp->if_input)(ifp, m);
- return;
-
- case IEEE80211_FC0_TYPE_MGT:
- if (dir != IEEE80211_FC1_DIR_NODS)
- goto err;
- if (ic->ic_opmode == IEEE80211_M_AHDEMO)
- goto out;
- subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
-
- /* drop frames without interest */
- if (ic->ic_state == IEEE80211_S_SCAN) {
- if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
- subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- goto out;
- } else {
- if (ic->ic_opmode != IEEE80211_M_IBSS &&
- subtype == IEEE80211_FC0_SUBTYPE_BEACON)
- goto out;
- }
-
- if (ifp->if_flags & IFF_DEBUG) {
- /* avoid to print too many frames */
- int doprint = 0;
-
- switch (subtype) {
- case IEEE80211_FC0_SUBTYPE_BEACON:
- if (ic->ic_state == IEEE80211_S_SCAN)
- doprint = 1;
- break;
- case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
- if (ic->ic_opmode == IEEE80211_M_IBSS)
- doprint = 1;
- break;
- default:
- doprint = 1;
- break;
- }
-#ifdef IEEE80211_DEBUG
- doprint += ieee80211_debug;
-#endif
- if (doprint)
- if_printf(ifp, "received %s from %s rssi %d\n",
- ieee80211_mgt_subtype_name[subtype
- >> IEEE80211_FC0_SUBTYPE_SHIFT],
- ether_sprintf(wh->i_addr2), rssi);
- }
-#if NBPFILTER > 0
- if (ic->ic_rawbpf)
- bpf_mtap(ic->ic_rawbpf, m);
-#endif
- rh = ic->ic_recv_mgmt[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT];
- if (rh != NULL)
- (*rh)(ic, m, rssi, rstamp);
- m_freem(m);
- return;
-
- case IEEE80211_FC0_TYPE_CTL:
- default:
- DPRINTF(("ieee80211_input: bad type %x\n", wh->i_fc[0]));
- /* should not come here */
- break;
- }
- err:
- ifp->if_ierrors++;
- out:
- if (m != NULL) {
-#if NBPFILTER > 0
- if (ic->ic_rawbpf)
- bpf_mtap(ic->ic_rawbpf, m);
-#endif
- m_freem(m);
- }
-}
-
-int
-ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
- struct mbuf *m, int type)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ieee80211_frame *wh;
-
- if (ni == NULL)
- ni = &ic->ic_bss;
- ni->ni_inact = 0;
- M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
- if (m == NULL)
- return ENOMEM;
- wh = mtod(m, struct ieee80211_frame *);
- wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
- wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
- *(u_int16_t *)wh->i_dur = 0;
- *(u_int16_t *)wh->i_seq =
- htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
- ni->ni_txseq++;
- IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
- IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
-
- if (ifp->if_flags & IFF_DEBUG) {
- /* avoid to print too many frames */
- if (ic->ic_opmode == IEEE80211_M_IBSS ||
-#ifdef IEEE80211_DEBUG
- ieee80211_debug > 1 ||
-#endif
- (type & IEEE80211_FC0_SUBTYPE_MASK) !=
- IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- if_printf(ifp, "sending %s to %s\n",
- ieee80211_mgt_subtype_name[
- (type & IEEE80211_FC0_SUBTYPE_MASK)
- >> IEEE80211_FC0_SUBTYPE_SHIFT],
- ether_sprintf(ni->ni_macaddr));
- }
- IF_ENQUEUE(&ic->ic_mgtq, m);
- ifp->if_timer = 1;
- (*ifp->if_start)(ifp);
- return 0;
-}
-
-struct mbuf *
-ieee80211_encap(struct ifnet *ifp, struct mbuf *m)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ether_header eh;
- struct ieee80211_frame *wh;
- struct llc *llc;
- struct ieee80211_node *ni;
-
- if (m->m_len < sizeof(struct ether_header)) {
- m = m_pullup(m, sizeof(struct ether_header));
- if (m == NULL)
- return NULL;
- }
- memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
-
- if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) &&
- (ic->ic_opmode == IEEE80211_M_IBSS ||
- ic->ic_opmode == IEEE80211_M_HOSTAP)) {
- ni = ieee80211_find_node(ic, eh.ether_dhost);
- if (ni == NULL)
- ni = &ic->ic_bss; /*XXX*/
- } else
- ni = &ic->ic_bss;
- ni->ni_inact = 0;
-
- m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
- llc = mtod(m, struct llc *);
- llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
- llc->llc_control = LLC_UI;
- llc->llc_snap.org_code[0] = 0;
- llc->llc_snap.org_code[1] = 0;
- llc->llc_snap.org_code[2] = 0;
- llc->llc_snap.ether_type = eh.ether_type;
- M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
- if (m == NULL)
- return NULL;
- wh = mtod(m, struct ieee80211_frame *);
- wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
- *(u_int16_t *)wh->i_dur = 0;
- *(u_int16_t *)wh->i_seq =
- htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
- ni->ni_txseq++;
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
- IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
- IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
- break;
- case IEEE80211_M_IBSS:
- case IEEE80211_M_AHDEMO:
- wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
- IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
- IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
- break;
- case IEEE80211_M_HOSTAP:
- wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
- IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
- IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
- IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
- break;
- }
- return m;
-}
-
-struct mbuf *
-ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
-{
- struct ether_header *eh;
- struct ieee80211_frame wh;
- struct llc *llc;
-
- if (m->m_len < sizeof(wh) + sizeof(*llc)) {
- m = m_pullup(m, sizeof(wh) + sizeof(*llc));
- if (m == NULL)
- return NULL;
- }
- memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
- llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
- if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
- llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
- llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
- m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
- llc = NULL;
- } else {
- m_adj(m, sizeof(wh) - sizeof(*eh));
- }
- eh = mtod(m, struct ether_header *);
- switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
- case IEEE80211_FC1_DIR_NODS:
- IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
- IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
- break;
- case IEEE80211_FC1_DIR_TODS:
- IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
- IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
- break;
- case IEEE80211_FC1_DIR_FROMDS:
- IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
- IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
- break;
- case IEEE80211_FC1_DIR_DSTODS:
- /* not yet supported */
- DPRINTF(("ieee80211_decap: DS to DS\n"));
- m_freem(m);
- return NULL;
- }
- if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
- struct mbuf *n, *n0, **np;
- caddr_t newdata;
- int off, pktlen;
-
- n0 = NULL;
- np = &n0;
- off = 0;
- pktlen = m->m_pkthdr.len;
- while (pktlen > off) {
- if (n0 == NULL) {
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (n == NULL) {
- m_freem(m);
- return NULL;
- }
- M_MOVE_PKTHDR(n, m);
- n->m_len = MHLEN;
- } else {
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n == NULL) {
- m_freem(m);
- m_freem(n0);
- return NULL;
- }
- n->m_len = MLEN;
- }
- if (pktlen - off >= MINCLSIZE) {
- MCLGET(n, M_DONTWAIT);
- if (n->m_flags & M_EXT)
- n->m_len = n->m_ext.ext_size;
- }
- if (n0 == NULL) {
- newdata =
- (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
- sizeof(*eh);
- n->m_len -= newdata - n->m_data;
- n->m_data = newdata;
- }
- if (n->m_len > pktlen - off)
- n->m_len = pktlen - off;
- m_copydata(m, off, n->m_len, mtod(n, caddr_t));
- off += n->m_len;
- *np = n;
- np = &n->m_next;
- }
- m_freem(m);
- m = n0;
- }
- if (llc != NULL) {
- eh = mtod(m, struct ether_header *);
- eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
- }
- return m;
-}
-
-int
-ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- struct ieee80211com *ic = (void *)ifp;
- int error = 0;
- u_int kid, len;
- struct ieee80211req *ireq;
- u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE];
- char tmpssid[IEEE80211_NWID_LEN];
-
- switch (cmd) {
- case SIOCG80211:
- ireq = (struct ieee80211req *) data;
- switch (ireq->i_type) {
- case IEEE80211_IOC_SSID:
- switch (ic->ic_state) {
- case IEEE80211_S_INIT:
- case IEEE80211_S_SCAN:
- ireq->i_len = ic->ic_des_esslen;
- memcpy(tmpssid, ic->ic_des_essid, ireq->i_len);
- break;
- default:
- ireq->i_len = ic->ic_bss.ni_esslen;
- memcpy(tmpssid, ic->ic_bss.ni_essid,
- ireq->i_len);
- break;
- }
- error = copyout(tmpssid, ireq->i_data, ireq->i_len);
- break;
- case IEEE80211_IOC_NUMSSIDS:
- ireq->i_val = 1;
- break;
- case IEEE80211_IOC_WEP:
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0) {
- ireq->i_val = IEEE80211_WEP_NOSUP;
- } else {
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- ireq->i_val =
- IEEE80211_WEP_MIXED;
- } else {
- ireq->i_val =
- IEEE80211_WEP_OFF;
- }
- }
- break;
- case IEEE80211_IOC_WEPKEY:
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0) {
- error = EINVAL;
- break;
- }
- kid = (u_int) ireq->i_val;
- if (kid >= IEEE80211_WEP_NKID) {
- error = EINVAL;
- break;
- }
- len = (u_int) ic->ic_nw_keys[kid].wk_len;
- /* NB: only root can read WEP keys */
- if (suser(curthread)) {
- bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
- } else {
- bzero(tmpkey, len);
- }
- ireq->i_len = len;
- error = copyout(tmpkey, ireq->i_data, len);
- break;
- case IEEE80211_IOC_NUMWEPKEYS:
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0)
- error = EINVAL;
- else
- ireq->i_val = IEEE80211_WEP_NKID;
- break;
- case IEEE80211_IOC_WEPTXKEY:
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0)
- error = EINVAL;
- else
- ireq->i_val = ic->ic_wep_txkey;
- break;
- case IEEE80211_IOC_AUTHMODE:
- ireq->i_val = IEEE80211_AUTH_OPEN;
- break;
- case IEEE80211_IOC_CHANNEL:
- switch (ic->ic_state) {
- case IEEE80211_S_INIT:
- case IEEE80211_S_SCAN:
- if (ic->ic_opmode == IEEE80211_M_STA)
- ireq->i_val = ic->ic_des_chan;
- else
- ireq->i_val = ic->ic_ibss_chan;
- break;
- default:
- ireq->i_val = ic->ic_bss.ni_chan;
- break;
- }
- break;
- case IEEE80211_IOC_POWERSAVE:
- if (ic->ic_flags & IEEE80211_F_PMGTON)
- ireq->i_val = IEEE80211_POWERSAVE_ON;
- else
- ireq->i_val = IEEE80211_POWERSAVE_OFF;
- break;
- case IEEE80211_IOC_POWERSAVESLEEP:
- ireq->i_val = ic->ic_lintval;
- break;
- default:
- error = EINVAL;
- }
- break;
- case SIOCS80211:
- error = suser(curthread);
- if (error)
- break;
- ireq = (struct ieee80211req *) data;
- switch (ireq->i_type) {
- case IEEE80211_IOC_SSID:
- if (ireq->i_val != 0 ||
- ireq->i_len > IEEE80211_NWID_LEN) {
- error = EINVAL;
- break;
- }
- error = copyin(ireq->i_data, tmpssid, ireq->i_len);
- if (error)
- break;
- memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
- ic->ic_des_esslen = ireq->i_len;
- memcpy(ic->ic_des_essid, tmpssid, ireq->i_len);
- error = ENETRESET;
- break;
- case IEEE80211_IOC_WEP:
- /*
- * These cards only support one mode so
- * we just turn wep on what ever is
- * passed in if it's not OFF.
- */
- if (ireq->i_val == IEEE80211_WEP_OFF) {
- ic->ic_flags &= ~IEEE80211_F_WEPON;
- } else {
- ic->ic_flags |= IEEE80211_F_WEPON;
- }
- error = ENETRESET;
- break;
- case IEEE80211_IOC_WEPKEY:
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0) {
- error = EINVAL;
- break;
- }
- kid = (u_int) ireq->i_val;
- if (kid >= IEEE80211_WEP_NKID) {
- error = EINVAL;
- break;
- }
- if (ireq->i_len > sizeof(tmpkey)) {
- error = EINVAL;
- break;
- }
- memset(tmpkey, 0, sizeof(tmpkey));
- error = copyin(ireq->i_data, tmpkey, ireq->i_len);
- if (error)
- break;
- memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey,
- sizeof(tmpkey));
- ic->ic_nw_keys[kid].wk_len = ireq->i_len;
- error = ENETRESET;
- break;
- case IEEE80211_IOC_WEPTXKEY:
- kid = (u_int) ireq->i_val;
- if (kid >= IEEE80211_WEP_NKID) {
- error = EINVAL;
- break;
- }
- ic->ic_wep_txkey = kid;
- error = ENETRESET;
- break;
-#if 0
- case IEEE80211_IOC_AUTHMODE:
- sc->wi_authmode = ireq->i_val;
- break;
-#endif
- case IEEE80211_IOC_CHANNEL:
- /* XXX 0xffff overflows 16-bit signed */
- if (ireq->i_val == (int16_t) IEEE80211_CHAN_ANY)
- ic->ic_des_chan = IEEE80211_CHAN_ANY;
- else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX ||
- isclr(ic->ic_chan_active, ireq->i_val)) {
- error = EINVAL;
- break;
- } else
- ic->ic_ibss_chan = ic->ic_des_chan = ireq->i_val;
- switch (ic->ic_state) {
- case IEEE80211_S_INIT:
- case IEEE80211_S_SCAN:
- error = ENETRESET;
- break;
- default:
- if (ic->ic_opmode == IEEE80211_M_STA) {
- if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
- ic->ic_bss.ni_chan != ic->ic_des_chan)
- error = ENETRESET;
- } else {
- if (ic->ic_bss.ni_chan != ic->ic_ibss_chan)
- error = ENETRESET;
- }
- break;
- }
- break;
- case IEEE80211_IOC_POWERSAVE:
- switch (ireq->i_val) {
- case IEEE80211_POWERSAVE_OFF:
- if (ic->ic_flags & IEEE80211_F_PMGTON) {
- ic->ic_flags &= ~IEEE80211_F_PMGTON;
- error = ENETRESET;
- }
- break;
- case IEEE80211_POWERSAVE_ON:
- if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
- error = EINVAL;
- else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
- ic->ic_flags |= IEEE80211_F_PMGTON;
- error = ENETRESET;
- }
- break;
- default:
- error = EINVAL;
- break;
- }
- break;
- case IEEE80211_IOC_POWERSAVESLEEP:
- if (ireq->i_val < 0) {
- error = EINVAL;
- break;
- }
- ic->ic_lintval = ireq->i_val;
- error = ENETRESET;
- break;
- default:
- error = EINVAL;
- break;
- }
- break;
- case SIOCGIFGENERIC:
- error = ieee80211_cfgget(ifp, cmd, data);
- break;
- case SIOCSIFGENERIC:
- error = suser(curthread);
- if (error)
- break;
- error = ieee80211_cfgset(ifp, cmd, data);
- break;
- default:
- error = ether_ioctl(ifp, cmd, data);
- break;
- }
- return error;
-}
-
-void
-ieee80211_print_essid(u_int8_t *essid, int len)
-{
- int i;
- u_int8_t *p;
-
- if (len > IEEE80211_NWID_LEN)
- len = IEEE80211_NWID_LEN;
- /* determine printable or not */
- for (i = 0, p = essid; i < len; i++, p++) {
- if (*p < ' ' || *p > 0x7e)
- break;
- }
- if (i == len) {
- printf("\"");
- for (i = 0, p = essid; i < len; i++, p++)
- printf("%c", *p);
- printf("\"");
- } else {
- printf("0x");
- for (i = 0, p = essid; i < len; i++, p++)
- printf("%02x", *p);
- }
-}
-
-void
-ieee80211_dump_pkt(u_int8_t *buf, int len, int rate, int rssi)
-{
- struct ieee80211_frame *wh;
- int i;
-
- wh = (struct ieee80211_frame *)buf;
- switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
- case IEEE80211_FC1_DIR_NODS:
- printf("NODS %s", ether_sprintf(wh->i_addr2));
- printf("->%s", ether_sprintf(wh->i_addr1));
- printf("(%s)", ether_sprintf(wh->i_addr3));
- break;
- case IEEE80211_FC1_DIR_TODS:
- printf("TODS %s", ether_sprintf(wh->i_addr2));
- printf("->%s", ether_sprintf(wh->i_addr3));
- printf("(%s)", ether_sprintf(wh->i_addr1));
- break;
- case IEEE80211_FC1_DIR_FROMDS:
- printf("FRDS %s", ether_sprintf(wh->i_addr3));
- printf("->%s", ether_sprintf(wh->i_addr1));
- printf("(%s)", ether_sprintf(wh->i_addr2));
- break;
- case IEEE80211_FC1_DIR_DSTODS:
- printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
- printf("->%s", ether_sprintf(wh->i_addr3));
- printf("(%s", ether_sprintf(wh->i_addr2));
- printf("->%s)", ether_sprintf(wh->i_addr1));
- break;
- }
- switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
- case IEEE80211_FC0_TYPE_DATA:
- printf(" data");
- break;
- case IEEE80211_FC0_TYPE_MGT:
- printf(" %s", ieee80211_mgt_subtype_name[
- (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
- >> IEEE80211_FC0_SUBTYPE_SHIFT]);
- break;
- default:
- printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
- break;
- }
- if (wh->i_fc[1] & IEEE80211_FC1_WEP)
- printf(" WEP");
- if (rate >= 0)
- printf(" %dM", rate / 2);
- if (rssi >= 0)
- printf(" +%d", rssi);
- printf("\n");
- if (len > 0) {
- for (i = 0; i < len; i++) {
- if ((i & 1) == 0)
- printf(" ");
- printf("%02x", buf[i]);
- }
- printf("\n");
- }
-}
-
-void
-ieee80211_watchdog(struct ifnet *ifp)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ieee80211_node *ni, *nextbs;
-
- if (ic->ic_scan_timer) {
- if (--ic->ic_scan_timer == 0) {
- if (ic->ic_state == IEEE80211_S_SCAN)
- ieee80211_end_scan(ifp);
- }
- }
- if (ic->ic_mgt_timer) {
- if (--ic->ic_mgt_timer == 0)
- ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
- }
- if (ic->ic_inact_timer) {
- if (--ic->ic_inact_timer == 0) {
- for (ni = TAILQ_FIRST(&ic->ic_node); ni != NULL; ) {
- if (++ni->ni_inact <= IEEE80211_INACT_MAX) {
- ni = TAILQ_NEXT(ni, ni_list);
- continue;
- }
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s deauthenticate"
- " (reason %d)\n",
- ether_sprintf(ni->ni_macaddr),
- IEEE80211_REASON_AUTH_EXPIRE);
- nextbs = TAILQ_NEXT(ni, ni_list);
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_AUTH_EXPIRE);
- ieee80211_free_node(ic, ni);
- ni = nextbs;
- }
- if (!TAILQ_EMPTY(&ic->ic_node))
- ic->ic_inact_timer = IEEE80211_INACT_WAIT;
- }
- }
- if (ic->ic_scan_timer != 0 || ic->ic_mgt_timer != 0 ||
- ic->ic_inact_timer != 0)
- ifp->if_timer = 1;
-}
-
-void
-ieee80211_next_scan(struct ifnet *ifp)
-{
- struct ieee80211com *ic = (void *)ifp;
- int chan;
-
- chan = ic->ic_bss.ni_chan;
- for (;;) {
- chan = (chan + 1) % (IEEE80211_CHAN_MAX + 1);
- if (isset(ic->ic_chan_active, chan))
- break;
- if (chan == ic->ic_bss.ni_chan) {
- DPRINTF(("ieee80211_next_scan: no chan available\n"));
- return;
- }
- }
- DPRINTF(("ieee80211_next_scan: chan %d->%d\n",
- ic->ic_bss.ni_chan, chan));
- ic->ic_bss.ni_chan = chan;
- ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
-}
-
-void
-ieee80211_end_scan(struct ifnet *ifp)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ieee80211_node *ni, *nextbs, *selbs;
- void *p;
- u_int8_t rate;
- int i, fail;
-
- ni = TAILQ_FIRST(&ic->ic_node);
- if (ni == NULL) {
- DPRINTF(("ieee80211_end_scan: no scan candidate\n"));
- notfound:
- if (ic->ic_opmode == IEEE80211_M_IBSS &&
- (ic->ic_flags & IEEE80211_F_IBSSON) &&
- ic->ic_des_esslen != 0) {
- ni = &ic->ic_bss;
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "creating ibss\n");
- ic->ic_flags |= IEEE80211_F_SIBSS;
- ni->ni_nrate = 0;
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (ic->ic_sup_rates[i])
- ni->ni_rates[ni->ni_nrate++] =
- ic->ic_sup_rates[i];
- }
- IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
- IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
- ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */
- ni->ni_esslen = ic->ic_des_esslen;
- memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
- ni->ni_rssi = 0;
- ni->ni_rstamp = 0;
- memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
- ni->ni_intval = ic->ic_lintval;
- ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
- if (ic->ic_flags & IEEE80211_F_WEPON)
- ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
- ni->ni_chan = ic->ic_ibss_chan;
- if (ic->ic_phytype == IEEE80211_T_FH) {
- ni->ni_fhdwell = 200; /* XXX */
- ni->ni_fhindex = 1;
- }
- ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
- return;
- }
- if (ic->ic_flags & IEEE80211_F_ASCAN) {
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "entering passive scan mode\n");
- ic->ic_flags &= ~IEEE80211_F_ASCAN;
- }
- ieee80211_next_scan(ifp);
- return;
- }
- selbs = NULL;
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "\tmacaddr bssid chan rssi rate flag wep essid\n");
- for (; ni != NULL; ni = nextbs) {
- nextbs = TAILQ_NEXT(ni, ni_list);
- if (ni->ni_fails) {
- /*
- * The configuration of the access points may change
- * during my scan. So delete the entry for the AP
- * and retry to associate if there is another beacon.
- */
- if (ni->ni_fails++ > 2)
- ieee80211_free_node(ic, ni);
- continue;
- }
- fail = 0;
- if (isclr(ic->ic_chan_active, ni->ni_chan))
- fail |= 0x01;
- if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
- ni->ni_chan != ic->ic_des_chan)
- fail |= 0x01;
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
- fail |= 0x02;
- } else {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
- fail |= 0x02;
- }
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
- fail |= 0x04;
- } else {
- if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
- fail |= 0x04;
- }
- rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
- if (rate & IEEE80211_RATE_BASIC)
- fail |= 0x08;
- if (ic->ic_des_esslen != 0 &&
- (ni->ni_esslen != ic->ic_des_esslen ||
- memcmp(ni->ni_essid, ic->ic_des_essid,
- ic->ic_des_esslen != 0)))
- fail |= 0x10;
- if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
- !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
- fail |= 0x20;
- if (ifp->if_flags & IFF_DEBUG) {
- printf(" %c %s", fail ? '-' : '+',
- ether_sprintf(ni->ni_macaddr));
- printf(" %s%c", ether_sprintf(ni->ni_bssid),
- fail & 0x20 ? '!' : ' ');
- printf(" %3d%c", ni->ni_chan, fail & 0x01 ? '!' : ' ');
- printf(" %+4d", ni->ni_rssi);
- printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
- fail & 0x08 ? '!' : ' ');
- printf(" %4s%c",
- (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
- (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
- "????",
- fail & 0x02 ? '!' : ' ');
- printf(" %3s%c ",
- (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
- "wep" : "no",
- fail & 0x04 ? '!' : ' ');
- ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
- printf("%s\n", fail & 0x10 ? "!" : "");
- }
- if (!fail) {
- if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)
- selbs = ni;
- }
- }
- if (selbs == NULL)
- goto notfound;
- p = ic->ic_bss.ni_private;
- ic->ic_bss = *selbs;
- ic->ic_bss.ni_private = p;
- if (p != NULL && ic->ic_node_privlen)
- memcpy(p, selbs->ni_private, ic->ic_node_privlen);
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- ieee80211_fix_rate(ic, &ic->ic_bss, IEEE80211_F_DOFRATE |
- IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
- if (ic->ic_bss.ni_nrate == 0) {
- selbs->ni_fails++;
- goto notfound;
- }
- ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
- } else
- ieee80211_new_state(ifp, IEEE80211_S_AUTH, -1);
-}
-
-struct ieee80211_node *
-ieee80211_alloc_node(struct ieee80211com *ic, u_int8_t *macaddr, int copy)
-{
- struct ieee80211_node *ni;
- int hash;
-
- ni = malloc(sizeof(struct ieee80211_node) + ic->ic_node_privlen,
- M_DEVBUF, M_NOWAIT);
- if (ni == NULL)
- return NULL;
- if (copy)
- memcpy(ni, &ic->ic_bss, sizeof(struct ieee80211_node));
- else
- memset(ni, 0, sizeof(struct ieee80211_node));
- IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
- if (ic->ic_node_privlen) {
- ni->ni_private = &ni[1];
- memset(ni->ni_private, 0, ic->ic_node_privlen);
- } else
- ni->ni_private = NULL;
-
- hash = IEEE80211_NODE_HASH(macaddr);
- IEEE80211_LOCK(ic);
- TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list);
- LIST_INSERT_HEAD(&ic->ic_hash[hash], ni, ni_hash);
- IEEE80211_UNLOCK(ic);
- ic->ic_inact_timer = IEEE80211_INACT_WAIT;
- return ni;
-}
-
-struct ieee80211_node *
-ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr)
-{
- struct ieee80211_node *ni;
- int hash;
-
- hash = IEEE80211_NODE_HASH(macaddr);
- IEEE80211_LOCK(ic);
- LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
- if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr))
- break;
- }
- IEEE80211_UNLOCK(ic);
- return ni;
-}
-
-void
-ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
-{
- IEEE80211_LOCK(ic);
- if (ic->ic_node_free != NULL)
- (*ic->ic_node_free)(ic, ni);
- TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
- LIST_REMOVE(ni, ni_hash);
- IEEE80211_UNLOCK(ic);
- free(ni, M_DEVBUF);
- if (TAILQ_EMPTY(&ic->ic_node))
- ic->ic_inact_timer = 0;
-}
-
-void
-ieee80211_free_allnodes(struct ieee80211com *ic)
-{
- struct ieee80211_node *ni;
-
- while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL)
- ieee80211_free_node(ic, ni);
-}
-
-int
-ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
-{
- int i, j, ignore, error;
- int okrate, badrate;
- u_int8_t r;
-
- error = 0;
- okrate = badrate = 0;
- for (i = 0; i < ni->ni_nrate; ) {
- ignore = 0;
- if (flags & IEEE80211_F_DOSORT) {
- for (j = i + 1; j < ni->ni_nrate; j++) {
- if ((ni->ni_rates[i] & IEEE80211_RATE_VAL) >
- (ni->ni_rates[j] & IEEE80211_RATE_VAL)) {
- r = ni->ni_rates[i];
- ni->ni_rates[i] = ni->ni_rates[j];
- ni->ni_rates[j] = r;
- }
- }
- }
- r = ni->ni_rates[i] & IEEE80211_RATE_VAL;
- badrate = r;
- if (flags & IEEE80211_F_DOFRATE) {
- if (ic->ic_fixed_rate >= 0 &&
- r != (ic->ic_sup_rates[ic->ic_fixed_rate] &
- IEEE80211_RATE_VAL))
- ignore++;
- }
- if (flags & IEEE80211_F_DONEGO) {
- for (j = 0; j < IEEE80211_RATE_SIZE; j++) {
- if (r ==
- (ic->ic_sup_rates[j] & IEEE80211_RATE_VAL))
- break;
- }
- if (j == IEEE80211_RATE_SIZE) {
- if (ni->ni_rates[i] & IEEE80211_RATE_BASIC)
- error++;
- ignore++;
- }
- }
- if (flags & IEEE80211_F_DODEL) {
- if (ignore) {
- ni->ni_nrate--;
- for (j = i; j < ni->ni_nrate; j++)
- ni->ni_rates[j] = ni->ni_rates[j + 1];
- ni->ni_rates[j] = 0;
- continue;
- }
- }
- if (!ignore)
- okrate = ni->ni_rates[i];
- i++;
- }
- if (okrate == 0 || error != 0)
- return badrate | IEEE80211_RATE_BASIC;
- return okrate & IEEE80211_RATE_VAL;
-}
-
-static int
-ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int dummy)
-{
- int i, ret;
- struct mbuf *m;
- u_int8_t *frm;
-
- /*
- * prreq frame format
- * [tlv] ssid
- * [tlv] supported rates
- */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- m->m_data += sizeof(struct ieee80211_frame);
- frm = mtod(m, u_int8_t *);
-
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = ic->ic_des_esslen;
- memcpy(frm, ic->ic_des_essid, ic->ic_des_esslen);
- frm += ic->ic_des_esslen;
-
- *frm++ = IEEE80211_ELEMID_RATES;
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (ic->ic_sup_rates[i] != 0)
- frm[i + 1] = ic->ic_sup_rates[i];
- }
- *frm++ = i;
- frm += i;
- m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
-
- ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
- ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
- return ret;
-}
-
-static int
-ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_node *bs0,
- int type, int dummy)
-{
- struct mbuf *m;
- u_int8_t *frm;
- struct ieee80211_node *ni = &ic->ic_bss;
- u_int16_t capinfo;
-
- /*
- * probe response frame format
- * [8] time stamp
- * [2] beacon interval
- * [2] cabability information
- * [tlv] ssid
- * [tlv] supported rates
- * [tlv] parameter set (IBSS)
- */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- m->m_data += sizeof(struct ieee80211_frame);
- frm = mtod(m, u_int8_t *);
-
- memset(frm, 0, 8); /* timestamp should be filled later */
- frm += 8;
- *(u_int16_t *)frm = htole16(ni->ni_intval);
- frm += 2;
- if (ic->ic_opmode == IEEE80211_M_IBSS)
- capinfo = IEEE80211_CAPINFO_IBSS;
- else
- capinfo = IEEE80211_CAPINFO_ESS;
- if (ic->ic_flags & IEEE80211_F_WEPON)
- capinfo |= IEEE80211_CAPINFO_PRIVACY;
- *(u_int16_t *)frm = htole16(capinfo);
- frm += 2;
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = ni->ni_esslen;
- memcpy(frm, ni->ni_essid, ni->ni_esslen);
- frm += ni->ni_esslen;
- *frm++ = IEEE80211_ELEMID_RATES;
- *frm++ = ni->ni_nrate;
- memcpy(frm, ni->ni_rates, ni->ni_nrate);
- frm += ni->ni_nrate;
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- *frm++ = IEEE80211_ELEMID_IBSSPARMS;
- *frm++ = 2;
- *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */
- } else { /* IEEE80211_M_HOSTAP */
- /* TODO: TIM */
- *frm++ = IEEE80211_ELEMID_TIM;
- *frm++ = 4; /* length */
- *frm++ = 0; /* DTIM count */
- *frm++ = 1; /* DTIM period */
- *frm++ = 0; /* bitmap control */
- *frm++ = 0; /* Partial Virtual Bitmap (variable length) */
- }
- /* TODO: check MHLEN limit */
- m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
-
- return ieee80211_mgmt_output(&ic->ic_if, bs0, m, type);
-}
-
-static int
-ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int seq)
-{
- struct mbuf *m;
- u_int16_t *frm;
- int ret;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- MH_ALIGN(m, 2 * 3);
- m->m_pkthdr.len = m->m_len = 6;
- frm = mtod(m, u_int16_t *);
- /* TODO: shared key auth */
- frm[0] = htole16(IEEE80211_AUTH_ALG_OPEN);
- frm[1] = htole16(seq);
- frm[2] = 0; /* status */
- ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
- if (ic->ic_opmode == IEEE80211_M_STA)
- ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
- return ret;
-}
-
-static int
-ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int reason)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct mbuf *m;
-
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s deauthenticate (reason %d)\n",
- ether_sprintf(ni->ni_macaddr), reason);
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- MH_ALIGN(m, 2);
- m->m_pkthdr.len = m->m_len = 2;
- *mtod(m, u_int16_t *) = htole16(reason);
- return ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
-}
-
-static int
-ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int dummy)
-{
- struct mbuf *m;
- u_int8_t *frm, *rates;
- u_int16_t capinfo;
- int i, ret;
-
- /*
- * asreq frame format
- * [2] capability information
- * [2] listen interval
- * [6*] current AP address (reassoc only)
- * [tlv] ssid
- * [tlv] supported rates
- */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- m->m_data += sizeof(struct ieee80211_frame);
- frm = mtod(m, u_int8_t *);
-
- capinfo = 0;
- if (ic->ic_opmode == IEEE80211_M_IBSS)
- capinfo |= IEEE80211_CAPINFO_IBSS;
- else /* IEEE80211_M_STA */
- capinfo |= IEEE80211_CAPINFO_ESS;
- if (ic->ic_flags & IEEE80211_F_WEPON)
- capinfo |= IEEE80211_CAPINFO_PRIVACY;
- *(u_int16_t *)frm = htole16(capinfo);
- frm += 2;
-
- *(u_int16_t *)frm = htole16(ic->ic_lintval);
- frm += 2;
-
- if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
- IEEE80211_ADDR_COPY(frm, ic->ic_bss.ni_bssid);
- frm += IEEE80211_ADDR_LEN;
- }
-
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = ni->ni_esslen;
- memcpy(frm, ni->ni_essid, ni->ni_esslen);
- frm += ni->ni_esslen;
-
- *frm++ = IEEE80211_ELEMID_RATES;
- rates = frm++; /* update later */
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (ni->ni_rates[i] != 0)
- *frm++ = ni->ni_rates[i];
- }
- *rates = frm - (rates + 1);
- m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
- ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
- ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
- return ret;
-}
-
-static int
-ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int status)
-{
- struct mbuf *m;
- u_int8_t *frm, *rates, *r;
- u_int16_t capinfo;
- int i;
-
- /*
- * asreq frame format
- * [2] capability information
- * [2] status
- * [2] association ID
- * [tlv] supported rates
- */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- m->m_data += sizeof(struct ieee80211_frame);
- frm = mtod(m, u_int8_t *);
-
- capinfo = IEEE80211_CAPINFO_ESS;
- if (ic->ic_flags & IEEE80211_F_WEPON)
- capinfo |= IEEE80211_CAPINFO_PRIVACY;
- *(u_int16_t *)frm = htole16(capinfo);
- frm += 2;
-
- *(u_int16_t *)frm = htole16(status);
- frm += 2;
-
- if (status == IEEE80211_STATUS_SUCCESS && ni != NULL)
- *(u_int16_t *)frm = htole16(ni->ni_associd);
- else
- *(u_int16_t *)frm = htole16(0);
- frm += 2;
-
- *frm++ = IEEE80211_ELEMID_RATES;
- rates = frm++; /* update later */
- if (ni != NULL)
- r = ni->ni_rates;
- else
- r = ic->ic_bss.ni_rates;
- for (i = 0; i < IEEE80211_RATE_SIZE; i++, r++) {
- if (*r != 0)
- *frm++ = *r;
- }
- *rates = frm - (rates + 1);
- m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
- return ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
-}
-
-static int
-ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
- int type, int reason)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct mbuf *m;
-
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s disassociate (reason %d)\n",
- ether_sprintf(ni->ni_macaddr), reason);
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return ENOMEM;
- MH_ALIGN(m, 2);
- m->m_pkthdr.len = m->m_len = 2;
- *mtod(m, u_int16_t *) = htole16(reason);
- return ieee80211_mgmt_output(&ic->ic_if, ni, m,
- IEEE80211_FC0_SUBTYPE_DISASSOC);
-}
-
-static void
-ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- u_int8_t *frm, *efrm, *tstamp, *bintval, *capinfo, *ssid, *rates;
- u_int8_t chan, fhindex;
- u_int16_t fhdwell;
-
- if (ic->ic_opmode != IEEE80211_M_IBSS &&
- ic->ic_state != IEEE80211_S_SCAN) {
- /* XXX: may be useful for background scan */
- return;
- }
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * beacon frame format
- * [8] time stamp
- * [2] beacon interval
- * [2] cabability information
- * [tlv] ssid
- * [tlv] supported rates
- * [tlv] parameter set (FH/DS)
- */
- tstamp = frm; frm += 8;
- bintval = frm; frm += 2;
- capinfo = frm; frm += 2;
- ssid = rates = NULL;
- chan = ic->ic_bss.ni_chan;
- fhdwell = 0;
- fhindex = 0;
- while (frm < efrm) {
- switch (*frm) {
- case IEEE80211_ELEMID_SSID:
- ssid = frm;
- break;
- case IEEE80211_ELEMID_RATES:
- rates = frm;
- break;
- case IEEE80211_ELEMID_FHPARMS:
- if (ic->ic_phytype == IEEE80211_T_FH) {
- fhdwell = (frm[3] << 8) | frm[2];
- chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
- fhindex = frm[6];
- }
- break;
- case IEEE80211_ELEMID_DSPARMS:
- if (ic->ic_phytype == IEEE80211_T_DS)
- chan = frm[2];
- break;
- }
- frm += frm[1] + 2;
- }
- if (ssid == NULL || rates == NULL) {
- DPRINTF(("ieee80211_recv_beacon: ssid=%p, rates=%p, chan=%d\n",
- ssid, rates, chan));
- return;
- }
- if (ssid[1] > IEEE80211_NWID_LEN) {
- DPRINTF(("ieee80211_recv_beacon: bad ssid len %d from %s\n",
- ssid[1], ether_sprintf(wh->i_addr2)));
- return;
- }
- ni = ieee80211_find_node(ic, wh->i_addr2);
-#ifdef IEEE80211_DEBUG
- if (ieee80211_debug &&
- (ieee80211_debug > 1 || ni == NULL ||
- ic->ic_state == IEEE80211_S_SCAN)) {
- printf("ieee80211_recv_prreq: %sbeacon on chan %u (bss chan %u) ",
- (ni == NULL ? "new " : ""), chan, ic->ic_bss.ni_chan);
- ieee80211_print_essid(ssid + 2, ssid[1]);
- printf(" from %s\n", ether_sprintf(wh->i_addr2));
- }
-#endif
- if (ni == NULL) {
- if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 0)) == NULL)
- return;
- ni->ni_esslen = ssid[1];
- memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
- memcpy(ni->ni_essid, ssid + 2, ssid[1]);
- } else {
- if (ssid[1] != 0) {
- /*
- * Update ESSID at probe response to adopt hidden AP by
- * Lucent/Cisco, which announces null ESSID in beacon.
- */
- if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
- IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
- ni->ni_esslen = ssid[1];
- memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
- memcpy(ni->ni_essid, ssid + 2, ssid[1]);
- }
- }
- }
- IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
- memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
- ni->ni_nrate = rates[1];
- memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
- ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT);
- ni->ni_rssi = rssi;
- ni->ni_rstamp = rstamp;
- memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
- ni->ni_intval = le16toh(*(u_int16_t *)bintval);
- ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
- ni->ni_chan = chan;
- ni->ni_fhdwell = fhdwell;
- ni->ni_fhindex = fhindex;
- if (ic->ic_state == IEEE80211_S_SCAN && ic->ic_scan_timer == 0)
- ieee80211_end_scan(&ic->ic_if);
-}
-
-static void
-ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- u_int8_t *frm, *efrm, *ssid, *rates;
- u_int8_t rate;
- int allocbs;
-
- if (ic->ic_opmode == IEEE80211_M_STA)
- return;
- if (ic->ic_state != IEEE80211_S_RUN)
- return;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * prreq frame format
- * [tlv] ssid
- * [tlv] supported rates
- */
- ssid = rates = NULL;
- while (frm < efrm) {
- switch (*frm) {
- case IEEE80211_ELEMID_SSID:
- ssid = frm;
- break;
- case IEEE80211_ELEMID_RATES:
- rates = frm;
- break;
- }
- frm += frm[1] + 2;
- }
- if (ssid == NULL || rates == NULL) {
- DPRINTF(("ieee80211_recv_prreq: ssid=%p, rates=%p\n",
- ssid, rates));
- return;
- }
- if (ssid[1] != 0 &&
- (ssid[1] != ic->ic_bss.ni_esslen ||
- memcmp(ssid + 2, ic->ic_bss.ni_essid, ic->ic_bss.ni_esslen) != 0)) {
-#ifdef IEEE80211_DEBUG
- if (ieee80211_debug) {
- printf("ieee80211_recv_prreq: ssid unmatch ");
- ieee80211_print_essid(ssid + 2, ssid[1]);
- printf(" from %s\n", ether_sprintf(wh->i_addr2));
- }
-#endif
- return;
- }
-
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni == NULL) {
- if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
- return;
- DPRINTF(("ieee80211_recv_prreq: new req from %s\n",
- ether_sprintf(wh->i_addr2)));
- allocbs = 1;
- } else
- allocbs = 0;
- memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
- ni->ni_nrate = rates[1];
- memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
- ni->ni_rssi = rssi;
- ni->ni_rstamp = rstamp;
- rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT |
- IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
- if (rate & IEEE80211_RATE_BASIC) {
- DPRINTF(("ieee80211_recv_prreq: rate negotiation failed: %s\n",
- ether_sprintf(wh->i_addr2)));
- } else {
- IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
- 0);
- }
- if (allocbs && (ic->ic_opmode == IEEE80211_M_HOSTAP))
- ieee80211_free_node(ic, ni);
-}
-
-static void
-ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- u_int8_t *frm, *efrm;
- u_int16_t algo, seq, status;
- int allocbs;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * auth frame format
- * [2] algorithm
- * [2] sequence
- * [2] status
- * [tlv*] challenge
- */
- if (frm + 6 > efrm) {
- DPRINTF(("ieee80211_recv_auth: too short from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
- algo = le16toh(*(u_int16_t *)frm);
- seq = le16toh(*(u_int16_t *)(frm + 2));
- status = le16toh(*(u_int16_t *)(frm + 4));
- if (algo != IEEE80211_AUTH_ALG_OPEN) {
- /* TODO: shared key auth */
- DPRINTF(("ieee80211_recv_auth: unsupported auth %d from %s\n",
- algo, ether_sprintf(wh->i_addr2)));
- return;
- }
- switch (ic->ic_opmode) {
- case IEEE80211_M_IBSS:
- if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
- return;
- ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
-
- case IEEE80211_M_AHDEMO:
- /* should not come here */
- break;
-
- case IEEE80211_M_HOSTAP:
- if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
- return;
- allocbs = 0;
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni == NULL) {
- ni = ieee80211_alloc_node(ic, wh->i_addr2, 0);
- if (ni == NULL)
- return;
- IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss.ni_bssid);
- allocbs = 1;
- }
- IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s %s authenticated\n",
- (allocbs ? "newly" : "already"),
- ether_sprintf(ni->ni_macaddr));
- break;
-
- case IEEE80211_M_STA:
- if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
- return;
- if (status != 0) {
- if_printf(&ic->ic_if,
- "authentication failed (reason %d) for %s\n",
- status,
- ether_sprintf(wh->i_addr3));
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni != NULL)
- ni->ni_fails++;
- return;
- }
- ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
- }
-}
-
-static void
-ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni = &ic->ic_bss;
- u_int8_t *frm, *efrm, *ssid, *rates;
- u_int16_t capinfo, bintval;
- int reassoc, resp, newassoc;
-
- if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
- (ic->ic_state != IEEE80211_S_RUN))
- return;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
- IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
- reassoc = 1;
- resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
- } else {
- reassoc = 0;
- resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
- }
- /*
- * asreq frame format
- * [2] capability information
- * [2] listen interval
- * [6*] current AP address (reassoc only)
- * [tlv] ssid
- * [tlv] supported rates
- */
- if (frm + (reassoc ? 10 : 4) > efrm) {
- DPRINTF(("ieee80211_recv_asreq: too short from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
-
- if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss.ni_bssid)) {
- DPRINTF(("ieee80211_recv_asreq: ignore other bss from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
- capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
- bintval = le16toh(*(u_int16_t *)frm); frm += 2;
- if (reassoc)
- frm += 6; /* ignore current AP info */
- ssid = rates = NULL;
- while (frm < efrm) {
- switch (*frm) {
- case IEEE80211_ELEMID_SSID:
- ssid = frm;
- break;
- case IEEE80211_ELEMID_RATES:
- rates = frm;
- break;
- }
- frm += frm[1] + 2;
- }
- if (ssid == NULL || rates == NULL) {
- DPRINTF(("ieee80211_recv_asreq: ssid=%p, rates=%p\n",
- ssid, rates));
- return;
- }
- if (ssid[1] > IEEE80211_NWID_LEN) {
- DPRINTF(("ieee80211_recv_asreq: bad ssid len %d from %s\n",
- ssid[1], ether_sprintf(wh->i_addr2)));
- return;
- }
- if (ssid[1] != ic->ic_bss.ni_esslen ||
- memcmp(ssid + 2, ic->ic_bss.ni_essid, ssid[1]) != 0) {
-#ifdef IEEE80211_DEBUG
- if (ieee80211_debug) {
- printf("ieee80211_recv_asreq: ssid unmatch ");
- ieee80211_print_essid(ssid + 2, ssid[1]);
- printf(" from %s\n", ether_sprintf(wh->i_addr2));
- }
-#endif
- return;
- }
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni == NULL) {
- DPRINTF(("ieee80211_recv_asreq: not authenticated for %s\n",
- ether_sprintf(wh->i_addr2)));
- if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
- return;
- IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_ASSOC_NOT_AUTHED);
- ieee80211_free_node(ic, ni);
- return;
- }
- if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
- (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
- ((ic->ic_flags & IEEE80211_F_WEPON) ?
- IEEE80211_CAPINFO_PRIVACY : 0)) {
- DPRINTF(("ieee80211_recv_asreq: capability unmatch %x for %s\n",
- capinfo, ether_sprintf(wh->i_addr2)));
- ni->ni_associd = 0;
- IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
- return;
- }
- memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
- ni->ni_nrate = rates[1];
- memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
- ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
- IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
- if (ni->ni_nrate == 0) {
- DPRINTF(("ieee80211_recv_asreq: rate unmatch for %s\n",
- ether_sprintf(wh->i_addr2)));
- ni->ni_associd = 0;
- IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
- return;
- }
- ni->ni_rssi = rssi;
- ni->ni_rstamp = rstamp;
- ni->ni_intval = bintval;
- ni->ni_capinfo = capinfo;
- ni->ni_chan = ic->ic_bss.ni_chan;
- ni->ni_fhdwell = ic->ic_bss.ni_fhdwell;
- ni->ni_fhindex = ic->ic_bss.ni_fhindex;
- if (ni->ni_associd == 0) {
- ni->ni_associd = 0xc000 | ic->ic_bss.ni_associd++;
- newassoc = 1;
- } else
- newassoc = 0;
- IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s %s associated\n",
- (newassoc ? "newly" : "already"),
- ether_sprintf(ni->ni_macaddr));
-}
-
-static void
-ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni = &ic->ic_bss;
- u_int8_t *frm, *efrm, *rates;
- int status;
-
- if (ic->ic_opmode != IEEE80211_M_STA ||
- ic->ic_state != IEEE80211_S_ASSOC)
- return;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * asresp frame format
- * [2] capability information
- * [2] status
- * [2] association ID
- * [tlv] supported rates
- */
- if (frm + 6 > efrm) {
- DPRINTF(("ieee80211_recv_asresp: too short from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
-
- ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
- frm += 2;
-
- status = le16toh(*(u_int16_t *)frm);
- frm += 2;
- if (status != 0) {
- if_printf(ifp, "association failed (reason %d) for %s\n",
- status, ether_sprintf(wh->i_addr3));
- ni = ieee80211_find_node(ic, wh->i_addr2);
- if (ni != NULL)
- ni->ni_fails++;
- return;
- }
- ni->ni_associd = le16toh(*(u_int16_t *)frm);
- frm += 2;
- rates = frm;
-
- memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
- ni->ni_nrate = rates[1];
- memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
- ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
- IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
- if (ni->ni_nrate == 0)
- return;
- ieee80211_new_state(ifp, IEEE80211_S_RUN,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
-}
-
-static void
-ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- u_int8_t *frm, *efrm;
- u_int16_t reason;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * disassoc frame format
- * [2] reason
- */
- if (frm + 2 > efrm) {
- DPRINTF(("ieee80211_recv_disassoc: too short from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
- reason = le16toh(*(u_int16_t *)frm);
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
- case IEEE80211_M_HOSTAP:
- if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s disassociated"
- " by peer (reason %d)\n",
- ether_sprintf(ni->ni_macaddr), reason);
- ni->ni_associd = 0;
- }
- break;
- default:
- break;
- }
-}
-
-static void
-ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
-{
- struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
- u_int8_t *frm, *efrm;
- u_int16_t reason;
-
- wh = mtod(m0, struct ieee80211_frame *);
- frm = (u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
- /*
- * dauth frame format
- * [2] reason
- */
- if (frm + 2 > efrm) {
- DPRINTF(("ieee80211_recv_deauth: too short from %s\n",
- ether_sprintf(wh->i_addr2)));
- return;
- }
- reason = le16toh(*(u_int16_t *)frm);
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
- case IEEE80211_M_HOSTAP:
- if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s deauthenticated"
- " by peer (reason %d)\n",
- ether_sprintf(ni->ni_macaddr), reason);
- ieee80211_free_node(ic, ni);
- }
- break;
- default:
- break;
- }
-}
-
-int
-ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct ieee80211_node *ni = &ic->ic_bss;
- int i, error, ostate;
-#ifdef IEEE80211_DEBUG
- static const char *stname[] =
- { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
-#endif
-
- ostate = ic->ic_state;
- DPRINTF(("ieee80211_new_state: %s -> %s\n",
- stname[ostate], stname[nstate]));
- if (ic->ic_newstate) {
- error = (*ic->ic_newstate)(ic->ic_softc, nstate);
- if (error == EINPROGRESS)
- return 0;
- if (error != 0)
- return error;
- }
-
- /* state transition */
- ic->ic_state = nstate;
- switch (nstate) {
- case IEEE80211_S_INIT:
- switch (ostate) {
- case IEEE80211_S_INIT:
- break;
- case IEEE80211_S_RUN:
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DISASSOC,
- IEEE80211_REASON_ASSOC_LEAVE);
- break;
- case IEEE80211_M_HOSTAP:
- TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
- if (ni->ni_associd == 0)
- continue;
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DISASSOC,
- IEEE80211_REASON_ASSOC_LEAVE);
- }
- break;
- default:
- break;
- }
- /* FALLTHRU */
- case IEEE80211_S_ASSOC:
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_AUTH_LEAVE);
- break;
- case IEEE80211_M_HOSTAP:
- TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_AUTH_LEAVE);
- }
- break;
- default:
- break;
- }
- /* FALLTHRU */
- case IEEE80211_S_AUTH:
- case IEEE80211_S_SCAN:
- ic->ic_scan_timer = 0;
- ic->ic_mgt_timer = 0;
- IF_DRAIN(&ic->ic_mgtq);
- if (ic->ic_wep_ctx != NULL) {
- free(ic->ic_wep_ctx, M_DEVBUF);
- ic->ic_wep_ctx = NULL;
- }
- ieee80211_free_allnodes(ic);
- break;
- }
- break;
- case IEEE80211_S_SCAN:
- ic->ic_flags &= ~IEEE80211_F_SIBSS;
- ni = &ic->ic_bss;
- /* initialize bss for probe request */
- IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr);
- IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr);
- ni->ni_nrate = 0;
- memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (ic->ic_sup_rates[i] != 0)
- ni->ni_rates[ni->ni_nrate++] =
- ic->ic_sup_rates[i];
- }
- ni->ni_associd = 0;
- ni->ni_rstamp = 0;
- switch (ostate) {
- case IEEE80211_S_INIT:
- ic->ic_flags |= IEEE80211_F_ASCAN;
- ic->ic_scan_timer = IEEE80211_ASCAN_WAIT;
- /* use lowest rate */
- ni->ni_txrate = 0;
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
- break;
- case IEEE80211_S_SCAN:
- /* scan next */
- if (ic->ic_flags & IEEE80211_F_ASCAN) {
- if (ic->ic_scan_timer == 0)
- ic->ic_scan_timer =
- IEEE80211_ASCAN_WAIT;
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
- } else {
- if (ic->ic_scan_timer == 0)
- ic->ic_scan_timer =
- IEEE80211_PSCAN_WAIT;
- ifp->if_timer = 1;
- }
- break;
- case IEEE80211_S_RUN:
- /* beacon miss */
- if (ifp->if_flags & IFF_DEBUG) {
- /* XXX bssid clobbered above */
- if_printf(ifp, "no recent beacons from %s;"
- " rescanning\n",
- ether_sprintf(ic->ic_bss.ni_bssid));
- }
- ieee80211_free_allnodes(ic);
- /* FALLTHRU */
- case IEEE80211_S_AUTH:
- case IEEE80211_S_ASSOC:
- /* timeout restart scan */
- ni = ieee80211_find_node(ic, ic->ic_bss.ni_macaddr);
- if (ni != NULL)
- ni->ni_fails++;
- ic->ic_flags |= IEEE80211_F_ASCAN;
- ic->ic_scan_timer = IEEE80211_ASCAN_WAIT;
- IEEE80211_SEND_MGMT(ic, &ic->ic_bss,
- IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
- break;
- }
- break;
- case IEEE80211_S_AUTH:
- switch (ostate) {
- case IEEE80211_S_INIT:
- DPRINTF(("ieee80211_new_state: invalid transition\n"));
- break;
- case IEEE80211_S_SCAN:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_AUTH, 1);
- break;
- case IEEE80211_S_AUTH:
- case IEEE80211_S_ASSOC:
- switch (mgt) {
- case IEEE80211_FC0_SUBTYPE_AUTH:
- /* ??? */
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_AUTH, 2);
- break;
- case IEEE80211_FC0_SUBTYPE_DEAUTH:
- /* ignore and retry scan on timeout */
- break;
- }
- break;
- case IEEE80211_S_RUN:
- switch (mgt) {
- case IEEE80211_FC0_SUBTYPE_AUTH:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_AUTH, 2);
- ic->ic_state = ostate; /* stay RUN */
- break;
- case IEEE80211_FC0_SUBTYPE_DEAUTH:
- /* try to reauth */
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_AUTH, 1);
- break;
- }
- break;
- }
- break;
- case IEEE80211_S_ASSOC:
- switch (ostate) {
- case IEEE80211_S_INIT:
- case IEEE80211_S_SCAN:
- case IEEE80211_S_ASSOC:
- DPRINTF(("ieee80211_new_state: invalid transition\n"));
- break;
- case IEEE80211_S_AUTH:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
- break;
- case IEEE80211_S_RUN:
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
- break;
- }
- break;
- case IEEE80211_S_RUN:
- switch (ostate) {
- case IEEE80211_S_INIT:
- case IEEE80211_S_AUTH:
- case IEEE80211_S_RUN:
- DPRINTF(("ieee80211_new_state: invalid transition\n"));
- break;
- case IEEE80211_S_SCAN: /* adhoc mode */
- case IEEE80211_S_ASSOC: /* infra mode */
- if (ifp->if_flags & IFF_DEBUG) {
- if_printf(ifp, " ");
- if (ic->ic_opmode == IEEE80211_M_STA)
- printf("associated ");
- else
- printf("synchronized ");
- printf("with %s ssid ",
- ether_sprintf(ic->ic_bss.ni_bssid));
- ieee80211_print_essid(ic->ic_bss.ni_essid,
- ic->ic_bss.ni_esslen);
- printf(" channel %d\n", ic->ic_bss.ni_chan);
- }
- /* start with highest negotiated rate */
- ic->ic_bss.ni_txrate = ic->ic_bss.ni_nrate - 1;
- ic->ic_mgt_timer = 0;
- (*ifp->if_start)(ifp);
- break;
- }
- break;
- }
- return 0;
-}
-
-struct mbuf *
-ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
-{
- struct ieee80211com *ic = (void *)ifp;
- struct mbuf *m, *n, *n0;
- struct ieee80211_frame *wh;
- int i, left, len, moff, noff, kid;
- u_int32_t iv, crc;
- u_int8_t *ivp;
- void *ctx;
- u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
- u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
-
- n0 = NULL;
- if ((ctx = ic->ic_wep_ctx) == NULL) {
- ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
- if (ctx == NULL)
- goto fail;
- ic->ic_wep_ctx = ctx;
- }
- m = m0;
- left = m->m_pkthdr.len;
- MGET(n, M_DONTWAIT, m->m_type);
- n0 = n;
- if (n == NULL)
- goto fail;
- M_MOVE_PKTHDR(n, m);
- len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
- if (txflag) {
- n->m_pkthdr.len += len;
- } else {
- n->m_pkthdr.len -= len;
- left -= len;
- }
- n->m_len = MHLEN;
- if (n->m_pkthdr.len >= MINCLSIZE) {
- MCLGET(n, M_DONTWAIT);
- if (n->m_flags & M_EXT)
- n->m_len = n->m_ext.ext_size;
- }
- len = sizeof(struct ieee80211_frame);
- memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
- wh = mtod(n, struct ieee80211_frame *);
- left -= len;
- moff = len;
- noff = len;
- if (txflag) {
- kid = ic->ic_wep_txkey;
- wh->i_fc[1] |= IEEE80211_FC1_WEP;
- iv = ic->ic_iv;
- /*
- * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
- * (B, 255, N) with 3 <= B < 8
- */
- if (iv >= 0x03ff00 &&
- (iv & 0xf8ff00) == 0x00ff00)
- iv += 0x000100;
- ic->ic_iv = iv + 1;
- /* put iv in little endian to prepare 802.11i */
- ivp = mtod(n, u_int8_t *) + noff;
- for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
- ivp[i] = iv & 0xff;
- iv >>= 8;
- }
- ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */
- noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
- } else {
- wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
- ivp = mtod(m, u_int8_t *) + moff;
- kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
- moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
- }
- memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
- memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
- ic->ic_nw_keys[kid].wk_len);
- arc4_setkey(ctx, keybuf,
- IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
-
- /* encrypt with calculating CRC */
- crc = ~0;
- while (left > 0) {
- len = m->m_len - moff;
- if (len == 0) {
- m = m->m_next;
- moff = 0;
- continue;
- }
- if (len > n->m_len - noff) {
- len = n->m_len - noff;
- if (len == 0) {
- MGET(n->m_next, M_DONTWAIT, n->m_type);
- if (n->m_next == NULL)
- goto fail;
- n = n->m_next;
- n->m_len = MLEN;
- if (left >= MINCLSIZE) {
- MCLGET(n, M_DONTWAIT);
- if (n->m_flags & M_EXT)
- n->m_len = n->m_ext.ext_size;
- }
- noff = 0;
- continue;
- }
- }
- if (len > left)
- len = left;
- arc4_encrypt(ctx, mtod(n, caddr_t) + noff,
- mtod(m, caddr_t) + moff, len);
- if (txflag)
- crc = ieee80211_crc_update(crc,
- mtod(m, u_int8_t *) + moff, len);
- else
- crc = ieee80211_crc_update(crc,
- mtod(n, u_int8_t *) + noff, len);
- left -= len;
- moff += len;
- noff += len;
- }
- crc = ~crc;
- if (txflag) {
- *(u_int32_t *)crcbuf = htole32(crc);
- if (n->m_len >= noff + sizeof(crcbuf))
- n->m_len = noff + sizeof(crcbuf);
- else {
- n->m_len = noff;
- MGET(n->m_next, M_DONTWAIT, n->m_type);
- if (n->m_next == NULL)
- goto fail;
- n = n->m_next;
- n->m_len = sizeof(crcbuf);
- noff = 0;
- }
- arc4_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
- sizeof(crcbuf));
- } else {
- n->m_len = noff;
- for (noff = 0; noff < sizeof(crcbuf); noff += len) {
- len = sizeof(crcbuf) - noff;
- if (len > m->m_len - moff)
- len = m->m_len - moff;
- if (len > 0)
- arc4_encrypt(ctx, crcbuf + noff,
- mtod(m, caddr_t) + moff, len);
- m = m->m_next;
- moff = 0;
- }
- if (crc != le32toh(*(u_int32_t *)crcbuf)) {
-#ifdef IEEE80211_DEBUG
- if (ieee80211_debug) {
- if_printf(ifp, "decrypt CRC error\n");
- if (ieee80211_debug > 1)
- ieee80211_dump_pkt(n0->m_data,
- n0->m_len, -1, -1);
- }
-#endif
- goto fail;
- }
- }
- m_freem(m0);
- return n0;
-
- fail:
- m_freem(m0);
- m_freem(n0);
- return NULL;
-}
-
-/*
- * CRC 32 -- routine from RFC 2083
- */
-
-/* Table of CRCs of all 8-bit messages */
-static u_int32_t ieee80211_crc_table[256];
-
-/* Make the table for a fast CRC. */
-static void
-ieee80211_crc_init(void)
-{
- u_int32_t c;
- int n, k;
-
- for (n = 0; n < 256; n++) {
- c = (u_int32_t)n;
- for (k = 0; k < 8; k++) {
- if (c & 1)
- c = 0xedb88320UL ^ (c >> 1);
- else
- c = c >> 1;
- }
- ieee80211_crc_table[n] = c;
- }
-}
-
-/*
- * Update a running CRC with the bytes buf[0..len-1]--the CRC
- * should be initialized to all 1's, and the transmitted value
- * is the 1's complement of the final running CRC
- */
-
-static u_int32_t
-ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
-{
- u_int8_t *endbuf;
-
- for (endbuf = buf + len; buf < endbuf; buf++)
- crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
- return crc;
-}
-
-/*
- * convert IEEE80211 rate value to ifmedia subtype.
- * ieee80211 rate is in unit of 0.5Mbps.
- */
-
-int
-ieee80211_rate2media(int rate, enum ieee80211_phytype phytype)
-{
- int mword;
-
- mword = 0;
- switch (phytype) {
- case IEEE80211_T_FH:
- switch (rate & IEEE80211_RATE_VAL) {
- case 0:
- mword = IFM_AUTO;
- break;
- case 2:
- mword = IFM_IEEE80211_FH1;
- break;
- case 4:
- mword = IFM_IEEE80211_FH2;
- break;
- default:
- mword = IFM_NONE;
- break;
- }
- break;
-
- case IEEE80211_T_DS:
- switch (rate & IEEE80211_RATE_VAL) {
- case 0:
- mword = IFM_AUTO;
- break;
- case 2:
- mword = IFM_IEEE80211_DS1;
- break;
- case 4:
- mword = IFM_IEEE80211_DS2;
- break;
- case 11:
- mword = IFM_IEEE80211_DS5;
- break;
- case 22:
- mword = IFM_IEEE80211_DS11;
- break;
- default:
- mword = IFM_NONE;
- break;
- }
- break;
-
- case IEEE80211_T_OFDM:
- switch (rate & IEEE80211_RATE_VAL) {
- case 0:
- mword = IFM_AUTO;
- break;
- case 12:
- mword = IFM_IEEE80211_OFDM6;
- break;
- case 18:
- mword = IFM_IEEE80211_OFDM9;
- break;
- case 24:
- mword = IFM_IEEE80211_OFDM12;
- break;
- case 36:
- mword = IFM_IEEE80211_OFDM18;
- break;
- case 48:
- mword = IFM_IEEE80211_OFDM24;
- break;
- case 72:
- mword = IFM_IEEE80211_OFDM36;
- break;
- case 108:
- mword = IFM_IEEE80211_OFDM54;
- break;
- case 144:
- mword = IFM_IEEE80211_OFDM72;
- break;
- default:
- mword = IFM_NONE;
- break;
- }
- break;
-
- default:
- mword = IFM_MANUAL;
- break;
- }
- return mword;
-}
-
-int
-ieee80211_media2rate(int mword, enum ieee80211_phytype phytype)
-{
- int rate;
-
- rate = 0;
- switch (phytype) {
- case IEEE80211_T_FH:
- switch (IFM_SUBTYPE(mword)) {
- case IFM_IEEE80211_FH1:
- rate = 2;
- break;
- case IFM_IEEE80211_FH2:
- rate = 4;
- break;
- }
- break;
-
- case IEEE80211_T_DS:
- switch (IFM_SUBTYPE(mword)) {
- case IFM_IEEE80211_DS1:
- rate = 2;
- break;
- case IFM_IEEE80211_DS2:
- rate = 4;
- break;
- case IFM_IEEE80211_DS5:
- rate = 11;
- break;
- case IFM_IEEE80211_DS11:
- rate = 22;
- break;
- }
- break;
-
- default:
- break;
- }
- return rate;
-}
-
-/*
- * XXX
- * Wireless LAN specific configuration interface, which is compatible
- * with wiconfig(8).
- */
-
-int
-ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- struct ieee80211com *ic = (void *)ifp;
- int i, j, error;
- struct ifreq *ifr = (struct ifreq *)data;
- struct wi_req wreq;
- struct wi_ltv_keys *keys;
- struct wi_apinfo *ap;
- struct ieee80211_node *ni;
- struct wi_sigcache wsc;
-
- error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
- if (error)
- return error;
- wreq.wi_len = 0;
- switch (wreq.wi_type) {
- case WI_RID_SERIALNO:
- /* nothing appropriate */
- break;
- case WI_RID_NODENAME:
- strcpy((char *)&wreq.wi_val[1], hostname);
- wreq.wi_val[0] = htole16(strlen(hostname));
- wreq.wi_len = (1 + strlen(hostname) + 1) / 2;
- break;
- case WI_RID_CURRENT_SSID:
- if (ic->ic_state != IEEE80211_S_RUN) {
- wreq.wi_val[0] = 0;
- wreq.wi_len = 1;
- break;
- }
- wreq.wi_val[0] = htole16(ic->ic_bss.ni_esslen);
- memcpy(&wreq.wi_val[1], ic->ic_bss.ni_essid,
- ic->ic_bss.ni_esslen);
- wreq.wi_len = (1 + ic->ic_bss.ni_esslen + 1) / 2;
- break;
- case WI_RID_OWN_SSID:
- case WI_RID_DESIRED_SSID:
- wreq.wi_val[0] = htole16(ic->ic_des_esslen);
- memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen);
- wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2;
- break;
- case WI_RID_CURRENT_BSSID:
- if (ic->ic_state == IEEE80211_S_RUN)
- IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss.ni_bssid);
- else
- memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN);
- wreq.wi_len = IEEE80211_ADDR_LEN / 2;
- break;
- case WI_RID_CHANNEL_LIST:
- memset(wreq.wi_val, 0, sizeof(wreq.wi_val));
- /*
- * Since channel 0 is not available for DS, channel 1
- * is assigned to LSB on WaveLAN.
- */
- if (ic->ic_phytype == IEEE80211_T_DS)
- i = 1;
- else
- i = 0;
- for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
- if (isset(ic->ic_chan_active, i)) {
- setbit((u_int8_t *)wreq.wi_val, j);
- wreq.wi_len = j / 16 + 1;
- }
- }
- break;
- case WI_RID_OWN_CHNL:
- wreq.wi_val[0] = htole16(ic->ic_ibss_chan);
- wreq.wi_len = 1;
- break;
- case WI_RID_CURRENT_CHAN:
- wreq.wi_val[0] = htole16(ic->ic_bss.ni_chan);
- wreq.wi_len = 1;
- break;
- case WI_RID_COMMS_QUALITY:
- wreq.wi_val[0] = 0; /* quality */
- wreq.wi_val[1] = htole16(ic->ic_bss.ni_rssi); /* signal */
- wreq.wi_val[2] = 0; /* noise */
- wreq.wi_len = 3;
- break;
- case WI_RID_PROMISC:
- wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0);
- wreq.wi_len = 1;
- break;
- case WI_RID_PORTTYPE:
- wreq.wi_val[0] = htole16(ic->ic_opmode);
- wreq.wi_len = 1;
- break;
- case WI_RID_MAC_NODE:
- IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr);
- wreq.wi_len = IEEE80211_ADDR_LEN / 2;
- break;
- case WI_RID_TX_RATE:
- if (ic->ic_fixed_rate == -1)
- wreq.wi_val[0] = 0; /* auto */
- else
- wreq.wi_val[0] = htole16(
- (ic->ic_sup_rates[ic->ic_fixed_rate] &
- IEEE80211_RATE_VAL) / 2);
- wreq.wi_len = 1;
- break;
- case WI_RID_CUR_TX_RATE:
- wreq.wi_val[0] = htole16(
- (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] &
- IEEE80211_RATE_VAL) / 2);
- wreq.wi_len = 1;
- break;
- case WI_RID_RTS_THRESH:
- wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: RTS */
- wreq.wi_len = 1;
- break;
- case WI_RID_CREATE_IBSS:
- wreq.wi_val[0] =
- htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0);
- wreq.wi_len = 1;
- break;
- case WI_RID_MICROWAVE_OVEN:
- wreq.wi_val[0] = 0; /* no ... not supported */
- wreq.wi_len = 1;
- break;
- case WI_RID_ROAMING_MODE:
- wreq.wi_val[0] = htole16(1); /* enabled ... not supported */
- wreq.wi_len = 1;
- break;
- case WI_RID_SYSTEM_SCALE:
- wreq.wi_val[0] = htole16(1); /* low density ... not supp */
- wreq.wi_len = 1;
- break;
- case WI_RID_PM_ENABLED:
- wreq.wi_val[0] =
- htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
- wreq.wi_len = 1;
- break;
- case WI_RID_MAX_SLEEP:
- wreq.wi_val[0] = htole16(ic->ic_lintval);
- wreq.wi_len = 1;
- break;
- case WI_RID_CUR_BEACON_INT:
- wreq.wi_val[0] = htole16(ic->ic_bss.ni_intval);
- wreq.wi_len = 1;
- break;
- case WI_RID_WEP_AVAIL:
- wreq.wi_val[0] =
- htole16((ic->ic_flags & IEEE80211_F_HASWEP) ? 1 : 0);
- wreq.wi_len = 1;
- break;
- case WI_RID_CNFAUTHMODE:
- wreq.wi_val[0] = htole16(1); /* TODO: open system only */
- wreq.wi_len = 1;
- break;
- case WI_RID_ENCRYPTION:
- wreq.wi_val[0] =
- htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0);
- wreq.wi_len = 1;
- break;
- case WI_RID_TX_CRYPT_KEY:
- wreq.wi_val[0] = htole16(ic->ic_wep_txkey);
- wreq.wi_len = 1;
- break;
- case WI_RID_DEFLT_CRYPT_KEYS:
- keys = (struct wi_ltv_keys *)&wreq;
- /* do not show keys to non-root user */
- error = suser(curthread);
- if (error) {
- memset(keys, 0, sizeof(*keys));
- error = 0;
- break;
- }
- for (i = 0; i < IEEE80211_WEP_NKID; i++) {
- keys->wi_keys[i].wi_keylen =
- htole16(ic->ic_nw_keys[i].wk_len);
- memcpy(keys->wi_keys[i].wi_keydat,
- ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len);
- }
- wreq.wi_len = sizeof(*keys) / 2;
- break;
- case WI_RID_MAX_DATALEN:
- wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: frag */
- wreq.wi_len = 1;
- break;
- case WI_RID_IFACE_STATS:
- /* XXX: should be implemented in lower drivers */
- break;
- case WI_RID_READ_APS:
- if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
- for (i = 0; i < IEEE80211_PSCAN_WAIT; i++) {
- tsleep((caddr_t)ic, PWAIT | PCATCH, "i80211",
- hz);
- if (ic->ic_state != IEEE80211_S_SCAN ||
- (ic->ic_flags & IEEE80211_F_SCANAP) == 0 ||
- (ic->ic_flags & IEEE80211_F_ASCAN) == 0)
- break;
- }
- ic->ic_flags &= ~IEEE80211_F_SCANAP;
- memcpy(ic->ic_chan_active, ic->ic_chan_avail,
- sizeof(ic->ic_chan_active));
- }
- i = 0;
- ap = (void *)((char *)wreq.wi_val + sizeof(i));
- TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
- if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1))
- break;
- memset(ap, 0, sizeof(*ap));
- if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
- IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr);
- ap->namelen = ic->ic_des_esslen;
- if (ic->ic_des_esslen)
- memcpy(ap->name, ic->ic_des_essid,
- ic->ic_des_esslen);
- } else {
- IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid);
- ap->namelen = ni->ni_esslen;
- if (ni->ni_esslen)
- memcpy(ap->name, ni->ni_essid,
- ni->ni_esslen);
- }
- ap->channel = ni->ni_chan;
- ap->signal = ni->ni_rssi;
- ap->capinfo = ni->ni_capinfo;
- ap->interval = ni->ni_intval;
- for (j = 0; j < ni->ni_nrate; j++) {
- if (ni->ni_rates[j] & IEEE80211_RATE_BASIC) {
- ap->rate = (ni->ni_rates[j] &
- IEEE80211_RATE_VAL) * 5; /* XXX */
- }
- }
- i++;
- ap++;
- }
- memcpy(wreq.wi_val, &i, sizeof(i));
- wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2;
- break;
- case WI_RID_READ_CACHE:
- i = 0;
- TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
- if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1)
- break;
- IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr);
- memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc));
- wsc.signal = ni->ni_rssi;
- wsc.noise = 0;
- wsc.quality = 0;
- memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
- &wsc, sizeof(wsc));
- i++;
- }
- wreq.wi_len = sizeof(wsc) * i / 2;
- break;
- case WI_RID_SCAN_APS:
- error = EINVAL;
- break;
- default:
- error = EINVAL;
- break;
- }
- if (error == 0) {
- wreq.wi_len++;
- error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
- }
- return error;
-}
-
-int
-ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- struct ieee80211com *ic = (void *)ifp;
- int i, j, len, error;
- struct ifreq *ifr = (struct ifreq *)data;
- struct wi_ltv_keys *keys;
- struct wi_req wreq;
- u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)];
-
- error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
- if (error)
- return error;
- if (wreq.wi_len-- < 1)
- return EINVAL;
- switch (wreq.wi_type) {
- case WI_RID_SERIALNO:
- case WI_RID_NODENAME:
- return EPERM;
- case WI_RID_CURRENT_SSID:
- return EPERM;
- case WI_RID_OWN_SSID:
- case WI_RID_DESIRED_SSID:
- len = le16toh(wreq.wi_val[0]);
- if (wreq.wi_len < (1 + len + 1) / 2)
- return EINVAL;
- if (len > IEEE80211_NWID_LEN)
- return EINVAL;
- ic->ic_des_esslen = len;
- memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid));
- memcpy(ic->ic_des_essid, &wreq.wi_val[1], len);
- error = ENETRESET;
- break;
- case WI_RID_CURRENT_BSSID:
- return EPERM;
- case WI_RID_OWN_CHNL:
- if (wreq.wi_len != 1)
- return EINVAL;
- i = le16toh(wreq.wi_val[0]);
- if (i < 0 ||
- i > IEEE80211_CHAN_MAX ||
- isclr(ic->ic_chan_active, i))
- return EINVAL;
- ic->ic_ibss_chan = i;
- if (ic->ic_flags & IEEE80211_F_SIBSS)
- error = ENETRESET;
- break;
- case WI_RID_CURRENT_CHAN:
- return EPERM;
- case WI_RID_COMMS_QUALITY:
- return EPERM;
- case WI_RID_PROMISC:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (ifp->if_flags & IFF_PROMISC) {
- if (wreq.wi_val[0] == 0) {
- ifp->if_flags &= ~IFF_PROMISC;
- error = ENETRESET;
- }
- } else {
- if (wreq.wi_val[0] != 0) {
- ifp->if_flags |= IFF_PROMISC;
- error = ENETRESET;
- }
- }
- break;
- case WI_RID_PORTTYPE:
- if (wreq.wi_len != 1)
- return EINVAL;
- switch (le16toh(wreq.wi_val[0])) {
- case IEEE80211_M_STA:
- break;
- case IEEE80211_M_IBSS:
- if (!(ic->ic_flags & IEEE80211_F_HASIBSS))
- return EINVAL;
- break;
- case IEEE80211_M_AHDEMO:
- if (ic->ic_phytype != IEEE80211_T_DS ||
- !(ic->ic_flags & IEEE80211_F_HASAHDEMO))
- return EINVAL;
- break;
- case IEEE80211_M_HOSTAP:
- if (!(ic->ic_flags & IEEE80211_F_HASHOSTAP))
- return EINVAL;
- break;
- default:
- return EINVAL;
- }
- if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) {
- ic->ic_opmode = le16toh(wreq.wi_val[0]);
- error = ENETRESET;
- }
- break;
-#if 0
- case WI_RID_MAC_NODE:
- if (wreq.wi_len != IEEE80211_ADDR_LEN / 2)
- return EINVAL;
- IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val);
- /* if_init will copy lladdr into ic_myaddr */
- error = ENETRESET;
- break;
-#endif
- case WI_RID_TX_RATE:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (wreq.wi_val[0] == 0) {
- /* auto */
- ic->ic_fixed_rate = -1;
- break;
- }
- for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
- if (le16toh(wreq.wi_val[0]) ==
- (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2)
- break;
- }
- if (i == IEEE80211_RATE_SIZE)
- return EINVAL;
- ic->ic_fixed_rate = i;
- error = ENETRESET;
- break;
- case WI_RID_CUR_TX_RATE:
- return EPERM;
- break;
- case WI_RID_RTS_THRESH:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN)
- return EINVAL; /* TODO: RTS */
- break;
- case WI_RID_CREATE_IBSS:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (wreq.wi_val[0] != 0) {
- if ((ic->ic_flags & IEEE80211_F_HASIBSS) == 0)
- return EINVAL;
- if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
- ic->ic_flags |= IEEE80211_F_IBSSON;
- if (ic->ic_opmode == IEEE80211_M_IBSS &&
- ic->ic_state == IEEE80211_S_SCAN)
- error = ENETRESET;
- }
- } else {
- if (ic->ic_flags & IEEE80211_F_IBSSON) {
- ic->ic_flags &= ~IEEE80211_F_IBSSON;
- if (ic->ic_flags & IEEE80211_F_SIBSS) {
- ic->ic_flags &= ~IEEE80211_F_SIBSS;
- error = ENETRESET;
- }
- }
- }
- break;
- case WI_RID_MICROWAVE_OVEN:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (wreq.wi_val[0] != 0)
- return EINVAL; /* not supported */
- break;
- case WI_RID_ROAMING_MODE:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (le16toh(wreq.wi_val[0]) != 1)
- return EINVAL; /* not supported */
- break;
- case WI_RID_SYSTEM_SCALE:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (le16toh(wreq.wi_val[0]) != 1)
- return EINVAL; /* not supported */
- break;
- case WI_RID_PM_ENABLED:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (wreq.wi_val[0] != 0) {
- if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
- return EINVAL;
- if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
- ic->ic_flags |= IEEE80211_F_PMGTON;
- error = ENETRESET;
- }
- } else {
- if (ic->ic_flags & IEEE80211_F_PMGTON) {
- ic->ic_flags &= ~IEEE80211_F_PMGTON;
- error = ENETRESET;
- }
- }
- break;
- case WI_RID_MAX_SLEEP:
- if (wreq.wi_len != 1)
- return EINVAL;
- ic->ic_lintval = le16toh(wreq.wi_val[0]);
- if (ic->ic_flags & IEEE80211_F_PMGTON)
- error = ENETRESET;
- break;
- case WI_RID_CUR_BEACON_INT:
- return EPERM;
- case WI_RID_WEP_AVAIL:
- return EPERM;
- case WI_RID_CNFAUTHMODE:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (le16toh(wreq.wi_val[0]) != 1)
- return EINVAL; /* TODO: shared key auth */
- break;
- case WI_RID_ENCRYPTION:
- if (wreq.wi_len != 1)
- return EINVAL;
- if (wreq.wi_val[0] != 0) {
- if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0)
- return EINVAL;
- if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
- ic->ic_flags |= IEEE80211_F_WEPON;
- error = ENETRESET;
- }
- } else {
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- ic->ic_flags &= ~IEEE80211_F_WEPON;
- error = ENETRESET;
- }
- }
- break;
- case WI_RID_TX_CRYPT_KEY:
- if (wreq.wi_len != 1)
- return EINVAL;
- i = le16toh(wreq.wi_val[0]);
- if (i >= IEEE80211_WEP_NKID)
- return EINVAL;
- ic->ic_wep_txkey = i;
- break;
- case WI_RID_DEFLT_CRYPT_KEYS:
- if (wreq.wi_len != sizeof(struct wi_ltv_keys) / 2)
- return EINVAL;
- keys = (struct wi_ltv_keys *)&wreq;
- for (i = 0; i < IEEE80211_WEP_NKID; i++) {
- len = le16toh(keys->wi_keys[i].wi_keylen);
- if (len != 0 && len < IEEE80211_WEP_KEYLEN)
- return EINVAL;
- if (len > sizeof(ic->ic_nw_keys[i].wk_key))
- return EINVAL;
- }
- memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys));
- for (i = 0; i < IEEE80211_WEP_NKID; i++) {
- len = le16toh(keys->wi_keys[i].wi_keylen);
- ic->ic_nw_keys[i].wk_len = len;
- memcpy(ic->ic_nw_keys[i].wk_key,
- keys->wi_keys[i].wi_keydat, len);
- }
- error = ENETRESET;
- break;
- case WI_RID_MAX_DATALEN:
- if (wreq.wi_len != 1)
- return EINVAL;
- len = le16toh(wreq.wi_val[0]);
- if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN)
- return EINVAL;
- if (len != IEEE80211_MAX_LEN)
- return EINVAL; /* TODO: fragment */
- break;
- case WI_RID_IFACE_STATS:
- error = EPERM;
- break;
- case WI_RID_SCAN_APS:
- if (ic->ic_opmode == IEEE80211_M_HOSTAP)
- break;
- wreq.wi_len -= 2; /* XXX: tx rate? */
- /* FALLTHRU */
- case WI_RID_CHANNEL_LIST:
- memset(chanlist, 0, sizeof(chanlist));
- /*
- * Since channel 0 is not available for DS, channel 1
- * is assigned to LSB on WaveLAN.
- */
- if (ic->ic_phytype == IEEE80211_T_DS)
- i = 1;
- else
- i = 0;
- for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
- if (j / 16 >= wreq.wi_len)
- break;
- if (isclr((u_int8_t *)wreq.wi_val, j))
- continue;
- if (isclr(ic->ic_chan_avail, i)) {
- if (wreq.wi_type == WI_RID_CHANNEL_LIST)
- error = EPERM;
- else
- continue;
- }
- setbit(chanlist, i);
- }
- if (error == EPERM && ic->ic_chancheck != NULL)
- error = (*ic->ic_chancheck)(ic->ic_softc, chanlist);
- if (error)
- return error;
- memcpy(ic->ic_chan_active, chanlist,
- sizeof(ic->ic_chan_active));
- if (isclr(chanlist, ic->ic_ibss_chan)) {
- for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
- if (isset(chanlist, i)) {
- ic->ic_ibss_chan = i;
- break;
- }
- }
- if (isclr(chanlist, ic->ic_bss.ni_chan))
- ic->ic_bss.ni_chan = ic->ic_ibss_chan;
- if (wreq.wi_type == WI_RID_CHANNEL_LIST)
- error = ENETRESET;
- else {
- ic->ic_flags |= IEEE80211_F_SCANAP;
- error = ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
- }
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
-}
-
-/*
- * Module glue.
- *
- * NB: the module name is "wlan" for compatibility with NetBSD.
- */
-
-static int
-ieee80211_modevent(module_t mod, int type, void *unused)
-{
- switch (type) {
- case MOD_LOAD:
- if (bootverbose)
- printf("wlan: <802.11 Link Layer>\n");
- return 0;
- case MOD_UNLOAD:
- return 0;
- }
- return EINVAL;
-}
-
-static moduledata_t ieee80211_mod = {
- "wlan",
- ieee80211_modevent,
- 0
-};
-DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
-MODULE_VERSION(wlan, 1);
-MODULE_DEPEND(wlan, rc4, 1, 1, 1);
OpenPOWER on IntegriCloud