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