1 /*-
2  * Copyright (c) 2009 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  * $FreeBSD: head/sys/net80211/ieee80211_action.c 199186 2009-11-11 14:58:48Z antoine $
26  * $DragonFly$
27  */
28 
29 /*
30  * IEEE 802.11 send/recv action frame support.
31  */
32 
33 #include "opt_inet.h"
34 #include "opt_wlan.h"
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 
40 #include <sys/socket.h>
41 
42 #include <net/if.h>
43 #include <net/if_media.h>
44 #include <net/ethernet.h>
45 #include <net/route.h>
46 
47 #include <netproto/802_11/ieee80211_var.h>
48 #include <netproto/802_11/ieee80211_action.h>
49 #include <netproto/802_11/ieee80211_mesh.h>
50 
51 static int
52 send_inval(struct ieee80211_node *ni, int cat, int act, void *sa)
53 {
54 	return EINVAL;
55 }
56 
57 static ieee80211_send_action_func *ba_send_action[8] = {
58 	send_inval, send_inval, send_inval, send_inval,
59 	send_inval, send_inval, send_inval, send_inval,
60 };
61 static ieee80211_send_action_func *ht_send_action[8] = {
62 	send_inval, send_inval, send_inval, send_inval,
63 	send_inval, send_inval, send_inval, send_inval,
64 };
65 static ieee80211_send_action_func *meshpl_send_action[8] = {
66 	send_inval, send_inval, send_inval, send_inval,
67 	send_inval, send_inval, send_inval, send_inval,
68 };
69 static ieee80211_send_action_func *meshlm_send_action[4] = {
70 	send_inval, send_inval, send_inval, send_inval,
71 };
72 static ieee80211_send_action_func *hwmp_send_action[8] = {
73 	send_inval, send_inval, send_inval, send_inval,
74 	send_inval, send_inval, send_inval, send_inval,
75 };
76 static ieee80211_send_action_func *vendor_send_action[8] = {
77 	send_inval, send_inval, send_inval, send_inval,
78 	send_inval, send_inval, send_inval, send_inval,
79 };
80 
81 int
82 ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
83 {
84 #define	N(a)	(sizeof(a) / sizeof(a[0]))
85 	switch (cat) {
86 	case IEEE80211_ACTION_CAT_BA:
87 		if (act >= N(ba_send_action))
88 			break;
89 		ba_send_action[act] = f;
90 		return 0;
91 	case IEEE80211_ACTION_CAT_HT:
92 		if (act >= N(ht_send_action))
93 			break;
94 		ht_send_action[act] = f;
95 		return 0;
96 	case IEEE80211_ACTION_CAT_MESHPEERING:
97 		if (act >= N(meshpl_send_action))
98 			break;
99 		meshpl_send_action[act] = f;
100 		return 0;
101 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
102 		if (act >= N(meshlm_send_action))
103 			break;
104 		meshlm_send_action[act] = f;
105 		return 0;
106 	case IEEE80211_ACTION_CAT_MESHPATH:
107 		if (act >= N(hwmp_send_action))
108 			break;
109 		hwmp_send_action[act] = f;
110 		return 0;
111 	case IEEE80211_ACTION_CAT_VENDOR:
112 		if (act >= N(vendor_send_action))
113 			break;
114 		vendor_send_action[act] = f;
115 		return 0;
116 	}
117 	return EINVAL;
118 #undef N
119 }
120 
121 void
122 ieee80211_send_action_unregister(int cat, int act)
123 {
124 	ieee80211_send_action_register(cat, act, send_inval);
125 }
126 
127 int
128 ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa)
129 {
130 #define	N(a)	(sizeof(a) / sizeof(a[0]))
131 	ieee80211_send_action_func *f = send_inval;
132 
133 	switch (cat) {
134 	case IEEE80211_ACTION_CAT_BA:
135 		if (act < N(ba_send_action))
136 			f = ba_send_action[act];
137 		break;
138 	case IEEE80211_ACTION_CAT_HT:
139 		if (act < N(ht_send_action))
140 			f = ht_send_action[act];
141 		break;
142 	case IEEE80211_ACTION_CAT_MESHPEERING:
143 		if (act < N(meshpl_send_action))
144 			f = meshpl_send_action[act];
145 		break;
146 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
147 		if (act < N(meshlm_send_action))
148 			f = meshlm_send_action[act];
149 		break;
150 	case IEEE80211_ACTION_CAT_MESHPATH:
151 		if (act < N(hwmp_send_action))
152 			f = hwmp_send_action[act];
153 		break;
154 	case IEEE80211_ACTION_CAT_VENDOR:
155 		if (act < N(vendor_send_action))
156 			f = vendor_send_action[act];
157 		break;
158 	}
159 	return f(ni, cat, act, sa);
160 #undef N
161 }
162 
163 static int
164 recv_inval(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
165 	const uint8_t *frm, const uint8_t *efrm)
166 {
167 	return EINVAL;
168 }
169 
170 static ieee80211_recv_action_func *ba_recv_action[8] = {
171 	recv_inval, recv_inval, recv_inval, recv_inval,
172 	recv_inval, recv_inval, recv_inval, recv_inval,
173 };
174 static ieee80211_recv_action_func *ht_recv_action[8] = {
175 	recv_inval, recv_inval, recv_inval, recv_inval,
176 	recv_inval, recv_inval, recv_inval, recv_inval,
177 };
178 static ieee80211_recv_action_func *meshpl_recv_action[8] = {
179 	recv_inval, recv_inval, recv_inval, recv_inval,
180 	recv_inval, recv_inval, recv_inval, recv_inval,
181 };
182 static ieee80211_recv_action_func *meshlm_recv_action[4] = {
183 	recv_inval, recv_inval, recv_inval, recv_inval,
184 };
185 static ieee80211_recv_action_func *hwmp_recv_action[8] = {
186 	recv_inval, recv_inval, recv_inval, recv_inval,
187 	recv_inval, recv_inval, recv_inval, recv_inval,
188 };
189 static ieee80211_recv_action_func *vendor_recv_action[8] = {
190 	recv_inval, recv_inval, recv_inval, recv_inval,
191 	recv_inval, recv_inval, recv_inval, recv_inval,
192 };
193 
194 int
195 ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f)
196 {
197 #define	N(a)	(sizeof(a) / sizeof(a[0]))
198 	switch (cat) {
199 	case IEEE80211_ACTION_CAT_BA:
200 		if (act >= N(ba_recv_action))
201 			break;
202 		ba_recv_action[act] = f;
203 		return 0;
204 	case IEEE80211_ACTION_CAT_HT:
205 		if (act >= N(ht_recv_action))
206 			break;
207 		ht_recv_action[act] = f;
208 		return 0;
209 	case IEEE80211_ACTION_CAT_MESHPEERING:
210 		if (act >= N(meshpl_recv_action))
211 			break;
212 		meshpl_recv_action[act] = f;
213 		return 0;
214 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
215 		if (act >= N(meshlm_recv_action))
216 			break;
217 		meshlm_recv_action[act] = f;
218 		return 0;
219 	case IEEE80211_ACTION_CAT_MESHPATH:
220 		if (act >= N(hwmp_recv_action))
221 			break;
222 		hwmp_recv_action[act] = f;
223 		return 0;
224 	case IEEE80211_ACTION_CAT_VENDOR:
225 		if (act >= N(vendor_recv_action))
226 			break;
227 		vendor_recv_action[act] = f;
228 		return 0;
229 	}
230 	return EINVAL;
231 #undef N
232 }
233 
234 void
235 ieee80211_recv_action_unregister(int cat, int act)
236 {
237 	ieee80211_recv_action_register(cat, act, recv_inval);
238 }
239 
240 int
241 ieee80211_recv_action(struct ieee80211_node *ni,
242 	const struct ieee80211_frame *wh,
243 	const uint8_t *frm, const uint8_t *efrm)
244 {
245 #define	N(a)	(sizeof(a) / sizeof(a[0]))
246 	ieee80211_recv_action_func *f = recv_inval;
247 	const struct ieee80211_action *ia =
248 	    (const struct ieee80211_action *) frm;
249 
250 	switch (ia->ia_category) {
251 	case IEEE80211_ACTION_CAT_BA:
252 		if (ia->ia_action < N(ba_recv_action))
253 			f = ba_recv_action[ia->ia_action];
254 		break;
255 	case IEEE80211_ACTION_CAT_HT:
256 		if (ia->ia_action < N(ht_recv_action))
257 			f = ht_recv_action[ia->ia_action];
258 		break;
259 	case IEEE80211_ACTION_CAT_MESHPEERING:
260 		if (ia->ia_action < N(meshpl_recv_action))
261 			f = meshpl_recv_action[ia->ia_action];
262 		break;
263 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
264 		if (ia->ia_action < N(meshlm_recv_action))
265 			f = meshlm_recv_action[ia->ia_action];
266 		break;
267 	case IEEE80211_ACTION_CAT_MESHPATH:
268 		if (ia->ia_action < N(hwmp_recv_action))
269 			f = hwmp_recv_action[ia->ia_action];
270 		break;
271 	case IEEE80211_ACTION_CAT_VENDOR:
272 		if (ia->ia_action < N(vendor_recv_action))
273 			f = vendor_recv_action[ia->ia_action];
274 		break;
275 	}
276 	return f(ni, wh, frm, efrm);
277 #undef N
278 }
279