| /* |
| * wl randmac command module |
| * |
| * Broadcom Proprietary and Confidential. Copyright (C) 2017, |
| * All Rights Reserved. |
| * |
| * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom; |
| * the contents of this file may not be disclosed to third parties, copied |
| * or duplicated in any form, in whole or in part, without the prior |
| * written permission of Broadcom. |
| * |
| * |
| * <<Broadcom-WL-IPTag/Proprietary:>> |
| * |
| * $Id$ |
| */ |
| #ifdef WIN32 |
| #include <windows.h> |
| #endif |
| |
| #include <wlioctl.h> |
| |
| #if defined(DONGLEBUILD) |
| #include <typedefs.h> |
| #include <osl.h> |
| #endif |
| |
| /* Because IL_BIGENDIAN was removed there are few warnings that need |
| * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN. |
| * Hence these warnings were not seen earlier. |
| * For now ignore the following warnings |
| */ |
| #ifdef WIN32 |
| #pragma warning(push) |
| #pragma warning(disable : 4244) |
| #pragma warning(disable : 4761) |
| #endif |
| |
| #include <bcmutils.h> |
| #include <bcmendian.h> |
| #include "wlu_common.h" |
| #include "wlu.h" |
| |
| #ifdef WIN32 |
| #define bzero(b, len) memset((b), 0, (len)) |
| #endif |
| |
| #ifdef LINUX |
| #include <unistd.h> |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/time.h> |
| #include <sys/ioctl.h> |
| #include <netinet/in.h> |
| #include <net/if.h> |
| #include <linux/if_packet.h> |
| #endif /* LINUX */ |
| |
| #include <miniopt.h> |
| #include <errno.h> |
| |
| #define RANDMAC_IOC_BUFSZ 2048 |
| #define WL_RANDMAC_IOV_VERSION_SIZE (sizeof(wl_randmac_version_t)) |
| #define WL_RANDMAC_IOV_CONFIG_SIZE (sizeof(wl_randmac_config_t)) |
| #define WL_RANDMAC_IOV_STATS_SIZE (sizeof(wl_randmac_stats_t)) |
| |
| static cmd_func_t wl_randmac; |
| |
| typedef struct randmac_subcmd_info randmac_subcmd_info_t; |
| typedef int (randmac_subcmd_handler_t)(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv); |
| |
| struct randmac_subcmd_info { |
| char *name; /* subcmd-name */ |
| wl_randmac_subcmd_t subcmd_id; /* id */ |
| wl_randmac_method_t method; |
| randmac_subcmd_handler_t *handler; /* subcmd handler */ |
| char *helpmsg; /* message for wl randmac -h config */ |
| }; |
| |
| typedef struct randmac_config_method_param_info { |
| char *name; |
| uint16 value; |
| } randmac_config_method_param_info_t; |
| |
| static const randmac_config_method_param_info_t randmac_config_methods[] = { |
| /* Name Value */ |
| { "None", WL_RANDMAC_USER_NONE }, |
| { "FTM", WL_RANDMAC_USER_FTM }, |
| { "NAN", WL_RANDMAC_USER_NAN }, |
| { "SCAN", WL_RANDMAC_USER_SCAN }, |
| { "ALL", 0xFFFF }, |
| }; |
| |
| typedef struct randmac_config_param_info { |
| char *name; /* <param-name> identify configuration item */ |
| wl_randmac_tlv_id_t tlvid; /* map config item TLV id */ |
| char *name_helpmsg; /* help message */ |
| } randmac_config_param_info_t; |
| |
| static const randmac_config_param_info_t randmac_config_param_info[] = { |
| /* Name TLV ID Help Message */ |
| {"mac-addr", WL_RANDMAC_TLV_ADDR, "Random MAC/OUI as xx:xx:xx:xx:xx:xx" }, |
| {"bitmask", WL_RANDMAC_TLV_MASK, "Bitmask yy:yy:yy:yy:yy:yy" }, |
| {"method", WL_RANDMAC_TLV_METHOD, "Methods using random MAC FTM|NAN|SCAN" } |
| }; |
| |
| static cmd_t wl_randmac_cmds[] = { |
| { "randmac", wl_randmac, WLC_GET_VAR, WLC_SET_VAR, |
| "\tEnable/Disable MAC Address Randomization\n" |
| "\t0 : disable\n" |
| "\t1 : enable\n" |
| "\tUsage: wl randmac enable\n\n" |
| "\t\t wl randmac disable\n\n" |
| "config [<param-name><param-value>...]\n" |
| "\tGet/Set MAC address (OUI), bitmask, method\n\n" |
| "\tGet current configuration\n" |
| "\tUsage: wl randmac config\n" |
| "\tSet or update new configuration\n" |
| "\tUsage: wl randmac config mac-addr <xx:xx:xx:xx:xx:xx> bitmask <yy:yy:yy:yy:yy:yy> " |
| "<method [ALL|FTM|NAN|SCAN]>" |
| "version" |
| "\tGet version\n\n" |
| "\tUsage: wl randmac version\n\n" |
| "getstats" |
| "\tGet statistics\n\n" |
| "\tUsage: wl randmac getstats\n\n" |
| "clearstats" |
| "\tClear statistics\n\n" |
| "\tUsage: wl randmac clearstats\n\n" }, |
| |
| { NULL, NULL, 0, 0, NULL } |
| }; |
| |
| static char *buf; |
| |
| static wl_randmac_t *randmac_alloc_getset_buf(wl_randmac_subcmd_t subcmd_id, |
| uint16 subcmd_bufsize); |
| static int wl_randmac_subcmd_method_handler(void *wl, cmd_t *cmd, char **argv); |
| static int randmac_common_getcmd_handler(void *wl, |
| const randmac_subcmd_info_t *p_subcmd_info, char **argv); |
| static int randmac_do_get_ioctl(void *wl, wl_randmac_t *p_iov, uint16 iov_len, |
| const randmac_subcmd_info_t *p_subcmd_info); |
| static int randmac_handle_help(char **argv); |
| static void randmac_display_config_help(); |
| |
| /* module initialization */ |
| void |
| wluc_randmac_module_init(void) |
| { |
| /* get the global buf */ |
| buf = wl_get_buf(); |
| |
| /* register randmac commands */ |
| wl_module_cmds_register(wl_randmac_cmds); |
| } |
| |
| static int |
| wl_randmac(void *wl, cmd_t *cmd, char **argv) |
| { |
| uint16 randmac_iovsize; |
| wl_randmac_t *p_randmac_iov = NULL; |
| int ret; |
| |
| /* skip the command name and check if NULL */ |
| if (argv[1] == NULL) { |
| wl_randmac_t *iov_resp; |
| randmac_iovsize = 0; |
| p_randmac_iov = randmac_alloc_getset_buf(WL_RANDMAC_SUBCMD_ENABLE, |
| randmac_iovsize); |
| /* Get wl randmac */ |
| if (!p_randmac_iov) { |
| ret = BCME_NOMEM; |
| goto done; |
| } |
| ret = wlu_var_getbuf(wl, cmd->name, p_randmac_iov, sizeof(*p_randmac_iov), |
| (void *)&iov_resp); |
| if (ret != BCME_OK) { |
| goto done; |
| } |
| |
| printf(">%s\n", |
| (iov_resp->subcmd_id == WL_RANDMAC_SUBCMD_ENABLE) ? "Enabled" : "Disabled"); |
| goto done; |
| |
| } else { |
| /* Set */ |
| argv++; |
| ret = wl_randmac_subcmd_method_handler(wl, cmd, argv); |
| } |
| done: |
| if (p_randmac_iov) { |
| free(p_randmac_iov); |
| } |
| return ret; |
| } |
| |
| /* declare randmac subcommand handlers randmac_subcmd_xxxx() */ |
| /* e.g. static randmac_cmd_handler_t randmac_subcmd_get_version; */ |
| #define RANDMAC_SUBCMD_FUNC(suffix) randmac_subcmd_ ##suffix |
| #define DECL_CMDHANDLER(X) static randmac_subcmd_handler_t randmac_subcmd_##X |
| |
| /* get */ |
| DECL_CMDHANDLER(get_version); /* method-only */ |
| |
| /* set */ |
| DECL_CMDHANDLER(enable); /* method */ |
| DECL_CMDHANDLER(disable); /* method */ |
| DECL_CMDHANDLER(config); /* method */ |
| DECL_CMDHANDLER(getstats); /* method */ |
| DECL_CMDHANDLER(clearstats); /* method */ |
| |
| static const randmac_subcmd_info_t randmac_subcmdlist[] = { |
| /* Name Subcommand Method Handler Help */ |
| {"version", WL_RANDMAC_SUBCMD_GET_VERSION, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(get_version), "Get randmac method API version information" }, |
| {"enable", WL_RANDMAC_SUBCMD_ENABLE, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(enable), "Enable randmac method"}, |
| {"disable", WL_RANDMAC_SUBCMD_ENABLE, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(disable), "Disable randmac method"}, |
| {"config", WL_RANDMAC_SUBCMD_CONFIG, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(config), |
| "Configure random MAC OUI, bitmask to randomize MAC address and method"}, |
| {"getstats", WL_RANDMAC_SUBCMD_STATS, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(getstats), |
| "Get MAC randomization method statistics"}, |
| {"clearstats", WL_RANDMAC_SUBCMD_CLEAR_STATS, WL_RANDMAC_USER_NONE, |
| RANDMAC_SUBCMD_FUNC(clearstats), "Clear MAC randomization method statistics"}, |
| }; |
| |
| const randmac_subcmd_info_t * |
| randmac_get_subcmd_info(char *cmdname) |
| { |
| int i; |
| const randmac_subcmd_info_t *p_subcmd_info; |
| |
| /* Search subcmd name */ |
| p_subcmd_info = &randmac_subcmdlist[0]; |
| for (i = 0; i < (int)ARRAYSIZE(randmac_subcmdlist); i++) { |
| if (stricmp(p_subcmd_info->name, cmdname) == 0) |
| return p_subcmd_info; |
| p_subcmd_info++; |
| } |
| |
| return NULL; |
| } |
| |
| static int |
| randmac_subcmd_get_version(void *wl, |
| const randmac_subcmd_info_t *p_subcmd_info, char **argv) |
| { |
| /* Issue IOVAR and display version information */ |
| return randmac_common_getcmd_handler(wl, p_subcmd_info, argv); |
| } |
| /* |
| * 'wl randmac ascii-method' handler |
| * handle 'wl randmac <cmdname> [<param-name><param-value>]*' |
| */ |
| static int |
| wl_randmac_subcmd_method_handler(void *wl, cmd_t *cmd, char **argv) |
| { |
| const randmac_subcmd_info_t *p_subcmd_info; |
| |
| /* ignore the command name 'proxd' */ |
| UNUSED_PARAMETER(cmd); |
| |
| /* |
| * check for "wl randmac -h config" or |
| * "wl randmac help config" --> display the usage |
| */ |
| if (!stricmp(*argv, "-h") || !stricmp(*argv, "help")) { |
| return randmac_handle_help(++argv); /* return BCME_USAGE_ERROR; */ |
| } |
| |
| /* |
| * search for the specified <cmdname> from the |
| * pre-defined supported cmd list |
| */ |
| p_subcmd_info = randmac_get_subcmd_info(*argv); |
| if (p_subcmd_info == NULL) { |
| /* cannot find the cmd in the randmac_subcmdlist */ |
| return BCME_USAGE_ERROR; |
| } |
| |
| /* dispatch cmd to appropriate handler */ |
| if (p_subcmd_info->handler) { |
| return p_subcmd_info->handler(wl, p_subcmd_info, ++argv); |
| } else { |
| return BCME_USAGE_ERROR; |
| } |
| |
| return BCME_OK; |
| |
| } |
| |
| /* ***************************** set commands ********************* */ |
| |
| /* randmac config-category definition */ |
| typedef enum { |
| RANDMAC_CONFIG_CAT_GENERAL = 1, /* generial configuration */ |
| } randmac_config_category_t; |
| |
| /* |
| * display help-messages for 'wl randmac -h config' |
| */ |
| static void |
| randmac_display_method_help() |
| { |
| int i; |
| int max_cmdname_len = 20; |
| const randmac_subcmd_info_t *p_subcmd_info; |
| |
| /* a header */ |
| printf("\n\tMAC Address Randomization\n"); |
| printf("\tUsage: wl randmac <cmd> [<param-name> <param-value>]*\n"); |
| printf("\t\t<cmd>: specify a command from the following list,\n"); |
| |
| /* show the command list and the help messages for each FTM command */ |
| p_subcmd_info = &randmac_subcmdlist[0]; |
| for (i = 0; i < (int) ARRAYSIZE(randmac_subcmdlist); i++) { |
| printf("\t\t %*s: %s\n", max_cmdname_len, p_subcmd_info->name, |
| p_subcmd_info->helpmsg); |
| p_subcmd_info++; |
| } |
| |
| printf("\t\t<param-name> <param-value>: <cmd>-specific parameters\n\n"); |
| |
| printf("\t\ttype 'wl randmac -h config' for configuration command usage.\n"); |
| |
| /* show examples */ |
| printf("\tExample: wl randmac [0/1 0 - Disable, 1 - Enable]\n\n"); |
| printf("\tExample: wl randmac config " |
| "[Random MAC Address/OUI<xx:xx:xx:xx:xx:xx>] " |
| "[Bitmask to randmize MAC Address<yy:yy:yy:yy:yy:yy>] [Method <FTM>]\n\n"); |
| |
| return; |
| } |
| |
| /* |
| * display help-messages for 'wl randmac -h config' |
| */ |
| static void |
| randmac_display_config_help() |
| { |
| int i; |
| int max_param_name_len = 20; |
| const randmac_config_param_info_t *p_config_param_info; |
| |
| /* a header */ |
| printf("\n\tConfigure MAC Address Randomization feature\n"); |
| printf("\tUsage: wl randmac config { <param-name> <param-value> }+ \n"); |
| /* print helpmsg for each config-item */ |
| printf("\t\t<param-name> <param-value>: " |
| "configuration parameters from the following\n"); |
| p_config_param_info = &randmac_config_param_info[0]; |
| for (i = 0; i < (int) ARRAYSIZE(randmac_config_param_info); i++) { |
| printf("\t\t %*s: %s\n", max_param_name_len, p_config_param_info->name, |
| p_config_param_info->name_helpmsg); |
| |
| p_config_param_info++; |
| } |
| |
| /* show examples */ |
| printf("\n\tExample: wl randmac config mac-addr <xx:xx:xx:xx:xx:xx> " |
| "bitmask <yy:yy:yy:yy:yy:yy> method <FTM>\n"); |
| } |
| |
| /* |
| * handle |
| * wl randmac -h |
| * wl randmac -h config |
| * Output: |
| * BCME_USAGE_ERROR -- caller should bring up 'randmac' level help messages |
| * BCME_OK -- this func displays context-help for RANDMAC method, |
| * caller does not need to show any help messages. |
| */ |
| static int |
| randmac_handle_help(char **argv) |
| { |
| if (!*argv) |
| return BCME_USAGE_ERROR; |
| |
| if (stricmp(*argv, "config") != 0) /* check 'wl randmac -h config' */ |
| return BCME_USAGE_ERROR; |
| |
| ++argv; |
| if (*argv == NULL) { |
| /* show help messages for 'wl randmac -h config' */ |
| randmac_display_config_help(); |
| return BCME_OK; |
| } |
| |
| /* invalid <cmd>, display help messages for RANDMAC method */ |
| randmac_display_method_help(); |
| return BCME_OK; |
| } |
| |
| static randmac_config_category_t |
| randmac_parse_config_category(char *arg_category) |
| { |
| BCM_REFERENCE(arg_category); |
| return RANDMAC_CONFIG_CAT_GENERAL; |
| } |
| |
| static const randmac_config_param_info_t * |
| randmac_get_config_param_info(char *p_param_name) |
| { |
| int i; |
| const randmac_config_param_info_t *p_config_param_info; |
| |
| p_config_param_info = &randmac_config_param_info[0]; |
| for (i = 0; i < (int) ARRAYSIZE(randmac_config_param_info); i++) { |
| if (stricmp(p_param_name, p_config_param_info->name) == 0) { |
| return p_config_param_info; |
| } |
| p_config_param_info++; /* next */ |
| } |
| return (randmac_config_param_info_t *) NULL; /* 'invalid param name' */ |
| } |
| |
| static uint16 |
| randmac_parse_method(char *method_name) |
| { |
| int i = 0; |
| const randmac_config_method_param_info_t *p_method_param_info; |
| |
| p_method_param_info = &randmac_config_methods[0]; |
| |
| for (; i < (int) ARRAYSIZE(randmac_config_methods); i++) { |
| if (stricmp(method_name, p_method_param_info->name) == 0) { |
| return p_method_param_info->value; |
| } |
| p_method_param_info++; |
| } |
| |
| return 0; |
| } |
| |
| static int |
| randmac_handle_config_general(char **argv, wl_randmac_config_t *p_config) |
| { |
| int status = BCME_OK; |
| const randmac_config_param_info_t *p_config_param_info; |
| char *method_name; |
| |
| /* check if user provides param-values for 'config options' command */ |
| if (*argv == NULL) |
| return BCME_USAGE_ERROR; |
| |
| /* <param-value> followed 'wl proxd ftm [session-id] config options' */ |
| while (*argv != NULL) { |
| /* look up 'config-param-info' based on 'param-name' */ |
| p_config_param_info = randmac_get_config_param_info(*argv); |
| if (p_config_param_info == (randmac_config_param_info_t *) NULL) { |
| printf("error: invalid param-name (%s)\n", *argv); |
| status = BCME_USAGE_ERROR; /* param-name is not specified */ |
| break; |
| } |
| |
| /* parse 'param-value' */ |
| if (*(argv + 1) == NULL) { |
| printf("error: invalid param-value\n"); |
| status = BCME_USAGE_ERROR; /* param-value is not specified */ |
| break; |
| } |
| ++argv; |
| |
| /* parse param-value */ |
| switch (p_config_param_info->tlvid) { |
| case WL_RANDMAC_TLV_ADDR: |
| p_config->addr = ether_null; |
| if (!wl_ether_atoe(*argv, &p_config->addr)) { |
| printf("error: invalid MAC address parameter\n"); |
| status = BCME_USAGE_ERROR; |
| break; |
| } |
| p_config->flags |= WL_RANDMAC_FLAGS_ADDR; |
| break; |
| |
| case WL_RANDMAC_TLV_MASK: |
| p_config->addr_mask = ether_null; |
| if (!wl_ether_atoe(*argv, &p_config->addr_mask)) { |
| printf("error: invalid MAC address parameter\n"); |
| status = BCME_USAGE_ERROR; |
| break; |
| } |
| p_config->flags |= WL_RANDMAC_FLAGS_MASK; |
| break; |
| |
| case WL_RANDMAC_TLV_METHOD: |
| method_name = *argv; |
| p_config->method |= randmac_parse_method(method_name); |
| p_config->flags |= WL_RANDMAC_FLAGS_METHOD; |
| break; |
| |
| default: |
| /* not supported */ |
| status = BCME_USAGE_ERROR; |
| break; |
| } |
| |
| if (status != BCME_OK) |
| break; /* abort */ |
| |
| ++argv; /* Next param */ |
| } |
| |
| return status; |
| } |
| |
| static int |
| randmac_subcmd_disable(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| return randmac_subcmd_enable(wl, p_subcmd_info, argv); |
| } |
| |
| static int |
| randmac_subcmd_enable(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| wl_randmac_t *p_iov = NULL; |
| int status = BCME_OK; |
| uint16 iov_len = WL_RANDMAC_IOV_HDR_SIZE; |
| |
| BCM_REFERENCE(*argv); |
| /* allocate a buffer for randmac config via 'set' iovar */ |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| if (p_iov == (wl_randmac_t *) NULL) { |
| status = BCME_NOMEM; |
| goto done; |
| } |
| |
| if (!(stricmp("enable", p_subcmd_info->name))) { |
| p_iov->subcmd_id = WL_RANDMAC_SUBCMD_ENABLE; |
| } else if (!(stricmp("disable", p_subcmd_info->name))) { |
| p_iov->subcmd_id = WL_RANDMAC_SUBCMD_DISABLE; |
| } else { |
| randmac_display_method_help(); |
| } |
| p_iov->version = WL_RANDMAC_API_VERSION; |
| p_iov->len = iov_len; |
| status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len); |
| |
| done: |
| if (p_iov) { |
| /* clean up */ |
| free(p_iov); |
| } |
| return status; |
| } |
| |
| static int |
| randmac_subcmd_config(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| wl_randmac_t *p_iov = NULL; |
| int status = BCME_OK; |
| wl_randmac_config_t *p_config; |
| uint16 iov_len = WL_RANDMAC_IOV_HDR_SIZE; |
| randmac_config_category_t category; |
| |
| if (*argv == NULL) { |
| status = randmac_common_getcmd_handler(wl, p_subcmd_info, argv); |
| goto done; |
| } |
| |
| /* allocate a buffer for randmac config via 'set' iovar */ |
| iov_len += sizeof(*p_config); |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| if (p_iov == (wl_randmac_t *) NULL) { |
| status = BCME_NOMEM; |
| goto done; |
| } |
| |
| /* setup config data */ |
| p_config = (wl_randmac_config_t *)&p_iov->data[0]; |
| |
| /* parse the cmd-line, get the config-category and dispatch to the handler */ |
| /* to parse the parameters based on the 'config-category' */ |
| category = randmac_parse_config_category(*argv); |
| if (category == RANDMAC_CONFIG_CAT_GENERAL) |
| status = randmac_handle_config_general(argv, p_config); |
| |
| if (status == BCME_USAGE_ERROR) { |
| randmac_display_config_help(); |
| } else { |
| p_iov->version = WL_RANDMAC_API_VERSION; |
| p_iov->subcmd_id = WL_RANDMAC_SUBCMD_CONFIG; |
| p_iov->len = WL_RANDMAC_IOV_CONFIG_SIZE; |
| status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len); |
| } |
| |
| done: |
| if (p_iov) { |
| /* clean up */ |
| free(p_iov); |
| } |
| return status; |
| } |
| |
| static int |
| randmac_subcmd_getstats(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| return randmac_common_getcmd_handler(wl, p_subcmd_info, argv); |
| } |
| |
| static int |
| randmac_subcmd_clearstats(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| wl_randmac_t *p_iov; |
| int status = BCME_OK; |
| uint16 iov_len = WL_RANDMAC_IOV_HDR_SIZE; |
| |
| BCM_REFERENCE(*argv); |
| /* allocate a buffer for randmac config via 'set' iovar */ |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| if (p_iov == (wl_randmac_t *) NULL) { |
| status = BCME_NOMEM; |
| goto done; |
| } |
| |
| p_iov->version = WL_RANDMAC_API_VERSION; |
| p_iov->subcmd_id = WL_RANDMAC_SUBCMD_CLEAR_STATS; |
| p_iov->len = iov_len; |
| status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len); |
| |
| done: |
| if (p_iov) { |
| /* clean up */ |
| free(p_iov); |
| } |
| return status; |
| } |
| |
| static wl_randmac_t * |
| randmac_alloc_getset_buf(wl_randmac_subcmd_t subcmd_id, uint16 subcmd_bufsize) |
| { |
| uint16 randmac_iovsize; |
| wl_randmac_t *p_randmac_iov = (wl_randmac_t *)NULL; |
| |
| BCM_REFERENCE(subcmd_id); |
| /* header + subcommand */ |
| randmac_iovsize = sizeof(wl_randmac_t) + subcmd_bufsize; |
| |
| p_randmac_iov = calloc(1, randmac_iovsize); |
| if (p_randmac_iov == NULL) { |
| printf("error: failed to allocate %d bytes of memory\n", randmac_iovsize); |
| return NULL; |
| } |
| |
| /* setup randmac method iovar header */ |
| p_randmac_iov->version = htol16(WL_RANDMAC_API_VERSION); |
| /* caller may adjust it based on subcommand */ |
| p_randmac_iov->len = htol16(randmac_iovsize); |
| p_randmac_iov->subcmd_id = htol16(subcmd_id); |
| |
| return p_randmac_iov; |
| } |
| |
| static int |
| randmac_common_getcmd_handler(void *wl, const randmac_subcmd_info_t *p_subcmd_info, |
| char **argv) |
| { |
| int status = BCME_OK; |
| uint16 iov_len = WL_RANDMAC_IOV_HDR_SIZE; |
| wl_randmac_t *p_iov = (wl_randmac_t *) NULL; |
| |
| BCM_REFERENCE(*argv); |
| switch (p_subcmd_info->subcmd_id) { |
| case WL_RANDMAC_SUBCMD_GET_VERSION: |
| iov_len += WL_RANDMAC_IOV_VERSION_SIZE; |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| break; |
| |
| case WL_RANDMAC_SUBCMD_CONFIG: |
| iov_len += WL_RANDMAC_IOV_CONFIG_SIZE; |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| break; |
| |
| case WL_RANDMAC_SUBCMD_STATS: |
| iov_len += WL_RANDMAC_IOV_STATS_SIZE; |
| p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len); |
| break; |
| |
| default: |
| /* Unknown subcommand */ |
| break; |
| } |
| |
| if (p_iov != NULL) { |
| /* get */ |
| status = randmac_do_get_ioctl(wl, p_iov, iov_len, p_subcmd_info); |
| } |
| |
| /* Clean up memory */ |
| free(p_iov); |
| |
| return status; |
| } |
| |
| static int |
| randmac_do_get_ioctl(void *wl, wl_randmac_t *p_iov, uint16 iov_len, |
| const randmac_subcmd_info_t *p_subcmd_info) |
| { |
| /* for gets we only need to pass ioc header */ |
| wl_randmac_t *p_iovresp = NULL; |
| int status; |
| /* send getbuf proxd iovar */ |
| status = wlu_var_getbuf(wl, "randmac", p_iov, iov_len, (void *)&p_iovresp); |
| if (status != BCME_OK) { |
| return status; |
| } |
| |
| if (p_iovresp != NULL) { |
| switch (p_subcmd_info->subcmd_id) { |
| case WL_RANDMAC_SUBCMD_GET_VERSION: |
| { |
| wl_randmac_version_t *p_iov_ver; |
| p_iov_ver = (wl_randmac_version_t *)(&p_iovresp->data[0]); |
| printf("> Version: 0x%04x\n", p_iov_ver->version); |
| } |
| break; |
| |
| case WL_RANDMAC_SUBCMD_DISABLE: |
| case WL_RANDMAC_SUBCMD_ENABLE: |
| { |
| printf(">%s\n", |
| (p_subcmd_info->subcmd_id == WL_RANDMAC_SUBCMD_ENABLE) ? |
| "Enabled" : "Disabled"); |
| } |
| break; |
| |
| case WL_RANDMAC_SUBCMD_CONFIG: |
| { |
| uint32 i = 0; |
| const randmac_config_method_param_info_t *methods_info; |
| wl_randmac_config_t *p_iov_config; |
| p_iov_config = (wl_randmac_config_t *)(&p_iovresp->data[0]); |
| printf(">MAC Address:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| p_iov_config->addr.octet[0], |
| p_iov_config->addr.octet[1], |
| p_iov_config->addr.octet[2], |
| p_iov_config->addr.octet[3], |
| p_iov_config->addr.octet[4], |
| p_iov_config->addr.octet[5]); |
| printf(">Bitmask:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| p_iov_config->addr_mask.octet[0], |
| p_iov_config->addr_mask.octet[1], |
| p_iov_config->addr_mask.octet[2], |
| p_iov_config->addr_mask.octet[3], |
| p_iov_config->addr_mask.octet[4], |
| p_iov_config->addr_mask.octet[5]); |
| if (p_iov_config->method == WL_RANDMAC_USER_NONE) { |
| printf("> Method: None\n"); |
| } else if (p_iov_config->method == WL_RANDMAC_USER_ALL) { |
| printf(">Method: All\n"); |
| } else { |
| printf(">Method:"); |
| while (p_iov_config->method) { |
| if (p_iov_config->method & (1 << i)) { |
| methods_info = |
| &randmac_config_methods[i + 1]; |
| printf(" %s ", methods_info->name); |
| p_iov_config->method &= ~(1 << i); |
| } |
| i++; |
| } |
| printf("\n"); |
| } |
| } |
| break; |
| case WL_RANDMAC_SUBCMD_STATS: |
| { |
| wl_randmac_stats_t *pstats = |
| (wl_randmac_stats_t *)(&p_iovresp->data[0]); |
| printf(">MAC randomization set calls success:\t %u\n", |
| pstats->set_ok); |
| printf(">MAC randomization set calls failed:\t %u\n", |
| pstats->set_fail); |
| printf(">MAC randomization set requests:\t %u\n", |
| pstats->set_reqs); |
| printf(">MAC randomization reset requests:\t %u\n", |
| pstats->reset_reqs); |
| printf(">MAC randomization restore calls success:%u\n", |
| pstats->restore_ok); |
| printf(">MAC randomization restore calls failed: %u\n", |
| pstats->restore_fail); |
| printf(">MAC randomization events sent:\t\t %u\n", |
| pstats->events_sent); |
| printf(">MAC randomization events received:\t %u\n", |
| pstats->events_rcvd); |
| printf("\n"); |
| } |
| break; |
| |
| default: |
| /* Unknown response */ |
| break; |
| } |
| } |
| |
| return status; |
| } |