X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fiw.git;a=blobdiff_plain;f=mesh.c;h=00610cd60a65cc9cb023d966b85b9f9a05fc97e7;hp=4fdad6a09a76991c73005be575bde5d0a9a9d4a5;hb=HEAD;hpb=83cb979bc161a163ac03e4fc8b34936de5d3763e diff --git a/mesh.c b/mesh.c index 4fdad6a..40e5e5e 100644 --- a/mesh.c +++ b/mesh.c @@ -1,4 +1,3 @@ -#include #include #include @@ -12,6 +11,7 @@ #include "iw.h" SECTION(mesh); +SECTION(mesh_param); typedef struct _any_t { @@ -109,6 +109,23 @@ static uint32_t _parse_s32(const char *str, _any *ret) 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) { @@ -140,11 +157,36 @@ static void _print_u32_timeout(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)); @@ -152,7 +194,7 @@ static void _print_s32_in_dBm(struct nlattr *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, @@ -217,11 +259,23 @@ const static struct mesh_param_descr _mesh_param_descrs[] = {"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"); @@ -231,7 +285,7 @@ static void print_all_mesh_param_descr(void) 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++) { @@ -239,13 +293,11 @@ static const struct mesh_param_descr *find_mesh_param(const char *name) 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) @@ -253,14 +305,16 @@ static int set_interface_meshparam(struct nl80211_state *state, 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; @@ -288,14 +342,24 @@ static int set_interface_meshparam(struct nl80211_state *state, } 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; } @@ -334,42 +398,50 @@ static int print_mesh_param_handler(struct nl_msg *msg, void *arg) 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; } @@ -377,13 +449,28 @@ COMMAND(get, mesh_param, "[]", 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; @@ -392,6 +479,50 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, 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--; @@ -405,6 +536,32 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, 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; @@ -427,16 +584,20 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, 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, " [mcast-rate ] [vendor_sync on|off]" - " [=]*", +COMMAND(mesh, join, " [[freq ]" + " [basic-rates ]], [mcast-rate ]" + " [beacon-interval