Deleted Added
sdiff udiff text old ( 118886 ) new ( 119150 )
full compact
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:

--- 17 unchanged lines hidden (view full) ---

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 119150 2003-08-19 22:17:04Z 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>

--- 18 unchanged lines hidden (view full) ---

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, subtype;
89 u_int8_t *bssid;
90 u_int16_t rxseq;
91
92 KASSERT(ni != NULL, ("null node"));
93
94 /* trim CRC here for 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
100 wh = mtod(m, struct ieee80211_frame *);
101 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
102 IEEE80211_FC0_VERSION_0) {
103 if (ifp->if_flags & IFF_DEBUG)
104 if_printf(ifp, "receive packet with wrong version: %x\n",
105 wh->i_fc[0]);
106 ieee80211_unref_node(&ni);
107 goto err;
108 }
109
110 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
111
112 if (ic->ic_state != IEEE80211_S_SCAN) {
113 switch (ic->ic_opmode) {
114 case IEEE80211_M_STA:
115 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
116 IEEE80211_DPRINTF2(("%s: discard frame from "
117 "bss %s\n", __func__,
118 ether_sprintf(wh->i_addr2)));
119 /* not interested in */
120 goto out;
121 }
122 break;
123 case IEEE80211_M_IBSS:
124 case IEEE80211_M_AHDEMO:
125 case IEEE80211_M_HOSTAP:
126 if (dir == IEEE80211_FC1_DIR_NODS)
127 bssid = wh->i_addr3;
128 else
129 bssid = wh->i_addr1;
130 if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&
131 !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
132 /* not interested in */
133 IEEE80211_DPRINTF2(("%s: other bss %s\n",
134 __func__, ether_sprintf(wh->i_addr3)));
135 goto out;
136 }
137 break;
138 case IEEE80211_M_MONITOR:
139 /* NB: this should collect everything */
140 goto out;
141 default:
142 /* XXX catch bad values */
143 break;
144 }
145 ni->ni_rssi = rssi;
146 ni->ni_rstamp = rstamp;
147 rxseq = ni->ni_rxseq;
148 ni->ni_rxseq =
149 le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
150 /* TODO: fragment */
151 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
152 rxseq == ni->ni_rxseq) {
153 /* duplicate, silently discarded */
154 goto out;
155 }
156 ni->ni_inact = 0;
157 }
158
159 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
160 case IEEE80211_FC0_TYPE_DATA:
161 switch (ic->ic_opmode) {
162 case IEEE80211_M_STA:
163 if (dir != IEEE80211_FC1_DIR_FROMDS)
164 goto out;

--- 13 unchanged lines hidden (view full) ---

178 case IEEE80211_M_AHDEMO:
179 if (dir != IEEE80211_FC1_DIR_NODS)
180 goto out;
181 break;
182 case IEEE80211_M_HOSTAP:
183 if (dir != IEEE80211_FC1_DIR_TODS)
184 goto out;
185 /* check if source STA is associated */
186 if (ni == ic->ic_bss) {
187 IEEE80211_DPRINTF(("%s: data from unknown src "
188 "%s\n", __func__,
189 ether_sprintf(wh->i_addr2)));
190 /* NB: caller deals with reference */
191 ni = ieee80211_dup_bss(ic, wh->i_addr2);
192 if (ni != NULL) {
193 IEEE80211_SEND_MGMT(ic, ni,
194 IEEE80211_FC0_SUBTYPE_DEAUTH,
195 IEEE80211_REASON_NOT_AUTHED);
196 ieee80211_free_node(ic, ni);
197 }
198 goto err;
199 }
200 if (ni->ni_associd == 0) {
201 IEEE80211_DPRINTF(("ieee80211_input: "
202 "data from unassoc src %s\n",
203 ether_sprintf(wh->i_addr2)));
204 IEEE80211_SEND_MGMT(ic, ni,
205 IEEE80211_FC0_SUBTYPE_DISASSOC,
206 IEEE80211_REASON_NOT_ASSOCED);
207 ieee80211_unref_node(&ni);
208 goto err;
209 }
210 break;
211 case IEEE80211_M_MONITOR:
212 break;
213 }
214 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
215 if (ic->ic_flags & IEEE80211_F_WEPON) {
216 m = ieee80211_wep_crypt(ifp, m, 0);
217 if (m == NULL)

--- 10 unchanged lines hidden (view full) ---

228 goto err;
229 ifp->if_ipackets++;
230
231 /* perform as a bridge within the AP */
232 m1 = NULL;
233 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
234 eh = mtod(m, struct ether_header *);
235 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
236 m1 = m_copypacket(m, M_DONTWAIT);
237 if (m1 == NULL)
238 ifp->if_oerrors++;
239 else
240 m1->m_flags |= M_MCAST;
241 } else {
242 ni = ieee80211_find_node(ic, eh->ether_dhost);
243 if (ni != NULL) {
244 if (ni->ni_associd != 0) {

--- 61 unchanged lines hidden (view full) ---

306 if (doprint)
307 if_printf(ifp, "received %s from %s rssi %d\n",
308 ieee80211_mgt_subtype_name[subtype
309 >> IEEE80211_FC0_SUBTYPE_SHIFT],
310 ether_sprintf(wh->i_addr2), rssi);
311 }
312 if (ic->ic_rawbpf)
313 bpf_mtap(ic->ic_rawbpf, m);
314 (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
315 m_freem(m);
316 return;
317
318 case IEEE80211_FC0_TYPE_CTL:
319 default:
320 IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, wh->i_fc[0]));
321 /* should not come here */
322 break;

--- 164 unchanged lines hidden (view full) ---

487 ieee80211_mgt_subtype_name[subtype >> \
488 IEEE80211_FC0_SUBTYPE_SHIFT], \
489 ether_sprintf(wh->i_addr2))); \
490 return; \
491 } \
492} while (0)
493
494void
495ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
496 struct ieee80211_node *ni,
497 int subtype, int rssi, u_int32_t rstamp)
498{
499#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
500 struct ifnet *ifp = &ic->ic_if;
501 struct ieee80211_frame *wh;
502 u_int8_t *frm, *efrm;
503 u_int8_t *ssid, *rates, *xrates;
504 int reassoc, resp, newassoc, allocbs;
505
506 wh = mtod(m0, struct ieee80211_frame *);
507 frm = (u_int8_t *)&wh[1];
508 efrm = mtod(m0, u_int8_t *) + m0->m_len;
509 switch (subtype) {

--- 150 unchanged lines hidden (view full) ---

660 */
661 ni->ni_esslen = ssid[1];
662 memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
663 memcpy(ni->ni_essid, ssid + 2, ssid[1]);
664 }
665 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
666 ni->ni_rssi = rssi;
667 ni->ni_rstamp = rstamp;
668 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
669 ni->ni_intval = le16toh(*(u_int16_t *)bintval);
670 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
671 /* XXX validate channel # */
672 ni->ni_chan = &ic->ic_channels[chan];
673 ni->ni_fhdwell = fhdwell;
674 ni->ni_fhindex = fhindex;
675 ni->ni_erp = erp;

--- 42 unchanged lines hidden (view full) ---

718 printf("%s: ssid unmatch ", __func__);
719 ieee80211_print_essid(ssid + 2, ssid[1]);
720 printf(" from %s\n", ether_sprintf(wh->i_addr2));
721 }
722#endif
723 return;
724 }
725
726 if (ni == ic->ic_bss) {
727 ni = ieee80211_dup_bss(ic, wh->i_addr2);
728 if (ni == NULL)
729 return;
730 IEEE80211_DPRINTF(("%s: new req from %s\n",
731 __func__, ether_sprintf(wh->i_addr2)));
732 allocbs = 1;
733 } else
734 allocbs = 0;
735 ni->ni_rssi = rssi;
736 ni->ni_rstamp = rstamp;
737 rate = ieee80211_setup_rates(ic, ni, rates, xrates,
738 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
739 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
740 if (rate & IEEE80211_RATE_BASIC) {
741 IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n",
742 __func__,ether_sprintf(wh->i_addr2)));
743 } else {
744 IEEE80211_SEND_MGMT(ic, ni,
745 IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
746 }
747 if (allocbs) {
748 /* XXX just use free? */
749 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
750 ieee80211_free_node(ic, ni);
751 else
752 ieee80211_unref_node(&ni);
753 }
754 break;
755 }
756
757 case IEEE80211_FC0_SUBTYPE_AUTH: {
758 u_int16_t algo, seq, status;
759 /*
760 * auth frame format
761 * [2] algorithm

--- 21 unchanged lines hidden (view full) ---

783
784 case IEEE80211_M_AHDEMO:
785 /* should not come here */
786 break;
787
788 case IEEE80211_M_HOSTAP:
789 if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
790 return;
791 if (ni == ic->ic_bss) {
792 ni = ieee80211_alloc_node(ic, wh->i_addr2);
793 if (ni == NULL)
794 return;
795 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
796 ni->ni_rssi = rssi;
797 ni->ni_rstamp = rstamp;
798 ni->ni_chan = ic->ic_bss->ni_chan;
799 allocbs = 1;
800 } else
801 allocbs = 0;
802 IEEE80211_SEND_MGMT(ic, ni,
803 IEEE80211_FC0_SUBTYPE_AUTH, 2);
804 if (ifp->if_flags & IFF_DEBUG)
805 if_printf(ifp, "station %s %s authenticated\n",
806 (allocbs ? "newly" : "already"),
807 ether_sprintf(ni->ni_macaddr));
808 break;
809
810 case IEEE80211_M_STA:
811 if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
812 return;
813 if (status != 0) {
814 if_printf(&ic->ic_if,
815 "authentication failed (reason %d) for %s\n",
816 status,
817 ether_sprintf(wh->i_addr3));
818 if (ni != ic->ic_bss)
819 ni->ni_fails++;
820 return;
821 }
822 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
823 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
824 break;
825 case IEEE80211_M_MONITOR:
826 break;
827 }

