1*92022041SSam Saccone #include <errno.h>
2*92022041SSam Saccone #include <string.h>
3*92022041SSam Saccone
4*92022041SSam Saccone #include <netlink/genl/genl.h>
5*92022041SSam Saccone #include <netlink/genl/family.h>
6*92022041SSam Saccone #include <netlink/genl/ctrl.h>
7*92022041SSam Saccone #include <netlink/msg.h>
8*92022041SSam Saccone #include <netlink/attr.h>
9*92022041SSam Saccone
10*92022041SSam Saccone #include "nl80211.h"
11*92022041SSam Saccone #include "iw.h"
12*92022041SSam Saccone
13*92022041SSam Saccone SECTION(vendor);
14*92022041SSam Saccone
print_vendor_response(struct nl_msg * msg,void * arg)15*92022041SSam Saccone static int print_vendor_response(struct nl_msg *msg, void *arg)
16*92022041SSam Saccone {
17*92022041SSam Saccone struct nlattr *attr;
18*92022041SSam Saccone struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
19*92022041SSam Saccone bool print_ascii = (bool) arg;
20*92022041SSam Saccone uint8_t *data;
21*92022041SSam Saccone int len;
22*92022041SSam Saccone
23*92022041SSam Saccone attr = nla_find(genlmsg_attrdata(gnlh, 0),
24*92022041SSam Saccone genlmsg_attrlen(gnlh, 0),
25*92022041SSam Saccone NL80211_ATTR_VENDOR_DATA);
26*92022041SSam Saccone if (!attr) {
27*92022041SSam Saccone fprintf(stderr, "vendor data attribute missing!\n");
28*92022041SSam Saccone return NL_SKIP;
29*92022041SSam Saccone }
30*92022041SSam Saccone
31*92022041SSam Saccone data = (uint8_t *) nla_data(attr);
32*92022041SSam Saccone len = nla_len(attr);
33*92022041SSam Saccone
34*92022041SSam Saccone if (print_ascii)
35*92022041SSam Saccone iw_hexdump("vendor response", data, len);
36*92022041SSam Saccone else
37*92022041SSam Saccone fwrite(data, 1, len, stdout);
38*92022041SSam Saccone
39*92022041SSam Saccone return NL_OK;
40*92022041SSam Saccone }
41*92022041SSam Saccone
read_file(FILE * file,char * buf,size_t size)42*92022041SSam Saccone static int read_file(FILE *file, char *buf, size_t size)
43*92022041SSam Saccone {
44*92022041SSam Saccone size_t count = 0;
45*92022041SSam Saccone int data;
46*92022041SSam Saccone
47*92022041SSam Saccone while ((data = fgetc(file)) != EOF) {
48*92022041SSam Saccone if (count >= size)
49*92022041SSam Saccone return -EINVAL;
50*92022041SSam Saccone buf[count] = data;
51*92022041SSam Saccone count++;
52*92022041SSam Saccone }
53*92022041SSam Saccone
54*92022041SSam Saccone return count;
55*92022041SSam Saccone }
56*92022041SSam Saccone
read_hex(unsigned int argc,char ** argv,char * buf,size_t size)57*92022041SSam Saccone static int read_hex(unsigned int argc, char **argv, char *buf, size_t size)
58*92022041SSam Saccone {
59*92022041SSam Saccone unsigned int i, data;
60*92022041SSam Saccone int res;
61*92022041SSam Saccone
62*92022041SSam Saccone if (argc > size)
63*92022041SSam Saccone return -EINVAL;
64*92022041SSam Saccone
65*92022041SSam Saccone for (i = 0; i < argc; i++) {
66*92022041SSam Saccone res = sscanf(argv[i], "0x%x", &data);
67*92022041SSam Saccone if (res != 1 || data > 0xff)
68*92022041SSam Saccone return -EINVAL;
69*92022041SSam Saccone buf[i] = data;
70*92022041SSam Saccone }
71*92022041SSam Saccone
72*92022041SSam Saccone return argc;
73*92022041SSam Saccone }
74*92022041SSam Saccone
handle_vendor(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)75*92022041SSam Saccone static int handle_vendor(struct nl80211_state *state,
76*92022041SSam Saccone struct nl_msg *msg, int argc, char **argv,
77*92022041SSam Saccone enum id_input id)
78*92022041SSam Saccone {
79*92022041SSam Saccone unsigned int oui;
80*92022041SSam Saccone unsigned int subcmd;
81*92022041SSam Saccone char buf[2048] = {};
82*92022041SSam Saccone int res, count = 0;
83*92022041SSam Saccone FILE *file = NULL;
84*92022041SSam Saccone
85*92022041SSam Saccone if (argc < 3)
86*92022041SSam Saccone return 1;
87*92022041SSam Saccone
88*92022041SSam Saccone res = sscanf(argv[0], "0x%x", &oui);
89*92022041SSam Saccone if (res != 1) {
90*92022041SSam Saccone printf("Vendor command must start with 0x\n");
91*92022041SSam Saccone return 2;
92*92022041SSam Saccone }
93*92022041SSam Saccone
94*92022041SSam Saccone res = sscanf(argv[1], "0x%x", &subcmd);
95*92022041SSam Saccone if (res != 1) {
96*92022041SSam Saccone printf("Sub command must start with 0x\n");
97*92022041SSam Saccone return 2;
98*92022041SSam Saccone }
99*92022041SSam Saccone
100*92022041SSam Saccone if (!strcmp(argv[2], "-"))
101*92022041SSam Saccone file = stdin;
102*92022041SSam Saccone else
103*92022041SSam Saccone file = fopen(argv[2], "r");
104*92022041SSam Saccone
105*92022041SSam Saccone NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, oui);
106*92022041SSam Saccone NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd);
107*92022041SSam Saccone
108*92022041SSam Saccone if (file) {
109*92022041SSam Saccone count = read_file(file, buf, sizeof(buf));
110*92022041SSam Saccone if (file != stdin)
111*92022041SSam Saccone fclose(file);
112*92022041SSam Saccone } else
113*92022041SSam Saccone count = read_hex(argc - 2, &argv[2], buf, sizeof(buf));
114*92022041SSam Saccone
115*92022041SSam Saccone if (count < 0)
116*92022041SSam Saccone return -EINVAL;
117*92022041SSam Saccone
118*92022041SSam Saccone if (count > 0)
119*92022041SSam Saccone NLA_PUT(msg, NL80211_ATTR_VENDOR_DATA, count, buf);
120*92022041SSam Saccone
121*92022041SSam Saccone return 0;
122*92022041SSam Saccone
123*92022041SSam Saccone nla_put_failure:
124*92022041SSam Saccone if (file && file != stdin)
125*92022041SSam Saccone fclose(file);
126*92022041SSam Saccone return -ENOBUFS;
127*92022041SSam Saccone }
128*92022041SSam Saccone
handle_vendor_recv(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)129*92022041SSam Saccone static int handle_vendor_recv(struct nl80211_state *state,
130*92022041SSam Saccone struct nl_msg *msg, int argc,
131*92022041SSam Saccone char **argv, enum id_input id)
132*92022041SSam Saccone {
133*92022041SSam Saccone register_handler(print_vendor_response, (void *) true);
134*92022041SSam Saccone return handle_vendor(state, msg, argc, argv, id);
135*92022041SSam Saccone }
136*92022041SSam Saccone
handle_vendor_recv_bin(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)137*92022041SSam Saccone static int handle_vendor_recv_bin(struct nl80211_state *state,
138*92022041SSam Saccone struct nl_msg *msg, int argc,
139*92022041SSam Saccone char **argv, enum id_input id)
140*92022041SSam Saccone {
141*92022041SSam Saccone register_handler(print_vendor_response, (void *) false);
142*92022041SSam Saccone return handle_vendor(state, msg, argc, argv, id);
143*92022041SSam Saccone }
144*92022041SSam Saccone
145*92022041SSam Saccone COMMAND(vendor, send, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor, "");
146*92022041SSam Saccone COMMAND(vendor, recv, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor_recv, "");
147*92022041SSam Saccone COMMAND(vendor, recvbin, "<oui> <subcmd> <filename|-|hex data>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_vendor_recv_bin, "");
148