42d58e1cbbe7bc0f80f7a4d7e2f42d6701136abb
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_action.c
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         switch (cat) {
85         case IEEE80211_ACTION_CAT_BA:
86                 if (act >= NELEM(ba_send_action))
87                         break;
88                 ba_send_action[act] = f;
89                 return 0;
90         case IEEE80211_ACTION_CAT_HT:
91                 if (act >= NELEM(ht_send_action))
92                         break;
93                 ht_send_action[act] = f;
94                 return 0;
95         case IEEE80211_ACTION_CAT_MESHPEERING:
96                 if (act >= NELEM(meshpl_send_action))
97                         break;
98                 meshpl_send_action[act] = f;
99                 return 0;
100         case IEEE80211_ACTION_CAT_MESHLMETRIC:
101                 if (act >= NELEM(meshlm_send_action))
102                         break;
103                 meshlm_send_action[act] = f;
104                 return 0;
105         case IEEE80211_ACTION_CAT_MESHPATH:
106                 if (act >= NELEM(hwmp_send_action))
107                         break;
108                 hwmp_send_action[act] = f;
109                 return 0;
110         case IEEE80211_ACTION_CAT_VENDOR:
111                 if (act >= NELEM(vendor_send_action))
112                         break;
113                 vendor_send_action[act] = f;
114                 return 0;
115         }
116         return EINVAL;
117 }
118
119 void
120 ieee80211_send_action_unregister(int cat, int act)
121 {
122         ieee80211_send_action_register(cat, act, send_inval);
123 }
124
125 int
126 ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa)
127 {
128         ieee80211_send_action_func *f = send_inval;
129
130         switch (cat) {
131         case IEEE80211_ACTION_CAT_BA:
132                 if (act < NELEM(ba_send_action))
133                         f = ba_send_action[act];
134                 break;
135         case IEEE80211_ACTION_CAT_HT:
136                 if (act < NELEM(ht_send_action))
137                         f = ht_send_action[act];
138                 break;
139         case IEEE80211_ACTION_CAT_MESHPEERING:
140                 if (act < NELEM(meshpl_send_action))
141                         f = meshpl_send_action[act];
142                 break;
143         case IEEE80211_ACTION_CAT_MESHLMETRIC:
144                 if (act < NELEM(meshlm_send_action))
145                         f = meshlm_send_action[act];
146                 break;
147         case IEEE80211_ACTION_CAT_MESHPATH:
148                 if (act < NELEM(hwmp_send_action))
149                         f = hwmp_send_action[act];
150                 break;
151         case IEEE80211_ACTION_CAT_VENDOR:
152                 if (act < NELEM(vendor_send_action))
153                         f = vendor_send_action[act];
154                 break;
155         }
156         return f(ni, cat, act, sa);
157 }
158
159 static int
160 recv_inval(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
161         const uint8_t *frm, const uint8_t *efrm)
162 {
163         return EINVAL;
164 }
165
166 static ieee80211_recv_action_func *ba_recv_action[8] = {
167         recv_inval, recv_inval, recv_inval, recv_inval,
168         recv_inval, recv_inval, recv_inval, recv_inval,
169 };
170 static ieee80211_recv_action_func *ht_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 *meshpl_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 *meshlm_recv_action[4] = {
179         recv_inval, recv_inval, recv_inval, recv_inval,
180 };
181 static ieee80211_recv_action_func *hwmp_recv_action[8] = {
182         recv_inval, recv_inval, recv_inval, recv_inval,
183         recv_inval, recv_inval, recv_inval, recv_inval,
184 };
185 static ieee80211_recv_action_func *vendor_recv_action[8] = {
186         recv_inval, recv_inval, recv_inval, recv_inval,
187         recv_inval, recv_inval, recv_inval, recv_inval,
188 };
189
190 int
191 ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f)
192 {
193         switch (cat) {
194         case IEEE80211_ACTION_CAT_BA:
195                 if (act >= NELEM(ba_recv_action))
196                         break;
197                 ba_recv_action[act] = f;
198                 return 0;
199         case IEEE80211_ACTION_CAT_HT:
200                 if (act >= NELEM(ht_recv_action))
201                         break;
202                 ht_recv_action[act] = f;
203                 return 0;
204         case IEEE80211_ACTION_CAT_MESHPEERING:
205                 if (act >= NELEM(meshpl_recv_action))
206                         break;
207                 meshpl_recv_action[act] = f;
208                 return 0;
209         case IEEE80211_ACTION_CAT_MESHLMETRIC:
210                 if (act >= NELEM(meshlm_recv_action))
211                         break;
212                 meshlm_recv_action[act] = f;
213                 return 0;
214         case IEEE80211_ACTION_CAT_MESHPATH:
215                 if (act >= NELEM(hwmp_recv_action))
216                         break;
217                 hwmp_recv_action[act] = f;
218                 return 0;
219         case IEEE80211_ACTION_CAT_VENDOR:
220                 if (act >= NELEM(vendor_recv_action))
221                         break;
222                 vendor_recv_action[act] = f;
223                 return 0;
224         }
225         return EINVAL;
226 }
227
228 void
229 ieee80211_recv_action_unregister(int cat, int act)
230 {
231         ieee80211_recv_action_register(cat, act, recv_inval);
232 }
233
234 int
235 ieee80211_recv_action(struct ieee80211_node *ni,
236         const struct ieee80211_frame *wh,
237         const uint8_t *frm, const uint8_t *efrm)
238 {
239         ieee80211_recv_action_func *f = recv_inval;
240         const struct ieee80211_action *ia =
241             (const struct ieee80211_action *) frm;
242
243         switch (ia->ia_category) {
244         case IEEE80211_ACTION_CAT_BA:
245                 if (ia->ia_action < NELEM(ba_recv_action))
246                         f = ba_recv_action[ia->ia_action];
247                 break;
248         case IEEE80211_ACTION_CAT_HT:
249                 if (ia->ia_action < NELEM(ht_recv_action))
250                         f = ht_recv_action[ia->ia_action];
251                 break;
252         case IEEE80211_ACTION_CAT_MESHPEERING:
253                 if (ia->ia_action < NELEM(meshpl_recv_action))
254                         f = meshpl_recv_action[ia->ia_action];
255                 break;
256         case IEEE80211_ACTION_CAT_MESHLMETRIC:
257                 if (ia->ia_action < NELEM(meshlm_recv_action))
258                         f = meshlm_recv_action[ia->ia_action];
259                 break;
260         case IEEE80211_ACTION_CAT_MESHPATH:
261                 if (ia->ia_action < NELEM(hwmp_recv_action))
262                         f = hwmp_recv_action[ia->ia_action];
263                 break;
264         case IEEE80211_ACTION_CAT_VENDOR:
265                 if (ia->ia_action < NELEM(vendor_recv_action))
266                         f = vendor_recv_action[ia->ia_action];
267                 break;
268         }
269         return f(ni, wh, frm, efrm);
270 }