diff options
author | sam <sam@FreeBSD.org> | 2009-07-05 17:59:19 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2009-07-05 17:59:19 +0000 |
commit | edf89f716262ec28b66e3ba8f49c4a1c11ff0f4c (patch) | |
tree | 2b0355c63191e76e8d9a8248e3dcb6081298f0c7 /sys/net80211/ieee80211_action.c | |
parent | c67dff7aca2dbc37c9abe5f0d576016dd2b9905c (diff) | |
download | FreeBSD-src-edf89f716262ec28b66e3ba8f49c4a1c11ff0f4c.zip FreeBSD-src-edf89f716262ec28b66e3ba8f49c4a1c11ff0f4c.tar.gz |
Revamp 802.11 action frame handling:
o add a new facility for components to register send+recv handlers
o ieee80211_send_action and ieee80211_recv_action now use the registered
handlers to dispatch operations
o rev ieee80211_send_action api to enable passing arbitrary data
o rev ieee80211_recv_action api to pass the 802.11 frame header as it may
be difficult to locate
o update existing IEEE80211_ACTION_CAT_BA and IEEE80211_ACTION_CAT_HT handling
o update mwl for api rev
Reviewed by: rpaulo
Approved by: re (kensmith)
Diffstat (limited to 'sys/net80211/ieee80211_action.c')
-rw-r--r-- | sys/net80211/ieee80211_action.c | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c new file mode 100644 index 0000000..a694d25 --- /dev/null +++ b/sys/net80211/ieee80211_action.c @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifdef __FreeBSD__ +__FBSDID("$FreeBSD$"); +#endif + +/* + * IEEE 802.11 send/recv action frame support. + */ + +#include "opt_inet.h" +#include "opt_wlan.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> + +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> +#include <net/ethernet.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_action.h> + +static int +send_inval(struct ieee80211_node *ni, int cat, int act, void *sa) +{ + return EINVAL; +} + +static ieee80211_send_action_func *ba_send_action[8] = { + send_inval, send_inval, send_inval, send_inval, + send_inval, send_inval, send_inval, send_inval, +}; +static ieee80211_send_action_func *ht_send_action[8] = { + send_inval, send_inval, send_inval, send_inval, + send_inval, send_inval, send_inval, send_inval, +}; +/* NB: temporary until 802.11s support is added */ +#ifdef IEEE80211_ACTION_CAT_MESHPEERING +static ieee80211_send_action_func *meshpl_send_action[8] = { + send_inval, send_inval, send_inval, send_inval, + send_inval, send_inval, send_inval, send_inval, +}; +static ieee80211_send_action_func *meshlm_send_action[4] = { + send_inval, send_inval, send_inval, send_inval, +}; +static ieee80211_send_action_func *hwmp_send_action[8] = { + send_inval, send_inval, send_inval, send_inval, + send_inval, send_inval, send_inval, send_inval, +}; +#endif +static ieee80211_send_action_func *vendor_send_action[8] = { + send_inval, send_inval, send_inval, send_inval, + send_inval, send_inval, send_inval, send_inval, +}; + +int +ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + switch (cat) { + case IEEE80211_ACTION_CAT_BA: + if (act >= N(ba_send_action)) + break; + ba_send_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_HT: + if (act >= N(ht_send_action)) + break; + ht_send_action[act] = f; + return 0; +#ifdef IEEE80211_ACTION_CAT_MESHPEERING + case IEEE80211_ACTION_CAT_MESHPEERING: + if (act >= N(meshpl_send_action)) + break; + meshpl_send_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_MESHLMETRIC: + if (act >= N(meshlm_send_action)) + break; + meshlm_send_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_MESHPATH: + if (act > N(hwmp_send_action)) + break; + hwmp_send_action[act] = f; + return 0; +#endif + case IEEE80211_ACTION_CAT_VENDOR: + if (act >= N(vendor_send_action)) + break; + vendor_send_action[act] = f; + return 0; + } + return EINVAL; +#undef N +} + +void +ieee80211_send_action_unregister(int cat, int act) +{ + ieee80211_send_action_register(cat, act, send_inval); +} + +int +ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + ieee80211_send_action_func *f = send_inval; + + switch (cat) { + case IEEE80211_ACTION_CAT_BA: + if (act < N(ba_send_action)) + f = ba_send_action[act]; + break; + case IEEE80211_ACTION_CAT_HT: + if (act < N(ht_send_action)) + f = ht_send_action[act]; + break; +#ifdef IEEE80211_ACTION_CAT_MESHPEERING + case IEEE80211_ACTION_CAT_MESHPEERING: + if (act < N(meshpl_send_action)) + f = meshpl_send_action[act]; + break; + case IEEE80211_ACTION_CAT_MESHLMETRIC: + if (act < N(meshlm_send_action)) + f = meshlm_send_action[act]; + break; + case IEEE80211_ACTION_CAT_MESHPATH: + if (act < N(hwmp_send_action)) + f = hwmp_send_action[act]; + break; +#endif + case IEEE80211_ACTION_CAT_VENDOR: + if (act < N(vendor_send_action)) + f = vendor_send_action[act]; + break; + } + return f(ni, cat, act, sa); +#undef N +} + +static int +recv_inval(struct ieee80211_node *ni, const struct ieee80211_frame *wh, + const uint8_t *frm, const uint8_t *efrm) +{ + return EINVAL; +} + +static ieee80211_recv_action_func *ba_recv_action[8] = { + recv_inval, recv_inval, recv_inval, recv_inval, + recv_inval, recv_inval, recv_inval, recv_inval, +}; +static ieee80211_recv_action_func *ht_recv_action[8] = { + recv_inval, recv_inval, recv_inval, recv_inval, + recv_inval, recv_inval, recv_inval, recv_inval, +}; +#ifdef IEEE80211_ACTION_CAT_MESHPEERING +static ieee80211_recv_action_func *meshpl_recv_action[8] = { + recv_inval, recv_inval, recv_inval, recv_inval, + recv_inval, recv_inval, recv_inval, recv_inval, +}; +static ieee80211_recv_action_func *meshlm_recv_action[4] = { + recv_inval, recv_inval, recv_inval, recv_inval, +}; +static ieee80211_recv_action_func *hwmp_recv_action[8] = { + recv_inval, recv_inval, recv_inval, recv_inval, + recv_inval, recv_inval, recv_inval, recv_inval, +}; +#endif +static ieee80211_recv_action_func *vendor_recv_action[8] = { + recv_inval, recv_inval, recv_inval, recv_inval, + recv_inval, recv_inval, recv_inval, recv_inval, +}; + +int +ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + switch (cat) { + case IEEE80211_ACTION_CAT_BA: + if (act >= N(ba_recv_action)) + break; + ba_recv_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_HT: + if (act >= N(ht_recv_action)) + break; + ht_recv_action[act] = f; + return 0; +#ifdef IEEE80211_ACTION_CAT_MESHPEERING + case IEEE80211_ACTION_CAT_MESHPEERING: + if (act >= N(meshpl_recv_action)) + break; + meshpl_recv_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_MESHLMETRIC: + if (act >= N(meshlm_recv_action)) + break; + meshlm_recv_action[act] = f; + return 0; + case IEEE80211_ACTION_CAT_MESHPATH: + if (act >= N(hwmp_recv_action)) + break; + hwmp_recv_action[act] = f; + return 0; +#endif + case IEEE80211_ACTION_CAT_VENDOR: + if (act >= N(vendor_recv_action)) + break; + vendor_recv_action[act] = f; + return 0; + } + return EINVAL; +#undef N +} + +void +ieee80211_recv_action_unregister(int cat, int act) +{ + ieee80211_recv_action_register(cat, act, recv_inval); +} + +int +ieee80211_recv_action(struct ieee80211_node *ni, + const struct ieee80211_frame *wh, + const uint8_t *frm, const uint8_t *efrm) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + ieee80211_recv_action_func *f = recv_inval; + const struct ieee80211_action *ia = + (const struct ieee80211_action *) frm; + + switch (ia->ia_category) { + case IEEE80211_ACTION_CAT_BA: + if (ia->ia_action < N(ba_recv_action)) + f = ba_recv_action[ia->ia_action]; + break; + case IEEE80211_ACTION_CAT_HT: + if (ia->ia_action < N(ht_recv_action)) + f = ht_recv_action[ia->ia_action]; + break; +#ifdef IEEE80211_ACTION_CAT_MESHPEERING + case IEEE80211_ACTION_CAT_MESHPEERING: + if (ia->ia_action < N(meshpl_recv_action)) + f = meshpl_recv_action[ia->ia_action]; + break; + case IEEE80211_ACTION_CAT_MESHLMETRIC: + if (ia->ia_action < N(meshlm_recv_action)) + f = meshlm_recv_action[ia->ia_action]; + break; + case IEEE80211_ACTION_CAT_MESHPATH: + if (ia->ia_action < N(hwmp_recv_action)) + f = hwmp_recv_action[ia->ia_action]; + break; +#endif + case IEEE80211_ACTION_CAT_VENDOR: + if (ia->ia_action < N(vendor_recv_action)) + f = vendor_recv_action[ia->ia_action]; + break; + } + return f(ni, wh, frm, efrm); +#undef N +} |