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