--- 57 unchanged lines hidden (view full) ---

885 if (ieee80211_debug) {
886 printf("%s: ssid unmatch ", __func__);
887 ieee80211_print_essid(ssid + 2, ssid[1]);
888 printf(" from %s\n", ether_sprintf(wh->i_addr2));
889 }
890#endif
891 return;
892 }
893 if (ni == ic->ic_bss) {
894 IEEE80211_DPRINTF(("%s: not authenticated for %s\n",
895 __func__, ether_sprintf(wh->i_addr2)));
896 ni = ieee80211_dup_bss(ic, wh->i_addr2);
897 if (ni != NULL) {
898 IEEE80211_SEND_MGMT(ic, ni,
899 IEEE80211_FC0_SUBTYPE_DEAUTH,
900 IEEE80211_REASON_ASSOC_NOT_AUTHED);
901 ieee80211_free_node(ic, ni);
902 }
903 return;
904 }
905 /* XXX per-node cipher suite */
906 /* XXX some stations use the privacy bit for handling APs
907 that suport both encrypted and unencrypted traffic */
908 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
909 (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
910 ((ic->ic_flags & IEEE80211_F_WEPON) ?
911 IEEE80211_CAPINFO_PRIVACY : 0)) {
912 IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
913 __func__, capinfo, ether_sprintf(wh->i_addr2)));
914 ni->ni_associd = 0;
915 IEEE80211_SEND_MGMT(ic, ni, resp,
916 IEEE80211_STATUS_CAPINFO);
917 return;
918 }
919 ieee80211_setup_rates(ic, ni, rates, xrates,
920 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
921 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
922 if (ni->ni_rates.rs_nrates == 0) {
923 IEEE80211_DPRINTF(("%s: rate unmatch for %s\n",
924 __func__, ether_sprintf(wh->i_addr2)));
925 ni->ni_associd = 0;
926 IEEE80211_SEND_MGMT(ic, ni, resp,
927 IEEE80211_STATUS_BASIC_RATE);
928 return;
929 }
930 ni->ni_rssi = rssi;
931 ni->ni_rstamp = rstamp;
932 ni->ni_intval = bintval;
933 ni->ni_capinfo = capinfo;
934 ni->ni_chan = ic->ic_bss->ni_chan;
935 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
936 ni->ni_fhindex = ic->ic_bss->ni_fhindex;
937 if (ni->ni_associd == 0) {
938 /* XXX handle rollover at 2007 */
939 /* XXX guarantee uniqueness */

--- 6 unchanged lines hidden (view full) ---

946 IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
947 if (ifp->if_flags & IFF_DEBUG)
948 if_printf(ifp, "station %s %s associated\n",
949 (newassoc ? "newly" : "already"),
950 ether_sprintf(ni->ni_macaddr));
951 /* give driver a chance to setup state like ni_txrate */
952 if (ic->ic_newassoc)
953 (*ic->ic_newassoc)(ic, ni, newassoc);
954 break;
955 }
956
957 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
958 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
959 u_int16_t status;
960
961 if (ic->ic_opmode != IEEE80211_M_STA ||

--- 13 unchanged lines hidden (view full) ---

975 ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
976 frm += 2;
977
978 status = le16toh(*(u_int16_t *)frm);
979 frm += 2;
980 if (status != 0) {
981 if_printf(ifp, "association failed (reason %d) for %s\n",
982 status, ether_sprintf(wh->i_addr3));
983 if (ni != ic->ic_bss)
984 ni->ni_fails++;
985 return;
986 }
987 ni->ni_associd = le16toh(*(u_int16_t *)frm);
988 frm += 2;
989
990 rates = xrates = NULL;
991 while (frm < efrm) {
992 switch (*frm) {

--- 26 unchanged lines hidden (view full) ---

1019 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1020 reason = le16toh(*(u_int16_t *)frm);
1021 switch (ic->ic_opmode) {
1022 case IEEE80211_M_STA:
1023 ieee80211_new_state(ic, IEEE80211_S_AUTH,
1024 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1025 break;
1026 case IEEE80211_M_HOSTAP:
1027 if (ni != ic->ic_bss) {
1028 if (ifp->if_flags & IFF_DEBUG)
1029 if_printf(ifp, "station %s deauthenticated"
1030 " by peer (reason %d)\n",
1031 ether_sprintf(ni->ni_macaddr), reason);
1032 /* node will be free'd on return */
1033 ieee80211_unref_node(&ni);
1034 }
1035 break;
1036 default:
1037 break;
1038 }
1039 break;
1040 }
1041

--- 6 unchanged lines hidden (view full) ---

1048 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1049 reason = le16toh(*(u_int16_t *)frm);
1050 switch (ic->ic_opmode) {
1051 case IEEE80211_M_STA:
1052 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1053 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1054 break;
1055 case IEEE80211_M_HOSTAP:
1056 if (ni != ic->ic_bss) {
1057 if (ifp->if_flags & IFF_DEBUG)
1058 if_printf(ifp, "station %s disassociated"
1059 " by peer (reason %d)\n",
1060 ether_sprintf(ni->ni_macaddr), reason);
1061 ni->ni_associd = 0;
1062 /* XXX node reclaimed how? */
1063 }
1064 break;
1065 default:
1066 break;
1067 }
1068 break;
1069 }
1070 default:
1071 IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
1072 "handled\n", __func__, subtype));
1073 break;
1074 }
1075#undef ISPROBE
1076}
1077#undef IEEE80211_VERIFY_LENGTH
1078#undef IEEE80211_VERIFY_ELEMENT