Line data Source code
1 : /* $OpenBSD: ieee80211_regdomain.c,v 1.10 2015/11/24 13:45:06 mpi Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /*
20 : * Basic regulation domain extensions for the IEEE 802.11 stack
21 : */
22 :
23 : #include <sys/param.h>
24 : #include <sys/systm.h>
25 : #include <sys/mbuf.h>
26 : #include <sys/kernel.h>
27 : #include <sys/socket.h>
28 : #include <sys/sockio.h>
29 : #include <sys/endian.h>
30 : #include <sys/errno.h>
31 :
32 : #include <net/if.h>
33 : #include <net/if_dl.h>
34 : #include <net/if_media.h>
35 : #include <net/if_llc.h>
36 :
37 : #include <netinet/in.h>
38 : #include <netinet/if_ether.h>
39 :
40 : #include <net80211/ieee80211_var.h>
41 : #include <net80211/ieee80211_regdomain.h>
42 :
43 : int ieee80211_regdomain_compare_cn(const void *, const void *);
44 : int ieee80211_regdomain_compare_rn(const void *, const void *);
45 :
46 : static const struct ieee80211_regdomainname
47 : ieee80211_r_names[] = IEEE80211_REGDOMAIN_NAMES;
48 :
49 : static const struct ieee80211_regdomainmap
50 : ieee80211_r_map[] = IEEE80211_REGDOMAIN_MAP;
51 :
52 : static const struct ieee80211_countryname
53 : ieee80211_r_ctry[] = IEEE80211_REGDOMAIN_COUNTRY_NAMES;
54 :
55 : #ifndef bsearch
56 : const void *bsearch(const void *, const void *, size_t, size_t,
57 : int (*)(const void *, const void *));
58 :
59 : const void *
60 0 : bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
61 : int (*compar)(const void *, const void *))
62 : {
63 : const char *base = base0;
64 : int lim, cmp;
65 : const void *p;
66 :
67 0 : for (lim = nmemb; lim != 0; lim >>= 1) {
68 0 : p = base + (lim >> 1) * size;
69 0 : cmp = (*compar)(key, p);
70 0 : if (cmp == 0)
71 0 : return ((const void *)p);
72 0 : if (cmp > 0) { /* key > p: move right */
73 0 : base = (const char *)p + size;
74 0 : lim--;
75 0 : } /* else move left */
76 : }
77 0 : return (NULL);
78 0 : }
79 : #endif
80 :
81 : int
82 0 : ieee80211_regdomain_compare_cn(const void *a, const void *b)
83 : {
84 0 : return (strcmp(((const struct ieee80211_countryname*)a)->cn_name,
85 0 : ((const struct ieee80211_countryname*)b)->cn_name));
86 : }
87 :
88 : int
89 0 : ieee80211_regdomain_compare_rn(const void *a, const void *b)
90 : {
91 0 : return (strcmp(((const struct ieee80211_regdomainname*)a)->rn_name,
92 0 : ((const struct ieee80211_regdomainname*)b)->rn_name));
93 : }
94 :
95 : u_int16_t
96 0 : ieee80211_name2countrycode(const char *name)
97 : {
98 0 : const struct ieee80211_countryname key = { CTRY_DEFAULT, name }, *value;
99 :
100 0 : if ((value = bsearch(&key, &ieee80211_r_ctry,
101 : nitems(ieee80211_r_ctry), sizeof(struct ieee80211_countryname),
102 0 : ieee80211_regdomain_compare_cn)) != NULL)
103 0 : return (value->cn_code);
104 :
105 0 : return (CTRY_DEFAULT);
106 0 : }
107 :
108 : u_int32_t
109 0 : ieee80211_name2regdomain(const char *name)
110 : {
111 : const struct ieee80211_regdomainname *value;
112 0 : struct ieee80211_regdomainname key;
113 :
114 0 : key.rn_domain = DMN_DEFAULT;
115 0 : key.rn_name = name;
116 :
117 0 : if ((value = bsearch(&key, &ieee80211_r_names,
118 : nitems(ieee80211_r_names), sizeof(struct ieee80211_regdomainname),
119 0 : ieee80211_regdomain_compare_rn)) != NULL)
120 0 : return ((u_int32_t)value->rn_domain);
121 :
122 0 : return ((u_int32_t)DMN_DEFAULT);
123 0 : }
124 :
125 : const char *
126 0 : ieee80211_countrycode2name(u_int16_t code)
127 : {
128 : int i;
129 :
130 : /* Linear search over the table */
131 0 : for (i = 0; i < (sizeof(ieee80211_r_ctry) /
132 0 : sizeof(ieee80211_r_ctry[0])); i++)
133 0 : if (ieee80211_r_ctry[i].cn_code == code)
134 0 : return (ieee80211_r_ctry[i].cn_name);
135 :
136 0 : return (NULL);
137 0 : }
138 :
139 : const char *
140 0 : ieee80211_regdomain2name(u_int32_t regdomain)
141 : {
142 : int i;
143 :
144 : /* Linear search over the table */
145 0 : for (i = 0; i < (sizeof(ieee80211_r_names) /
146 0 : sizeof(ieee80211_r_names[0])); i++)
147 0 : if (ieee80211_r_names[i].rn_domain == regdomain)
148 0 : return (ieee80211_r_names[i].rn_name);
149 :
150 0 : return (ieee80211_r_names[0].rn_name);
151 0 : }
152 :
153 : u_int32_t
154 0 : ieee80211_regdomain2flag(u_int16_t regdomain, u_int16_t mhz)
155 : {
156 : int i;
157 :
158 0 : for (i = 0; i < (sizeof(ieee80211_r_map) /
159 0 : sizeof(ieee80211_r_map[0])); i++) {
160 0 : if (ieee80211_r_map[i].rm_domain == regdomain) {
161 0 : if (mhz >= 2000 && mhz <= 3000)
162 0 : return ((u_int32_t)
163 0 : ieee80211_r_map[i].rm_domain_2ghz);
164 0 : if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
165 0 : mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
166 0 : return ((u_int32_t)
167 0 : ieee80211_r_map[i].rm_domain_5ghz);
168 : }
169 : }
170 :
171 0 : return ((u_int32_t)DMN_DEBUG);
172 0 : }
173 :
174 : u_int32_t
175 0 : ieee80211_countrycode2regdomain(u_int16_t code)
176 : {
177 : int i;
178 :
179 0 : for (i = 0; i < nitems(ieee80211_r_ctry); i++)
180 0 : if (ieee80211_r_ctry[i].cn_code == code)
181 0 : return (ieee80211_r_ctry[i].cn_domain);
182 :
183 0 : return ((u_int32_t)DMN_DEFAULT);
184 0 : }
|