1/*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2001 Atsushi Onoe 3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
|
34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 121179 2003-10-17 22:15:26Z sam $");
| 34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_input.c 121180 2003-10-17 23:15:30Z sam $");
|
35 36#include "opt_inet.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/mbuf.h> 41#include <sys/malloc.h> 42#include <sys/kernel.h> 43#include <sys/socket.h> 44#include <sys/sockio.h> 45#include <sys/endian.h> 46#include <sys/errno.h> 47#include <sys/bus.h> 48#include <sys/proc.h> 49#include <sys/sysctl.h> 50 51#include <machine/atomic.h> 52 53#include <net/if.h> 54#include <net/if_dl.h> 55#include <net/if_media.h> 56#include <net/if_arp.h> 57#include <net/ethernet.h> 58#include <net/if_llc.h> 59 60#include <net80211/ieee80211_var.h> 61 62#include <net/bpf.h> 63 64#ifdef INET 65#include <netinet/in.h> 66#include <netinet/if_ether.h> 67#endif 68 69/* 70 * Process a received frame. The node associated with the sender 71 * should be supplied. If nothing was found in the node table then 72 * the caller is assumed to supply a reference to ic_bss instead. 73 * The RSSI and a timestamp are also supplied. The RSSI data is used 74 * during AP scanning to select a AP to associate with; it can have 75 * any units so long as values have consistent units and higher values 76 * mean ``better signal''. The receive timestamp is currently not used 77 * by the 802.11 layer. 78 */ 79void 80ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, 81 int rssi, u_int32_t rstamp) 82{ 83 struct ieee80211com *ic = (void *)ifp; 84 struct ieee80211_frame *wh; 85 struct ether_header *eh; 86 struct mbuf *m1; 87 int len; 88 u_int8_t dir, type, subtype; 89 u_int8_t *bssid; 90 u_int16_t rxseq; 91 92 KASSERT(ni != NULL, ("null node")); 93 94 /* trim CRC here so WEP can find its own CRC at the end of packet. */ 95 if (m->m_flags & M_HASFCS) { 96 m_adj(m, -IEEE80211_CRC_LEN); 97 m->m_flags &= ~M_HASFCS; 98 } 99 KASSERT(m->m_pkthdr.len >= sizeof(struct ieee80211_frame_min), 100 ("frame length too short: %u", m->m_pkthdr.len)); 101 102 /* 103 * In monitor mode, send everything directly to bpf. 104 * XXX may want to include the CRC 105 */ 106 if (ic->ic_opmode == IEEE80211_M_MONITOR) 107 goto out; 108 109 wh = mtod(m, struct ieee80211_frame *); 110 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != 111 IEEE80211_FC0_VERSION_0) { 112 if (ifp->if_flags & IFF_DEBUG) 113 if_printf(ifp, "receive packet with wrong version: %x\n", 114 wh->i_fc[0]); 115 ieee80211_unref_node(&ni);
| 35 36#include "opt_inet.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/mbuf.h> 41#include <sys/malloc.h> 42#include <sys/kernel.h> 43#include <sys/socket.h> 44#include <sys/sockio.h> 45#include <sys/endian.h> 46#include <sys/errno.h> 47#include <sys/bus.h> 48#include <sys/proc.h> 49#include <sys/sysctl.h> 50 51#include <machine/atomic.h> 52 53#include <net/if.h> 54#include <net/if_dl.h> 55#include <net/if_media.h> 56#include <net/if_arp.h> 57#include <net/ethernet.h> 58#include <net/if_llc.h> 59 60#include <net80211/ieee80211_var.h> 61 62#include <net/bpf.h> 63 64#ifdef INET 65#include <netinet/in.h> 66#include <netinet/if_ether.h> 67#endif 68 69/* 70 * Process a received frame. The node associated with the sender 71 * should be supplied. If nothing was found in the node table then 72 * the caller is assumed to supply a reference to ic_bss instead. 73 * The RSSI and a timestamp are also supplied. The RSSI data is used 74 * during AP scanning to select a AP to associate with; it can have 75 * any units so long as values have consistent units and higher values 76 * mean ``better signal''. The receive timestamp is currently not used 77 * by the 802.11 layer. 78 */ 79void 80ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, 81 int rssi, u_int32_t rstamp) 82{ 83 struct ieee80211com *ic = (void *)ifp; 84 struct ieee80211_frame *wh; 85 struct ether_header *eh; 86 struct mbuf *m1; 87 int len; 88 u_int8_t dir, type, subtype; 89 u_int8_t *bssid; 90 u_int16_t rxseq; 91 92 KASSERT(ni != NULL, ("null node")); 93 94 /* trim CRC here so WEP can find its own CRC at the end of packet. */ 95 if (m->m_flags & M_HASFCS) { 96 m_adj(m, -IEEE80211_CRC_LEN); 97 m->m_flags &= ~M_HASFCS; 98 } 99 KASSERT(m->m_pkthdr.len >= sizeof(struct ieee80211_frame_min), 100 ("frame length too short: %u", m->m_pkthdr.len)); 101 102 /* 103 * In monitor mode, send everything directly to bpf. 104 * XXX may want to include the CRC 105 */ 106 if (ic->ic_opmode == IEEE80211_M_MONITOR) 107 goto out; 108 109 wh = mtod(m, struct ieee80211_frame *); 110 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != 111 IEEE80211_FC0_VERSION_0) { 112 if (ifp->if_flags & IFF_DEBUG) 113 if_printf(ifp, "receive packet with wrong version: %x\n", 114 wh->i_fc[0]); 115 ieee80211_unref_node(&ni);
|
| 116 ic->ic_stats.is_rx_badversion++;
|
116 goto err; 117 } 118 119 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 120 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 121 /* 122 * NB: We are not yet prepared to handle control frames, 123 * but permitting drivers to send them to us allows 124 * them to go through bpf tapping at the 802.11 layer. 125 */ 126 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
| 117 goto err; 118 } 119 120 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 121 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 122 /* 123 * NB: We are not yet prepared to handle control frames, 124 * but permitting drivers to send them to us allows 125 * them to go through bpf tapping at the 802.11 layer. 126 */ 127 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
|
| 128 /* XXX statistic */
|
127 IEEE80211_DPRINTF2(("%s: frame too short, len %u\n", 128 __func__, m->m_pkthdr.len));
| 129 IEEE80211_DPRINTF2(("%s: frame too short, len %u\n", 130 __func__, m->m_pkthdr.len));
|
129 /* XXX statistic */
| 131 ic->ic_stats.is_rx_tooshort++;
|
130 goto out; /* XXX */ 131 } 132 if (ic->ic_state != IEEE80211_S_SCAN) { 133 switch (ic->ic_opmode) { 134 case IEEE80211_M_STA: 135 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
| 132 goto out; /* XXX */ 133 } 134 if (ic->ic_state != IEEE80211_S_SCAN) { 135 switch (ic->ic_opmode) { 136 case IEEE80211_M_STA: 137 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
|
| 138 /* not interested in */
|
136 IEEE80211_DPRINTF2(("%s: discard frame from " 137 "bss %s\n", __func__, 138 ether_sprintf(wh->i_addr2)));
| 139 IEEE80211_DPRINTF2(("%s: discard frame from " 140 "bss %s\n", __func__, 141 ether_sprintf(wh->i_addr2)));
|
139 /* not interested in */
| 142 ic->ic_stats.is_rx_wrongbss++;
|
140 goto out; 141 } 142 break; 143 case IEEE80211_M_IBSS: 144 case IEEE80211_M_AHDEMO: 145 case IEEE80211_M_HOSTAP: 146 if (dir == IEEE80211_FC1_DIR_NODS) 147 bssid = wh->i_addr3; 148 else 149 bssid = wh->i_addr1; 150 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) && 151 !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { 152 /* not interested in */ 153 IEEE80211_DPRINTF2(("%s: discard frame from " 154 "bss %s\n", __func__, 155 ether_sprintf(bssid)));
| 143 goto out; 144 } 145 break; 146 case IEEE80211_M_IBSS: 147 case IEEE80211_M_AHDEMO: 148 case IEEE80211_M_HOSTAP: 149 if (dir == IEEE80211_FC1_DIR_NODS) 150 bssid = wh->i_addr3; 151 else 152 bssid = wh->i_addr1; 153 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) && 154 !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { 155 /* not interested in */ 156 IEEE80211_DPRINTF2(("%s: discard frame from " 157 "bss %s\n", __func__, 158 ether_sprintf(bssid)));
|
| 159 ic->ic_stats.is_rx_wrongbss++;
|
156 goto out; 157 } 158 break; 159 case IEEE80211_M_MONITOR: 160 goto out; 161 default: 162 /* XXX catch bad values */ 163 break; 164 } 165 ni->ni_rssi = rssi; 166 ni->ni_rstamp = rstamp; 167 rxseq = ni->ni_rxseq; 168 ni->ni_rxseq = 169 le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; 170 /* TODO: fragment */ 171 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && 172 rxseq == ni->ni_rxseq) { 173 /* duplicate, silently discarded */
| 160 goto out; 161 } 162 break; 163 case IEEE80211_M_MONITOR: 164 goto out; 165 default: 166 /* XXX catch bad values */ 167 break; 168 } 169 ni->ni_rssi = rssi; 170 ni->ni_rstamp = rstamp; 171 rxseq = ni->ni_rxseq; 172 ni->ni_rxseq = 173 le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; 174 /* TODO: fragment */ 175 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && 176 rxseq == ni->ni_rxseq) { 177 /* duplicate, silently discarded */
|
| 178 ic->ic_stats.is_rx_dup++; /* XXX per-station stat */
|
174 goto out; 175 } 176 ni->ni_inact = 0; 177 } 178 179 switch (type) { 180 case IEEE80211_FC0_TYPE_DATA: 181 switch (ic->ic_opmode) { 182 case IEEE80211_M_STA:
| 179 goto out; 180 } 181 ni->ni_inact = 0; 182 } 183 184 switch (type) { 185 case IEEE80211_FC0_TYPE_DATA: 186 switch (ic->ic_opmode) { 187 case IEEE80211_M_STA:
|
183 if (dir != IEEE80211_FC1_DIR_FROMDS)
| 188 if (dir != IEEE80211_FC1_DIR_FROMDS) { 189 ic->ic_stats.is_rx_wrongdir++;
|
184 goto out;
| 190 goto out;
|
| 191 }
|
185 if ((ifp->if_flags & IFF_SIMPLEX) && 186 IEEE80211_IS_MULTICAST(wh->i_addr1) && 187 IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) { 188 /* 189 * In IEEE802.11 network, multicast packet 190 * sent from me is broadcasted from AP. 191 * It should be silently discarded for 192 * SIMPLEX interface. 193 */
| 192 if ((ifp->if_flags & IFF_SIMPLEX) && 193 IEEE80211_IS_MULTICAST(wh->i_addr1) && 194 IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) { 195 /* 196 * In IEEE802.11 network, multicast packet 197 * sent from me is broadcasted from AP. 198 * It should be silently discarded for 199 * SIMPLEX interface. 200 */
|
| 201 ic->ic_stats.is_rx_mcastecho++;
|
194 goto out; 195 } 196 break; 197 case IEEE80211_M_IBSS: 198 case IEEE80211_M_AHDEMO:
| 202 goto out; 203 } 204 break; 205 case IEEE80211_M_IBSS: 206 case IEEE80211_M_AHDEMO:
|
199 if (dir != IEEE80211_FC1_DIR_NODS)
| 207 if (dir != IEEE80211_FC1_DIR_NODS) { 208 ic->ic_stats.is_rx_wrongdir++;
|
200 goto out;
| 209 goto out;
|
| 210 }
|
201 break; 202 case IEEE80211_M_HOSTAP:
| 211 break; 212 case IEEE80211_M_HOSTAP:
|
203 if (dir != IEEE80211_FC1_DIR_TODS)
| 213 if (dir != IEEE80211_FC1_DIR_TODS) { 214 ic->ic_stats.is_rx_wrongdir++;
|
204 goto out;
| 215 goto out;
|
| 216 }
|
205 /* check if source STA is associated */ 206 if (ni == ic->ic_bss) { 207 IEEE80211_DPRINTF(("%s: data from unknown src " 208 "%s\n", __func__, 209 ether_sprintf(wh->i_addr2))); 210 /* NB: caller deals with reference */ 211 ni = ieee80211_dup_bss(ic, wh->i_addr2); 212 if (ni != NULL) { 213 IEEE80211_SEND_MGMT(ic, ni, 214 IEEE80211_FC0_SUBTYPE_DEAUTH, 215 IEEE80211_REASON_NOT_AUTHED); 216 ieee80211_free_node(ic, ni); 217 }
| 217 /* check if source STA is associated */ 218 if (ni == ic->ic_bss) { 219 IEEE80211_DPRINTF(("%s: data from unknown src " 220 "%s\n", __func__, 221 ether_sprintf(wh->i_addr2))); 222 /* NB: caller deals with reference */ 223 ni = ieee80211_dup_bss(ic, wh->i_addr2); 224 if (ni != NULL) { 225 IEEE80211_SEND_MGMT(ic, ni, 226 IEEE80211_FC0_SUBTYPE_DEAUTH, 227 IEEE80211_REASON_NOT_AUTHED); 228 ieee80211_free_node(ic, ni); 229 }
|
| 230 ic->ic_stats.is_rx_notassoc++;
|
218 goto err; 219 } 220 if (ni->ni_associd == 0) { 221 IEEE80211_DPRINTF(("ieee80211_input: " 222 "data from unassoc src %s\n", 223 ether_sprintf(wh->i_addr2))); 224 IEEE80211_SEND_MGMT(ic, ni, 225 IEEE80211_FC0_SUBTYPE_DISASSOC, 226 IEEE80211_REASON_NOT_ASSOCED); 227 ieee80211_unref_node(&ni);
| 231 goto err; 232 } 233 if (ni->ni_associd == 0) { 234 IEEE80211_DPRINTF(("ieee80211_input: " 235 "data from unassoc src %s\n", 236 ether_sprintf(wh->i_addr2))); 237 IEEE80211_SEND_MGMT(ic, ni, 238 IEEE80211_FC0_SUBTYPE_DISASSOC, 239 IEEE80211_REASON_NOT_ASSOCED); 240 ieee80211_unref_node(&ni);
|
| 241 ic->ic_stats.is_rx_notassoc++;
|
228 goto err; 229 } 230 break; 231 case IEEE80211_M_MONITOR: 232 break; 233 } 234 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 235 if (ic->ic_flags & IEEE80211_F_WEPON) { 236 m = ieee80211_wep_crypt(ifp, m, 0);
| 242 goto err; 243 } 244 break; 245 case IEEE80211_M_MONITOR: 246 break; 247 } 248 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 249 if (ic->ic_flags & IEEE80211_F_WEPON) { 250 m = ieee80211_wep_crypt(ifp, m, 0);
|
237 if (m == NULL)
| 251 if (m == NULL) { 252 ic->ic_stats.is_rx_wepfail++;
|
238 goto err;
| 253 goto err;
|
| 254 }
|
239 wh = mtod(m, struct ieee80211_frame *);
| 255 wh = mtod(m, struct ieee80211_frame *);
|
240 } else
| 256 } else { 257 ic->ic_stats.is_rx_nowep++;
|
241 goto out;
| 258 goto out;
|
| 259 }
|
242 } 243 /* copy to listener after decrypt */ 244 if (ic->ic_rawbpf) 245 bpf_mtap(ic->ic_rawbpf, m); 246 m = ieee80211_decap(ifp, m);
| 260 } 261 /* copy to listener after decrypt */ 262 if (ic->ic_rawbpf) 263 bpf_mtap(ic->ic_rawbpf, m); 264 m = ieee80211_decap(ifp, m);
|
247 if (m == NULL)
| 265 if (m == NULL) { 266 ic->ic_stats.is_rx_decap++;
|
248 goto err;
| 267 goto err;
|
| 268 }
|
249 ifp->if_ipackets++; 250 251 /* perform as a bridge within the AP */ 252 m1 = NULL; 253 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 254 eh = mtod(m, struct ether_header *); 255 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 256 m1 = m_copypacket(m, M_DONTWAIT); 257 if (m1 == NULL) 258 ifp->if_oerrors++; 259 else 260 m1->m_flags |= M_MCAST; 261 } else { 262 ni = ieee80211_find_node(ic, eh->ether_dhost); 263 if (ni != NULL) { 264 if (ni->ni_associd != 0) { 265 m1 = m; 266 m = NULL; 267 } 268 ieee80211_unref_node(&ni); 269 } 270 } 271 if (m1 != NULL) { 272#ifdef ALTQ 273 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 274 altq_etherclassify(&ifp->if_snd, m1, 275 &pktattr); 276#endif 277 len = m1->m_pkthdr.len; 278 IF_ENQUEUE(&ifp->if_snd, m1); 279 if (m != NULL) 280 ifp->if_omcasts++; 281 ifp->if_obytes += len; 282 } 283 } 284 if (m != NULL) 285 (*ifp->if_input)(ifp, m); 286 return; 287 288 case IEEE80211_FC0_TYPE_MGT:
| 269 ifp->if_ipackets++; 270 271 /* perform as a bridge within the AP */ 272 m1 = NULL; 273 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 274 eh = mtod(m, struct ether_header *); 275 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 276 m1 = m_copypacket(m, M_DONTWAIT); 277 if (m1 == NULL) 278 ifp->if_oerrors++; 279 else 280 m1->m_flags |= M_MCAST; 281 } else { 282 ni = ieee80211_find_node(ic, eh->ether_dhost); 283 if (ni != NULL) { 284 if (ni->ni_associd != 0) { 285 m1 = m; 286 m = NULL; 287 } 288 ieee80211_unref_node(&ni); 289 } 290 } 291 if (m1 != NULL) { 292#ifdef ALTQ 293 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 294 altq_etherclassify(&ifp->if_snd, m1, 295 &pktattr); 296#endif 297 len = m1->m_pkthdr.len; 298 IF_ENQUEUE(&ifp->if_snd, m1); 299 if (m != NULL) 300 ifp->if_omcasts++; 301 ifp->if_obytes += len; 302 } 303 } 304 if (m != NULL) 305 (*ifp->if_input)(ifp, m); 306 return; 307 308 case IEEE80211_FC0_TYPE_MGT:
|
289 if (dir != IEEE80211_FC1_DIR_NODS)
| 309 if (dir != IEEE80211_FC1_DIR_NODS) { 310 ic->ic_stats.is_rx_wrongdir++;
|
290 goto err;
| 311 goto err;
|
291 if (ic->ic_opmode == IEEE80211_M_AHDEMO)
| 312 } 313 if (ic->ic_opmode == IEEE80211_M_AHDEMO) { 314 ic->ic_stats.is_rx_ahdemo_mgt++;
|
292 goto out;
| 315 goto out;
|
| 316 }
|
293 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 294 295 /* drop frames without interest */ 296 if (ic->ic_state == IEEE80211_S_SCAN) { 297 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
| 317 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 318 319 /* drop frames without interest */ 320 if (ic->ic_state == IEEE80211_S_SCAN) { 321 if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
|
298 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
| 322 subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) { 323 ic->ic_stats.is_rx_mgtdiscard++;
|
299 goto out;
| 324 goto out;
|
| 325 }
|
300 } else { 301 if (ic->ic_opmode != IEEE80211_M_IBSS &&
| 326 } else { 327 if (ic->ic_opmode != IEEE80211_M_IBSS &&
|
302 subtype == IEEE80211_FC0_SUBTYPE_BEACON)
| 328 subtype == IEEE80211_FC0_SUBTYPE_BEACON) { 329 ic->ic_stats.is_rx_mgtdiscard++;
|
303 goto out;
| 330 goto out;
|
| 331 }
|
304 } 305 306 if (ifp->if_flags & IFF_DEBUG) { 307 /* avoid to print too many frames */ 308 int doprint = 0; 309 310 switch (subtype) { 311 case IEEE80211_FC0_SUBTYPE_BEACON: 312 if (ic->ic_state == IEEE80211_S_SCAN) 313 doprint = 1; 314 break; 315 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 316 if (ic->ic_opmode == IEEE80211_M_IBSS) 317 doprint = 1; 318 break; 319 default: 320 doprint = 1; 321 break; 322 } 323#ifdef IEEE80211_DEBUG 324 doprint += ieee80211_debug; 325#endif 326 if (doprint) 327 if_printf(ifp, "received %s from %s rssi %d\n", 328 ieee80211_mgt_subtype_name[subtype 329 >> IEEE80211_FC0_SUBTYPE_SHIFT], 330 ether_sprintf(wh->i_addr2), rssi); 331 } 332 if (ic->ic_rawbpf) 333 bpf_mtap(ic->ic_rawbpf, m); 334 (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); 335 m_freem(m); 336 return; 337 338 case IEEE80211_FC0_TYPE_CTL:
| 332 } 333 334 if (ifp->if_flags & IFF_DEBUG) { 335 /* avoid to print too many frames */ 336 int doprint = 0; 337 338 switch (subtype) { 339 case IEEE80211_FC0_SUBTYPE_BEACON: 340 if (ic->ic_state == IEEE80211_S_SCAN) 341 doprint = 1; 342 break; 343 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 344 if (ic->ic_opmode == IEEE80211_M_IBSS) 345 doprint = 1; 346 break; 347 default: 348 doprint = 1; 349 break; 350 } 351#ifdef IEEE80211_DEBUG 352 doprint += ieee80211_debug; 353#endif 354 if (doprint) 355 if_printf(ifp, "received %s from %s rssi %d\n", 356 ieee80211_mgt_subtype_name[subtype 357 >> IEEE80211_FC0_SUBTYPE_SHIFT], 358 ether_sprintf(wh->i_addr2), rssi); 359 } 360 if (ic->ic_rawbpf) 361 bpf_mtap(ic->ic_rawbpf, m); 362 (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); 363 m_freem(m); 364 return; 365 366 case IEEE80211_FC0_TYPE_CTL:
|
| 367 ic->ic_stats.is_rx_ctl++;
|
339 goto out; 340 default: 341 IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type)); 342 /* should not come here */ 343 break; 344 } 345 err: 346 ifp->if_ierrors++; 347 out: 348 if (m != NULL) { 349 if (ic->ic_rawbpf) 350 bpf_mtap(ic->ic_rawbpf, m); 351 m_freem(m); 352 } 353} 354 355struct mbuf * 356ieee80211_decap(struct ifnet *ifp, struct mbuf *m) 357{ 358 struct ether_header *eh; 359 struct ieee80211_frame wh; 360 struct llc *llc; 361 362 if (m->m_len < sizeof(wh) + sizeof(*llc)) { 363 m = m_pullup(m, sizeof(wh) + sizeof(*llc)); 364 if (m == NULL) 365 return NULL; 366 } 367 memcpy(&wh, mtod(m, caddr_t), sizeof(wh)); 368 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); 369 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP && 370 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 && 371 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) { 372 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh)); 373 llc = NULL; 374 } else { 375 m_adj(m, sizeof(wh) - sizeof(*eh)); 376 } 377 eh = mtod(m, struct ether_header *); 378 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { 379 case IEEE80211_FC1_DIR_NODS: 380 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); 381 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); 382 break; 383 case IEEE80211_FC1_DIR_TODS: 384 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3); 385 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); 386 break; 387 case IEEE80211_FC1_DIR_FROMDS: 388 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); 389 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3); 390 break; 391 case IEEE80211_FC1_DIR_DSTODS: 392 /* not yet supported */ 393 IEEE80211_DPRINTF(("%s: DS to DS\n", __func__)); 394 m_freem(m); 395 return NULL; 396 } 397#ifdef ALIGNED_POINTER 398 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) { 399 struct mbuf *n, *n0, **np; 400 caddr_t newdata; 401 int off, pktlen; 402 403 n0 = NULL; 404 np = &n0; 405 off = 0; 406 pktlen = m->m_pkthdr.len; 407 while (pktlen > off) { 408 if (n0 == NULL) { 409 MGETHDR(n, M_DONTWAIT, MT_DATA); 410 if (n == NULL) { 411 m_freem(m); 412 return NULL; 413 } 414 M_MOVE_PKTHDR(n, m); 415 n->m_len = MHLEN; 416 } else { 417 MGET(n, M_DONTWAIT, MT_DATA); 418 if (n == NULL) { 419 m_freem(m); 420 m_freem(n0); 421 return NULL; 422 } 423 n->m_len = MLEN; 424 } 425 if (pktlen - off >= MINCLSIZE) { 426 MCLGET(n, M_DONTWAIT); 427 if (n->m_flags & M_EXT) 428 n->m_len = n->m_ext.ext_size; 429 } 430 if (n0 == NULL) { 431 newdata = 432 (caddr_t)ALIGN(n->m_data + sizeof(*eh)) - 433 sizeof(*eh); 434 n->m_len -= newdata - n->m_data; 435 n->m_data = newdata; 436 } 437 if (n->m_len > pktlen - off) 438 n->m_len = pktlen - off; 439 m_copydata(m, off, n->m_len, mtod(n, caddr_t)); 440 off += n->m_len; 441 *np = n; 442 np = &n->m_next; 443 } 444 m_freem(m); 445 m = n0; 446 } 447#endif /* ALIGNED_POINTER */ 448 if (llc != NULL) { 449 eh = mtod(m, struct ether_header *); 450 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh)); 451 } 452 return m; 453} 454 455/* 456 * Install received rate set information in the node's state block. 457 */ 458static int 459ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni, 460 u_int8_t *rates, u_int8_t *xrates, int flags) 461{ 462 struct ieee80211_rateset *rs = &ni->ni_rates; 463 464 memset(rs, 0, sizeof(*rs)); 465 rs->rs_nrates = rates[1]; 466 memcpy(rs->rs_rates, rates + 2, rs->rs_nrates); 467 if (xrates != NULL) { 468 u_int8_t nxrates; 469 /* 470 * Tack on 11g extended supported rate element. 471 */ 472 nxrates = xrates[1]; 473 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) { 474 nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates; 475 IEEE80211_DPRINTF(("%s: extended rate set too large;" 476 " only using %u of %u rates\n", 477 __func__, nxrates, xrates[1]));
| 368 goto out; 369 default: 370 IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type)); 371 /* should not come here */ 372 break; 373 } 374 err: 375 ifp->if_ierrors++; 376 out: 377 if (m != NULL) { 378 if (ic->ic_rawbpf) 379 bpf_mtap(ic->ic_rawbpf, m); 380 m_freem(m); 381 } 382} 383 384struct mbuf * 385ieee80211_decap(struct ifnet *ifp, struct mbuf *m) 386{ 387 struct ether_header *eh; 388 struct ieee80211_frame wh; 389 struct llc *llc; 390 391 if (m->m_len < sizeof(wh) + sizeof(*llc)) { 392 m = m_pullup(m, sizeof(wh) + sizeof(*llc)); 393 if (m == NULL) 394 return NULL; 395 } 396 memcpy(&wh, mtod(m, caddr_t), sizeof(wh)); 397 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); 398 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP && 399 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 && 400 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) { 401 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh)); 402 llc = NULL; 403 } else { 404 m_adj(m, sizeof(wh) - sizeof(*eh)); 405 } 406 eh = mtod(m, struct ether_header *); 407 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { 408 case IEEE80211_FC1_DIR_NODS: 409 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); 410 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); 411 break; 412 case IEEE80211_FC1_DIR_TODS: 413 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3); 414 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); 415 break; 416 case IEEE80211_FC1_DIR_FROMDS: 417 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); 418 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3); 419 break; 420 case IEEE80211_FC1_DIR_DSTODS: 421 /* not yet supported */ 422 IEEE80211_DPRINTF(("%s: DS to DS\n", __func__)); 423 m_freem(m); 424 return NULL; 425 } 426#ifdef ALIGNED_POINTER 427 if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) { 428 struct mbuf *n, *n0, **np; 429 caddr_t newdata; 430 int off, pktlen; 431 432 n0 = NULL; 433 np = &n0; 434 off = 0; 435 pktlen = m->m_pkthdr.len; 436 while (pktlen > off) { 437 if (n0 == NULL) { 438 MGETHDR(n, M_DONTWAIT, MT_DATA); 439 if (n == NULL) { 440 m_freem(m); 441 return NULL; 442 } 443 M_MOVE_PKTHDR(n, m); 444 n->m_len = MHLEN; 445 } else { 446 MGET(n, M_DONTWAIT, MT_DATA); 447 if (n == NULL) { 448 m_freem(m); 449 m_freem(n0); 450 return NULL; 451 } 452 n->m_len = MLEN; 453 } 454 if (pktlen - off >= MINCLSIZE) { 455 MCLGET(n, M_DONTWAIT); 456 if (n->m_flags & M_EXT) 457 n->m_len = n->m_ext.ext_size; 458 } 459 if (n0 == NULL) { 460 newdata = 461 (caddr_t)ALIGN(n->m_data + sizeof(*eh)) - 462 sizeof(*eh); 463 n->m_len -= newdata - n->m_data; 464 n->m_data = newdata; 465 } 466 if (n->m_len > pktlen - off) 467 n->m_len = pktlen - off; 468 m_copydata(m, off, n->m_len, mtod(n, caddr_t)); 469 off += n->m_len; 470 *np = n; 471 np = &n->m_next; 472 } 473 m_freem(m); 474 m = n0; 475 } 476#endif /* ALIGNED_POINTER */ 477 if (llc != NULL) { 478 eh = mtod(m, struct ether_header *); 479 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh)); 480 } 481 return m; 482} 483 484/* 485 * Install received rate set information in the node's state block. 486 */ 487static int 488ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni, 489 u_int8_t *rates, u_int8_t *xrates, int flags) 490{ 491 struct ieee80211_rateset *rs = &ni->ni_rates; 492 493 memset(rs, 0, sizeof(*rs)); 494 rs->rs_nrates = rates[1]; 495 memcpy(rs->rs_rates, rates + 2, rs->rs_nrates); 496 if (xrates != NULL) { 497 u_int8_t nxrates; 498 /* 499 * Tack on 11g extended supported rate element. 500 */ 501 nxrates = xrates[1]; 502 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) { 503 nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates; 504 IEEE80211_DPRINTF(("%s: extended rate set too large;" 505 " only using %u of %u rates\n", 506 __func__, nxrates, xrates[1]));
|
| 507 ic->ic_stats.is_rx_rstoobig++;
|
478 } 479 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates); 480 rs->rs_nrates += nxrates; 481 } 482 return ieee80211_fix_rate(ic, ni, flags); 483} 484
| 508 } 509 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates); 510 rs->rs_nrates += nxrates; 511 } 512 return ieee80211_fix_rate(ic, ni, flags); 513} 514
|
485/* XXX statistics */
| |
486/* Verify the existence and length of __elem or get out. */ 487#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ 488 if ((__elem) == NULL) { \ 489 IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \ 490 __func__, ieee80211_mgt_subtype_name[subtype >> \ 491 IEEE80211_FC0_SUBTYPE_SHIFT])); \
| 515/* Verify the existence and length of __elem or get out. */ 516#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ 517 if ((__elem) == NULL) { \ 518 IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \ 519 __func__, ieee80211_mgt_subtype_name[subtype >> \ 520 IEEE80211_FC0_SUBTYPE_SHIFT])); \
|
| 521 ic->ic_stats.is_rx_elem_missing++; \
|
492 return; \ 493 } \ 494 if ((__elem)[1] > (__maxlen)) { \ 495 IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \ 496 "frame from %s\n", __func__, (__elem)[1], \ 497 ieee80211_mgt_subtype_name[subtype >> \ 498 IEEE80211_FC0_SUBTYPE_SHIFT], \ 499 ether_sprintf(wh->i_addr2))); \
| 522 return; \ 523 } \ 524 if ((__elem)[1] > (__maxlen)) { \ 525 IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \ 526 "frame from %s\n", __func__, (__elem)[1], \ 527 ieee80211_mgt_subtype_name[subtype >> \ 528 IEEE80211_FC0_SUBTYPE_SHIFT], \ 529 ether_sprintf(wh->i_addr2))); \
|
| 530 ic->ic_stats.is_rx_elem_toobig++; \
|
500 return; \ 501 } \ 502} while (0) 503 504#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ 505 if ((_len) < (_minlen)) { \ 506 IEEE80211_DPRINTF(("%s: %s frame too short from %s\n", \ 507 __func__, \ 508 ieee80211_mgt_subtype_name[subtype >> \ 509 IEEE80211_FC0_SUBTYPE_SHIFT], \ 510 ether_sprintf(wh->i_addr2))); \
| 531 return; \ 532 } \ 533} while (0) 534 535#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ 536 if ((_len) < (_minlen)) { \ 537 IEEE80211_DPRINTF(("%s: %s frame too short from %s\n", \ 538 __func__, \ 539 ieee80211_mgt_subtype_name[subtype >> \ 540 IEEE80211_FC0_SUBTYPE_SHIFT], \ 541 ether_sprintf(wh->i_addr2))); \
|
| 542 ic->ic_stats.is_rx_elem_toosmall++; \
|
511 return; \ 512 } \ 513} while (0) 514 515void 516ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, 517 struct ieee80211_node *ni, 518 int subtype, int rssi, u_int32_t rstamp) 519{ 520#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP) 521 struct ifnet *ifp = &ic->ic_if; 522 struct ieee80211_frame *wh; 523 u_int8_t *frm, *efrm; 524 u_int8_t *ssid, *rates, *xrates; 525 int reassoc, resp, newassoc, allocbs; 526 527 wh = mtod(m0, struct ieee80211_frame *); 528 frm = (u_int8_t *)&wh[1]; 529 efrm = mtod(m0, u_int8_t *) + m0->m_len; 530 switch (subtype) { 531 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 532 case IEEE80211_FC0_SUBTYPE_BEACON: { 533 u_int8_t *tstamp, *bintval, *capinfo, *country; 534 u_int8_t chan, bchan, fhindex, erp; 535 u_int16_t fhdwell; 536 537 if (ic->ic_opmode != IEEE80211_M_IBSS && 538 ic->ic_state != IEEE80211_S_SCAN) { 539 /* XXX: may be useful for background scan */ 540 return; 541 } 542 543 /* 544 * beacon/probe response frame format 545 * [8] time stamp 546 * [2] beacon interval 547 * [2] capability information 548 * [tlv] ssid 549 * [tlv] supported rates 550 * [tlv] country information 551 * [tlv] parameter set (FH/DS) 552 * [tlv] erp information 553 * [tlv] extended supported rates 554 */ 555 IEEE80211_VERIFY_LENGTH(efrm - frm, 12); 556 tstamp = frm; frm += 8; 557 bintval = frm; frm += 2; 558 capinfo = frm; frm += 2; 559 ssid = rates = xrates = country = NULL; 560 bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); 561 chan = bchan; 562 fhdwell = 0; 563 fhindex = 0; 564 erp = 0; 565 while (frm < efrm) { 566 switch (*frm) { 567 case IEEE80211_ELEMID_SSID: 568 ssid = frm; 569 break; 570 case IEEE80211_ELEMID_RATES: 571 rates = frm; 572 break; 573 case IEEE80211_ELEMID_COUNTRY: 574 country = frm; 575 break; 576 case IEEE80211_ELEMID_FHPARMS: 577 if (ic->ic_phytype == IEEE80211_T_FH) { 578 fhdwell = (frm[3] << 8) | frm[2]; 579 chan = IEEE80211_FH_CHAN(frm[4], frm[5]); 580 fhindex = frm[6]; 581 } 582 break; 583 case IEEE80211_ELEMID_DSPARMS: 584 /* 585 * XXX hack this since depending on phytype 586 * is problematic for multi-mode devices. 587 */ 588 if (ic->ic_phytype != IEEE80211_T_FH) 589 chan = frm[2]; 590 break; 591 case IEEE80211_ELEMID_TIM: 592 break; 593 case IEEE80211_ELEMID_XRATES: 594 xrates = frm; 595 break; 596 case IEEE80211_ELEMID_ERP: 597 if (frm[1] != 1) { 598 IEEE80211_DPRINTF(("%s: invalid ERP " 599 "element; length %u, expecting " 600 "1\n", __func__, frm[1]));
| 543 return; \ 544 } \ 545} while (0) 546 547void 548ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, 549 struct ieee80211_node *ni, 550 int subtype, int rssi, u_int32_t rstamp) 551{ 552#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP) 553 struct ifnet *ifp = &ic->ic_if; 554 struct ieee80211_frame *wh; 555 u_int8_t *frm, *efrm; 556 u_int8_t *ssid, *rates, *xrates; 557 int reassoc, resp, newassoc, allocbs; 558 559 wh = mtod(m0, struct ieee80211_frame *); 560 frm = (u_int8_t *)&wh[1]; 561 efrm = mtod(m0, u_int8_t *) + m0->m_len; 562 switch (subtype) { 563 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 564 case IEEE80211_FC0_SUBTYPE_BEACON: { 565 u_int8_t *tstamp, *bintval, *capinfo, *country; 566 u_int8_t chan, bchan, fhindex, erp; 567 u_int16_t fhdwell; 568 569 if (ic->ic_opmode != IEEE80211_M_IBSS && 570 ic->ic_state != IEEE80211_S_SCAN) { 571 /* XXX: may be useful for background scan */ 572 return; 573 } 574 575 /* 576 * beacon/probe response frame format 577 * [8] time stamp 578 * [2] beacon interval 579 * [2] capability information 580 * [tlv] ssid 581 * [tlv] supported rates 582 * [tlv] country information 583 * [tlv] parameter set (FH/DS) 584 * [tlv] erp information 585 * [tlv] extended supported rates 586 */ 587 IEEE80211_VERIFY_LENGTH(efrm - frm, 12); 588 tstamp = frm; frm += 8; 589 bintval = frm; frm += 2; 590 capinfo = frm; frm += 2; 591 ssid = rates = xrates = country = NULL; 592 bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); 593 chan = bchan; 594 fhdwell = 0; 595 fhindex = 0; 596 erp = 0; 597 while (frm < efrm) { 598 switch (*frm) { 599 case IEEE80211_ELEMID_SSID: 600 ssid = frm; 601 break; 602 case IEEE80211_ELEMID_RATES: 603 rates = frm; 604 break; 605 case IEEE80211_ELEMID_COUNTRY: 606 country = frm; 607 break; 608 case IEEE80211_ELEMID_FHPARMS: 609 if (ic->ic_phytype == IEEE80211_T_FH) { 610 fhdwell = (frm[3] << 8) | frm[2]; 611 chan = IEEE80211_FH_CHAN(frm[4], frm[5]); 612 fhindex = frm[6]; 613 } 614 break; 615 case IEEE80211_ELEMID_DSPARMS: 616 /* 617 * XXX hack this since depending on phytype 618 * is problematic for multi-mode devices. 619 */ 620 if (ic->ic_phytype != IEEE80211_T_FH) 621 chan = frm[2]; 622 break; 623 case IEEE80211_ELEMID_TIM: 624 break; 625 case IEEE80211_ELEMID_XRATES: 626 xrates = frm; 627 break; 628 case IEEE80211_ELEMID_ERP: 629 if (frm[1] != 1) { 630 IEEE80211_DPRINTF(("%s: invalid ERP " 631 "element; length %u, expecting " 632 "1\n", __func__, frm[1]));
|
| 633 ic->ic_stats.is_rx_elem_toobig++;
|
601 break; 602 } 603 erp = frm[2]; 604 break; 605 default: 606 IEEE80211_DPRINTF2(("%s: element id %u/len %u " 607 "ignored\n", __func__, *frm, frm[1]));
| 634 break; 635 } 636 erp = frm[2]; 637 break; 638 default: 639 IEEE80211_DPRINTF2(("%s: element id %u/len %u " 640 "ignored\n", __func__, *frm, frm[1]));
|
| 641 ic->ic_stats.is_rx_elem_unknown++;
|
608 break; 609 } 610 frm += frm[1] + 2; 611 } 612 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 613 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 614 if ( 615#if IEEE80211_CHAN_MAX < 255 616 chan > IEEE80211_CHAN_MAX || 617#endif 618 isclr(ic->ic_chan_active, chan)) { 619 IEEE80211_DPRINTF(("%s: ignore %s with invalid channel " 620 "%u\n", __func__, 621 ISPROBE(subtype) ? "probe response" : "beacon", 622 chan));
| 642 break; 643 } 644 frm += frm[1] + 2; 645 } 646 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 647 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 648 if ( 649#if IEEE80211_CHAN_MAX < 255 650 chan > IEEE80211_CHAN_MAX || 651#endif 652 isclr(ic->ic_chan_active, chan)) { 653 IEEE80211_DPRINTF(("%s: ignore %s with invalid channel " 654 "%u\n", __func__, 655 ISPROBE(subtype) ? "probe response" : "beacon", 656 chan));
|
| 657 ic->ic_stats.is_rx_badchan++;
|
623 return; 624 } 625 if (chan != bchan) { 626 /* 627 * Frame was received on a channel different from the 628 * one indicated in the DS/FH params element id; 629 * silently discard it. 630 * 631 * NB: this can happen due to signal leakage. 632 */ 633 IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked " 634 "for channel %u\n", __func__, 635 ISPROBE(subtype) ? "probe response" : "beacon", 636 bchan, chan));
| 658 return; 659 } 660 if (chan != bchan) { 661 /* 662 * Frame was received on a channel different from the 663 * one indicated in the DS/FH params element id; 664 * silently discard it. 665 * 666 * NB: this can happen due to signal leakage. 667 */ 668 IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked " 669 "for channel %u\n", __func__, 670 ISPROBE(subtype) ? "probe response" : "beacon", 671 bchan, chan));
|
637 /* XXX statistic */
| 672 ic->ic_stats.is_rx_chanmismatch++;
|
638 return; 639 } 640 641 /* 642 * Use mac and channel for lookup so we collect all 643 * potential AP's when scanning. Otherwise we may 644 * see the same AP on multiple channels and will only 645 * record the last one. We could filter APs here based 646 * on rssi, etc. but leave that to the end of the scan 647 * so we can keep the selection criteria in one spot. 648 * This may result in a bloat of the scanned AP list but 649 * it shouldn't be too much. 650 */ 651 ni = ieee80211_lookup_node(ic, wh->i_addr2, 652 &ic->ic_channels[chan]); 653#ifdef IEEE80211_DEBUG 654 if (ieee80211_debug && 655 (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) { 656 printf("%s: %s%s on chan %u (bss chan %u) ", 657 __func__, (ni == NULL ? "new " : ""), 658 ISPROBE(subtype) ? "probe response" : "beacon", 659 chan, bchan); 660 ieee80211_print_essid(ssid + 2, ssid[1]); 661 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 662 printf("%s: caps 0x%x bintval %u erp 0x%x\n", 663 __func__, le16toh(*(u_int16_t *)capinfo), 664 le16toh(*(u_int16_t *)bintval), erp); 665 if (country) 666 printf("%s: country info %*D\n", 667 __func__, country[1], country+2, " "); 668 } 669#endif 670 if (ni == NULL) { 671 ni = ieee80211_alloc_node(ic, wh->i_addr2);
| 673 return; 674 } 675 676 /* 677 * Use mac and channel for lookup so we collect all 678 * potential AP's when scanning. Otherwise we may 679 * see the same AP on multiple channels and will only 680 * record the last one. We could filter APs here based 681 * on rssi, etc. but leave that to the end of the scan 682 * so we can keep the selection criteria in one spot. 683 * This may result in a bloat of the scanned AP list but 684 * it shouldn't be too much. 685 */ 686 ni = ieee80211_lookup_node(ic, wh->i_addr2, 687 &ic->ic_channels[chan]); 688#ifdef IEEE80211_DEBUG 689 if (ieee80211_debug && 690 (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) { 691 printf("%s: %s%s on chan %u (bss chan %u) ", 692 __func__, (ni == NULL ? "new " : ""), 693 ISPROBE(subtype) ? "probe response" : "beacon", 694 chan, bchan); 695 ieee80211_print_essid(ssid + 2, ssid[1]); 696 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 697 printf("%s: caps 0x%x bintval %u erp 0x%x\n", 698 __func__, le16toh(*(u_int16_t *)capinfo), 699 le16toh(*(u_int16_t *)bintval), erp); 700 if (country) 701 printf("%s: country info %*D\n", 702 __func__, country[1], country+2, " "); 703 } 704#endif 705 if (ni == NULL) { 706 ni = ieee80211_alloc_node(ic, wh->i_addr2);
|
672 if (ni == NULL)
| 707 if (ni == NULL) { 708 ic->ic_stats.is_rx_nodealloc++;
|
673 return;
| 709 return;
|
| 710 }
|
674 ni->ni_esslen = ssid[1]; 675 memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); 676 memcpy(ni->ni_essid, ssid + 2, ssid[1]); 677 } else if (ssid[1] != 0 && ISPROBE(subtype)) { 678 /* 679 * Update ESSID at probe response to adopt hidden AP by 680 * Lucent/Cisco, which announces null ESSID in beacon. 681 */ 682 ni->ni_esslen = ssid[1]; 683 memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); 684 memcpy(ni->ni_essid, ssid + 2, ssid[1]); 685 } 686 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); 687 ni->ni_rssi = rssi; 688 ni->ni_rstamp = rstamp; 689 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp)); 690 ni->ni_intval = le16toh(*(u_int16_t *)bintval); 691 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo); 692 /* XXX validate channel # */ 693 ni->ni_chan = &ic->ic_channels[chan]; 694 ni->ni_fhdwell = fhdwell; 695 ni->ni_fhindex = fhindex; 696 ni->ni_erp = erp; 697 /* NB: must be after ni_chan is setup */ 698 ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT); 699 ieee80211_unref_node(&ni); 700 break; 701 } 702 703 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: { 704 u_int8_t rate; 705 706 if (ic->ic_opmode == IEEE80211_M_STA) 707 return; 708 if (ic->ic_state != IEEE80211_S_RUN) 709 return; 710 711 /* 712 * prreq frame format 713 * [tlv] ssid 714 * [tlv] supported rates 715 * [tlv] extended supported rates 716 */ 717 ssid = rates = xrates = NULL; 718 while (frm < efrm) { 719 switch (*frm) { 720 case IEEE80211_ELEMID_SSID: 721 ssid = frm; 722 break; 723 case IEEE80211_ELEMID_RATES: 724 rates = frm; 725 break; 726 case IEEE80211_ELEMID_XRATES: 727 xrates = frm; 728 break; 729 } 730 frm += frm[1] + 2; 731 } 732 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 733 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 734 if (ssid[1] != 0 && 735 (ssid[1] != ic->ic_bss->ni_esslen || 736 memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) { 737#ifdef IEEE80211_DEBUG 738 if (ieee80211_debug) { 739 printf("%s: ssid unmatch ", __func__); 740 ieee80211_print_essid(ssid + 2, ssid[1]); 741 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 742 } 743#endif
| 711 ni->ni_esslen = ssid[1]; 712 memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); 713 memcpy(ni->ni_essid, ssid + 2, ssid[1]); 714 } else if (ssid[1] != 0 && ISPROBE(subtype)) { 715 /* 716 * Update ESSID at probe response to adopt hidden AP by 717 * Lucent/Cisco, which announces null ESSID in beacon. 718 */ 719 ni->ni_esslen = ssid[1]; 720 memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); 721 memcpy(ni->ni_essid, ssid + 2, ssid[1]); 722 } 723 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); 724 ni->ni_rssi = rssi; 725 ni->ni_rstamp = rstamp; 726 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp)); 727 ni->ni_intval = le16toh(*(u_int16_t *)bintval); 728 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo); 729 /* XXX validate channel # */ 730 ni->ni_chan = &ic->ic_channels[chan]; 731 ni->ni_fhdwell = fhdwell; 732 ni->ni_fhindex = fhindex; 733 ni->ni_erp = erp; 734 /* NB: must be after ni_chan is setup */ 735 ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT); 736 ieee80211_unref_node(&ni); 737 break; 738 } 739 740 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: { 741 u_int8_t rate; 742 743 if (ic->ic_opmode == IEEE80211_M_STA) 744 return; 745 if (ic->ic_state != IEEE80211_S_RUN) 746 return; 747 748 /* 749 * prreq frame format 750 * [tlv] ssid 751 * [tlv] supported rates 752 * [tlv] extended supported rates 753 */ 754 ssid = rates = xrates = NULL; 755 while (frm < efrm) { 756 switch (*frm) { 757 case IEEE80211_ELEMID_SSID: 758 ssid = frm; 759 break; 760 case IEEE80211_ELEMID_RATES: 761 rates = frm; 762 break; 763 case IEEE80211_ELEMID_XRATES: 764 xrates = frm; 765 break; 766 } 767 frm += frm[1] + 2; 768 } 769 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 770 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 771 if (ssid[1] != 0 && 772 (ssid[1] != ic->ic_bss->ni_esslen || 773 memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) { 774#ifdef IEEE80211_DEBUG 775 if (ieee80211_debug) { 776 printf("%s: ssid unmatch ", __func__); 777 ieee80211_print_essid(ssid + 2, ssid[1]); 778 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 779 } 780#endif
|
| 781 ic->ic_stats.is_rx_ssidmismatch++;
|
744 return; 745 } 746 747 if (ni == ic->ic_bss) { 748 ni = ieee80211_dup_bss(ic, wh->i_addr2);
| 782 return; 783 } 784 785 if (ni == ic->ic_bss) { 786 ni = ieee80211_dup_bss(ic, wh->i_addr2);
|
749 if (ni == NULL)
| 787 if (ni == NULL) { 788 ic->ic_stats.is_rx_nodealloc++;
|
750 return;
| 789 return;
|
| 790 }
|
751 IEEE80211_DPRINTF(("%s: new req from %s\n", 752 __func__, ether_sprintf(wh->i_addr2))); 753 allocbs = 1; 754 } else 755 allocbs = 0; 756 ni->ni_rssi = rssi; 757 ni->ni_rstamp = rstamp; 758 rate = ieee80211_setup_rates(ic, ni, rates, xrates, 759 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE 760 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 761 if (rate & IEEE80211_RATE_BASIC) { 762 IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n", 763 __func__,ether_sprintf(wh->i_addr2))); 764 } else { 765 IEEE80211_SEND_MGMT(ic, ni, 766 IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); 767 } 768 if (allocbs) { 769 /* XXX just use free? */ 770 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 771 ieee80211_free_node(ic, ni); 772 else 773 ieee80211_unref_node(&ni); 774 } 775 break; 776 } 777 778 case IEEE80211_FC0_SUBTYPE_AUTH: { 779 u_int16_t algo, seq, status; 780 /* 781 * auth frame format 782 * [2] algorithm 783 * [2] sequence 784 * [2] status 785 * [tlv*] challenge 786 */ 787 IEEE80211_VERIFY_LENGTH(efrm - frm, 6); 788 algo = le16toh(*(u_int16_t *)frm); 789 seq = le16toh(*(u_int16_t *)(frm + 2)); 790 status = le16toh(*(u_int16_t *)(frm + 4)); 791 if (algo != IEEE80211_AUTH_ALG_OPEN) { 792 /* TODO: shared key auth */ 793 IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n", 794 __func__, algo, ether_sprintf(wh->i_addr2)));
| 791 IEEE80211_DPRINTF(("%s: new req from %s\n", 792 __func__, ether_sprintf(wh->i_addr2))); 793 allocbs = 1; 794 } else 795 allocbs = 0; 796 ni->ni_rssi = rssi; 797 ni->ni_rstamp = rstamp; 798 rate = ieee80211_setup_rates(ic, ni, rates, xrates, 799 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE 800 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 801 if (rate & IEEE80211_RATE_BASIC) { 802 IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n", 803 __func__,ether_sprintf(wh->i_addr2))); 804 } else { 805 IEEE80211_SEND_MGMT(ic, ni, 806 IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); 807 } 808 if (allocbs) { 809 /* XXX just use free? */ 810 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 811 ieee80211_free_node(ic, ni); 812 else 813 ieee80211_unref_node(&ni); 814 } 815 break; 816 } 817 818 case IEEE80211_FC0_SUBTYPE_AUTH: { 819 u_int16_t algo, seq, status; 820 /* 821 * auth frame format 822 * [2] algorithm 823 * [2] sequence 824 * [2] status 825 * [tlv*] challenge 826 */ 827 IEEE80211_VERIFY_LENGTH(efrm - frm, 6); 828 algo = le16toh(*(u_int16_t *)frm); 829 seq = le16toh(*(u_int16_t *)(frm + 2)); 830 status = le16toh(*(u_int16_t *)(frm + 4)); 831 if (algo != IEEE80211_AUTH_ALG_OPEN) { 832 /* TODO: shared key auth */ 833 IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n", 834 __func__, algo, ether_sprintf(wh->i_addr2)));
|
| 835 ic->ic_stats.is_rx_auth_unsupported++;
|
795 return; 796 }
| 836 return; 837 }
|
| 838 if (ic->ic_state != IEEE80211_S_RUN) { 839 IEEE80211_DPRINTF(("%s: discard auth from %s; " 840 "state %u\n", __func__, 841 ether_sprintf(wh->i_addr2), ic->ic_state)); 842 ic->ic_stats.is_rx_bad_auth++; 843 break; 844 } 845 if (seq != (ic->ic_opmode == IEEE80211_M_STA ? 2 : 1)) { 846 IEEE80211_DPRINTF(("%s: discard auth from %s; seq %u\n", 847 __func__, ether_sprintf(wh->i_addr2), seq)); 848 ic->ic_stats.is_rx_bad_auth++; 849 break; 850 }
|
797 switch (ic->ic_opmode) { 798 case IEEE80211_M_IBSS:
| 851 switch (ic->ic_opmode) { 852 case IEEE80211_M_IBSS:
|
799 if (ic->ic_state != IEEE80211_S_RUN || seq != 1) 800 return;
| |
801 ieee80211_new_state(ic, IEEE80211_S_AUTH, 802 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 803 break; 804 805 case IEEE80211_M_AHDEMO: 806 /* should not come here */ 807 break; 808 809 case IEEE80211_M_HOSTAP:
| 853 ieee80211_new_state(ic, IEEE80211_S_AUTH, 854 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 855 break; 856 857 case IEEE80211_M_AHDEMO: 858 /* should not come here */ 859 break; 860 861 case IEEE80211_M_HOSTAP:
|
810 if (ic->ic_state != IEEE80211_S_RUN || seq != 1) 811 return;
| |
812 if (ni == ic->ic_bss) { 813 ni = ieee80211_alloc_node(ic, wh->i_addr2);
| 862 if (ni == ic->ic_bss) { 863 ni = ieee80211_alloc_node(ic, wh->i_addr2);
|
814 if (ni == NULL)
| 864 if (ni == NULL) { 865 ic->ic_stats.is_rx_nodealloc++;
|
815 return;
| 866 return;
|
| 867 }
|
816 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); 817 ni->ni_rssi = rssi; 818 ni->ni_rstamp = rstamp; 819 ni->ni_chan = ic->ic_bss->ni_chan; 820 allocbs = 1; 821 } else 822 allocbs = 0; 823 IEEE80211_SEND_MGMT(ic, ni, 824 IEEE80211_FC0_SUBTYPE_AUTH, 2); 825 if (ifp->if_flags & IFF_DEBUG) 826 if_printf(ifp, "station %s %s authenticated\n", 827 (allocbs ? "newly" : "already"), 828 ether_sprintf(ni->ni_macaddr)); 829 break; 830 831 case IEEE80211_M_STA:
| 868 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); 869 ni->ni_rssi = rssi; 870 ni->ni_rstamp = rstamp; 871 ni->ni_chan = ic->ic_bss->ni_chan; 872 allocbs = 1; 873 } else 874 allocbs = 0; 875 IEEE80211_SEND_MGMT(ic, ni, 876 IEEE80211_FC0_SUBTYPE_AUTH, 2); 877 if (ifp->if_flags & IFF_DEBUG) 878 if_printf(ifp, "station %s %s authenticated\n", 879 (allocbs ? "newly" : "already"), 880 ether_sprintf(ni->ni_macaddr)); 881 break; 882 883 case IEEE80211_M_STA:
|
832 if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) 833 return;
| |
834 if (status != 0) { 835 if_printf(&ic->ic_if, 836 "authentication failed (reason %d) for %s\n", 837 status, 838 ether_sprintf(wh->i_addr3)); 839 if (ni != ic->ic_bss) 840 ni->ni_fails++;
| 884 if (status != 0) { 885 if_printf(&ic->ic_if, 886 "authentication failed (reason %d) for %s\n", 887 status, 888 ether_sprintf(wh->i_addr3)); 889 if (ni != ic->ic_bss) 890 ni->ni_fails++;
|
| 891 ic->ic_stats.is_rx_auth_fail++;
|
841 return; 842 } 843 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 844 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 845 break; 846 case IEEE80211_M_MONITOR: 847 break; 848 } 849 break; 850 } 851 852 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 853 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: { 854 u_int16_t capinfo, bintval; 855 856 if (ic->ic_opmode != IEEE80211_M_HOSTAP || 857 (ic->ic_state != IEEE80211_S_RUN)) 858 return; 859 860 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { 861 reassoc = 1; 862 resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; 863 } else { 864 reassoc = 0; 865 resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; 866 } 867 /* 868 * asreq frame format 869 * [2] capability information 870 * [2] listen interval 871 * [6*] current AP address (reassoc only) 872 * [tlv] ssid 873 * [tlv] supported rates 874 * [tlv] extended supported rates 875 */ 876 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4)); 877 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) { 878 IEEE80211_DPRINTF(("%s: ignore other bss from %s\n", 879 __func__, ether_sprintf(wh->i_addr2)));
| 892 return; 893 } 894 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 895 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 896 break; 897 case IEEE80211_M_MONITOR: 898 break; 899 } 900 break; 901 } 902 903 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 904 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: { 905 u_int16_t capinfo, bintval; 906 907 if (ic->ic_opmode != IEEE80211_M_HOSTAP || 908 (ic->ic_state != IEEE80211_S_RUN)) 909 return; 910 911 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { 912 reassoc = 1; 913 resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; 914 } else { 915 reassoc = 0; 916 resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; 917 } 918 /* 919 * asreq frame format 920 * [2] capability information 921 * [2] listen interval 922 * [6*] current AP address (reassoc only) 923 * [tlv] ssid 924 * [tlv] supported rates 925 * [tlv] extended supported rates 926 */ 927 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4)); 928 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) { 929 IEEE80211_DPRINTF(("%s: ignore other bss from %s\n", 930 __func__, ether_sprintf(wh->i_addr2)));
|
| 931 ic->ic_stats.is_rx_assoc_bss++;
|
880 return; 881 } 882 capinfo = le16toh(*(u_int16_t *)frm); frm += 2; 883 bintval = le16toh(*(u_int16_t *)frm); frm += 2; 884 if (reassoc) 885 frm += 6; /* ignore current AP info */ 886 ssid = rates = xrates = NULL; 887 while (frm < efrm) { 888 switch (*frm) { 889 case IEEE80211_ELEMID_SSID: 890 ssid = frm; 891 break; 892 case IEEE80211_ELEMID_RATES: 893 rates = frm; 894 break; 895 case IEEE80211_ELEMID_XRATES: 896 xrates = frm; 897 break; 898 } 899 frm += frm[1] + 2; 900 } 901 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 902 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 903 if (ssid[1] != ic->ic_bss->ni_esslen || 904 memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) { 905#ifdef IEEE80211_DEBUG 906 if (ieee80211_debug) { 907 printf("%s: ssid unmatch ", __func__); 908 ieee80211_print_essid(ssid + 2, ssid[1]); 909 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 910 } 911#endif
| 932 return; 933 } 934 capinfo = le16toh(*(u_int16_t *)frm); frm += 2; 935 bintval = le16toh(*(u_int16_t *)frm); frm += 2; 936 if (reassoc) 937 frm += 6; /* ignore current AP info */ 938 ssid = rates = xrates = NULL; 939 while (frm < efrm) { 940 switch (*frm) { 941 case IEEE80211_ELEMID_SSID: 942 ssid = frm; 943 break; 944 case IEEE80211_ELEMID_RATES: 945 rates = frm; 946 break; 947 case IEEE80211_ELEMID_XRATES: 948 xrates = frm; 949 break; 950 } 951 frm += frm[1] + 2; 952 } 953 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 954 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); 955 if (ssid[1] != ic->ic_bss->ni_esslen || 956 memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) { 957#ifdef IEEE80211_DEBUG 958 if (ieee80211_debug) { 959 printf("%s: ssid unmatch ", __func__); 960 ieee80211_print_essid(ssid + 2, ssid[1]); 961 printf(" from %s\n", ether_sprintf(wh->i_addr2)); 962 } 963#endif
|
| 964 ic->ic_stats.is_rx_ssidmismatch++;
|
912 return; 913 } 914 if (ni == ic->ic_bss) { 915 IEEE80211_DPRINTF(("%s: not authenticated for %s\n", 916 __func__, ether_sprintf(wh->i_addr2))); 917 ni = ieee80211_dup_bss(ic, wh->i_addr2); 918 if (ni != NULL) { 919 IEEE80211_SEND_MGMT(ic, ni, 920 IEEE80211_FC0_SUBTYPE_DEAUTH, 921 IEEE80211_REASON_ASSOC_NOT_AUTHED); 922 ieee80211_free_node(ic, ni); 923 }
| 965 return; 966 } 967 if (ni == ic->ic_bss) { 968 IEEE80211_DPRINTF(("%s: not authenticated for %s\n", 969 __func__, ether_sprintf(wh->i_addr2))); 970 ni = ieee80211_dup_bss(ic, wh->i_addr2); 971 if (ni != NULL) { 972 IEEE80211_SEND_MGMT(ic, ni, 973 IEEE80211_FC0_SUBTYPE_DEAUTH, 974 IEEE80211_REASON_ASSOC_NOT_AUTHED); 975 ieee80211_free_node(ic, ni); 976 }
|
| 977 ic->ic_stats.is_rx_assoc_notauth++;
|
924 return; 925 } 926 /* XXX per-node cipher suite */ 927 /* XXX some stations use the privacy bit for handling APs 928 that suport both encrypted and unencrypted traffic */ 929 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 || 930 (capinfo & IEEE80211_CAPINFO_PRIVACY) != 931 ((ic->ic_flags & IEEE80211_F_WEPON) ? 932 IEEE80211_CAPINFO_PRIVACY : 0)) { 933 IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n", 934 __func__, capinfo, ether_sprintf(wh->i_addr2))); 935 ni->ni_associd = 0; 936 IEEE80211_SEND_MGMT(ic, ni, resp, 937 IEEE80211_STATUS_CAPINFO);
| 978 return; 979 } 980 /* XXX per-node cipher suite */ 981 /* XXX some stations use the privacy bit for handling APs 982 that suport both encrypted and unencrypted traffic */ 983 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 || 984 (capinfo & IEEE80211_CAPINFO_PRIVACY) != 985 ((ic->ic_flags & IEEE80211_F_WEPON) ? 986 IEEE80211_CAPINFO_PRIVACY : 0)) { 987 IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n", 988 __func__, capinfo, ether_sprintf(wh->i_addr2))); 989 ni->ni_associd = 0; 990 IEEE80211_SEND_MGMT(ic, ni, resp, 991 IEEE80211_STATUS_CAPINFO);
|
| 992 ic->ic_stats.is_rx_assoc_capmismatch++;
|
938 return; 939 } 940 ieee80211_setup_rates(ic, ni, rates, xrates, 941 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | 942 IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 943 if (ni->ni_rates.rs_nrates == 0) { 944 IEEE80211_DPRINTF(("%s: rate unmatch for %s\n", 945 __func__, ether_sprintf(wh->i_addr2))); 946 ni->ni_associd = 0; 947 IEEE80211_SEND_MGMT(ic, ni, resp, 948 IEEE80211_STATUS_BASIC_RATE);
| 993 return; 994 } 995 ieee80211_setup_rates(ic, ni, rates, xrates, 996 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | 997 IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 998 if (ni->ni_rates.rs_nrates == 0) { 999 IEEE80211_DPRINTF(("%s: rate unmatch for %s\n", 1000 __func__, ether_sprintf(wh->i_addr2))); 1001 ni->ni_associd = 0; 1002 IEEE80211_SEND_MGMT(ic, ni, resp, 1003 IEEE80211_STATUS_BASIC_RATE);
|
| 1004 ic->ic_stats.is_rx_assoc_norate++;
|
949 return; 950 } 951 ni->ni_rssi = rssi; 952 ni->ni_rstamp = rstamp; 953 ni->ni_intval = bintval; 954 ni->ni_capinfo = capinfo; 955 ni->ni_chan = ic->ic_bss->ni_chan; 956 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell; 957 ni->ni_fhindex = ic->ic_bss->ni_fhindex; 958 if (ni->ni_associd == 0) { 959 /* XXX handle rollover at 2007 */ 960 /* XXX guarantee uniqueness */ 961 ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++; 962 newassoc = 1; 963 } else 964 newassoc = 0; 965 /* XXX for 11g must turn off short slot time if long 966 slot time sta associates */ 967 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); 968 if (ifp->if_flags & IFF_DEBUG) 969 if_printf(ifp, "station %s %s associated\n", 970 (newassoc ? "newly" : "already"), 971 ether_sprintf(ni->ni_macaddr)); 972 /* give driver a chance to setup state like ni_txrate */ 973 if (ic->ic_newassoc) 974 (*ic->ic_newassoc)(ic, ni, newassoc); 975 break; 976 } 977 978 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 979 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: { 980 u_int16_t status; 981 982 if (ic->ic_opmode != IEEE80211_M_STA || 983 ic->ic_state != IEEE80211_S_ASSOC) 984 return; 985 986 /* 987 * asresp frame format 988 * [2] capability information 989 * [2] status 990 * [2] association ID 991 * [tlv] supported rates 992 * [tlv] extended supported rates 993 */ 994 IEEE80211_VERIFY_LENGTH(efrm - frm, 6); 995 ni = ic->ic_bss; 996 ni->ni_capinfo = le16toh(*(u_int16_t *)frm); 997 frm += 2; 998 999 status = le16toh(*(u_int16_t *)frm); 1000 frm += 2; 1001 if (status != 0) { 1002 if_printf(ifp, "association failed (reason %d) for %s\n", 1003 status, ether_sprintf(wh->i_addr3)); 1004 if (ni != ic->ic_bss) 1005 ni->ni_fails++;
| 1005 return; 1006 } 1007 ni->ni_rssi = rssi; 1008 ni->ni_rstamp = rstamp; 1009 ni->ni_intval = bintval; 1010 ni->ni_capinfo = capinfo; 1011 ni->ni_chan = ic->ic_bss->ni_chan; 1012 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell; 1013 ni->ni_fhindex = ic->ic_bss->ni_fhindex; 1014 if (ni->ni_associd == 0) { 1015 /* XXX handle rollover at 2007 */ 1016 /* XXX guarantee uniqueness */ 1017 ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++; 1018 newassoc = 1; 1019 } else 1020 newassoc = 0; 1021 /* XXX for 11g must turn off short slot time if long 1022 slot time sta associates */ 1023 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); 1024 if (ifp->if_flags & IFF_DEBUG) 1025 if_printf(ifp, "station %s %s associated\n", 1026 (newassoc ? "newly" : "already"), 1027 ether_sprintf(ni->ni_macaddr)); 1028 /* give driver a chance to setup state like ni_txrate */ 1029 if (ic->ic_newassoc) 1030 (*ic->ic_newassoc)(ic, ni, newassoc); 1031 break; 1032 } 1033 1034 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 1035 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: { 1036 u_int16_t status; 1037 1038 if (ic->ic_opmode != IEEE80211_M_STA || 1039 ic->ic_state != IEEE80211_S_ASSOC) 1040 return; 1041 1042 /* 1043 * asresp frame format 1044 * [2] capability information 1045 * [2] status 1046 * [2] association ID 1047 * [tlv] supported rates 1048 * [tlv] extended supported rates 1049 */ 1050 IEEE80211_VERIFY_LENGTH(efrm - frm, 6); 1051 ni = ic->ic_bss; 1052 ni->ni_capinfo = le16toh(*(u_int16_t *)frm); 1053 frm += 2; 1054 1055 status = le16toh(*(u_int16_t *)frm); 1056 frm += 2; 1057 if (status != 0) { 1058 if_printf(ifp, "association failed (reason %d) for %s\n", 1059 status, ether_sprintf(wh->i_addr3)); 1060 if (ni != ic->ic_bss) 1061 ni->ni_fails++;
|
| 1062 ic->ic_stats.is_rx_auth_fail++;
|
1006 return; 1007 } 1008 ni->ni_associd = le16toh(*(u_int16_t *)frm); 1009 frm += 2; 1010 1011 rates = xrates = NULL; 1012 while (frm < efrm) { 1013 switch (*frm) { 1014 case IEEE80211_ELEMID_RATES: 1015 rates = frm; 1016 break; 1017 case IEEE80211_ELEMID_XRATES: 1018 xrates = frm; 1019 break; 1020 } 1021 frm += frm[1] + 2; 1022 } 1023 1024 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 1025 ieee80211_setup_rates(ic, ni, rates, xrates, 1026 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | 1027 IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 1028 if (ni->ni_rates.rs_nrates != 0) 1029 ieee80211_new_state(ic, IEEE80211_S_RUN, 1030 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1031 break; 1032 } 1033 1034 case IEEE80211_FC0_SUBTYPE_DEAUTH: { 1035 u_int16_t reason; 1036 /* 1037 * deauth frame format 1038 * [2] reason 1039 */ 1040 IEEE80211_VERIFY_LENGTH(efrm - frm, 2); 1041 reason = le16toh(*(u_int16_t *)frm);
| 1063 return; 1064 } 1065 ni->ni_associd = le16toh(*(u_int16_t *)frm); 1066 frm += 2; 1067 1068 rates = xrates = NULL; 1069 while (frm < efrm) { 1070 switch (*frm) { 1071 case IEEE80211_ELEMID_RATES: 1072 rates = frm; 1073 break; 1074 case IEEE80211_ELEMID_XRATES: 1075 xrates = frm; 1076 break; 1077 } 1078 frm += frm[1] + 2; 1079 } 1080 1081 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); 1082 ieee80211_setup_rates(ic, ni, rates, xrates, 1083 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | 1084 IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 1085 if (ni->ni_rates.rs_nrates != 0) 1086 ieee80211_new_state(ic, IEEE80211_S_RUN, 1087 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1088 break; 1089 } 1090 1091 case IEEE80211_FC0_SUBTYPE_DEAUTH: { 1092 u_int16_t reason; 1093 /* 1094 * deauth frame format 1095 * [2] reason 1096 */ 1097 IEEE80211_VERIFY_LENGTH(efrm - frm, 2); 1098 reason = le16toh(*(u_int16_t *)frm);
|
| 1099 ic->ic_stats.is_rx_deauth++;
|
1042 switch (ic->ic_opmode) { 1043 case IEEE80211_M_STA: 1044 ieee80211_new_state(ic, IEEE80211_S_AUTH, 1045 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1046 break; 1047 case IEEE80211_M_HOSTAP: 1048 if (ni != ic->ic_bss) { 1049 if (ifp->if_flags & IFF_DEBUG) 1050 if_printf(ifp, "station %s deauthenticated" 1051 " by peer (reason %d)\n", 1052 ether_sprintf(ni->ni_macaddr), reason); 1053 /* node will be free'd on return */ 1054 ieee80211_unref_node(&ni); 1055 } 1056 break; 1057 default: 1058 break; 1059 } 1060 break; 1061 } 1062 1063 case IEEE80211_FC0_SUBTYPE_DISASSOC: { 1064 u_int16_t reason; 1065 /* 1066 * disassoc frame format 1067 * [2] reason 1068 */ 1069 IEEE80211_VERIFY_LENGTH(efrm - frm, 2); 1070 reason = le16toh(*(u_int16_t *)frm);
| 1100 switch (ic->ic_opmode) { 1101 case IEEE80211_M_STA: 1102 ieee80211_new_state(ic, IEEE80211_S_AUTH, 1103 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1104 break; 1105 case IEEE80211_M_HOSTAP: 1106 if (ni != ic->ic_bss) { 1107 if (ifp->if_flags & IFF_DEBUG) 1108 if_printf(ifp, "station %s deauthenticated" 1109 " by peer (reason %d)\n", 1110 ether_sprintf(ni->ni_macaddr), reason); 1111 /* node will be free'd on return */ 1112 ieee80211_unref_node(&ni); 1113 } 1114 break; 1115 default: 1116 break; 1117 } 1118 break; 1119 } 1120 1121 case IEEE80211_FC0_SUBTYPE_DISASSOC: { 1122 u_int16_t reason; 1123 /* 1124 * disassoc frame format 1125 * [2] reason 1126 */ 1127 IEEE80211_VERIFY_LENGTH(efrm - frm, 2); 1128 reason = le16toh(*(u_int16_t *)frm);
|
| 1129 ic->ic_stats.is_rx_disassoc++;
|
1071 switch (ic->ic_opmode) { 1072 case IEEE80211_M_STA: 1073 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1074 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1075 break; 1076 case IEEE80211_M_HOSTAP: 1077 if (ni != ic->ic_bss) { 1078 if (ifp->if_flags & IFF_DEBUG) 1079 if_printf(ifp, "station %s disassociated" 1080 " by peer (reason %d)\n", 1081 ether_sprintf(ni->ni_macaddr), reason); 1082 ni->ni_associd = 0; 1083 /* XXX node reclaimed how? */ 1084 } 1085 break; 1086 default: 1087 break; 1088 } 1089 break; 1090 } 1091 default: 1092 IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not " 1093 "handled\n", __func__, subtype));
| 1130 switch (ic->ic_opmode) { 1131 case IEEE80211_M_STA: 1132 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1133 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 1134 break; 1135 case IEEE80211_M_HOSTAP: 1136 if (ni != ic->ic_bss) { 1137 if (ifp->if_flags & IFF_DEBUG) 1138 if_printf(ifp, "station %s disassociated" 1139 " by peer (reason %d)\n", 1140 ether_sprintf(ni->ni_macaddr), reason); 1141 ni->ni_associd = 0; 1142 /* XXX node reclaimed how? */ 1143 } 1144 break; 1145 default: 1146 break; 1147 } 1148 break; 1149 } 1150 default: 1151 IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not " 1152 "handled\n", __func__, subtype));
|
| 1153 ic->ic_stats.is_rx_badsubtype++;
|
1094 break; 1095 } 1096#undef ISPROBE 1097} 1098#undef IEEE80211_VERIFY_LENGTH 1099#undef IEEE80211_VERIFY_ELEMENT
| 1154 break; 1155 } 1156#undef ISPROBE 1157} 1158#undef IEEE80211_VERIFY_LENGTH 1159#undef IEEE80211_VERIFY_ELEMENT
|