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