xref: /aosp_15_r20/external/iw/vendor.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
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