Clean up routing code before I parallelize it.
[dragonfly.git] / sys / netproto / 802_11 / ieee80211_proto.c
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_proto.c,v 1.8 2004/04/02 20:22:25 sam Exp $
33  * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_proto.c,v 1.1 2004/07/26 16:30:17 joerg Exp $
34  */
35
36 /*
37  * IEEE 802.11 protocol support.
38  */
39
40 #include "opt_inet.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h> 
44 #include <sys/mbuf.h>   
45 #include <sys/malloc.h>
46 #include <sys/kernel.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
49 #include <sys/endian.h>
50 #include <sys/errno.h>
51 #include <sys/bus.h>
52 #include <sys/proc.h>
53 #include <sys/sysctl.h>
54
55 #include <machine/atomic.h>
56  
57 #include <net/if.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_arp.h>
61 #include <net/ethernet.h>
62 #include <net/if_llc.h>
63
64 #include <netproto/802_11/ieee80211_var.h>
65
66 #include <net/bpf.h>
67
68 #ifdef INET
69 #include <netinet/in.h> 
70 #include <netinet/if_ether.h>
71 #endif
72
73 #define IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
74
75 const char *ieee80211_mgt_subtype_name[] = {
76         "assoc_req",    "assoc_resp",   "reassoc_req",  "reassoc_resp",
77         "probe_req",    "probe_resp",   "reserved#6",   "reserved#7",
78         "beacon",       "atim",         "disassoc",     "auth",
79         "deauth",       "reserved#13",  "reserved#14",  "reserved#15"
80 };
81 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
82         "INIT",         /* IEEE80211_S_INIT */
83         "SCAN",         /* IEEE80211_S_SCAN */
84         "AUTH",         /* IEEE80211_S_AUTH */
85         "ASSOC",        /* IEEE80211_S_ASSOC */
86         "RUN"           /* IEEE80211_S_RUN */
87 };
88
89 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
90
91 void
92 ieee80211_proto_attach(struct ifnet *ifp)
93 {
94         struct ieee80211com *ic = (void *)ifp;
95
96         ifp->if_hdrlen = sizeof(struct ieee80211_frame);
97
98 #ifdef notdef
99         ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
100 #else
101         ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
102 #endif
103         ic->ic_fragthreshold = 2346;            /* XXX not used yet */
104         ic->ic_fixed_rate = -1;                 /* no fixed rate */
105         ic->ic_protmode = IEEE80211_PROT_CTSONLY;
106
107         /* protocol state change handler */
108         ic->ic_newstate = ieee80211_newstate;
109
110         /* initialize management frame handlers */
111         ic->ic_recv_mgmt = ieee80211_recv_mgmt;
112         ic->ic_send_mgmt = ieee80211_send_mgmt;
113 }
114
115 void
116 ieee80211_proto_detach(struct ifnet *ifp)
117 {
118         struct ieee80211com *ic = (void *)ifp;
119
120         IF_DRAIN(&ic->ic_mgtq);
121 }
122
123 void
124 ieee80211_print_essid(uint8_t *essid, int len)
125 {
126         int i;
127         uint8_t *p; 
128
129         if (len > IEEE80211_NWID_LEN)
130                 len = IEEE80211_NWID_LEN;
131         /* determine printable or not */
132         for (i = 0, p = essid; i < len; i++, p++) {
133                 if (*p < ' ' || *p > 0x7e)
134                         break;
135         }
136         if (i == len) {
137                 printf("\"");
138                 for (i = 0, p = essid; i < len; i++, p++)
139                         printf("%c", *p);
140                 printf("\"");
141         } else {
142                 printf("0x");
143                 for (i = 0, p = essid; i < len; i++, p++)
144                         printf("%02x", *p);
145         }
146 }
147
148 void
149 ieee80211_dump_pkt(uint8_t *buf, int len, int rate, int rssi)
150 {
151         struct ieee80211_frame *wh;
152         int i;
153
154         wh = (struct ieee80211_frame *)buf;
155         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
156         case IEEE80211_FC1_DIR_NODS:
157                 printf("NODS %6D->%6D(%6D)", wh->i_addr2, ":",
158                        wh->i_addr1, ":", wh->i_addr3, ":");
159                 break;
160         case IEEE80211_FC1_DIR_TODS:
161                 printf("TODS %6D->%6D(%6D)", wh->i_addr2, ":",
162                        wh->i_addr3, ":", wh->i_addr1, ":");
163                 break;
164         case IEEE80211_FC1_DIR_FROMDS:
165                 printf("FRDS %6D->%6D(%6D)", wh->i_addr3, ":",
166                        wh->i_addr1, ":", wh->i_addr2, ":");
167                 break;
168         case IEEE80211_FC1_DIR_DSTODS:
169                 printf("DSDS %6D->%6D(%6D->%6D)", (uint8_t *)&wh[1], ":",
170                        wh->i_addr3, ":", wh->i_addr2, ":", wh->i_addr1, ":");
171                 break;
172         }
173         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
174         case IEEE80211_FC0_TYPE_DATA:
175                 printf(" data");
176                 break;
177         case IEEE80211_FC0_TYPE_MGT:
178                 printf(" %s", ieee80211_mgt_subtype_name[
179                     (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
180                     >> IEEE80211_FC0_SUBTYPE_SHIFT]);
181                 break;
182         default:
183                 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
184                 break;
185         }
186         if (wh->i_fc[1] & IEEE80211_FC1_WEP)
187                 printf(" WEP");
188         if (rate >= 0)
189                 printf(" %dM", rate / 2);
190         if (rssi >= 0)
191                 printf(" +%d", rssi);
192         printf("\n");
193         if (len > 0) {
194                 for (i = 0; i < len; i++) {
195                         if ((i & 1) == 0)
196                                 printf(" ");
197                         printf("%02x", buf[i]);
198                 }
199                 printf("\n");
200         }
201 }
202
203 int
204 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
205 {
206 #define RV(v)   ((v) & IEEE80211_RATE_VAL)
207         int i, j, ignore, error;
208         int okrate, badrate;
209         struct ieee80211_rateset *srs, *nrs;
210         uint8_t r;
211
212         error = 0;
213         okrate = badrate = 0;
214         srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
215         nrs = &ni->ni_rates;
216         for (i = 0; i < nrs->rs_nrates; ) {
217                 ignore = 0;
218                 if (flags & IEEE80211_F_DOSORT) {
219                         /*
220                          * Sort rates.
221                          */
222                         for (j = i + 1; j < nrs->rs_nrates; j++) {
223                                 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
224                                         r = nrs->rs_rates[i];
225                                         nrs->rs_rates[i] = nrs->rs_rates[j];
226                                         nrs->rs_rates[j] = r;
227                                 }
228                         }
229                 }
230                 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
231                 badrate = r;
232                 if (flags & IEEE80211_F_DOFRATE) {
233                         /*
234                          * Apply fixed rate constraint.  Note that we do
235                          * not apply the constraint to basic rates as
236                          * otherwise we may not be able to associate if
237                          * the rate set we submit to the AP is invalid
238                          * (e.g. fix rate at 36Mb/s which is not a basic
239                          * rate for 11a operation).
240                          */
241                         if ((nrs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0 &&
242                             ic->ic_fixed_rate >= 0 &&
243                             r != RV(srs->rs_rates[ic->ic_fixed_rate]))
244                                 ignore++;
245                 }
246                 if (flags & IEEE80211_F_DONEGO) {
247                         /*
248                          * Check against supported rates.
249                          */
250                         for (j = 0; j < srs->rs_nrates; j++) {
251                                 if (r == RV(srs->rs_rates[j])) {
252                                         /*
253                                          * Overwrite with the supported rate
254                                          * value so any basic rate bit is set.
255                                          * This insures that response we send
256                                          * to stations have the necessary basic
257                                          * rate bit set.
258                                          */
259                                         nrs->rs_rates[i] = srs->rs_rates[j];
260                                         break;
261                                 }
262                         }
263                         if (j == srs->rs_nrates) {
264                                 /*
265                                  * A rate in the node's rate set is not
266                                  * supported.  If this is a basic rate and we
267                                  * are operating as an AP then this is an error.
268                                  * Otherwise we just discard/ignore the rate.
269                                  * Note that this is important for 11b stations
270                                  * when they want to associate with an 11g AP.
271                                  */
272                                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
273                                     (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
274                                         error++;
275                                 ignore++;
276                         }
277                 }
278                 if (flags & IEEE80211_F_DODEL) {
279                         /*
280                          * Delete unacceptable rates.
281                          */
282                         if (ignore) {
283                                 nrs->rs_nrates--;
284                                 for (j = i; j < nrs->rs_nrates; j++)
285                                         nrs->rs_rates[j] = nrs->rs_rates[j + 1];
286                                 nrs->rs_rates[j] = 0;
287                                 continue;
288                         }
289                 }
290                 if (!ignore)
291                         okrate = nrs->rs_rates[i];
292                 i++;
293         }
294         if (okrate == 0 || error != 0)
295                 return badrate | IEEE80211_RATE_BASIC;
296         else
297                 return RV(okrate);
298 #undef RV
299 }
300
301 static int
302 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int mgt)
303 {
304         struct ifnet *ifp = &ic->ic_if;
305         struct ieee80211_node *ni;
306         enum ieee80211_state ostate;
307         struct lwkt_tokref ilock;
308
309         ostate = ic->ic_state;
310         IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__,
311                 ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
312         ic->ic_state = nstate;                  /* state transition */
313         ni = ic->ic_bss;                        /* NB: no reference held */
314         switch (nstate) {
315         case IEEE80211_S_INIT:
316                 switch (ostate) {
317                 case IEEE80211_S_INIT:
318                         break;
319                 case IEEE80211_S_RUN:
320                         switch (ic->ic_opmode) {
321                         case IEEE80211_M_STA:
322                                 IEEE80211_SEND_MGMT(ic, ni,
323                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
324                                     IEEE80211_REASON_ASSOC_LEAVE);
325                                 break;
326                         case IEEE80211_M_HOSTAP:
327                                 lwkt_gettoken(&ilock, &ic->ic_nodetoken);
328                                 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
329                                         if (ni->ni_associd == 0)
330                                                 continue;
331                                         IEEE80211_SEND_MGMT(ic, ni,
332                                             IEEE80211_FC0_SUBTYPE_DISASSOC,
333                                             IEEE80211_REASON_ASSOC_LEAVE);
334                                 }
335                                 lwkt_reltoken(&ilock);
336                                 break;
337                         default:
338                                 break;
339                         }
340                         /* FALLTHRU */
341                 case IEEE80211_S_ASSOC:
342                         switch (ic->ic_opmode) {
343                         case IEEE80211_M_STA:
344                                 IEEE80211_SEND_MGMT(ic, ni,
345                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
346                                     IEEE80211_REASON_AUTH_LEAVE);
347                                 break;
348                         case IEEE80211_M_HOSTAP:
349                                 lwkt_gettoken(&ilock, &ic->ic_nodetoken);
350                                 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
351                                         IEEE80211_SEND_MGMT(ic, ni,
352                                             IEEE80211_FC0_SUBTYPE_DEAUTH,
353                                             IEEE80211_REASON_AUTH_LEAVE);
354                                 }
355                                 lwkt_reltoken(&ilock);
356                                 break;
357                         default:
358                                 break;
359                         }
360                         /* FALLTHRU */
361                 case IEEE80211_S_AUTH:
362                 case IEEE80211_S_SCAN:
363                         ic->ic_mgt_timer = 0;
364                         IF_DRAIN(&ic->ic_mgtq);
365                         if (ic->ic_wep_ctx != NULL) {
366                                 free(ic->ic_wep_ctx, M_DEVBUF);
367                                 ic->ic_wep_ctx = NULL;
368                         }
369                         ieee80211_free_allnodes(ic);
370                         break;
371                 }
372                 break;
373         case IEEE80211_S_SCAN:
374                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
375                 /* initialize bss for probe request */
376                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr);
377                 IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr);
378                 ni->ni_rates = ic->ic_sup_rates[
379                         ieee80211_chan2mode(ic, ni->ni_chan)];
380                 ni->ni_associd = 0;
381                 ni->ni_rstamp = 0;
382                 switch (ostate) {
383                 case IEEE80211_S_INIT:
384                         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
385                             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
386                                 /*
387                                  * AP operation and we already have a channel;
388                                  * bypass the scan and startup immediately.
389                                  */
390                                 ieee80211_create_ibss(ic, ic->ic_des_chan);
391                         } else {
392                                 ieee80211_begin_scan(ifp);
393                         }
394                         break;
395                 case IEEE80211_S_SCAN:
396                         /* scan next */
397                         if (ic->ic_flags & IEEE80211_F_ASCAN) {
398                                 IEEE80211_SEND_MGMT(ic, ni,
399                                     IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
400                         }
401                         break;
402                 case IEEE80211_S_RUN:
403                         /* beacon miss */
404                         if (ifp->if_flags & IFF_DEBUG) {
405                                 /* XXX bssid clobbered above */
406                                 if_printf(ifp, "no recent beacons from %6D;"
407                                     " rescanning\n",
408                                     ic->ic_bss->ni_bssid, ":");
409                         }
410                         ieee80211_free_allnodes(ic);
411                         /* FALLTHRU */
412                 case IEEE80211_S_AUTH:
413                 case IEEE80211_S_ASSOC:
414                         /* timeout restart scan */
415                         ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
416                         if (ni != NULL) {
417                                 ni->ni_fails++;
418                                 ieee80211_unref_node(&ni);
419                         }
420                         ieee80211_begin_scan(ifp);
421                         break;
422                 }
423                 break;
424         case IEEE80211_S_AUTH:
425                 switch (ostate) {
426                 case IEEE80211_S_INIT:
427                         IEEE80211_DPRINTF(("%s: invalid transition\n",
428                                 __func__));
429                         break;
430                 case IEEE80211_S_SCAN:
431                         IEEE80211_SEND_MGMT(ic, ni,
432                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
433                         break;
434                 case IEEE80211_S_AUTH:
435                 case IEEE80211_S_ASSOC:
436                         switch (mgt) {
437                         case IEEE80211_FC0_SUBTYPE_AUTH:
438                                 /* ??? */
439                                 IEEE80211_SEND_MGMT(ic, ni,
440                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
441                                 break;
442                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
443                                 /* ignore and retry scan on timeout */
444                                 break;
445                         }
446                         break;
447                 case IEEE80211_S_RUN:
448                         switch (mgt) {
449                         case IEEE80211_FC0_SUBTYPE_AUTH:
450                                 IEEE80211_SEND_MGMT(ic, ni,
451                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
452                                 ic->ic_state = ostate;  /* stay RUN */
453                                 break;
454                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
455                                 /* try to reauth */
456                                 IEEE80211_SEND_MGMT(ic, ni,
457                                     IEEE80211_FC0_SUBTYPE_AUTH, 1);
458                                 break;
459                         }
460                         break;
461                 }
462                 break;
463         case IEEE80211_S_ASSOC:
464                 switch (ostate) {
465                 case IEEE80211_S_INIT:
466                 case IEEE80211_S_SCAN:
467                 case IEEE80211_S_ASSOC:
468                         IEEE80211_DPRINTF(("%s: invalid transition\n",
469                                 __func__));
470                         break;
471                 case IEEE80211_S_AUTH:
472                         IEEE80211_SEND_MGMT(ic, ni,
473                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
474                         break;
475                 case IEEE80211_S_RUN:
476                         IEEE80211_SEND_MGMT(ic, ni,
477                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
478                         break;
479                 }
480                 break;
481         case IEEE80211_S_RUN:
482                 switch (ostate) {
483                 case IEEE80211_S_INIT:
484                 case IEEE80211_S_AUTH:
485                 case IEEE80211_S_RUN:
486                         IEEE80211_DPRINTF(("%s: invalid transition\n",
487                                 __func__));
488                         break;
489                 case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
490                 case IEEE80211_S_ASSOC:         /* infra mode */
491                         KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
492                                 ("%s: bogus xmit rate %u setup\n", __func__,
493                                         ni->ni_txrate));
494                         if (ifp->if_flags & IFF_DEBUG) {
495                                 if_printf(ifp, " ");
496                                 if (ic->ic_opmode == IEEE80211_M_STA)
497                                         printf("associated ");
498                                 else
499                                         printf("synchronized ");
500                                 printf("with %6D ssid ", ni->ni_bssid, ":");
501                                 ieee80211_print_essid(ic->ic_bss->ni_essid,
502                                     ni->ni_esslen);
503                                 printf(" channel %d start %uMb\n",
504                                         ieee80211_chan2ieee(ic, ni->ni_chan),
505                                         IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
506                         }
507                         ic->ic_mgt_timer = 0;
508                         (*ifp->if_start)(ifp);
509                         break;
510                 }
511                 break;
512         }
513         return 0;
514 }