diff options
Diffstat (limited to 'vendor.c')
-rw-r--r-- | vendor.c | 76 |
1 files changed, 64 insertions, 12 deletions
@@ -1,4 +1,3 @@ -#include <net/if.h> #include <errno.h> #include <string.h> @@ -13,9 +12,37 @@ SECTION(vendor); +static int print_vendor_response(struct nl_msg *msg, void *arg) +{ + struct nlattr *attr; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + bool print_ascii = (bool) arg; + uint8_t *data; + int len; + + attr = nla_find(genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), + NL80211_ATTR_VENDOR_DATA); + if (!attr) { + fprintf(stderr, "vendor data attribute missing!\n"); + return NL_SKIP; + } + + data = (uint8_t *) nla_data(attr); + len = nla_len(attr); + + if (print_ascii) + iw_hexdump("vendor response", data, len); + else + fwrite(data, 1, len, stdout); + + return NL_OK; +} + static int read_file(FILE *file, char *buf, size_t size) { - int data, count = 0; + size_t count = 0; + int data; while ((data = fgetc(file)) != EOF) { if (count >= size) @@ -27,10 +54,10 @@ static int read_file(FILE *file, char *buf, size_t size) return count; } -static int read_hex(int argc, char **argv, char *buf, size_t size) +static int read_hex(unsigned int argc, char **argv, char *buf, size_t size) { - int i, res; - unsigned int data; + unsigned int i, data; + int res; if (argc > size) return -EINVAL; @@ -45,7 +72,7 @@ static int read_hex(int argc, char **argv, char *buf, size_t size) return argc; } -static int handle_vendor(struct nl80211_state *state, struct nl_cb *cb, +static int handle_vendor(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, enum id_input id) { @@ -56,15 +83,19 @@ static int handle_vendor(struct nl80211_state *state, struct nl_cb *cb, FILE *file = NULL; if (argc < 3) - return -EINVAL; + return 1; res = sscanf(argv[0], "0x%x", &oui); - if (res != 1) - return -EINVAL; + if (res != 1) { + printf("Vendor command must start with 0x\n"); + return 2; + } res = sscanf(argv[1], "0x%x", &subcmd); - if (res != 1) - return -EINVAL; + if (res != 1) { + printf("Sub command must start with 0x\n"); + return 2; + } if (!strcmp(argv[2], "-")) file = stdin; @@ -76,7 +107,8 @@ static int handle_vendor(struct nl80211_state *state, struct nl_cb *cb, if (file) { count = read_file(file, buf, sizeof(buf)); - fclose(file); + if (file != stdin) + fclose(file); } else count = read_hex(argc - 2, &argv[2], buf, sizeof(buf)); @@ -89,7 +121,27 @@ static int handle_vendor(struct nl80211_state *state, struct nl_cb *cb, return 0; nla_put_failure: + if (file && file != stdin) + fclose(file); return -ENOBUFS; } +static int handle_vendor_recv(struct nl80211_state *state, + struct nl_msg *msg, int argc, + char **argv, enum id_input id) +{ + register_handler(print_vendor_response, (void *) true); + return handle_vendor(state, msg, argc, argv, id); +} + +static int handle_vendor_recv_bin(struct nl80211_state *state, + struct nl_msg *msg, int argc, + char **argv, enum id_input id) +{ + register_handler(print_vendor_response, (void *) false); + return handle_vendor(state, msg, argc, argv, id); +} + COMMAND(vendor, send, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor, ""); +COMMAND(vendor, recv, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor_recv, ""); +COMMAND(vendor, recvbin, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor_recv_bin, ""); |