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