xref: /dflybsd-src/sys/netproto/802_11/wlan/ieee80211_action.c (revision 32176cfd8803dac7f65c423373f231a378375c86)
1*32176cfdSRui Paulo /*-
2*32176cfdSRui Paulo  * Copyright (c) 2009 Sam Leffler, Errno Consulting
3*32176cfdSRui Paulo  * All rights reserved.
4*32176cfdSRui Paulo  *
5*32176cfdSRui Paulo  * Redistribution and use in source and binary forms, with or without
6*32176cfdSRui Paulo  * modification, are permitted provided that the following conditions
7*32176cfdSRui Paulo  * are met:
8*32176cfdSRui Paulo  * 1. Redistributions of source code must retain the above copyright
9*32176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer.
10*32176cfdSRui Paulo  * 2. Redistributions in binary form must reproduce the above copyright
11*32176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer in the
12*32176cfdSRui Paulo  *    documentation and/or other materials provided with the distribution.
13*32176cfdSRui Paulo  *
14*32176cfdSRui Paulo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*32176cfdSRui Paulo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*32176cfdSRui Paulo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*32176cfdSRui Paulo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*32176cfdSRui Paulo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*32176cfdSRui Paulo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*32176cfdSRui Paulo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*32176cfdSRui Paulo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*32176cfdSRui Paulo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*32176cfdSRui Paulo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*32176cfdSRui Paulo  *
25*32176cfdSRui Paulo  * $FreeBSD: head/sys/net80211/ieee80211_action.c 199186 2009-11-11 14:58:48Z antoine $
26*32176cfdSRui Paulo  * $DragonFly$
27*32176cfdSRui Paulo  */
28*32176cfdSRui Paulo 
29*32176cfdSRui Paulo /*
30*32176cfdSRui Paulo  * IEEE 802.11 send/recv action frame support.
31*32176cfdSRui Paulo  */
32*32176cfdSRui Paulo 
33*32176cfdSRui Paulo #include "opt_inet.h"
34*32176cfdSRui Paulo #include "opt_wlan.h"
35*32176cfdSRui Paulo 
36*32176cfdSRui Paulo #include <sys/param.h>
37*32176cfdSRui Paulo #include <sys/kernel.h>
38*32176cfdSRui Paulo #include <sys/systm.h>
39*32176cfdSRui Paulo 
40*32176cfdSRui Paulo #include <sys/socket.h>
41*32176cfdSRui Paulo 
42*32176cfdSRui Paulo #include <net/if.h>
43*32176cfdSRui Paulo #include <net/if_media.h>
44*32176cfdSRui Paulo #include <net/ethernet.h>
45*32176cfdSRui Paulo #include <net/route.h>
46*32176cfdSRui Paulo 
47*32176cfdSRui Paulo #include <netproto/802_11/ieee80211_var.h>
48*32176cfdSRui Paulo #include <netproto/802_11/ieee80211_action.h>
49*32176cfdSRui Paulo #include <netproto/802_11/ieee80211_mesh.h>
50*32176cfdSRui Paulo 
51*32176cfdSRui Paulo static int
52*32176cfdSRui Paulo send_inval(struct ieee80211_node *ni, int cat, int act, void *sa)
53*32176cfdSRui Paulo {
54*32176cfdSRui Paulo 	return EINVAL;
55*32176cfdSRui Paulo }
56*32176cfdSRui Paulo 
57*32176cfdSRui Paulo static ieee80211_send_action_func *ba_send_action[8] = {
58*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
59*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
60*32176cfdSRui Paulo };
61*32176cfdSRui Paulo static ieee80211_send_action_func *ht_send_action[8] = {
62*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
63*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
64*32176cfdSRui Paulo };
65*32176cfdSRui Paulo static ieee80211_send_action_func *meshpl_send_action[8] = {
66*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
67*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
68*32176cfdSRui Paulo };
69*32176cfdSRui Paulo static ieee80211_send_action_func *meshlm_send_action[4] = {
70*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
71*32176cfdSRui Paulo };
72*32176cfdSRui Paulo static ieee80211_send_action_func *hwmp_send_action[8] = {
73*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
74*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
75*32176cfdSRui Paulo };
76*32176cfdSRui Paulo static ieee80211_send_action_func *vendor_send_action[8] = {
77*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
78*32176cfdSRui Paulo 	send_inval, send_inval, send_inval, send_inval,
79*32176cfdSRui Paulo };
80*32176cfdSRui Paulo 
81*32176cfdSRui Paulo int
82*32176cfdSRui Paulo ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
83*32176cfdSRui Paulo {
84*32176cfdSRui Paulo #define	N(a)	(sizeof(a) / sizeof(a[0]))
85*32176cfdSRui Paulo 	switch (cat) {
86*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_BA:
87*32176cfdSRui Paulo 		if (act >= N(ba_send_action))
88*32176cfdSRui Paulo 			break;
89*32176cfdSRui Paulo 		ba_send_action[act] = f;
90*32176cfdSRui Paulo 		return 0;
91*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_HT:
92*32176cfdSRui Paulo 		if (act >= N(ht_send_action))
93*32176cfdSRui Paulo 			break;
94*32176cfdSRui Paulo 		ht_send_action[act] = f;
95*32176cfdSRui Paulo 		return 0;
96*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPEERING:
97*32176cfdSRui Paulo 		if (act >= N(meshpl_send_action))
98*32176cfdSRui Paulo 			break;
99*32176cfdSRui Paulo 		meshpl_send_action[act] = f;
100*32176cfdSRui Paulo 		return 0;
101*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
102*32176cfdSRui Paulo 		if (act >= N(meshlm_send_action))
103*32176cfdSRui Paulo 			break;
104*32176cfdSRui Paulo 		meshlm_send_action[act] = f;
105*32176cfdSRui Paulo 		return 0;
106*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPATH:
107*32176cfdSRui Paulo 		if (act >= N(hwmp_send_action))
108*32176cfdSRui Paulo 			break;
109*32176cfdSRui Paulo 		hwmp_send_action[act] = f;
110*32176cfdSRui Paulo 		return 0;
111*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_VENDOR:
112*32176cfdSRui Paulo 		if (act >= N(vendor_send_action))
113*32176cfdSRui Paulo 			break;
114*32176cfdSRui Paulo 		vendor_send_action[act] = f;
115*32176cfdSRui Paulo 		return 0;
116*32176cfdSRui Paulo 	}
117*32176cfdSRui Paulo 	return EINVAL;
118*32176cfdSRui Paulo #undef N
119*32176cfdSRui Paulo }
120*32176cfdSRui Paulo 
121*32176cfdSRui Paulo void
122*32176cfdSRui Paulo ieee80211_send_action_unregister(int cat, int act)
123*32176cfdSRui Paulo {
124*32176cfdSRui Paulo 	ieee80211_send_action_register(cat, act, send_inval);
125*32176cfdSRui Paulo }
126*32176cfdSRui Paulo 
127*32176cfdSRui Paulo int
128*32176cfdSRui Paulo ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa)
129*32176cfdSRui Paulo {
130*32176cfdSRui Paulo #define	N(a)	(sizeof(a) / sizeof(a[0]))
131*32176cfdSRui Paulo 	ieee80211_send_action_func *f = send_inval;
132*32176cfdSRui Paulo 
133*32176cfdSRui Paulo 	switch (cat) {
134*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_BA:
135*32176cfdSRui Paulo 		if (act < N(ba_send_action))
136*32176cfdSRui Paulo 			f = ba_send_action[act];
137*32176cfdSRui Paulo 		break;
138*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_HT:
139*32176cfdSRui Paulo 		if (act < N(ht_send_action))
140*32176cfdSRui Paulo 			f = ht_send_action[act];
141*32176cfdSRui Paulo 		break;
142*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPEERING:
143*32176cfdSRui Paulo 		if (act < N(meshpl_send_action))
144*32176cfdSRui Paulo 			f = meshpl_send_action[act];
145*32176cfdSRui Paulo 		break;
146*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
147*32176cfdSRui Paulo 		if (act < N(meshlm_send_action))
148*32176cfdSRui Paulo 			f = meshlm_send_action[act];
149*32176cfdSRui Paulo 		break;
150*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPATH:
151*32176cfdSRui Paulo 		if (act < N(hwmp_send_action))
152*32176cfdSRui Paulo 			f = hwmp_send_action[act];
153*32176cfdSRui Paulo 		break;
154*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_VENDOR:
155*32176cfdSRui Paulo 		if (act < N(vendor_send_action))
156*32176cfdSRui Paulo 			f = vendor_send_action[act];
157*32176cfdSRui Paulo 		break;
158*32176cfdSRui Paulo 	}
159*32176cfdSRui Paulo 	return f(ni, cat, act, sa);
160*32176cfdSRui Paulo #undef N
161*32176cfdSRui Paulo }
162*32176cfdSRui Paulo 
163*32176cfdSRui Paulo static int
164*32176cfdSRui Paulo recv_inval(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
165*32176cfdSRui Paulo 	const uint8_t *frm, const uint8_t *efrm)
166*32176cfdSRui Paulo {
167*32176cfdSRui Paulo 	return EINVAL;
168*32176cfdSRui Paulo }
169*32176cfdSRui Paulo 
170*32176cfdSRui Paulo static ieee80211_recv_action_func *ba_recv_action[8] = {
171*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
172*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
173*32176cfdSRui Paulo };
174*32176cfdSRui Paulo static ieee80211_recv_action_func *ht_recv_action[8] = {
175*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
176*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
177*32176cfdSRui Paulo };
178*32176cfdSRui Paulo static ieee80211_recv_action_func *meshpl_recv_action[8] = {
179*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
180*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
181*32176cfdSRui Paulo };
182*32176cfdSRui Paulo static ieee80211_recv_action_func *meshlm_recv_action[4] = {
183*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
184*32176cfdSRui Paulo };
185*32176cfdSRui Paulo static ieee80211_recv_action_func *hwmp_recv_action[8] = {
186*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
187*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
188*32176cfdSRui Paulo };
189*32176cfdSRui Paulo static ieee80211_recv_action_func *vendor_recv_action[8] = {
190*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
191*32176cfdSRui Paulo 	recv_inval, recv_inval, recv_inval, recv_inval,
192*32176cfdSRui Paulo };
193*32176cfdSRui Paulo 
194*32176cfdSRui Paulo int
195*32176cfdSRui Paulo ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f)
196*32176cfdSRui Paulo {
197*32176cfdSRui Paulo #define	N(a)	(sizeof(a) / sizeof(a[0]))
198*32176cfdSRui Paulo 	switch (cat) {
199*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_BA:
200*32176cfdSRui Paulo 		if (act >= N(ba_recv_action))
201*32176cfdSRui Paulo 			break;
202*32176cfdSRui Paulo 		ba_recv_action[act] = f;
203*32176cfdSRui Paulo 		return 0;
204*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_HT:
205*32176cfdSRui Paulo 		if (act >= N(ht_recv_action))
206*32176cfdSRui Paulo 			break;
207*32176cfdSRui Paulo 		ht_recv_action[act] = f;
208*32176cfdSRui Paulo 		return 0;
209*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPEERING:
210*32176cfdSRui Paulo 		if (act >= N(meshpl_recv_action))
211*32176cfdSRui Paulo 			break;
212*32176cfdSRui Paulo 		meshpl_recv_action[act] = f;
213*32176cfdSRui Paulo 		return 0;
214*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
215*32176cfdSRui Paulo 		if (act >= N(meshlm_recv_action))
216*32176cfdSRui Paulo 			break;
217*32176cfdSRui Paulo 		meshlm_recv_action[act] = f;
218*32176cfdSRui Paulo 		return 0;
219*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPATH:
220*32176cfdSRui Paulo 		if (act >= N(hwmp_recv_action))
221*32176cfdSRui Paulo 			break;
222*32176cfdSRui Paulo 		hwmp_recv_action[act] = f;
223*32176cfdSRui Paulo 		return 0;
224*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_VENDOR:
225*32176cfdSRui Paulo 		if (act >= N(vendor_recv_action))
226*32176cfdSRui Paulo 			break;
227*32176cfdSRui Paulo 		vendor_recv_action[act] = f;
228*32176cfdSRui Paulo 		return 0;
229*32176cfdSRui Paulo 	}
230*32176cfdSRui Paulo 	return EINVAL;
231*32176cfdSRui Paulo #undef N
232*32176cfdSRui Paulo }
233*32176cfdSRui Paulo 
234*32176cfdSRui Paulo void
235*32176cfdSRui Paulo ieee80211_recv_action_unregister(int cat, int act)
236*32176cfdSRui Paulo {
237*32176cfdSRui Paulo 	ieee80211_recv_action_register(cat, act, recv_inval);
238*32176cfdSRui Paulo }
239*32176cfdSRui Paulo 
240*32176cfdSRui Paulo int
241*32176cfdSRui Paulo ieee80211_recv_action(struct ieee80211_node *ni,
242*32176cfdSRui Paulo 	const struct ieee80211_frame *wh,
243*32176cfdSRui Paulo 	const uint8_t *frm, const uint8_t *efrm)
244*32176cfdSRui Paulo {
245*32176cfdSRui Paulo #define	N(a)	(sizeof(a) / sizeof(a[0]))
246*32176cfdSRui Paulo 	ieee80211_recv_action_func *f = recv_inval;
247*32176cfdSRui Paulo 	const struct ieee80211_action *ia =
248*32176cfdSRui Paulo 	    (const struct ieee80211_action *) frm;
249*32176cfdSRui Paulo 
250*32176cfdSRui Paulo 	switch (ia->ia_category) {
251*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_BA:
252*32176cfdSRui Paulo 		if (ia->ia_action < N(ba_recv_action))
253*32176cfdSRui Paulo 			f = ba_recv_action[ia->ia_action];
254*32176cfdSRui Paulo 		break;
255*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_HT:
256*32176cfdSRui Paulo 		if (ia->ia_action < N(ht_recv_action))
257*32176cfdSRui Paulo 			f = ht_recv_action[ia->ia_action];
258*32176cfdSRui Paulo 		break;
259*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPEERING:
260*32176cfdSRui Paulo 		if (ia->ia_action < N(meshpl_recv_action))
261*32176cfdSRui Paulo 			f = meshpl_recv_action[ia->ia_action];
262*32176cfdSRui Paulo 		break;
263*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHLMETRIC:
264*32176cfdSRui Paulo 		if (ia->ia_action < N(meshlm_recv_action))
265*32176cfdSRui Paulo 			f = meshlm_recv_action[ia->ia_action];
266*32176cfdSRui Paulo 		break;
267*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_MESHPATH:
268*32176cfdSRui Paulo 		if (ia->ia_action < N(hwmp_recv_action))
269*32176cfdSRui Paulo 			f = hwmp_recv_action[ia->ia_action];
270*32176cfdSRui Paulo 		break;
271*32176cfdSRui Paulo 	case IEEE80211_ACTION_CAT_VENDOR:
272*32176cfdSRui Paulo 		if (ia->ia_action < N(vendor_recv_action))
273*32176cfdSRui Paulo 			f = vendor_recv_action[ia->ia_action];
274*32176cfdSRui Paulo 		break;
275*32176cfdSRui Paulo 	}
276*32176cfdSRui Paulo 	return f(ni, wh, frm, efrm);
277*32176cfdSRui Paulo #undef N
278*32176cfdSRui Paulo }
279