-#include <net/if.h>
#include <errno.h>
#include <string.h>
#include "iw.h"
SECTION(mesh);
+SECTION(mesh_param);
typedef struct _any_t {
return 0;
}
+static uint32_t _parse_u32_power_mode(const char *str, _any *ret)
+{
+ unsigned long int v;
+
+ /* Parse attribute for the name of power mode */
+ if (!strcmp(str, "active"))
+ v = NL80211_MESH_POWER_ACTIVE;
+ else if (!strcmp(str, "light"))
+ v = NL80211_MESH_POWER_LIGHT_SLEEP;
+ else if (!strcmp(str, "deep"))
+ v = NL80211_MESH_POWER_DEEP_SLEEP;
+ else
+ return 0xff;
+
+ ret->u.as_32 = (uint32_t)v;
+ return 0;
+}
static void _print_u8(struct nlattr *a)
{
printf("%u milliseconds", nla_get_u32(a));
}
+static void _print_u32_in_seconds(struct nlattr *a)
+{
+ printf("%d seconds", nla_get_u32(a));
+}
+
static void _print_u32_in_TUs(struct nlattr *a)
{
printf("%d TUs", nla_get_u32(a));
}
+static void _print_u32_power_mode(struct nlattr *a)
+{
+ unsigned long v = nla_get_u32(a);
+
+ switch (v) {
+ case NL80211_MESH_POWER_ACTIVE:
+ printf("active");
+ break;
+ case NL80211_MESH_POWER_LIGHT_SLEEP:
+ printf("light");
+ break;
+ case NL80211_MESH_POWER_DEEP_SLEEP:
+ printf("deep");
+ break;
+ default:
+ printf("undefined");
+ break;
+ }
+}
+
static void _print_s32_in_dBm(struct nlattr *a)
{
printf("%d dBm", (int32_t) nla_get_u32(a));
/* The current mesh parameters */
-const static struct mesh_param_descr _mesh_param_descrs[] =
+static const struct mesh_param_descr _mesh_param_descrs[] =
{
{"mesh_retry_timeout",
NL80211_MESHCONF_RETRY_TIMEOUT,
{"mesh_hwmp_confirmation_interval",
NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
_my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
+ {"mesh_power_mode", NL80211_MESHCONF_POWER_MODE,
+ _my_nla_put_u32, _parse_u32_power_mode, _print_u32_power_mode},
+ {"mesh_awake_window", NL80211_MESHCONF_AWAKE_WINDOW,
+ _my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
+ {"mesh_plink_timeout", NL80211_MESHCONF_PLINK_TIMEOUT,
+ _my_nla_put_u32, _parse_u32, _print_u32_in_seconds},
+ {"mesh_connected_to_gate", NL80211_MESHCONF_CONNECTED_TO_GATE,
+ _my_nla_put_u8, _parse_u8_as_bool, _print_u8},
+ {"mesh_nolearn", NL80211_MESHCONF_NOLEARN,
+ _my_nla_put_u8, _parse_u8_as_bool, _print_u8},
+ {"mesh_connected_to_as", NL80211_MESHCONF_CONNECTED_TO_AS,
+ _my_nla_put_u8, _parse_u8_as_bool, _print_u8},
};
static void print_all_mesh_param_descr(void)
{
- int i;
+ unsigned int i;
printf("Possible mesh parameters are:\n");
static const struct mesh_param_descr *find_mesh_param(const char *name)
{
- int i;
+ unsigned int i;
/* Find out what mesh parameter we want to change. */
for (i = 0; i < ARRAY_SIZE(_mesh_param_descrs); i++) {
return _mesh_param_descrs + i;
}
- print_all_mesh_param_descr();
return NULL;
}
/* Setter */
static int set_interface_meshparam(struct nl80211_state *state,
- struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv,
enum id_input id)
const struct mesh_param_descr *mdescr;
struct nlattr *container;
uint32_t ret;
- int err;
+ int err = 2;
container = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS);
if (!container)
return -ENOBUFS;
- if (!argc)
+ if (!argc) {
+ print_all_mesh_param_descr();
return 1;
+ }
while (argc) {
const char *name;
}
mdescr = find_mesh_param(name);
- if (!mdescr)
+ if (!mdescr) {
+ printf("Could not find the parameter %s.\n", name);
+ print_all_mesh_param_descr();
return 2;
+ }
/* Parse the new value */
ret = mdescr->parse_fn(value, &any);
if (ret != 0) {
- printf("%s must be set to a number "
- "between 0 and %u\n", mdescr->name, ret);
+ if (mdescr->mesh_param_num
+ == NL80211_MESHCONF_POWER_MODE)
+ printf("%s must be set to active, light or "
+ "deep.\n", mdescr->name);
+ else
+ printf("%s must be set to a number "
+ "between 0 and %u\n",
+ mdescr->name, ret);
+
return 2;
}
return -EINVAL;
if (!mdescr) {
- int i;
+ unsigned int i;
+ /* print out all the supported mesh parameters */
for (i = 0; i < ARRAY_SIZE(_mesh_param_descrs); i++) {
mdescr = &_mesh_param_descrs[i];
- printf("%s = ", mdescr->name);
- mdescr->nla_print_fn(mesh_params[mdescr->mesh_param_num]);
- printf("\n");
+ if (mesh_params[mdescr->mesh_param_num]) {
+ printf("%s = ", mdescr->name);
+ mdescr->nla_print_fn(mesh_params[mdescr->mesh_param_num]);
+ printf("\n");
+ }
}
return NL_SKIP;
}
- /* print out the mesh parameter */
- mdescr->nla_print_fn(mesh_params[mdescr->mesh_param_num]);
- printf("\n");
+ /* print out the requested mesh parameter */
+ if (mesh_params[mdescr->mesh_param_num]) {
+ mdescr->nla_print_fn(mesh_params[mdescr->mesh_param_num]);
+ printf("\n");
+ }
return NL_SKIP;
}
static int get_interface_meshparam(struct nl80211_state *state,
- struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv,
enum id_input id)
{
const struct mesh_param_descr *mdescr = NULL;
- if (argc > 1)
+ if (argc == 0) {
+ print_all_mesh_param_descr();
return 1;
-
- if (argc == 1) {
+ } else if (argc == 1) {
mdescr = find_mesh_param(argv[0]);
- if (!mdescr)
+ if (!mdescr) {
+ printf("Could not find the parameter %s.\n", argv[0]);
+ print_all_mesh_param_descr();
return 2;
+ }
+ } else {
+ return 1;
}
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
- print_mesh_param_handler, (void *)mdescr);
+ register_handler(print_mesh_param_handler, (void *)mdescr);
return 0;
}
NL80211_CMD_GET_MESH_PARAMS, 0, CIB_NETDEV, get_interface_meshparam,
"Retrieve mesh parameter (run command without any to see available ones).");
-static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
+static int dump_interface_meshparam(struct nl80211_state *state,
+ struct nl_msg *msg,
+ int argc, char **argv,
+ enum id_input id)
+{
+ register_handler(print_mesh_param_handler, NULL);
+ return 0;
+}
+
+COMMAND(mesh_param, dump, "",
+ NL80211_CMD_GET_MESH_PARAMS, 0, CIB_NETDEV, dump_interface_meshparam,
+ "List all supported mesh parameters");
+
+static int join_mesh(struct nl80211_state *state,
struct nl_msg *msg, int argc, char **argv,
enum id_input id)
{
struct nlattr *container;
float rate;
- char *end;
+ unsigned char rates[NL80211_MAX_SUPP_RATES];
+ int bintval, dtim_period, n_rates = 0;
+ char *end, *value = NULL, *sptr = NULL;
if (argc < 1)
return 1;
argc--;
argv++;
+ /* freq */
+ if (argc > 1 && strcmp(argv[0], "freq") == 0) {
+ struct chandef chandef;
+ int err, parsed;
+
+ err = parse_freqchan(&chandef, false, argc - 1, argv + 1,
+ &parsed, false);
+ if (err)
+ return err;
+
+ argv += parsed + 1;
+ argc -= parsed + 1;
+
+ err = put_chandef(msg, &chandef);
+ if (err)
+ return err;
+ }
+
+ /* basic rates */
+ if (argc > 1 && strcmp(argv[0], "basic-rates") == 0) {
+ argv++;
+ argc--;
+
+ value = strtok_r(argv[0], ",", &sptr);
+
+ while (value && n_rates < NL80211_MAX_SUPP_RATES) {
+ rate = strtod(value, &end);
+ rates[n_rates] = rate * 2;
+
+ /* filter out suspicious values */
+ if (*end != '\0' || !rates[n_rates] ||
+ rate*2 != rates[n_rates])
+ return 1;
+
+ n_rates++;
+ value = strtok_r(NULL, ",", &sptr);
+ }
+
+ NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, n_rates, rates);
+ argv++;
+ argc--;
+ }
+
+ /* multicast rate */
if (argc > 1 && strcmp(argv[0], "mcast-rate") == 0) {
argv++;
argc--;
argc--;
}
+ if (argc > 1 && strcmp(argv[0], "beacon-interval") == 0) {
+ argc--;
+ argv++;
+
+ bintval = strtoul(argv[0], &end, 10);
+ if (*end != '\0')
+ return 1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, bintval);
+ argv++;
+ argc--;
+ }
+
+ if (argc > 1 && strcmp(argv[0], "dtim-period") == 0) {
+ argc--;
+ argv++;
+
+ dtim_period = strtoul(argv[0], &end, 10);
+ if (*end != '\0')
+ return 1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
+ argv++;
+ argc--;
+ }
+
container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
if (!container)
return -ENOBUFS;
if (!argc)
return 0;
- return set_interface_meshparam(state, cb, msg, argc, argv, id);
+ return set_interface_meshparam(state, msg, argc, argv, id);
nla_put_failure:
return -ENOBUFS;
}
-COMMAND(mesh, join, "<mesh ID> [mcast-rate <rate in Mbps>] [vendor_sync on|off]"
- " [<param>=<value>]*",
+COMMAND(mesh, join, "<mesh ID> [[freq <freq in MHz> <NOHT|HT20|HT40+|HT40-|80MHz>]"
+ " [basic-rates <rate in Mbps,rate2,...>]], [mcast-rate <rate in Mbps>]"
+ " [beacon-interval <time in TUs>] [dtim-period <value>]"
+ " [vendor_sync on|off] [<param>=<value>]*",
NL80211_CMD_JOIN_MESH, 0, CIB_NETDEV, join_mesh,
- "Join a mesh with the given mesh ID with mcast-rate and mesh parameters.");
+ "Join a mesh with the given mesh ID with frequency, basic-rates,\n"
+ "mcast-rate and mesh parameters. Basic-rates are applied only if\n"
+ "frequency is provided.");
-static int leave_mesh(struct nl80211_state *state, struct nl_cb *cb,
+static int leave_mesh(struct nl80211_state *state,
struct nl_msg *msg, int argc, char **argv,
enum id_input id)
{