xref: /aosp_15_r20/external/iw/nan.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
1*92022041SSam Saccone #include <net/if.h>
2*92022041SSam Saccone #include <errno.h>
3*92022041SSam Saccone #include <string.h>
4*92022041SSam Saccone 
5*92022041SSam Saccone #include <netlink/genl/genl.h>
6*92022041SSam Saccone #include <netlink/genl/family.h>
7*92022041SSam Saccone #include <netlink/genl/ctrl.h>
8*92022041SSam Saccone #include <netlink/msg.h>
9*92022041SSam Saccone #include <netlink/attr.h>
10*92022041SSam Saccone 
11*92022041SSam Saccone #include <ctype.h>
12*92022041SSam Saccone #include <inttypes.h>
13*92022041SSam Saccone #include "nl80211.h"
14*92022041SSam Saccone #include "iw.h"
15*92022041SSam Saccone #include "sha256.h"
16*92022041SSam Saccone 
17*92022041SSam Saccone SECTION(nan);
18*92022041SSam Saccone 
parse_bands(int argc,char ** argv)19*92022041SSam Saccone static int parse_bands(int argc, char **argv)
20*92022041SSam Saccone {
21*92022041SSam Saccone 	int i = 0, bands = 0;
22*92022041SSam Saccone 
23*92022041SSam Saccone 	for (i = 0; i < argc; i++) {
24*92022041SSam Saccone 		if (!strcasecmp("2ghz", argv[i]))
25*92022041SSam Saccone 			bands |= BIT(NL80211_BAND_2GHZ);
26*92022041SSam Saccone 		else if (!strcasecmp("5ghz", argv[i]))
27*92022041SSam Saccone 			bands |= BIT(NL80211_BAND_5GHZ);
28*92022041SSam Saccone 		else
29*92022041SSam Saccone 			return -EINVAL;
30*92022041SSam Saccone 	}
31*92022041SSam Saccone 
32*92022041SSam Saccone 	return bands;
33*92022041SSam Saccone }
34*92022041SSam Saccone 
handle_nan_start(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)35*92022041SSam Saccone static int handle_nan_start(struct nl80211_state *state,
36*92022041SSam Saccone 			    struct nl_msg *msg, int argc, char **argv,
37*92022041SSam Saccone 			    enum id_input id)
38*92022041SSam Saccone {
39*92022041SSam Saccone 	int bands = 0;
40*92022041SSam Saccone 
41*92022041SSam Saccone 	if (argc < 2)
42*92022041SSam Saccone 		return -EINVAL;
43*92022041SSam Saccone 
44*92022041SSam Saccone 	if (strcmp(argv[0], "pref") == 0) {
45*92022041SSam Saccone 		argv++;
46*92022041SSam Saccone 		argc--;
47*92022041SSam Saccone 		NLA_PUT_U8(msg, NL80211_ATTR_NAN_MASTER_PREF, atoi(argv[0]));
48*92022041SSam Saccone 		argv++;
49*92022041SSam Saccone 		argc--;
50*92022041SSam Saccone 	} else {
51*92022041SSam Saccone 		/* Master preference is mandatory */
52*92022041SSam Saccone 		return -EINVAL;
53*92022041SSam Saccone 	}
54*92022041SSam Saccone 
55*92022041SSam Saccone 	if (argc > 1 && !strcmp(argv[0], "bands")) {
56*92022041SSam Saccone 		argv++;
57*92022041SSam Saccone 		argc--;
58*92022041SSam Saccone 
59*92022041SSam Saccone 		bands = parse_bands(argc, argv);
60*92022041SSam Saccone 		if (bands < 0)
61*92022041SSam Saccone 			return bands;
62*92022041SSam Saccone 
63*92022041SSam Saccone 		NLA_PUT_U32(msg, NL80211_ATTR_BANDS, bands);
64*92022041SSam Saccone 	} else if (argc != 0)
65*92022041SSam Saccone 		return -EINVAL;
66*92022041SSam Saccone 
67*92022041SSam Saccone 	return 0;
68*92022041SSam Saccone nla_put_failure:
69*92022041SSam Saccone 	return -ENOBUFS;
70*92022041SSam Saccone }
71*92022041SSam Saccone COMMAND(nan, start, "pref <pref> [bands [2GHz] [5GHz]]",
72*92022041SSam Saccone 	NL80211_CMD_START_NAN, 0, CIB_WDEV, handle_nan_start, "");
73*92022041SSam Saccone 
handle_nan_stop(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)74*92022041SSam Saccone static int handle_nan_stop(struct nl80211_state *state,
75*92022041SSam Saccone 			   struct nl_msg *msg, int argc, char **argv,
76*92022041SSam Saccone 			   enum id_input id)
77*92022041SSam Saccone {
78*92022041SSam Saccone 	return 0;
79*92022041SSam Saccone }
80*92022041SSam Saccone COMMAND(nan, stop, "", NL80211_CMD_STOP_NAN, 0, CIB_WDEV, handle_nan_stop, "");
81*92022041SSam Saccone 
handle_nan_config(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)82*92022041SSam Saccone static int handle_nan_config(struct nl80211_state *state,
83*92022041SSam Saccone 			     struct nl_msg *msg, int argc, char **argv,
84*92022041SSam Saccone 			     enum id_input id)
85*92022041SSam Saccone {
86*92022041SSam Saccone 	int bands = 0;
87*92022041SSam Saccone 
88*92022041SSam Saccone 	if (argc < 2)
89*92022041SSam Saccone 		return -EINVAL;
90*92022041SSam Saccone 
91*92022041SSam Saccone 	if (strcmp(argv[0], "pref") == 0) {
92*92022041SSam Saccone 		argv++;
93*92022041SSam Saccone 		argc--;
94*92022041SSam Saccone 		NLA_PUT_U8(msg, NL80211_ATTR_NAN_MASTER_PREF, atoi(argv[0]));
95*92022041SSam Saccone 		argv++;
96*92022041SSam Saccone 		argc--;
97*92022041SSam Saccone 	}
98*92022041SSam Saccone 
99*92022041SSam Saccone 	if (argc > 1 && !strcmp(argv[0], "bands")) {
100*92022041SSam Saccone 		argv++;
101*92022041SSam Saccone 		argc--;
102*92022041SSam Saccone 
103*92022041SSam Saccone 		bands = parse_bands(argc, argv);
104*92022041SSam Saccone 		if (bands < 0)
105*92022041SSam Saccone 			return bands;
106*92022041SSam Saccone 
107*92022041SSam Saccone 		NLA_PUT_U32(msg, NL80211_ATTR_BANDS, bands);
108*92022041SSam Saccone 		argv++;
109*92022041SSam Saccone 		argc--;
110*92022041SSam Saccone 	} else if (argc != 0)
111*92022041SSam Saccone 		return -EINVAL;
112*92022041SSam Saccone 
113*92022041SSam Saccone 	return 0;
114*92022041SSam Saccone nla_put_failure:
115*92022041SSam Saccone 	return -ENOBUFS;
116*92022041SSam Saccone }
117*92022041SSam Saccone COMMAND(nan, config, "[pref <pref>] [bands [2GHz] [5GHz]]",
118*92022041SSam Saccone 	NL80211_CMD_CHANGE_NAN_CONFIG, 0, CIB_WDEV, handle_nan_config, "");
119*92022041SSam Saccone 
handle_nan_rm_func(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)120*92022041SSam Saccone static int handle_nan_rm_func(struct nl80211_state *state,
121*92022041SSam Saccone 			      struct nl_msg *msg, int argc, char **argv,
122*92022041SSam Saccone 			      enum id_input id)
123*92022041SSam Saccone {
124*92022041SSam Saccone 	if (argc != 2)
125*92022041SSam Saccone 		return -EINVAL;
126*92022041SSam Saccone 
127*92022041SSam Saccone 	if (strcmp(argv[0], "cookie") == 0) {
128*92022041SSam Saccone 		argv++;
129*92022041SSam Saccone 		argc--;
130*92022041SSam Saccone 		NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, atoi(argv[0]));
131*92022041SSam Saccone 		argv++;
132*92022041SSam Saccone 		argc--;
133*92022041SSam Saccone 	}
134*92022041SSam Saccone 
135*92022041SSam Saccone 	if (argc != 0)
136*92022041SSam Saccone 		return -EINVAL;
137*92022041SSam Saccone 
138*92022041SSam Saccone 	return 0;
139*92022041SSam Saccone nla_put_failure:
140*92022041SSam Saccone 	return -ENOBUFS;
141*92022041SSam Saccone }
142*92022041SSam Saccone COMMAND(nan, rm_func, "cookie <cookie>", NL80211_CMD_DEL_NAN_FUNCTION, 0,
143*92022041SSam Saccone 	CIB_WDEV, handle_nan_rm_func, "");
144*92022041SSam Saccone 
compute_service_id(const unsigned char * serv_name,unsigned int len,unsigned char * res)145*92022041SSam Saccone static int compute_service_id(const unsigned char *serv_name,
146*92022041SSam Saccone 			      unsigned int len, unsigned char *res)
147*92022041SSam Saccone {
148*92022041SSam Saccone 	size_t size = len;
149*92022041SSam Saccone 	unsigned char md_value[32];
150*92022041SSam Saccone 	int retcode = sha256(serv_name, size, md_value);
151*92022041SSam Saccone 
152*92022041SSam Saccone 	if (retcode)
153*92022041SSam Saccone 		return retcode;
154*92022041SSam Saccone 	memcpy(res, md_value, 6);
155*92022041SSam Saccone 
156*92022041SSam Saccone 	return 0;
157*92022041SSam Saccone }
158*92022041SSam Saccone 
print_instance_id_handler(struct nl_msg * msg,void * arg)159*92022041SSam Saccone static int print_instance_id_handler(struct nl_msg *msg, void *arg)
160*92022041SSam Saccone {
161*92022041SSam Saccone 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
162*92022041SSam Saccone 	struct nlattr *func[NL80211_NAN_FUNC_ATTR_MAX + 1];
163*92022041SSam Saccone 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
164*92022041SSam Saccone 
165*92022041SSam Saccone 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
166*92022041SSam Saccone 		  genlmsg_attrlen(gnlh, 0), NULL);
167*92022041SSam Saccone 
168*92022041SSam Saccone 	if (!tb[NL80211_ATTR_COOKIE]) {
169*92022041SSam Saccone 		fprintf(stderr, "cookie is missing!\n");
170*92022041SSam Saccone 		return NL_SKIP;
171*92022041SSam Saccone 	}
172*92022041SSam Saccone 
173*92022041SSam Saccone 	nla_parse_nested(func, NL80211_NAN_FUNC_ATTR_MAX,
174*92022041SSam Saccone 			 tb[NL80211_ATTR_NAN_FUNC],
175*92022041SSam Saccone 			 NULL);
176*92022041SSam Saccone 	if (!func[NL80211_NAN_FUNC_INSTANCE_ID]) {
177*92022041SSam Saccone 		fprintf(stderr, "instance id is missing!\n");
178*92022041SSam Saccone 		return NL_SKIP;
179*92022041SSam Saccone 	}
180*92022041SSam Saccone 
181*92022041SSam Saccone 	printf("instance_id: %d, cookie: %" PRIu64 "\n",
182*92022041SSam Saccone 	       nla_get_u8(func[NL80211_NAN_FUNC_INSTANCE_ID]),
183*92022041SSam Saccone 	       nla_get_u64(tb[NL80211_ATTR_COOKIE]));
184*92022041SSam Saccone 
185*92022041SSam Saccone 	return NL_SKIP;
186*92022041SSam Saccone }
187*92022041SSam Saccone 
parse_srf(char ** argv,int argc,struct nl_msg * func_attrs)188*92022041SSam Saccone static int parse_srf(char **argv, int argc, struct nl_msg *func_attrs)
189*92022041SSam Saccone {
190*92022041SSam Saccone 	struct nl_msg *srf_attrs;
191*92022041SSam Saccone 	int old_argc = argc;
192*92022041SSam Saccone 	unsigned char mac_addr[ETH_ALEN];
193*92022041SSam Saccone 	char *cur_mac, *sptr = NULL;
194*92022041SSam Saccone 
195*92022041SSam Saccone 	srf_attrs = nlmsg_alloc();
196*92022041SSam Saccone 	if (strcmp(argv[0], "include") == 0)
197*92022041SSam Saccone 		NLA_PUT_FLAG(srf_attrs, NL80211_NAN_SRF_INCLUDE);
198*92022041SSam Saccone 	else if (strcmp(argv[0], "exclude") != 0)
199*92022041SSam Saccone 		return -EINVAL;
200*92022041SSam Saccone 
201*92022041SSam Saccone 	argc--;
202*92022041SSam Saccone 	argv++;
203*92022041SSam Saccone 	if (strcmp(argv[0], "bf") == 0) {
204*92022041SSam Saccone 		unsigned char *srf;
205*92022041SSam Saccone 		size_t srf_len;
206*92022041SSam Saccone 		__u8 bf_idx;
207*92022041SSam Saccone 		int err;
208*92022041SSam Saccone 
209*92022041SSam Saccone 		argc--;
210*92022041SSam Saccone 		argv++;
211*92022041SSam Saccone 
212*92022041SSam Saccone 		if (argc < 3)
213*92022041SSam Saccone 			return -EINVAL;
214*92022041SSam Saccone 
215*92022041SSam Saccone 		bf_idx = atoi(argv[0]);
216*92022041SSam Saccone 		NLA_PUT_U8(srf_attrs, NL80211_NAN_SRF_BF_IDX, bf_idx);
217*92022041SSam Saccone 
218*92022041SSam Saccone 		argc--;
219*92022041SSam Saccone 		argv++;
220*92022041SSam Saccone 		srf_len = atoi(argv[0]);
221*92022041SSam Saccone 		if (srf_len == 0 || srf_len > NL80211_NAN_FUNC_SRF_MAX_LEN)
222*92022041SSam Saccone 			return -EINVAL;
223*92022041SSam Saccone 
224*92022041SSam Saccone 		argc--;
225*92022041SSam Saccone 		argv++;
226*92022041SSam Saccone 		srf = malloc(srf_len);
227*92022041SSam Saccone 		if (!srf)
228*92022041SSam Saccone 			return -ENOBUFS;
229*92022041SSam Saccone 
230*92022041SSam Saccone 		memset(srf, 0, srf_len);
231*92022041SSam Saccone 		cur_mac = strtok_r(argv[0], ";", &sptr);
232*92022041SSam Saccone 		while (cur_mac) {
233*92022041SSam Saccone 			if (mac_addr_a2n(mac_addr, cur_mac)) {
234*92022041SSam Saccone 				printf("mac format error %s\n", cur_mac);
235*92022041SSam Saccone 				free(srf);
236*92022041SSam Saccone 				return -EINVAL;
237*92022041SSam Saccone 			}
238*92022041SSam Saccone 
239*92022041SSam Saccone 			nan_bf(bf_idx, srf, srf_len, mac_addr, ETH_ALEN);
240*92022041SSam Saccone 			cur_mac = strtok_r(NULL, ";", &sptr);
241*92022041SSam Saccone 		}
242*92022041SSam Saccone 
243*92022041SSam Saccone 		err = nla_put(srf_attrs, NL80211_NAN_SRF_BF, srf_len, srf);
244*92022041SSam Saccone 		free(srf);
245*92022041SSam Saccone 		if (err)
246*92022041SSam Saccone 			goto nla_put_failure;
247*92022041SSam Saccone 		argv++;
248*92022041SSam Saccone 		argc--;
249*92022041SSam Saccone 	} else if  (strcmp(argv[0], "list") == 0) {
250*92022041SSam Saccone 		struct nlattr *nl_macs = nla_nest_start(srf_attrs,
251*92022041SSam Saccone 						NL80211_NAN_SRF_MAC_ADDRS);
252*92022041SSam Saccone 		int i = 0;
253*92022041SSam Saccone 
254*92022041SSam Saccone 		argc--;
255*92022041SSam Saccone 		argv++;
256*92022041SSam Saccone 		cur_mac = strtok_r(argv[0], ";", &sptr);
257*92022041SSam Saccone 		while (cur_mac) {
258*92022041SSam Saccone 			if (mac_addr_a2n(mac_addr, cur_mac))
259*92022041SSam Saccone 				return -EINVAL;
260*92022041SSam Saccone 
261*92022041SSam Saccone 			nla_put(srf_attrs, ++i, ETH_ALEN, mac_addr);
262*92022041SSam Saccone 			cur_mac = strtok_r(NULL, ";", &sptr);
263*92022041SSam Saccone 		}
264*92022041SSam Saccone 
265*92022041SSam Saccone 		nla_nest_end(srf_attrs, nl_macs);
266*92022041SSam Saccone 		argv++;
267*92022041SSam Saccone 		argc--;
268*92022041SSam Saccone 	} else {
269*92022041SSam Saccone 		return -EINVAL;
270*92022041SSam Saccone 	}
271*92022041SSam Saccone 
272*92022041SSam Saccone 	nla_put_nested(func_attrs, NL80211_NAN_FUNC_SRF, srf_attrs);
273*92022041SSam Saccone 	return old_argc - argc;
274*92022041SSam Saccone nla_put_failure:
275*92022041SSam Saccone 	return -ENOBUFS;
276*92022041SSam Saccone }
277*92022041SSam Saccone 
parse_match_filter(char * filter,struct nl_msg * func_attrs,int tx)278*92022041SSam Saccone static void parse_match_filter(char *filter, struct nl_msg *func_attrs, int tx)
279*92022041SSam Saccone {
280*92022041SSam Saccone 	struct nlattr *nl_filt;
281*92022041SSam Saccone 	char *cur_filt, *sptr = NULL;
282*92022041SSam Saccone 	int i = 0;
283*92022041SSam Saccone 
284*92022041SSam Saccone 	if (tx)
285*92022041SSam Saccone 		nl_filt = nla_nest_start(func_attrs,
286*92022041SSam Saccone 					 NL80211_NAN_FUNC_TX_MATCH_FILTER);
287*92022041SSam Saccone 	else
288*92022041SSam Saccone 		nl_filt = nla_nest_start(func_attrs,
289*92022041SSam Saccone 					 NL80211_NAN_FUNC_RX_MATCH_FILTER);
290*92022041SSam Saccone 
291*92022041SSam Saccone 	cur_filt = strtok_r(filter, ":", &sptr);
292*92022041SSam Saccone 	while (cur_filt) {
293*92022041SSam Saccone 		if (strcmp(cur_filt, "*") != 0)
294*92022041SSam Saccone 			nla_put(func_attrs, ++i, strlen(cur_filt), cur_filt);
295*92022041SSam Saccone 		else
296*92022041SSam Saccone 			nla_put(func_attrs, ++i, 0, NULL);
297*92022041SSam Saccone 
298*92022041SSam Saccone 		cur_filt = strtok_r(NULL, ":", &sptr);
299*92022041SSam Saccone 	}
300*92022041SSam Saccone 
301*92022041SSam Saccone 	nla_nest_end(func_attrs, nl_filt);
302*92022041SSam Saccone }
303*92022041SSam Saccone 
handle_nan_add_func(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)304*92022041SSam Saccone static int handle_nan_add_func(struct nl80211_state *state,
305*92022041SSam Saccone 			       struct nl_msg *msg, int argc, char **argv,
306*92022041SSam Saccone 			       enum id_input id)
307*92022041SSam Saccone {
308*92022041SSam Saccone 	struct nl_msg *func_attrs = NULL;
309*92022041SSam Saccone 	int err = 0;
310*92022041SSam Saccone 	__u8 type;
311*92022041SSam Saccone 
312*92022041SSam Saccone 	func_attrs = nlmsg_alloc();
313*92022041SSam Saccone 	if (!func_attrs) {
314*92022041SSam Saccone 		err = -ENOBUFS;
315*92022041SSam Saccone 		goto out;
316*92022041SSam Saccone 	}
317*92022041SSam Saccone 
318*92022041SSam Saccone 	if (argc > 1 && strcmp(argv[0], "type") == 0) {
319*92022041SSam Saccone 		argv++;
320*92022041SSam Saccone 		argc--;
321*92022041SSam Saccone 		if (strcmp(argv[0], "publish") == 0)
322*92022041SSam Saccone 			type = NL80211_NAN_FUNC_PUBLISH;
323*92022041SSam Saccone 		else if (strcmp(argv[0], "subscribe") == 0)
324*92022041SSam Saccone 			type = NL80211_NAN_FUNC_SUBSCRIBE;
325*92022041SSam Saccone 		else if (strcmp(argv[0], "followup") == 0)
326*92022041SSam Saccone 			type = NL80211_NAN_FUNC_FOLLOW_UP;
327*92022041SSam Saccone 		else
328*92022041SSam Saccone 			return -EINVAL;
329*92022041SSam Saccone 		argv++;
330*92022041SSam Saccone 		argc--;
331*92022041SSam Saccone 
332*92022041SSam Saccone 		NLA_PUT_U8(func_attrs, NL80211_NAN_FUNC_TYPE, type);
333*92022041SSam Saccone 	} else {
334*92022041SSam Saccone 		return -EINVAL;
335*92022041SSam Saccone 	}
336*92022041SSam Saccone 
337*92022041SSam Saccone 	if (type == NL80211_NAN_FUNC_SUBSCRIBE) {
338*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "active") == 0) {
339*92022041SSam Saccone 			argv++;
340*92022041SSam Saccone 			argc--;
341*92022041SSam Saccone 			NLA_PUT_FLAG(func_attrs,
342*92022041SSam Saccone 				     NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE);
343*92022041SSam Saccone 		}
344*92022041SSam Saccone 	}
345*92022041SSam Saccone 
346*92022041SSam Saccone 	if (type == NL80211_NAN_FUNC_PUBLISH) {
347*92022041SSam Saccone 		__u8 publish_type = 0;
348*92022041SSam Saccone 
349*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "solicited") == 0) {
350*92022041SSam Saccone 			argv++;
351*92022041SSam Saccone 			argc--;
352*92022041SSam Saccone 			publish_type |= NL80211_NAN_SOLICITED_PUBLISH;
353*92022041SSam Saccone 		}
354*92022041SSam Saccone 
355*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "unsolicited") == 0) {
356*92022041SSam Saccone 			argv++;
357*92022041SSam Saccone 			argc--;
358*92022041SSam Saccone 			publish_type |= NL80211_NAN_UNSOLICITED_PUBLISH;
359*92022041SSam Saccone 		}
360*92022041SSam Saccone 
361*92022041SSam Saccone 		NLA_PUT_U8(func_attrs, NL80211_NAN_FUNC_PUBLISH_TYPE,
362*92022041SSam Saccone 			   publish_type);
363*92022041SSam Saccone 
364*92022041SSam Saccone 		/* only allow for solicited publish */
365*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "bcast") == 0) {
366*92022041SSam Saccone 			argv++;
367*92022041SSam Saccone 			argc--;
368*92022041SSam Saccone 			if (!(publish_type & NL80211_NAN_SOLICITED_PUBLISH))
369*92022041SSam Saccone 				return -EINVAL;
370*92022041SSam Saccone 
371*92022041SSam Saccone 			NLA_PUT_FLAG(func_attrs,
372*92022041SSam Saccone 				     NL80211_NAN_FUNC_PUBLISH_BCAST);
373*92022041SSam Saccone 		}
374*92022041SSam Saccone 	}
375*92022041SSam Saccone 
376*92022041SSam Saccone 	if (argc > 1 && strcmp(argv[0], "close_range") == 0) {
377*92022041SSam Saccone 		argv++;
378*92022041SSam Saccone 		argc--;
379*92022041SSam Saccone 		NLA_PUT_FLAG(func_attrs, NL80211_NAN_FUNC_CLOSE_RANGE);
380*92022041SSam Saccone 	}
381*92022041SSam Saccone 
382*92022041SSam Saccone 	if (argc > 1 && strcmp(argv[0], "name") == 0) {
383*92022041SSam Saccone 		unsigned char serv_id_c[6] = {0};
384*92022041SSam Saccone 		__u64 service_id;
385*92022041SSam Saccone 
386*92022041SSam Saccone 		argv++;
387*92022041SSam Saccone 		argc--;
388*92022041SSam Saccone 		compute_service_id((const unsigned char *)argv[0],
389*92022041SSam Saccone 				   strlen(argv[0]), serv_id_c);
390*92022041SSam Saccone 		service_id = (__u64)serv_id_c[0] << 0  |
391*92022041SSam Saccone 			     (__u64)serv_id_c[1] << 8  |
392*92022041SSam Saccone 			     (__u64)serv_id_c[2] << 16 |
393*92022041SSam Saccone 			     (__u64)serv_id_c[3] << 24 |
394*92022041SSam Saccone 			     (__u64)serv_id_c[4] << 32 |
395*92022041SSam Saccone 			     (__u64)serv_id_c[5] << 40;
396*92022041SSam Saccone 
397*92022041SSam Saccone 		NLA_PUT(func_attrs, NL80211_NAN_FUNC_SERVICE_ID, 6,
398*92022041SSam Saccone 			&service_id);
399*92022041SSam Saccone 		argv++;
400*92022041SSam Saccone 		argc--;
401*92022041SSam Saccone 	} else {
402*92022041SSam Saccone 		return -EINVAL;
403*92022041SSam Saccone 	}
404*92022041SSam Saccone 
405*92022041SSam Saccone 	if (argc > 1 && strcmp(argv[0], "info") == 0) {
406*92022041SSam Saccone 		argv++;
407*92022041SSam Saccone 		argc--;
408*92022041SSam Saccone 		NLA_PUT(func_attrs, NL80211_NAN_FUNC_SERVICE_INFO,
409*92022041SSam Saccone 			strlen(argv[0]), argv[0]);
410*92022041SSam Saccone 		argv++;
411*92022041SSam Saccone 		argc--;
412*92022041SSam Saccone 	}
413*92022041SSam Saccone 
414*92022041SSam Saccone 	if (type == NL80211_NAN_FUNC_FOLLOW_UP) {
415*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "flw_up_id") == 0) {
416*92022041SSam Saccone 			argv++;
417*92022041SSam Saccone 			argc--;
418*92022041SSam Saccone 			NLA_PUT_U8(func_attrs, NL80211_NAN_FUNC_FOLLOW_UP_ID,
419*92022041SSam Saccone 				   atoi(argv[0]));
420*92022041SSam Saccone 			argv++;
421*92022041SSam Saccone 			argc--;
422*92022041SSam Saccone 		}
423*92022041SSam Saccone 
424*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "flw_up_req_id") == 0) {
425*92022041SSam Saccone 			argv++;
426*92022041SSam Saccone 			argc--;
427*92022041SSam Saccone 			NLA_PUT_U8(func_attrs,
428*92022041SSam Saccone 				   NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID,
429*92022041SSam Saccone 				   atoi(argv[0]));
430*92022041SSam Saccone 			argv++;
431*92022041SSam Saccone 			argc--;
432*92022041SSam Saccone 		}
433*92022041SSam Saccone 
434*92022041SSam Saccone 		if (argc > 1 && strcmp(argv[0], "flw_up_dest") == 0) {
435*92022041SSam Saccone 			unsigned char addr[6];
436*92022041SSam Saccone 
437*92022041SSam Saccone 			argv++;
438*92022041SSam Saccone 			argc--;
439*92022041SSam Saccone 			if (mac_addr_a2n(addr, argv[0]))
440*92022041SSam Saccone 				goto nla_put_failure;
441*92022041SSam Saccone 			nla_put(func_attrs, NL80211_NAN_FUNC_FOLLOW_UP_DEST,
442*92022041SSam Saccone 				ETH_ALEN, addr);
443*92022041SSam Saccone 			argv++;
444*92022041SSam Saccone 			argc--;
445*92022041SSam Saccone 		}
446*92022041SSam Saccone 	}
447*92022041SSam Saccone 
448*92022041SSam Saccone 	if (type != NL80211_NAN_FUNC_FOLLOW_UP &&
449*92022041SSam Saccone 	    argc > 1 && strcmp(argv[0], "ttl") == 0) {
450*92022041SSam Saccone 		argv++;
451*92022041SSam Saccone 		argc--;
452*92022041SSam Saccone 		NLA_PUT_U32(func_attrs, NL80211_NAN_FUNC_TTL, atoi(argv[0]));
453*92022041SSam Saccone 		argv++;
454*92022041SSam Saccone 		argc--;
455*92022041SSam Saccone 	}
456*92022041SSam Saccone 
457*92022041SSam Saccone 	if (type != NL80211_NAN_FUNC_FOLLOW_UP &&
458*92022041SSam Saccone 	    argc >= 4 && strcmp(argv[0], "srf") == 0) {
459*92022041SSam Saccone 		int res;
460*92022041SSam Saccone 
461*92022041SSam Saccone 		argv++;
462*92022041SSam Saccone 		argc--;
463*92022041SSam Saccone 		res = parse_srf(argv, argc, func_attrs);
464*92022041SSam Saccone 		if (res < 0)
465*92022041SSam Saccone 			return -EINVAL;
466*92022041SSam Saccone 
467*92022041SSam Saccone 		argc -= res;
468*92022041SSam Saccone 		argv += res;
469*92022041SSam Saccone 	}
470*92022041SSam Saccone 
471*92022041SSam Saccone 	if (type != NL80211_NAN_FUNC_FOLLOW_UP &&
472*92022041SSam Saccone 	    argc > 1 && strcmp(argv[0], "rx_filter") == 0) {
473*92022041SSam Saccone 		argv++;
474*92022041SSam Saccone 		argc--;
475*92022041SSam Saccone 		parse_match_filter(argv[0], func_attrs, 0);
476*92022041SSam Saccone 
477*92022041SSam Saccone 		argv++;
478*92022041SSam Saccone 		argc--;
479*92022041SSam Saccone 	}
480*92022041SSam Saccone 
481*92022041SSam Saccone 	if (type != NL80211_NAN_FUNC_FOLLOW_UP &&
482*92022041SSam Saccone 	    argc > 1 && strcmp(argv[0], "tx_filter") == 0) {
483*92022041SSam Saccone 		argv++;
484*92022041SSam Saccone 		argc--;
485*92022041SSam Saccone 		parse_match_filter(argv[0], func_attrs, 1);
486*92022041SSam Saccone 
487*92022041SSam Saccone 		argv++;
488*92022041SSam Saccone 		argc--;
489*92022041SSam Saccone 	}
490*92022041SSam Saccone 
491*92022041SSam Saccone 	if (argc != 0)
492*92022041SSam Saccone 		return -EINVAL;
493*92022041SSam Saccone 
494*92022041SSam Saccone 	nla_put_nested(msg, NL80211_ATTR_NAN_FUNC, func_attrs);
495*92022041SSam Saccone 	register_handler(print_instance_id_handler, NULL);
496*92022041SSam Saccone 
497*92022041SSam Saccone 	return err;
498*92022041SSam Saccone nla_put_failure:
499*92022041SSam Saccone 	return -ENOBUFS;
500*92022041SSam Saccone out:
501*92022041SSam Saccone 	return err;
502*92022041SSam Saccone }
503*92022041SSam Saccone COMMAND(nan, add_func,
504*92022041SSam Saccone 	"type <publish|subscribe|followup> [active] [solicited] [unsolicited] [bcast] [close_range] name <name> [info <info>] [flw_up_id <id> flw_up_req_id <id> flw_up_dest <mac>] [ttl <ttl>] [srf <include|exclude> <bf|list> [bf_idx] [bf_len] <mac1;mac2...>] [rx_filter <str1:str2...>] [tx_filter <str1:str2...>]",
505*92022041SSam Saccone 	NL80211_CMD_ADD_NAN_FUNCTION, 0, CIB_WDEV,
506*92022041SSam Saccone 	handle_nan_add_func, "");
507