static int __handle_cmd(struct nl80211_state *state, enum id_input idby, int argc, char **argv, const struct cmd **cmdout) { const struct cmd *cmd, *match = NULL, *sectcmd; struct nl_cb *cb; struct nl_cb *s_cb; struct nl_msg *msg; signed long long devidx = 0; int err, o_argc; const char *command, *section; char *tmp, **o_argv; enum command_identify_by command_idby = CIB_NONE; if (argc <= 1 && idby != II_NONE) return 1; o_argc = argc; o_argv = argv; switch (idby) { case II_PHY_IDX: command_idby = CIB_PHY; devidx = strtoul(*argv + 4, &tmp, 0); if (*tmp != '\0') return 1; argc--; argv++; break; case II_PHY_NAME: command_idby = CIB_PHY; devidx = phy_lookup(*argv); argc--; argv++; break; case II_NETDEV: command_idby = CIB_NETDEV; devidx = if_nametoindex(*argv); if (devidx == 0) devidx = -1; argc--; argv++; break; case II_WDEV: command_idby = CIB_WDEV; devidx = strtoll(*argv, &tmp, 0); if (*tmp != '\0') return 1; argc--; argv++; default: break; } if (devidx < 0) return -errno; section = *argv; argc--; argv++; for_each_cmd(sectcmd) { if (sectcmd->parent) continue; /* ok ... bit of a hack for the dupe 'info' section */ if (match && sectcmd->idby != command_idby) continue; if (strcmp(sectcmd->name, section) == 0) match = sectcmd; } sectcmd = match; match = NULL; if (!sectcmd) return 1; if (argc > 0) { command = *argv; for_each_cmd(cmd) { if (!cmd->handler) continue; if (cmd->parent != sectcmd) continue; /* * ignore mismatch id by, but allow WDEV * in place of NETDEV */ if (cmd->idby != command_idby && !(cmd->idby == CIB_NETDEV && command_idby == CIB_WDEV)) continue; if (strcmp(cmd->name, command)) continue; if (argc > 1 && !cmd->args) continue; match = cmd; break; } if (match) { argc--; argv++; } }
static int __handle_cmd(struct nl80211_state *state, enum id_input idby, int argc, char **argv, const struct cmd **cmdout) { const struct cmd *cmd, *match = NULL, *sectcmd; struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err, o_argc; const char *command, *section; char *tmp, **o_argv; enum command_identify_by command_idby = CIB_NONE; #if 0 if (file_exist(CURRENT_NVS_NAME) < 0) { fprintf(stderr, "\n\tUnable to find NVS file (%s).\n\t" "Make sure to use reference-nvs.bin instead.\n\n", CURRENT_NVS_NAME); return 2; } #endif if (argc <= 1) return 1; o_argc = argc; o_argv = argv; switch (idby) { case II_PHY_IDX: command_idby = CIB_PHY; devidx = strtoul(*argv + 4, &tmp, 0); if (*tmp != '\0') return 1; argc--; argv++; break; case II_PHY_NAME: command_idby = CIB_PHY; devidx = phy_lookup(*argv); argc--; argv++; break; case II_NETDEV: command_idby = CIB_NETDEV; devidx = if_nametoindex(*argv); if (devidx == 0) devidx = -1; argc--; argv++; break; default: break; } if (devidx < 0) return -errno; section = *argv; argc--; argv++; for_each_cmd(sectcmd) { if (sectcmd->parent) continue; /* ok ... bit of a hack for the dupe 'info' section */ if (match && sectcmd->idby != command_idby) continue; if (strcmp(sectcmd->name, section) == 0) match = sectcmd; } sectcmd = match; match = NULL; if (!sectcmd) return 1; if (argc > 0) { command = *argv; for_each_cmd(cmd) { if (!cmd->handler) continue; if (cmd->parent != sectcmd) continue; if (cmd->idby != command_idby) continue; if (strcmp(cmd->name, command)) continue; if (argc > 1 && !cmd->args) continue; match = cmd; break; } if (match) { argc--; argv++; } }
static int execute_nl_interface_cmd(const char *iface, enum nl80211_iftype type, uint8_t cmd) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; int add_interface = (cmd == NL80211_CMD_NEW_INTERFACE); if (add_interface) { devidx = phy_lookup(); } else { devidx = if_nametoindex(iface); if (devidx == 0) { ALOGE("failed to translate ifname to idx"); return -errno; } } msg = nlmsg_alloc(); if (!msg) { ALOGE("failed to allocate netlink message"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { ALOGE("failed to allocate netlink callbacks"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, 0, cmd, 0); if (add_interface) { NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx); } else { NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); } if (add_interface) { NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, iface); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type); } err = nl_send_auto_complete(nl_soc, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &err); while (err > 0) nl_recvmsgs(nl_soc, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: ALOGW("building message failed"); return 2; }
int main(int argc, char **argv) { int opt, optind = 0; struct option long_opts[] = { {"help", no_argument, 0, 'h'}, {"command", required_argument, 0, 'c'}, {"ascii", no_argument, 0, 'a'}, {"verbose", no_argument, 0, 'v'}, {"if", required_argument, 0, 1000}, {"interface", required_argument, 0, 1001}, {"phy", required_argument, 0, 1002}, {"print-commands", no_argument, 0, 1003}, {"version", no_argument, 0, 1004}, {"syslog", no_argument, 0, 1005}, {NULL, 0, 0, 0}, }; while ((opt = getopt_long(argc, argv, "hc:av", long_opts, &optind)) != -1) { switch (opt) { case 1000: /* Fallthrough */ case 1001: dev_by_phy = false; devidx = if_nametoindex(optarg); devidx_set = true; break; case 1002: dev_by_phy = true; devidx = phy_lookup(optarg); devidx_set = true; break; case 1003: print_nl80211_cmds(); return 0; case 1004: print_version(); return 0; case 1005: log_stderr = false; break; case 'a': print_ascii = true; break; case 'c': cur_cmd = nl80211_cmd_from_str(optarg); if (cur_cmd == NL80211_CMD_UNSPEC) fprintf(stderr, "Unknown command: %s\n", optarg); else cmd_set = true; break; case 'v': log_level++; break; case 'h': default: print_usage(argv[0]); return 0; } } return run_iwraw(); }