]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/net80211/ieee80211_regdomain.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / net80211 / ieee80211_regdomain.c
1 /*-
2  * Copyright (c) 2005-2007 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 /*
30  * IEEE 802.11 regdomain support.
31  */
32
33 #include <sys/param.h>
34 #include <sys/systm.h> 
35 #include <sys/kernel.h>
36  
37 #include <sys/socket.h>
38
39 #include <net/if.h>
40 #include <net/if_arp.h>
41 #include <net/if_dl.h>
42 #include <net/if_media.h>
43 #include <net/if_types.h>
44 #include <net/ethernet.h>
45
46 #include <net80211/ieee80211_var.h>
47 #include <net80211/ieee80211_regdomain.h>
48
49 void
50 ieee80211_regdomain_attach(struct ieee80211com *ic)
51 {
52         ic->ic_regdomain = 0;                   /* XXX */
53         ic->ic_countrycode = CTRY_UNITED_STATES;/* XXX */
54         ic->ic_location = 1+2;                  /* both */
55 }
56
57 void
58 ieee80211_regdomain_detach(struct ieee80211com *ic)
59 {
60 }
61
62 static void
63 addchan(struct ieee80211com *ic, int ieee, int flags)
64 {
65         struct ieee80211_channel *c;
66
67         c = &ic->ic_channels[ic->ic_nchans++];
68         c->ic_freq = ieee80211_ieee2mhz(ieee, flags);
69         c->ic_ieee = ieee;
70         c->ic_flags = flags;
71 }
72
73 /*
74  * Setup the channel list for the specified regulatory domain,
75  * country code, and operating modes.  This interface is used
76  * when a driver does not obtain the channel list from another
77  * source (such as firmware).
78  */
79 void
80 ieee80211_init_channels(struct ieee80211com *ic,
81         int rd, enum ISOCountryCode cc, int bands, int outdoor, int ecm)
82 {
83         int i;
84
85         /* XXX just do something for now */
86         ic->ic_nchans = 0;
87         if (isset(&bands, IEEE80211_MODE_11B) ||
88             isset(&bands, IEEE80211_MODE_11G)) {
89                 for (i = 1; i <= (ecm ? 14 : 11); i++) {
90                         if (isset(&bands, IEEE80211_MODE_11B))
91                                 addchan(ic, i, IEEE80211_CHAN_B);
92                         if (isset(&bands, IEEE80211_MODE_11G))
93                                 addchan(ic, i, IEEE80211_CHAN_G);
94                 }
95         }
96         if (isset(&bands, IEEE80211_MODE_11A)) {
97                 for (i = 36; i <= 64; i += 4)
98                         addchan(ic, i, IEEE80211_CHAN_A);
99                 for (i = 100; i <= 140; i += 4)
100                         addchan(ic, i, IEEE80211_CHAN_A);
101                 for (i = 149; i <= 161; i += 4)
102                         addchan(ic, i, IEEE80211_CHAN_A);
103         }
104         ic->ic_regdomain = rd;
105         ic->ic_countrycode = cc;
106         ic->ic_location = outdoor;
107 }
108
109 /*
110  * Add Country Information IE.
111  */
112 uint8_t *
113 ieee80211_add_countryie(uint8_t *frm, struct ieee80211com *ic,
114         enum ISOCountryCode cc, int location)
115 {
116 #define CHAN_UNINTERESTING \
117     (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO | \
118      IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)
119         /* XXX what about auto? */
120         /* flag set of channels to be excluded */
121         static const int skipflags[IEEE80211_MODE_MAX] = {
122             CHAN_UNINTERESTING,                         /* MODE_AUTO */
123             CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ,   /* MODE_11A */
124             CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ,   /* MODE_11B */
125             CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ,   /* MODE_11G */
126             CHAN_UNINTERESTING | IEEE80211_CHAN_OFDM |  /* MODE_FH */
127                 IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN,
128             CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ,   /* MODE_TURBO_A */
129             CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ,   /* MODE_TURBO_G */
130             CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ,   /* MODE_STURBO_A */
131             CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ,   /* MODE_11NA */
132             CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ,   /* MODE_11NG */
133         };
134         struct ieee80211_country_ie *ie = (struct ieee80211_country_ie *)frm;
135         const char *iso_name;
136         uint8_t nextchan, chans[IEEE80211_CHAN_BYTES];
137         int i, skip;
138
139         ie->ie = IEEE80211_ELEMID_COUNTRY;
140         iso_name = ieee80211_cctoiso(cc);
141         if (iso_name == NULL) {
142                 if_printf(ic->ic_ifp, "bad country code %d ignored\n", cc);
143                 iso_name = "  ";
144         }
145         ie->cc[0] = iso_name[0];
146         ie->cc[1] = iso_name[1];
147         /* 
148          * Indoor/Outdoor portion of country string.
149          * NB: this is not quite right, since we should have one of:
150          *     'I' indoor only
151          *     'O' outdoor only
152          *     ' ' all enviroments
153          */
154         ie->cc[2] = ((location & 3) == 3 ? ' ' : location & 1 ? 'I' : 'O');
155
156         /* 
157          * Run-length encoded channel+max tx power info.
158          */
159         frm = (uint8_t *)&ie->band[0];
160         nextchan = 0;                   /* NB: impossible channel # */
161         memset(chans, 0, sizeof(chans));
162         skip = skipflags[ic->ic_curmode];
163         for (i = 0; i < ic->ic_nchans; i++) {
164                 const struct ieee80211_channel *c = &ic->ic_channels[i];
165
166                 if (isset(chans, c->ic_ieee))           /* suppress dup's */
167                         continue;
168                 if (c->ic_flags & skip)                 /* skip band, etc. */
169                         continue;
170                 setbit(chans, c->ic_ieee);
171                 if (c->ic_ieee != nextchan ||
172                     c->ic_maxregpower != frm[-1]) {     /* new run */
173                         /* XXX max of 83 runs */
174                         frm[0] = c->ic_ieee;            /* starting channel # */
175                         frm[1] = 1;                     /* # channels in run */
176                         frm[2] = c->ic_maxregpower;     /* tx power cap */
177                         frm += 3;
178                         nextchan = c->ic_ieee + 1;      /* overflow? */
179                 } else {                                /* extend run */
180                         frm[-2]++;
181                         nextchan++;
182                 }
183         }
184         ie->len = frm - ie->cc;
185         if (ie->len & 1) {              /* Zero pad to multiple of 2 */
186                 ie->len++;
187                 *frm++ = 0;
188         }
189         return frm;
190 #undef CHAN_UNINTERESTING
191 }
192
193 /*
194  * Country Code Table for code-to-string conversion.
195  */
196 static const struct {
197         enum ISOCountryCode iso_code;      
198         const char*     iso_name;
199 } country_strings[] = {
200     { CTRY_DEBUG,               "DB" },         /* NB: nonstandard */
201     { CTRY_DEFAULT,             "NA" },         /* NB: nonstandard */
202     { CTRY_ALBANIA,             "AL" },
203     { CTRY_ALGERIA,             "DZ" },
204     { CTRY_ARGENTINA,           "AR" },
205     { CTRY_ARMENIA,             "AM" },
206     { CTRY_AUSTRALIA,           "AU" },
207     { CTRY_AUSTRIA,             "AT" },
208     { CTRY_AZERBAIJAN,          "AZ" },
209     { CTRY_BAHRAIN,             "BH" },
210     { CTRY_BELARUS,             "BY" },
211     { CTRY_BELGIUM,             "BE" },
212     { CTRY_BELIZE,              "BZ" },
213     { CTRY_BOLIVIA,             "BO" },
214     { CTRY_BRAZIL,              "BR" },
215     { CTRY_BRUNEI_DARUSSALAM,   "BN" },
216     { CTRY_BULGARIA,            "BG" },
217     { CTRY_CANADA,              "CA" },
218     { CTRY_CHILE,               "CL" },
219     { CTRY_CHINA,               "CN" },
220     { CTRY_COLOMBIA,            "CO" },
221     { CTRY_COSTA_RICA,          "CR" },
222     { CTRY_CROATIA,             "HR" },
223     { CTRY_CYPRUS,              "CY" },
224     { CTRY_CZECH,               "CZ" },
225     { CTRY_DENMARK,             "DK" },
226     { CTRY_DOMINICAN_REPUBLIC,  "DO" },
227     { CTRY_ECUADOR,             "EC" },
228     { CTRY_EGYPT,               "EG" },
229     { CTRY_EL_SALVADOR,         "SV" },    
230     { CTRY_ESTONIA,             "EE" },
231     { CTRY_FINLAND,             "FI" },
232     { CTRY_FRANCE,              "FR" },
233     { CTRY_FRANCE2,             "F2" },
234     { CTRY_GEORGIA,             "GE" },
235     { CTRY_GERMANY,             "DE" },
236     { CTRY_GREECE,              "GR" },
237     { CTRY_GUATEMALA,           "GT" },
238     { CTRY_HONDURAS,            "HN" },
239     { CTRY_HONG_KONG,           "HK" },
240     { CTRY_HUNGARY,             "HU" },
241     { CTRY_ICELAND,             "IS" },
242     { CTRY_INDIA,               "IN" },
243     { CTRY_INDONESIA,           "ID" },
244     { CTRY_IRAN,                "IR" },
245     { CTRY_IRELAND,             "IE" },
246     { CTRY_ISRAEL,              "IL" },
247     { CTRY_ITALY,               "IT" },
248     { CTRY_JAMAICA,             "JM" },
249     { CTRY_JAPAN,               "JP" },
250     { CTRY_JAPAN1,              "J1" },
251     { CTRY_JAPAN2,              "J2" },    
252     { CTRY_JAPAN3,              "J3" },
253     { CTRY_JAPAN4,              "J4" },
254     { CTRY_JAPAN5,              "J5" },    
255     { CTRY_JORDAN,              "JO" },
256     { CTRY_KAZAKHSTAN,          "KZ" },
257     { CTRY_KOREA_NORTH,         "KP" },
258     { CTRY_KOREA_ROC,           "KR" },
259     { CTRY_KOREA_ROC2,          "K2" },
260     { CTRY_KUWAIT,              "KW" },
261     { CTRY_LATVIA,              "LV" },
262     { CTRY_LEBANON,             "LB" },
263     { CTRY_LIECHTENSTEIN,       "LI" },
264     { CTRY_LITHUANIA,           "LT" },
265     { CTRY_LUXEMBOURG,          "LU" },
266     { CTRY_MACAU,               "MO" },
267     { CTRY_MACEDONIA,           "MK" },
268     { CTRY_MALAYSIA,            "MY" },
269     { CTRY_MEXICO,              "MX" },
270     { CTRY_MONACO,              "MC" },
271     { CTRY_MOROCCO,             "MA" },
272     { CTRY_NETHERLANDS,         "NL" },
273     { CTRY_NEW_ZEALAND,         "NZ" },
274     { CTRY_NORWAY,              "NO" },
275     { CTRY_OMAN,                "OM" },
276     { CTRY_PAKISTAN,            "PK" },
277     { CTRY_PANAMA,              "PA" },
278     { CTRY_PERU,                "PE" },
279     { CTRY_PHILIPPINES,         "PH" },
280     { CTRY_POLAND,              "PL" },
281     { CTRY_PORTUGAL,            "PT" },
282     { CTRY_PUERTO_RICO,         "PR" },
283     { CTRY_QATAR,               "QA" },
284     { CTRY_ROMANIA,             "RO" },
285     { CTRY_RUSSIA,              "RU" },
286     { CTRY_SAUDI_ARABIA,        "SA" },
287     { CTRY_SINGAPORE,           "SG" },
288     { CTRY_SLOVAKIA,            "SK" },
289     { CTRY_SLOVENIA,            "SI" },
290     { CTRY_SOUTH_AFRICA,        "ZA" },
291     { CTRY_SPAIN,               "ES" },
292     { CTRY_SWEDEN,              "SE" },
293     { CTRY_SWITZERLAND,         "CH" },
294     { CTRY_SYRIA,               "SY" },
295     { CTRY_TAIWAN,              "TW" },
296     { CTRY_THAILAND,            "TH" },
297     { CTRY_TRINIDAD_Y_TOBAGO,   "TT" },
298     { CTRY_TUNISIA,             "TN" },
299     { CTRY_TURKEY,              "TR" },
300     { CTRY_UKRAINE,             "UA" },
301     { CTRY_UAE,                 "AE" },
302     { CTRY_UNITED_KINGDOM,      "GB" },
303     { CTRY_UNITED_STATES,       "US" },
304     { CTRY_URUGUAY,             "UY" },
305     { CTRY_UZBEKISTAN,          "UZ" },    
306     { CTRY_VENEZUELA,           "VE" },
307     { CTRY_VIET_NAM,            "VN" },
308     { CTRY_YEMEN,               "YE" },
309     { CTRY_ZIMBABWE,            "ZW" }    
310 };
311
312 const char *
313 ieee80211_cctoiso(enum ISOCountryCode cc)
314 {
315 #define N(a)    (sizeof(a) / sizeof(a[0]))
316         int i;
317
318         for (i = 0; i < N(country_strings); i++) {
319                 if (country_strings[i].iso_code == cc)
320                         return country_strings[i].iso_name;
321         }
322         return NULL;
323 #undef N
324 }
325
326 int
327 ieee80211_isotocc(const char iso[2])
328 {
329 #define N(a)    (sizeof(a) / sizeof(a[0]))
330         int i;
331
332         for (i = 0; i < N(country_strings); i++) {
333                 if (country_strings[i].iso_name[0] == iso[0] &&
334                     country_strings[i].iso_name[1] == iso[1])
335                         return country_strings[i].iso_code;
336         }
337         return -1;
338 #undef N
339 }