168e8e04eSSam Leffler /*- 268e8e04eSSam Leffler * Copyright (c) 2005-2007 Sam Leffler, Errno Consulting 368e8e04eSSam Leffler * All rights reserved. 468e8e04eSSam Leffler * 568e8e04eSSam Leffler * Redistribution and use in source and binary forms, with or without 668e8e04eSSam Leffler * modification, are permitted provided that the following conditions 768e8e04eSSam Leffler * are met: 868e8e04eSSam Leffler * 1. Redistributions of source code must retain the above copyright 968e8e04eSSam Leffler * notice, this list of conditions and the following disclaimer. 1068e8e04eSSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 1168e8e04eSSam Leffler * notice, this list of conditions and the following disclaimer in the 1268e8e04eSSam Leffler * documentation and/or other materials provided with the distribution. 1368e8e04eSSam Leffler * 1468e8e04eSSam Leffler * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1568e8e04eSSam Leffler * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1668e8e04eSSam Leffler * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1768e8e04eSSam Leffler * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1868e8e04eSSam Leffler * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1968e8e04eSSam Leffler * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2068e8e04eSSam Leffler * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2168e8e04eSSam Leffler * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2268e8e04eSSam Leffler * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2368e8e04eSSam Leffler * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2468e8e04eSSam Leffler */ 2568e8e04eSSam Leffler 2668e8e04eSSam Leffler #include <sys/cdefs.h> 2768e8e04eSSam Leffler __FBSDID("$FreeBSD$"); 2868e8e04eSSam Leffler 2968e8e04eSSam Leffler /* 3068e8e04eSSam Leffler * IEEE 802.11 regdomain support. 3168e8e04eSSam Leffler */ 3268e8e04eSSam Leffler 3368e8e04eSSam Leffler #include <sys/param.h> 3468e8e04eSSam Leffler #include <sys/systm.h> 3568e8e04eSSam Leffler #include <sys/kernel.h> 3668e8e04eSSam Leffler 3768e8e04eSSam Leffler #include <sys/socket.h> 3868e8e04eSSam Leffler 3968e8e04eSSam Leffler #include <net/if.h> 4068e8e04eSSam Leffler #include <net/if_arp.h> 4168e8e04eSSam Leffler #include <net/if_dl.h> 4268e8e04eSSam Leffler #include <net/if_media.h> 4368e8e04eSSam Leffler #include <net/if_types.h> 4468e8e04eSSam Leffler #include <net/ethernet.h> 4568e8e04eSSam Leffler 4668e8e04eSSam Leffler #include <net80211/ieee80211_var.h> 4768e8e04eSSam Leffler #include <net80211/ieee80211_regdomain.h> 4868e8e04eSSam Leffler 4968e8e04eSSam Leffler void 5068e8e04eSSam Leffler ieee80211_regdomain_attach(struct ieee80211com *ic) 5168e8e04eSSam Leffler { 5268e8e04eSSam Leffler ic->ic_regdomain = 0; /* XXX */ 5368e8e04eSSam Leffler ic->ic_countrycode = CTRY_UNITED_STATES;/* XXX */ 5468e8e04eSSam Leffler ic->ic_location = 1+2; /* both */ 5568e8e04eSSam Leffler } 5668e8e04eSSam Leffler 5768e8e04eSSam Leffler void 5868e8e04eSSam Leffler ieee80211_regdomain_detach(struct ieee80211com *ic) 5968e8e04eSSam Leffler { 6068e8e04eSSam Leffler } 6168e8e04eSSam Leffler 6268e8e04eSSam Leffler static void 6368e8e04eSSam Leffler addchan(struct ieee80211com *ic, int ieee, int flags) 6468e8e04eSSam Leffler { 6568e8e04eSSam Leffler struct ieee80211_channel *c; 6668e8e04eSSam Leffler 6768e8e04eSSam Leffler c = &ic->ic_channels[ic->ic_nchans++]; 6868e8e04eSSam Leffler c->ic_freq = ieee80211_ieee2mhz(ieee, flags); 6968e8e04eSSam Leffler c->ic_ieee = ieee; 7068e8e04eSSam Leffler c->ic_flags = flags; 7168e8e04eSSam Leffler } 7268e8e04eSSam Leffler 7368e8e04eSSam Leffler /* 7468e8e04eSSam Leffler * Setup the channel list for the specified regulatory domain, 7568e8e04eSSam Leffler * country code, and operating modes. This interface is used 7668e8e04eSSam Leffler * when a driver does not obtain the channel list from another 7768e8e04eSSam Leffler * source (such as firmware). 7868e8e04eSSam Leffler */ 7968e8e04eSSam Leffler void 8068e8e04eSSam Leffler ieee80211_init_channels(struct ieee80211com *ic, 8168e8e04eSSam Leffler int rd, enum ISOCountryCode cc, int bands, int outdoor, int ecm) 8268e8e04eSSam Leffler { 8368e8e04eSSam Leffler int i; 8468e8e04eSSam Leffler 8568e8e04eSSam Leffler /* XXX just do something for now */ 8668e8e04eSSam Leffler ic->ic_nchans = 0; 8768e8e04eSSam Leffler if (isset(&bands, IEEE80211_MODE_11B) || 8868e8e04eSSam Leffler isset(&bands, IEEE80211_MODE_11G)) { 8968e8e04eSSam Leffler for (i = 1; i <= (ecm ? 14 : 11); i++) { 9068e8e04eSSam Leffler if (isset(&bands, IEEE80211_MODE_11B)) 9168e8e04eSSam Leffler addchan(ic, i, IEEE80211_CHAN_B); 9268e8e04eSSam Leffler if (isset(&bands, IEEE80211_MODE_11G)) 9368e8e04eSSam Leffler addchan(ic, i, IEEE80211_CHAN_G); 9468e8e04eSSam Leffler } 9568e8e04eSSam Leffler } 9668e8e04eSSam Leffler if (isset(&bands, IEEE80211_MODE_11A)) { 9768e8e04eSSam Leffler for (i = 36; i <= 64; i += 4) 9868e8e04eSSam Leffler addchan(ic, i, IEEE80211_CHAN_A); 9968e8e04eSSam Leffler for (i = 100; i <= 140; i += 4) 10068e8e04eSSam Leffler addchan(ic, i, IEEE80211_CHAN_A); 10168e8e04eSSam Leffler for (i = 149; i <= 161; i += 4) 10268e8e04eSSam Leffler addchan(ic, i, IEEE80211_CHAN_A); 10368e8e04eSSam Leffler } 10468e8e04eSSam Leffler ic->ic_regdomain = rd; 10568e8e04eSSam Leffler ic->ic_countrycode = cc; 10668e8e04eSSam Leffler ic->ic_location = outdoor; 10768e8e04eSSam Leffler } 10868e8e04eSSam Leffler 10968e8e04eSSam Leffler /* 11068e8e04eSSam Leffler * Add Country Information IE. 11168e8e04eSSam Leffler */ 11268e8e04eSSam Leffler uint8_t * 11368e8e04eSSam Leffler ieee80211_add_countryie(uint8_t *frm, struct ieee80211com *ic, 11468e8e04eSSam Leffler enum ISOCountryCode cc, int location) 11568e8e04eSSam Leffler { 11668e8e04eSSam Leffler #define CHAN_UNINTERESTING \ 11768e8e04eSSam Leffler (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO | \ 11868e8e04eSSam Leffler IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER) 11968e8e04eSSam Leffler /* XXX what about auto? */ 12068e8e04eSSam Leffler /* flag set of channels to be excluded */ 12168e8e04eSSam Leffler static const int skipflags[IEEE80211_MODE_MAX] = { 12268e8e04eSSam Leffler CHAN_UNINTERESTING, /* MODE_AUTO */ 12368e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ, /* MODE_11A */ 12468e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ, /* MODE_11B */ 12568e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ, /* MODE_11G */ 12668e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_OFDM | /* MODE_FH */ 12768e8e04eSSam Leffler IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN, 12868e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ, /* MODE_TURBO_A */ 12968e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ, /* MODE_TURBO_G */ 13068e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ, /* MODE_STURBO_A */ 13168e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_2GHZ, /* MODE_11NA */ 13268e8e04eSSam Leffler CHAN_UNINTERESTING | IEEE80211_CHAN_5GHZ, /* MODE_11NG */ 13368e8e04eSSam Leffler }; 13468e8e04eSSam Leffler struct ieee80211_country_ie *ie = (struct ieee80211_country_ie *)frm; 13568e8e04eSSam Leffler const char *iso_name; 13668e8e04eSSam Leffler uint8_t nextchan, chans[IEEE80211_CHAN_BYTES]; 13768e8e04eSSam Leffler int i, skip; 13868e8e04eSSam Leffler 13968e8e04eSSam Leffler ie->ie = IEEE80211_ELEMID_COUNTRY; 14068e8e04eSSam Leffler iso_name = ieee80211_cctoiso(cc); 14168e8e04eSSam Leffler if (iso_name == NULL) { 14268e8e04eSSam Leffler if_printf(ic->ic_ifp, "bad country code %d ignored\n", cc); 14368e8e04eSSam Leffler iso_name = " "; 14468e8e04eSSam Leffler } 14568e8e04eSSam Leffler ie->cc[0] = iso_name[0]; 14668e8e04eSSam Leffler ie->cc[1] = iso_name[1]; 14768e8e04eSSam Leffler /* 14868e8e04eSSam Leffler * Indoor/Outdoor portion of country string. 14968e8e04eSSam Leffler * NB: this is not quite right, since we should have one of: 15068e8e04eSSam Leffler * 'I' indoor only 15168e8e04eSSam Leffler * 'O' outdoor only 15268e8e04eSSam Leffler * ' ' all enviroments 15368e8e04eSSam Leffler */ 15468e8e04eSSam Leffler ie->cc[2] = ((location & 3) == 3 ? ' ' : location & 1 ? 'I' : 'O'); 15568e8e04eSSam Leffler 15668e8e04eSSam Leffler /* 15768e8e04eSSam Leffler * Run-length encoded channel+max tx power info. 15868e8e04eSSam Leffler */ 15968e8e04eSSam Leffler frm = (uint8_t *)&ie->band[0]; 16068e8e04eSSam Leffler nextchan = 0; /* NB: impossible channel # */ 16168e8e04eSSam Leffler memset(chans, 0, sizeof(chans)); 16268e8e04eSSam Leffler skip = skipflags[ic->ic_curmode]; 16368e8e04eSSam Leffler for (i = 0; i < ic->ic_nchans; i++) { 16468e8e04eSSam Leffler const struct ieee80211_channel *c = &ic->ic_channels[i]; 16568e8e04eSSam Leffler 16668e8e04eSSam Leffler if (isset(chans, c->ic_ieee)) /* suppress dup's */ 16768e8e04eSSam Leffler continue; 1685ef9cd6cSSam Leffler if (c->ic_flags & skip) /* skip band, etc. */ 16968e8e04eSSam Leffler continue; 17068e8e04eSSam Leffler setbit(chans, c->ic_ieee); 17168e8e04eSSam Leffler if (c->ic_ieee != nextchan || 17268e8e04eSSam Leffler c->ic_maxregpower != frm[-1]) { /* new run */ 17368e8e04eSSam Leffler /* XXX max of 83 runs */ 17468e8e04eSSam Leffler frm[0] = c->ic_ieee; /* starting channel # */ 17568e8e04eSSam Leffler frm[1] = 1; /* # channels in run */ 17668e8e04eSSam Leffler frm[2] = c->ic_maxregpower; /* tx power cap */ 17768e8e04eSSam Leffler frm += 3; 17868e8e04eSSam Leffler nextchan = c->ic_ieee + 1; /* overflow? */ 17968e8e04eSSam Leffler } else { /* extend run */ 18068e8e04eSSam Leffler frm[-2]++; 18168e8e04eSSam Leffler nextchan++; 18268e8e04eSSam Leffler } 18368e8e04eSSam Leffler } 18468e8e04eSSam Leffler ie->len = frm - ie->cc; 185f05ba5eeSSepherosa Ziehau if (ie->len & 1) { /* Zero pad to multiple of 2 */ 18668e8e04eSSam Leffler ie->len++; 187f05ba5eeSSepherosa Ziehau *frm++ = 0; 188f05ba5eeSSepherosa Ziehau } 18968e8e04eSSam Leffler return frm; 19068e8e04eSSam Leffler #undef CHAN_UNINTERESTING 19168e8e04eSSam Leffler } 19268e8e04eSSam Leffler 19368e8e04eSSam Leffler /* 19468e8e04eSSam Leffler * Country Code Table for code-to-string conversion. 19568e8e04eSSam Leffler */ 19668e8e04eSSam Leffler static const struct { 19768e8e04eSSam Leffler enum ISOCountryCode iso_code; 19868e8e04eSSam Leffler const char* iso_name; 19968e8e04eSSam Leffler } country_strings[] = { 20068e8e04eSSam Leffler { CTRY_DEBUG, "DB" }, /* NB: nonstandard */ 20168e8e04eSSam Leffler { CTRY_DEFAULT, "NA" }, /* NB: nonstandard */ 20268e8e04eSSam Leffler { CTRY_ALBANIA, "AL" }, 20368e8e04eSSam Leffler { CTRY_ALGERIA, "DZ" }, 20468e8e04eSSam Leffler { CTRY_ARGENTINA, "AR" }, 20568e8e04eSSam Leffler { CTRY_ARMENIA, "AM" }, 20668e8e04eSSam Leffler { CTRY_AUSTRALIA, "AU" }, 20768e8e04eSSam Leffler { CTRY_AUSTRIA, "AT" }, 20868e8e04eSSam Leffler { CTRY_AZERBAIJAN, "AZ" }, 20968e8e04eSSam Leffler { CTRY_BAHRAIN, "BH" }, 21068e8e04eSSam Leffler { CTRY_BELARUS, "BY" }, 21168e8e04eSSam Leffler { CTRY_BELGIUM, "BE" }, 21268e8e04eSSam Leffler { CTRY_BELIZE, "BZ" }, 21368e8e04eSSam Leffler { CTRY_BOLIVIA, "BO" }, 21468e8e04eSSam Leffler { CTRY_BRAZIL, "BR" }, 21568e8e04eSSam Leffler { CTRY_BRUNEI_DARUSSALAM, "BN" }, 21668e8e04eSSam Leffler { CTRY_BULGARIA, "BG" }, 21768e8e04eSSam Leffler { CTRY_CANADA, "CA" }, 21868e8e04eSSam Leffler { CTRY_CHILE, "CL" }, 21968e8e04eSSam Leffler { CTRY_CHINA, "CN" }, 22068e8e04eSSam Leffler { CTRY_COLOMBIA, "CO" }, 22168e8e04eSSam Leffler { CTRY_COSTA_RICA, "CR" }, 22268e8e04eSSam Leffler { CTRY_CROATIA, "HR" }, 22368e8e04eSSam Leffler { CTRY_CYPRUS, "CY" }, 22468e8e04eSSam Leffler { CTRY_CZECH, "CZ" }, 22568e8e04eSSam Leffler { CTRY_DENMARK, "DK" }, 22668e8e04eSSam Leffler { CTRY_DOMINICAN_REPUBLIC, "DO" }, 22768e8e04eSSam Leffler { CTRY_ECUADOR, "EC" }, 22868e8e04eSSam Leffler { CTRY_EGYPT, "EG" }, 22968e8e04eSSam Leffler { CTRY_EL_SALVADOR, "SV" }, 23068e8e04eSSam Leffler { CTRY_ESTONIA, "EE" }, 23168e8e04eSSam Leffler { CTRY_FINLAND, "FI" }, 23268e8e04eSSam Leffler { CTRY_FRANCE, "FR" }, 23368e8e04eSSam Leffler { CTRY_FRANCE2, "F2" }, 23468e8e04eSSam Leffler { CTRY_GEORGIA, "GE" }, 23568e8e04eSSam Leffler { CTRY_GERMANY, "DE" }, 23668e8e04eSSam Leffler { CTRY_GREECE, "GR" }, 23768e8e04eSSam Leffler { CTRY_GUATEMALA, "GT" }, 23868e8e04eSSam Leffler { CTRY_HONDURAS, "HN" }, 23968e8e04eSSam Leffler { CTRY_HONG_KONG, "HK" }, 24068e8e04eSSam Leffler { CTRY_HUNGARY, "HU" }, 24168e8e04eSSam Leffler { CTRY_ICELAND, "IS" }, 24268e8e04eSSam Leffler { CTRY_INDIA, "IN" }, 24368e8e04eSSam Leffler { CTRY_INDONESIA, "ID" }, 24468e8e04eSSam Leffler { CTRY_IRAN, "IR" }, 24568e8e04eSSam Leffler { CTRY_IRELAND, "IE" }, 24668e8e04eSSam Leffler { CTRY_ISRAEL, "IL" }, 24768e8e04eSSam Leffler { CTRY_ITALY, "IT" }, 24868e8e04eSSam Leffler { CTRY_JAMAICA, "JM" }, 24968e8e04eSSam Leffler { CTRY_JAPAN, "JP" }, 25068e8e04eSSam Leffler { CTRY_JAPAN1, "J1" }, 25168e8e04eSSam Leffler { CTRY_JAPAN2, "J2" }, 25268e8e04eSSam Leffler { CTRY_JAPAN3, "J3" }, 25368e8e04eSSam Leffler { CTRY_JAPAN4, "J4" }, 25468e8e04eSSam Leffler { CTRY_JAPAN5, "J5" }, 25568e8e04eSSam Leffler { CTRY_JORDAN, "JO" }, 25668e8e04eSSam Leffler { CTRY_KAZAKHSTAN, "KZ" }, 25768e8e04eSSam Leffler { CTRY_KOREA_NORTH, "KP" }, 25868e8e04eSSam Leffler { CTRY_KOREA_ROC, "KR" }, 25968e8e04eSSam Leffler { CTRY_KOREA_ROC2, "K2" }, 26068e8e04eSSam Leffler { CTRY_KUWAIT, "KW" }, 26168e8e04eSSam Leffler { CTRY_LATVIA, "LV" }, 26268e8e04eSSam Leffler { CTRY_LEBANON, "LB" }, 26368e8e04eSSam Leffler { CTRY_LIECHTENSTEIN, "LI" }, 26468e8e04eSSam Leffler { CTRY_LITHUANIA, "LT" }, 26568e8e04eSSam Leffler { CTRY_LUXEMBOURG, "LU" }, 26668e8e04eSSam Leffler { CTRY_MACAU, "MO" }, 26768e8e04eSSam Leffler { CTRY_MACEDONIA, "MK" }, 26868e8e04eSSam Leffler { CTRY_MALAYSIA, "MY" }, 26968e8e04eSSam Leffler { CTRY_MEXICO, "MX" }, 27068e8e04eSSam Leffler { CTRY_MONACO, "MC" }, 27168e8e04eSSam Leffler { CTRY_MOROCCO, "MA" }, 27268e8e04eSSam Leffler { CTRY_NETHERLANDS, "NL" }, 27368e8e04eSSam Leffler { CTRY_NEW_ZEALAND, "NZ" }, 27468e8e04eSSam Leffler { CTRY_NORWAY, "NO" }, 27568e8e04eSSam Leffler { CTRY_OMAN, "OM" }, 27668e8e04eSSam Leffler { CTRY_PAKISTAN, "PK" }, 27768e8e04eSSam Leffler { CTRY_PANAMA, "PA" }, 27868e8e04eSSam Leffler { CTRY_PERU, "PE" }, 27968e8e04eSSam Leffler { CTRY_PHILIPPINES, "PH" }, 28068e8e04eSSam Leffler { CTRY_POLAND, "PL" }, 28168e8e04eSSam Leffler { CTRY_PORTUGAL, "PT" }, 28268e8e04eSSam Leffler { CTRY_PUERTO_RICO, "PR" }, 28368e8e04eSSam Leffler { CTRY_QATAR, "QA" }, 28468e8e04eSSam Leffler { CTRY_ROMANIA, "RO" }, 28568e8e04eSSam Leffler { CTRY_RUSSIA, "RU" }, 28668e8e04eSSam Leffler { CTRY_SAUDI_ARABIA, "SA" }, 28768e8e04eSSam Leffler { CTRY_SINGAPORE, "SG" }, 28868e8e04eSSam Leffler { CTRY_SLOVAKIA, "SK" }, 28968e8e04eSSam Leffler { CTRY_SLOVENIA, "SI" }, 29068e8e04eSSam Leffler { CTRY_SOUTH_AFRICA, "ZA" }, 29168e8e04eSSam Leffler { CTRY_SPAIN, "ES" }, 29268e8e04eSSam Leffler { CTRY_SWEDEN, "SE" }, 29368e8e04eSSam Leffler { CTRY_SWITZERLAND, "CH" }, 29468e8e04eSSam Leffler { CTRY_SYRIA, "SY" }, 29568e8e04eSSam Leffler { CTRY_TAIWAN, "TW" }, 29668e8e04eSSam Leffler { CTRY_THAILAND, "TH" }, 29768e8e04eSSam Leffler { CTRY_TRINIDAD_Y_TOBAGO, "TT" }, 29868e8e04eSSam Leffler { CTRY_TUNISIA, "TN" }, 29968e8e04eSSam Leffler { CTRY_TURKEY, "TR" }, 30068e8e04eSSam Leffler { CTRY_UKRAINE, "UA" }, 30168e8e04eSSam Leffler { CTRY_UAE, "AE" }, 30268e8e04eSSam Leffler { CTRY_UNITED_KINGDOM, "GB" }, 30368e8e04eSSam Leffler { CTRY_UNITED_STATES, "US" }, 30468e8e04eSSam Leffler { CTRY_URUGUAY, "UY" }, 30568e8e04eSSam Leffler { CTRY_UZBEKISTAN, "UZ" }, 30668e8e04eSSam Leffler { CTRY_VENEZUELA, "VE" }, 30768e8e04eSSam Leffler { CTRY_VIET_NAM, "VN" }, 30868e8e04eSSam Leffler { CTRY_YEMEN, "YE" }, 30968e8e04eSSam Leffler { CTRY_ZIMBABWE, "ZW" } 31068e8e04eSSam Leffler }; 31168e8e04eSSam Leffler 31268e8e04eSSam Leffler const char * 31368e8e04eSSam Leffler ieee80211_cctoiso(enum ISOCountryCode cc) 31468e8e04eSSam Leffler { 31568e8e04eSSam Leffler #define N(a) (sizeof(a) / sizeof(a[0])) 31668e8e04eSSam Leffler int i; 31768e8e04eSSam Leffler 31868e8e04eSSam Leffler for (i = 0; i < N(country_strings); i++) { 31968e8e04eSSam Leffler if (country_strings[i].iso_code == cc) 32068e8e04eSSam Leffler return country_strings[i].iso_name; 32168e8e04eSSam Leffler } 32268e8e04eSSam Leffler return NULL; 32368e8e04eSSam Leffler #undef N 32468e8e04eSSam Leffler } 32568e8e04eSSam Leffler 32668e8e04eSSam Leffler int 32768e8e04eSSam Leffler ieee80211_isotocc(const char iso[2]) 32868e8e04eSSam Leffler { 32968e8e04eSSam Leffler #define N(a) (sizeof(a) / sizeof(a[0])) 33068e8e04eSSam Leffler int i; 33168e8e04eSSam Leffler 33268e8e04eSSam Leffler for (i = 0; i < N(country_strings); i++) { 33368e8e04eSSam Leffler if (country_strings[i].iso_name[0] == iso[0] && 33468e8e04eSSam Leffler country_strings[i].iso_name[1] == iso[1]) 33568e8e04eSSam Leffler return country_strings[i].iso_code; 33668e8e04eSSam Leffler } 33768e8e04eSSam Leffler return -1; 33868e8e04eSSam Leffler #undef N 33968e8e04eSSam Leffler } 340