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