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$"); 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 #include <net80211/ieee80211_mesh.h> 51 52 static int 53 send_inval(struct ieee80211_node *ni, int cat, int act, void *sa) 54 { 55 return EINVAL; 56 } 57 58 static ieee80211_send_action_func *ba_send_action[8] = { 59 send_inval, send_inval, send_inval, send_inval, 60 send_inval, send_inval, send_inval, send_inval, 61 }; 62 static ieee80211_send_action_func *ht_send_action[8] = { 63 send_inval, send_inval, send_inval, send_inval, 64 send_inval, send_inval, send_inval, send_inval, 65 }; 66 static ieee80211_send_action_func *meshpl_send_action[8] = { 67 send_inval, send_inval, send_inval, send_inval, 68 send_inval, send_inval, send_inval, send_inval, 69 }; 70 static ieee80211_send_action_func *meshlm_send_action[4] = { 71 send_inval, send_inval, send_inval, send_inval, 72 }; 73 static ieee80211_send_action_func *hwmp_send_action[8] = { 74 send_inval, send_inval, send_inval, send_inval, 75 send_inval, send_inval, send_inval, send_inval, 76 }; 77 static ieee80211_send_action_func *vendor_send_action[8] = { 78 send_inval, send_inval, send_inval, send_inval, 79 send_inval, send_inval, send_inval, send_inval, 80 }; 81 82 int 83 ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f) 84 { 85 #define N(a) (sizeof(a) / sizeof(a[0])) 86 switch (cat) { 87 case IEEE80211_ACTION_CAT_BA: 88 if (act >= N(ba_send_action)) 89 break; 90 ba_send_action[act] = f; 91 return 0; 92 case IEEE80211_ACTION_CAT_HT: 93 if (act >= N(ht_send_action)) 94 break; 95 ht_send_action[act] = f; 96 return 0; 97 case IEEE80211_ACTION_CAT_SELF_PROT: 98 if (act >= N(meshpl_send_action)) 99 break; 100 meshpl_send_action[act] = f; 101 return 0; 102 case IEEE80211_ACTION_CAT_MESH: 103 switch (act) { 104 case IEEE80211_ACTION_MESH_LMETRIC: 105 if (act >= N(meshlm_send_action)) 106 break; 107 meshlm_send_action[act] = f; 108 return 0; 109 case IEEE80211_ACTION_MESH_HWMP: 110 if (act >= N(hwmp_send_action)) 111 break; 112 hwmp_send_action[act] = f; 113 return 0; 114 } 115 break; 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 126 void 127 ieee80211_send_action_unregister(int cat, int act) 128 { 129 ieee80211_send_action_register(cat, act, send_inval); 130 } 131 132 int 133 ieee80211_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 case IEEE80211_ACTION_CAT_SELF_PROT: 148 if (act < N(meshpl_send_action)) 149 f = meshpl_send_action[act]; 150 break; 151 case IEEE80211_ACTION_CAT_MESH: 152 switch (act) { 153 case IEEE80211_ACTION_MESH_LMETRIC: 154 if (act < N(meshlm_send_action)) 155 f = meshlm_send_action[act]; 156 break; 157 case IEEE80211_ACTION_MESH_HWMP: 158 if (act < N(hwmp_send_action)) 159 f = hwmp_send_action[act]; 160 break; 161 } 162 break; 163 case IEEE80211_ACTION_CAT_VENDOR: 164 if (act < N(vendor_send_action)) 165 f = vendor_send_action[act]; 166 break; 167 } 168 return f(ni, cat, act, sa); 169 #undef N 170 } 171 172 static int 173 recv_inval(struct ieee80211_node *ni, const struct ieee80211_frame *wh, 174 const uint8_t *frm, const uint8_t *efrm) 175 { 176 return EINVAL; 177 } 178 179 static ieee80211_recv_action_func *ba_recv_action[8] = { 180 recv_inval, recv_inval, recv_inval, recv_inval, 181 recv_inval, recv_inval, recv_inval, recv_inval, 182 }; 183 static ieee80211_recv_action_func *ht_recv_action[8] = { 184 recv_inval, recv_inval, recv_inval, recv_inval, 185 recv_inval, recv_inval, recv_inval, recv_inval, 186 }; 187 static ieee80211_recv_action_func *meshpl_recv_action[8] = { 188 recv_inval, recv_inval, recv_inval, recv_inval, 189 recv_inval, recv_inval, recv_inval, recv_inval, 190 }; 191 static ieee80211_recv_action_func *meshlm_recv_action[4] = { 192 recv_inval, recv_inval, recv_inval, recv_inval, 193 }; 194 static ieee80211_recv_action_func *hwmp_recv_action[8] = { 195 recv_inval, recv_inval, recv_inval, recv_inval, 196 recv_inval, recv_inval, recv_inval, recv_inval, 197 }; 198 static 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 203 int 204 ieee80211_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 case IEEE80211_ACTION_CAT_SELF_PROT: 219 if (act >= N(meshpl_recv_action)) 220 break; 221 meshpl_recv_action[act] = f; 222 return 0; 223 case IEEE80211_ACTION_CAT_MESH: 224 switch (act) { 225 case IEEE80211_ACTION_MESH_LMETRIC: 226 if (act >= N(meshlm_recv_action)) 227 break; 228 meshlm_recv_action[act] = f; 229 return 0; 230 case IEEE80211_ACTION_MESH_HWMP: 231 if (act >= N(hwmp_recv_action)) 232 break; 233 hwmp_recv_action[act] = f; 234 return 0; 235 } 236 break; 237 case IEEE80211_ACTION_CAT_VENDOR: 238 if (act >= N(vendor_recv_action)) 239 break; 240 vendor_recv_action[act] = f; 241 return 0; 242 } 243 return EINVAL; 244 #undef N 245 } 246 247 void 248 ieee80211_recv_action_unregister(int cat, int act) 249 { 250 ieee80211_recv_action_register(cat, act, recv_inval); 251 } 252 253 int 254 ieee80211_recv_action(struct ieee80211_node *ni, 255 const struct ieee80211_frame *wh, 256 const uint8_t *frm, const uint8_t *efrm) 257 { 258 #define N(a) (sizeof(a) / sizeof(a[0])) 259 ieee80211_recv_action_func *f = recv_inval; 260 const struct ieee80211_action *ia = 261 (const struct ieee80211_action *) frm; 262 263 switch (ia->ia_category) { 264 case IEEE80211_ACTION_CAT_BA: 265 if (ia->ia_action < N(ba_recv_action)) 266 f = ba_recv_action[ia->ia_action]; 267 break; 268 case IEEE80211_ACTION_CAT_HT: 269 if (ia->ia_action < N(ht_recv_action)) 270 f = ht_recv_action[ia->ia_action]; 271 break; 272 case IEEE80211_ACTION_CAT_SELF_PROT: 273 if (ia->ia_action < N(meshpl_recv_action)) 274 f = meshpl_recv_action[ia->ia_action]; 275 break; 276 case IEEE80211_ACTION_CAT_MESH: 277 switch (ia->ia_action) { 278 case IEEE80211_ACTION_MESH_LMETRIC: 279 if (ia->ia_action < N(meshlm_recv_action)) 280 f = meshlm_recv_action[ia->ia_action]; 281 break; 282 case IEEE80211_ACTION_MESH_HWMP: 283 if (ia->ia_action < N(hwmp_recv_action)) 284 f = hwmp_recv_action[ia->ia_action]; 285 break; 286 } 287 break; 288 case IEEE80211_ACTION_CAT_VENDOR: 289 if (ia->ia_action < N(vendor_recv_action)) 290 f = vendor_recv_action[ia->ia_action]; 291 break; 292 } 293 return f(ni, wh, frm, efrm); 294 #undef N 295 } 296