xref: /wlan-dirver/utils/sigma-dut/nan.c (revision 8f8e74b5cc5e5f3af68301cca123929a7dfba76d)
1 /*
2  * Sigma Control API DUT (NAN functionality)
3  * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
4  * All Rights Reserved.
5  * Licensed under the Clear BSD license. See README for more details.
6  */
7 
8 #include "sigma_dut.h"
9 #include <sys/stat.h>
10 #include "wpa_ctrl.h"
11 #include "wpa_helpers.h"
12 #include "wifi_hal.h"
13 #include "nan_cert.h"
14 
15 #if NAN_CERT_VERSION >= 2
16 
17 pthread_cond_t gCondition;
18 pthread_mutex_t gMutex;
19 wifi_handle global_wifi_handle;
20 wifi_interface_handle global_interface_handle;
21 static NanSyncStats global_nan_sync_stats;
22 static int nan_state = 0;
23 static int event_anyresponse = 0;
24 static int is_fam = 0;
25 
26 static uint16_t global_ndp_instance_id = 0;
27 static uint16_t global_publish_id = 0;
28 static uint16_t global_subscribe_id = 0;
29 uint16_t global_header_handle = 0;
30 uint32_t global_match_handle = 0;
31 
32 #define DEFAULT_SVC "QNanCluster"
33 #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
34 #define MAC_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
35 #ifndef ETH_ALEN
36 #define ETH_ALEN 6
37 #endif
38 
39 struct sigma_dut *global_dut = NULL;
40 static char global_nan_mac_addr[ETH_ALEN];
41 static char global_peer_mac_addr[ETH_ALEN];
42 static char global_event_resp_buf[1024];
43 static u8 global_publish_service_name[NAN_MAX_SERVICE_NAME_LEN];
44 static u32 global_publish_service_name_len = 0;
45 
46 static int nan_further_availability_tx(struct sigma_dut *dut,
47 				       struct sigma_conn *conn,
48 				       struct sigma_cmd *cmd);
49 static int nan_further_availability_rx(struct sigma_dut *dut,
50 				       struct sigma_conn *conn,
51 				       struct sigma_cmd *cmd);
52 
53 
54 void nan_hex_dump(struct sigma_dut *dut, uint8_t *data, size_t len)
55 {
56 	char buf[512];
57 	uint16_t index;
58 	uint8_t *ptr;
59 	int pos;
60 
61 	memset(buf, 0, sizeof(buf));
62 	ptr = data;
63 	pos = 0;
64 	for (index = 0; index < len; index++) {
65 		pos += sprintf(&(buf[pos]), "%02x ", *ptr++);
66 		if (pos > 508)
67 			break;
68 	}
69 	sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
70 	sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
71 }
72 
73 
74 int nan_parse_hex(unsigned char c)
75 {
76 	if (c >= '0' && c <= '9')
77 		return c - '0';
78 	if (c >= 'a' && c <= 'f')
79 		return c - 'a' + 10;
80 	if (c >= 'A' && c <= 'F')
81 		return c - 'A' + 10;
82 	return 0;
83 }
84 
85 
86 int nan_parse_token(const char *tokenIn, u8 *tokenOut, int *filterLen)
87 {
88 	int total_len = 0, len = 0;
89 	char *saveptr = NULL;
90 
91 	tokenIn = strtok_r((char *) tokenIn, ":", &saveptr);
92 	while (tokenIn != NULL) {
93 		len = strlen(tokenIn);
94 		if (len == 1 && *tokenIn == '*')
95 			len = 0;
96 		tokenOut[total_len++] = (u8) len;
97 		if (len != 0)
98 			memcpy((u8 *) tokenOut + total_len, tokenIn, len);
99 		total_len += len;
100 		tokenIn = strtok_r(NULL, ":", &saveptr);
101 	}
102 	*filterLen = total_len;
103 	return 0;
104 }
105 
106 
107 int nan_parse_mac_address(struct sigma_dut *dut, const char *arg, u8 *addr)
108 {
109 	if (strlen(arg) != 17) {
110 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid mac address %s",
111 				arg);
112 		sigma_dut_print(dut, DUT_MSG_ERROR,
113 				"expected format xx:xx:xx:xx:xx:xx");
114 		return -1;
115 	}
116 
117 	addr[0] = nan_parse_hex(arg[0]) << 4 | nan_parse_hex(arg[1]);
118 	addr[1] = nan_parse_hex(arg[3]) << 4 | nan_parse_hex(arg[4]);
119 	addr[2] = nan_parse_hex(arg[6]) << 4 | nan_parse_hex(arg[7]);
120 	addr[3] = nan_parse_hex(arg[9]) << 4 | nan_parse_hex(arg[10]);
121 	addr[4] = nan_parse_hex(arg[12]) << 4 | nan_parse_hex(arg[13]);
122 	addr[5] = nan_parse_hex(arg[15]) << 4 | nan_parse_hex(arg[16]);
123 
124 	return 0;
125 }
126 
127 
128 int nan_parse_mac_address_list(struct sigma_dut *dut, const char *input,
129 			       u8 *output, u16 max_addr_allowed)
130 {
131 	/*
132 	 * Reads a list of mac address separated by space. Each MAC address
133 	 * should have the format of aa:bb:cc:dd:ee:ff.
134 	 */
135 	char *saveptr;
136 	char *token;
137 	int i = 0;
138 
139 	for (i = 0; i < max_addr_allowed; i++) {
140 		token = strtok_r((i == 0) ? (char *) input : NULL,
141 				 " ", &saveptr);
142 		if (token) {
143 			nan_parse_mac_address(dut, token, output);
144 			output += NAN_MAC_ADDR_LEN;
145 		} else
146 			break;
147 	}
148 
149 	sigma_dut_print(dut, DUT_MSG_INFO, "Num MacAddress:%d", i);
150 
151 	return i;
152 }
153 
154 
155 int nan_parse_hex_string(struct sigma_dut *dut, const char *input,
156 			 u8 *output, int *outputlen)
157 {
158 	int i = 0;
159 	int j = 0;
160 
161 	for (i = 0; i < (int) strlen(input) && j < *outputlen; i += 2) {
162 		output[j] = nan_parse_hex(input[i]);
163 		if (i + 1 < (int) strlen(input)) {
164 			output[j] = ((output[j] << 4) |
165 				     nan_parse_hex(input[i + 1]));
166 		}
167 		j++;
168 	}
169 	*outputlen = j;
170 	sigma_dut_print(dut, DUT_MSG_INFO, "Input:%s inputlen:%d outputlen:%d",
171 			input, (int) strlen(input), (int) *outputlen);
172 	return 0;
173 }
174 
175 
176 int wait(struct timespec abstime)
177 {
178 	struct timeval now;
179 
180 	gettimeofday(&now, NULL);
181 
182 	abstime.tv_sec += now.tv_sec;
183 	if (((abstime.tv_nsec + now.tv_usec * 1000) > 1000 * 1000 * 1000) ||
184 	    (abstime.tv_nsec + now.tv_usec * 1000 < 0)) {
185 		abstime.tv_sec += 1;
186 		abstime.tv_nsec += now.tv_usec * 1000;
187 		abstime.tv_nsec -= 1000 * 1000 * 1000;
188 	} else {
189 		abstime.tv_nsec  += now.tv_usec * 1000;
190 	}
191 
192 	return pthread_cond_timedwait(&gCondition, &gMutex, &abstime);
193 }
194 
195 
196 int nan_cmd_sta_preset_testparameters(struct sigma_dut *dut,
197 				      struct sigma_conn *conn,
198 				      struct sigma_cmd *cmd)
199 {
200 	const char *oper_chan = get_param(cmd, "oper_chn");
201 	const char *pmk = get_param(cmd, "PMK");
202 
203 	if (oper_chan) {
204 		sigma_dut_print(dut, DUT_MSG_INFO, "Operating Channel: %s",
205 				oper_chan);
206 		dut->sta_channel = atoi(oper_chan);
207 	}
208 
209 	if (pmk) {
210 		int pmk_len;
211 
212 		sigma_dut_print(dut, DUT_MSG_INFO, "%s given string pmk: %s",
213 				__func__, pmk);
214 		memset(dut->nan_pmk, 0, NAN_PMK_INFO_LEN);
215 		dut->nan_pmk_len = 0;
216 		pmk_len = NAN_PMK_INFO_LEN;
217 		nan_parse_hex_string(dut, &pmk[2], &dut->nan_pmk[0], &pmk_len);
218 		dut->nan_pmk_len = pmk_len;
219 		sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d",
220 				__func__, dut->nan_pmk_len);
221 		sigma_dut_print(dut, DUT_MSG_INFO, "%s:hex pmk", __func__);
222 		nan_hex_dump(dut, &dut->nan_pmk[0], dut->nan_pmk_len);
223 	}
224 
225 	send_resp(dut, conn, SIGMA_COMPLETE, NULL);
226 	return 0;
227 }
228 
229 
230 void nan_print_further_availability_chan(struct sigma_dut *dut,
231 					 u8 num_chans,
232 					 NanFurtherAvailabilityChannel *fachan)
233 {
234 	int idx;
235 
236 	sigma_dut_print(dut, DUT_MSG_INFO,
237 			"********Printing FurtherAvailabilityChan Info******");
238 	sigma_dut_print(dut, DUT_MSG_INFO, "Numchans:%d", num_chans);
239 	for (idx = 0; idx < num_chans; idx++) {
240 		sigma_dut_print(dut, DUT_MSG_INFO,
241 				"[%d]: NanAvailDuration:%d class_val:%02x channel:%d",
242 				idx, fachan->entry_control,
243 				fachan->class_val, fachan->channel);
244 		sigma_dut_print(dut, DUT_MSG_INFO,
245 				"[%d]: mapid:%d Availability bitmap:%08x",
246 				idx, fachan->mapid,
247 				fachan->avail_interval_bitmap);
248 	}
249 	sigma_dut_print(dut, DUT_MSG_INFO,
250 			"*********************Done**********************");
251 }
252 
253 
254 int sigma_nan_enable(struct sigma_dut *dut, struct sigma_conn *conn,
255 		     struct sigma_cmd *cmd)
256 {
257 	const char *master_pref = get_param(cmd, "MasterPref");
258 	const char *rand_fac = get_param(cmd, "RandFactor");
259 	const char *hop_count = get_param(cmd, "HopCount");
260 	const char *high_tsf = get_param(cmd, "HighTSF");
261 	const char *sdftx_band = get_param(cmd, "SDFTxBand");
262 	const char *oper_chan = get_param(cmd, "oper_chn");
263 	const char *further_avail_ind = get_param(cmd, "FurtherAvailInd");
264 	const char *band = get_param(cmd, "Band");
265 	const char *only_5g = get_param(cmd, "5GOnly");
266 	const char *nan_availability = get_param(cmd, "NANAvailability");
267 	struct timespec abstime;
268 	NanEnableRequest req;
269 
270 	memset(&req, 0, sizeof(NanEnableRequest));
271 	req.cluster_low = 0;
272 	req.cluster_high = 0xFFFF;
273 	req.master_pref = 100;
274 
275 	/* This is a debug hack to beacon in channel 11 */
276 	if (oper_chan) {
277 		req.config_2dot4g_support = 1;
278 		req.support_2dot4g_val = 111;
279 	}
280 
281 	if (master_pref) {
282 		int master_pref_val = strtoul(master_pref, NULL, 0);
283 
284 		req.master_pref = master_pref_val;
285 	}
286 
287 	if (rand_fac) {
288 		int rand_fac_val = strtoul(rand_fac, NULL, 0);
289 
290 		req.config_random_factor_force = 1;
291 		req.random_factor_force_val = rand_fac_val;
292 	}
293 
294 	if (hop_count) {
295 		int hop_count_val = strtoul(hop_count, NULL, 0);
296 
297 		req.config_hop_count_force = 1;
298 		req.hop_count_force_val = hop_count_val;
299 	}
300 
301 	if (sdftx_band) {
302 		if (strcasecmp(sdftx_band, "5G") == 0) {
303 			req.config_2dot4g_support = 1;
304 			req.support_2dot4g_val = 0;
305 		}
306 	}
307 
308 	sigma_dut_print(dut, DUT_MSG_INFO,
309 			"%s: Setting dual band 2.4 GHz and 5 GHz by default",
310 			__func__);
311 	/* Enable 2.4 GHz support */
312 	req.config_2dot4g_support = 1;
313 	req.support_2dot4g_val = 1;
314 	req.config_2dot4g_beacons = 1;
315 	req.beacon_2dot4g_val = 1;
316 	req.config_2dot4g_sdf = 1;
317 	req.sdf_2dot4g_val = 1;
318 
319 	/* Enable 5 GHz support */
320 	req.config_support_5g = 1;
321 	req.support_5g_val = 1;
322 	req.config_5g_beacons = 1;
323 	req.beacon_5g_val = 1;
324 	req.config_5g_sdf = 1;
325 	req.sdf_5g_val = 1;
326 
327 	if (band) {
328 		if (strcasecmp(band, "24G") == 0) {
329 			sigma_dut_print(dut, DUT_MSG_INFO,
330 					"Band 2.4 GHz selected, disable 5 GHz");
331 			/* Disable 5G support */
332 			req.config_support_5g = 1;
333 			req.support_5g_val = 0;
334 			req.config_5g_beacons = 1;
335 			req.beacon_5g_val = 0;
336 			req.config_5g_sdf = 1;
337 			req.sdf_5g_val = 0;
338 		}
339 	}
340 
341 	if (further_avail_ind) {
342 		sigma_dut_print(dut, DUT_MSG_INFO, "FAM Test Enabled");
343 		if (strcasecmp(further_avail_ind, "tx") == 0) {
344 			is_fam = 1;
345 			nan_further_availability_tx(dut, conn, cmd);
346 			return 0;
347 		} else if (strcasecmp(further_avail_ind, "rx") == 0) {
348 			nan_further_availability_rx(dut, conn, cmd);
349 			return 0;
350 		}
351 	}
352 
353 	if (only_5g && atoi(only_5g)) {
354 		sigma_dut_print(dut, DUT_MSG_INFO, "5GHz only enabled");
355 		req.config_2dot4g_support = 1;
356 		req.support_2dot4g_val = 1;
357 		req.config_2dot4g_beacons = 1;
358 		req.beacon_2dot4g_val = 0;
359 		req.config_2dot4g_sdf = 1;
360 		req.sdf_2dot4g_val = 1;
361 	}
362 
363 	nan_enable_request(0, global_interface_handle, &req);
364 
365 	if (nan_availability) {
366 		int cmd_len, size;
367 		NanDebugParams cfg_debug;
368 
369 		sigma_dut_print(dut, DUT_MSG_INFO,
370 				"%s given string nan_availability: %s",
371 				__func__, nan_availability);
372 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
373 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_AVAILABILITY;
374 		size = NAN_MAX_DEBUG_MESSAGE_DATA_LEN;
375 		nan_parse_hex_string(dut, &nan_availability[2],
376 				     &cfg_debug.debug_cmd_data[0], &size);
377 		sigma_dut_print(dut, DUT_MSG_INFO, "%s:hex nan_availability",
378 				__func__);
379 		nan_hex_dump(dut, &cfg_debug.debug_cmd_data[0], size);
380 		cmd_len = size + sizeof(u32);
381 		nan_debug_command_config(0, global_interface_handle,
382 					 cfg_debug, cmd_len);
383 	}
384 
385 	/* To ensure sta_get_events to get the events
386 	 * only after joining the NAN cluster. */
387 	abstime.tv_sec = 30;
388 	abstime.tv_nsec = 0;
389 	wait(abstime);
390 
391 	return 0;
392 }
393 
394 
395 int sigma_nan_disable(struct sigma_dut *dut, struct sigma_conn *conn,
396 		      struct sigma_cmd *cmd)
397 {
398 	struct timespec abstime;
399 
400 	nan_disable_request(0, global_interface_handle);
401 
402 	abstime.tv_sec = 4;
403 	abstime.tv_nsec = 0;
404 	wait(abstime);
405 
406 	return 0;
407 }
408 
409 
410 int sigma_nan_config_enable(struct sigma_dut *dut, struct sigma_conn *conn,
411 			    struct sigma_cmd *cmd)
412 {
413 	const char *master_pref = get_param(cmd, "MasterPref");
414 	const char *rand_fac = get_param(cmd, "RandFactor");
415 	const char *hop_count = get_param(cmd, "HopCount");
416 	wifi_error ret;
417 	struct timespec abstime;
418 	NanConfigRequest req;
419 
420 	memset(&req, 0, sizeof(NanConfigRequest));
421 	req.config_rssi_proximity = 1;
422 	req.rssi_proximity = 70;
423 
424 	if (master_pref) {
425 		int master_pref_val = strtoul(master_pref, NULL, 0);
426 
427 		req.config_master_pref = 1;
428 		req.master_pref = master_pref_val;
429 	}
430 
431 	if (rand_fac) {
432 		int rand_fac_val = strtoul(rand_fac, NULL, 0);
433 
434 		req.config_random_factor_force = 1;
435 		req.random_factor_force_val = rand_fac_val;
436 	}
437 
438 	if (hop_count) {
439 		int hop_count_val = strtoul(hop_count, NULL, 0);
440 
441 		req.config_hop_count_force = 1;
442 		req.hop_count_force_val = hop_count_val;
443 	}
444 
445 	ret = nan_config_request(0, global_interface_handle, &req);
446 	if (ret != WIFI_SUCCESS)
447 		send_resp(dut, conn, SIGMA_ERROR, "NAN config request failed");
448 
449 	abstime.tv_sec = 4;
450 	abstime.tv_nsec = 0;
451 	wait(abstime);
452 
453 	return 0;
454 }
455 
456 
457 static int sigma_nan_subscribe_request(struct sigma_dut *dut,
458 				       struct sigma_conn *conn,
459 				       struct sigma_cmd *cmd)
460 {
461 	const char *subscribe_type = get_param(cmd, "SubscribeType");
462 	const char *service_name = get_param(cmd, "ServiceName");
463 	const char *disc_range = get_param(cmd, "DiscoveryRange");
464 	const char *rx_match_filter = get_param(cmd, "rxMatchFilter");
465 	const char *tx_match_filter = get_param(cmd, "txMatchFilter");
466 	const char *sdftx_dw = get_param(cmd, "SDFTxDW");
467 	const char *discrange_ltd = get_param(cmd, "DiscRangeLtd");
468 	const char *include_bit = get_param(cmd, "IncludeBit");
469 	const char *mac = get_param(cmd, "MAC");
470 	const char *srf_type = get_param(cmd, "SRFType");
471 	const char *awake_dw_interval = get_param(cmd, "awakeDWint");
472 	NanSubscribeRequest req;
473 	NanConfigRequest config_req;
474 	int filter_len_rx = 0, filter_len_tx = 0;
475 	u8 input_rx[NAN_MAX_MATCH_FILTER_LEN];
476 	u8 input_tx[NAN_MAX_MATCH_FILTER_LEN];
477 	wifi_error ret;
478 
479 	memset(&req, 0, sizeof(NanSubscribeRequest));
480 	memset(&config_req, 0, sizeof(NanConfigRequest));
481 	req.ttl = 0;
482 	req.period = 1;
483 	req.subscribe_type = 1;
484 	req.serviceResponseFilter = 1; /* MAC */
485 	req.serviceResponseInclude = 0;
486 	req.ssiRequiredForMatchIndication = 0;
487 	req.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS;
488 	req.subscribe_count = 0;
489 
490 	if (subscribe_type) {
491 		if (strcasecmp(subscribe_type, "Active") == 0) {
492 			req.subscribe_type = 1;
493 		} else if (strcasecmp(subscribe_type, "Passive") == 0) {
494 			req.subscribe_type = 0;
495 		} else if (strcasecmp(subscribe_type, "Cancel") == 0) {
496 			NanSubscribeCancelRequest req;
497 
498 			memset(&req, 0, sizeof(NanSubscribeCancelRequest));
499 			ret = nan_subscribe_cancel_request(
500 				0, global_interface_handle, &req);
501 			if (ret != WIFI_SUCCESS) {
502 				send_resp(dut, conn, SIGMA_ERROR,
503 					  "NAN subscribe cancel request failed");
504 			}
505 			return 0;
506 		}
507 	}
508 
509 	if (disc_range)
510 		req.rssi_threshold_flag = atoi(disc_range);
511 
512 	if (sdftx_dw)
513 		req.subscribe_count = atoi(sdftx_dw);
514 
515 	/* Check this once again if config can be called here (TBD) */
516 	if (discrange_ltd)
517 		req.rssi_threshold_flag = atoi(discrange_ltd);
518 
519 	if (include_bit) {
520 		int include_bit_val = atoi(include_bit);
521 
522 		req.serviceResponseInclude = include_bit_val;
523 		sigma_dut_print(dut, DUT_MSG_INFO, "Includebit set %d",
524 				req.serviceResponseInclude);
525 	}
526 
527 	if (srf_type) {
528 		int srf_type_val = atoi(srf_type);
529 
530 		if (srf_type_val == 1)
531 			req.serviceResponseFilter = 0; /* Bloom */
532 		else
533 			req.serviceResponseFilter = 1; /* MAC */
534 		req.useServiceResponseFilter = 1;
535 		sigma_dut_print(dut, DUT_MSG_INFO, "srfFilter %d",
536 				req.serviceResponseFilter);
537 	}
538 
539 	if (mac) {
540 		sigma_dut_print(dut, DUT_MSG_INFO, "MAC_ADDR List %s", mac);
541 		req.num_intf_addr_present = nan_parse_mac_address_list(
542 			dut, mac, &req.intf_addr[0][0],
543 			NAN_MAX_SUBSCRIBE_MAX_ADDRESS);
544 	}
545 
546 	memset(input_rx, 0, sizeof(input_rx));
547 	memset(input_tx, 0, sizeof(input_tx));
548 	if (rx_match_filter) {
549 		nan_parse_token(rx_match_filter, input_rx, &filter_len_rx);
550 		sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d",
551 				filter_len_rx);
552 	}
553 	if (tx_match_filter) {
554 		nan_parse_token(tx_match_filter, input_tx, &filter_len_tx);
555 		sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d",
556 				filter_len_tx);
557 	}
558 
559 	if (tx_match_filter) {
560 		req.tx_match_filter_len = filter_len_tx;
561 		memcpy(req.tx_match_filter, input_tx, filter_len_tx);
562 		nan_hex_dump(dut, req.tx_match_filter, filter_len_tx);
563 	}
564 	if (rx_match_filter) {
565 		req.rx_match_filter_len = filter_len_rx;
566 		memcpy(req.rx_match_filter, input_rx, filter_len_rx);
567 		nan_hex_dump(dut, req.rx_match_filter, filter_len_rx);
568 	}
569 
570 	if (service_name) {
571 		strlcpy((char *) req.service_name, service_name,
572 			strlen(service_name) + 1);
573 		req.service_name_len = strlen(service_name);
574 	}
575 
576 	if (awake_dw_interval) {
577 		int input_dw_interval_val = atoi(awake_dw_interval);
578 		int awake_dw_int = 0;
579 
580 		if (input_dw_interval_val > NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL) {
581 			sigma_dut_print(dut, DUT_MSG_INFO,
582 					"%s: input active dw interval = %d overwritting dw interval to Max allowed dw interval 16",
583 					__func__, input_dw_interval_val);
584 			input_dw_interval_val =
585 				NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL;
586 		}
587 		sigma_dut_print(dut, DUT_MSG_INFO,
588 				"%s: input active DW interval = %d",
589 				__func__, input_dw_interval_val);
590 		/*
591 		 * Indicates the interval for Sync beacons and SDF's in 2.4 GHz
592 		 * or 5 GHz band. Valid values of DW Interval are: 1, 2, 3, 4,
593 		 * and 5; 0 is reserved. The SDF includes in OTA when enabled.
594 		 * The publish/subscribe period values don't override the device
595 		 * level configurations.
596 		 * input_dw_interval_val is provided by the user are in the
597 		 * format 2^n-1 = 1/2/4/8/16. Internal implementation expects n
598 		 * to be passed to indicate the awake_dw_interval.
599 		 */
600 		if (input_dw_interval_val == 1 ||
601 		    input_dw_interval_val % 2 == 0) {
602 			while (input_dw_interval_val > 0) {
603 				input_dw_interval_val >>= 1;
604 				awake_dw_int++;
605 			}
606 		}
607 		sigma_dut_print(dut, DUT_MSG_INFO,
608 				"%s:converted active DW interval = %d",
609 				__func__, awake_dw_int);
610 		config_req.config_dw.config_2dot4g_dw_band = 1;
611 		config_req.config_dw.dw_2dot4g_interval_val = awake_dw_int;
612 		config_req.config_dw.config_5g_dw_band = 1;
613 		config_req.config_dw.dw_5g_interval_val = awake_dw_int;
614 		ret = nan_config_request(0, global_interface_handle,
615 					 &config_req);
616 		if (ret != WIFI_SUCCESS) {
617 			sigma_dut_print(dut, DUT_MSG_ERROR,
618 					"%s:NAN config request failed",
619 					__func__);
620 			return -2;
621 		}
622 	}
623 
624 	ret = nan_subscribe_request(0, global_interface_handle, &req);
625 	if (ret != WIFI_SUCCESS) {
626 		send_resp(dut, conn, SIGMA_ERROR,
627 			  "NAN subscribe request failed");
628 	}
629 
630 	return 0;
631 }
632 
633 
634 static int sigma_ndp_configure_band(struct sigma_dut *dut,
635 				    struct sigma_conn *conn,
636 				    struct sigma_cmd *cmd,
637 				    NdpSupportedBand band_config_val)
638 {
639 	wifi_error ret;
640 	NanDebugParams cfg_debug;
641 	int size;
642 
643 	memset(&cfg_debug, 0, sizeof(NanDebugParams));
644 	cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SUPPORTED_BANDS;
645 	memcpy(cfg_debug.debug_cmd_data, &band_config_val, sizeof(int));
646 	sigma_dut_print(dut, DUT_MSG_INFO, "%s:setting debug cmd=0x%x",
647 			__func__, cfg_debug.cmd);
648 	size = sizeof(u32) + sizeof(int);
649 	ret = nan_debug_command_config(0, global_interface_handle, cfg_debug,
650 				       size);
651 	if (ret != WIFI_SUCCESS)
652 		send_resp(dut, conn, SIGMA_ERROR, "Nan config request failed");
653 
654 	return 0;
655 }
656 
657 
658 static int sigma_nan_data_request(struct sigma_dut *dut,
659 				  struct sigma_conn *conn,
660 				  struct sigma_cmd *cmd)
661 {
662 	const char *ndp_security = get_param(cmd, "DataPathSecurity");
663 	const char *ndp_resp_mac = get_param(cmd, "RespNanMac");
664 	const char *include_immutable = get_param(cmd, "includeimmutable");
665 	const char *avoid_channel = get_param(cmd, "avoidchannel");
666 	const char *invalid_nan_schedule = get_param(cmd, "InvalidNANSchedule");
667 	const char *map_order = get_param(cmd, "maporder");
668 #if NAN_CERT_VERSION >= 3
669 	const char *qos_config = get_param(cmd, "QoS");
670 #endif
671 	wifi_error ret;
672 	NanDataPathInitiatorRequest init_req;
673 	NanDebugParams cfg_debug;
674 	int size;
675 
676 	memset(&init_req, 0, sizeof(NanDataPathInitiatorRequest));
677 
678 	if (ndp_security) {
679 		if (strcasecmp(ndp_security, "open") == 0)
680 			init_req.ndp_cfg.security_cfg =
681 				NAN_DP_CONFIG_NO_SECURITY;
682 		else if (strcasecmp(ndp_security, "secure") == 0)
683 			init_req.ndp_cfg.security_cfg = NAN_DP_CONFIG_SECURITY;
684 	}
685 
686 	if (include_immutable) {
687 		int include_immutable_val = 0;
688 
689 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
690 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NDP_INCLUDE_IMMUTABLE;
691 		include_immutable_val = atoi(include_immutable);
692 		memcpy(cfg_debug.debug_cmd_data, &include_immutable_val,
693 		       sizeof(int));
694 		size = sizeof(u32) + sizeof(int);
695 		nan_debug_command_config(0, global_interface_handle,
696 		cfg_debug, size);
697 	}
698 
699 	if (avoid_channel) {
700 		int avoid_channel_freq = 0;
701 
702 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
703 		avoid_channel_freq = channel_to_freq(atoi(avoid_channel));
704 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NDP_AVOID_CHANNEL;
705 		memcpy(cfg_debug.debug_cmd_data, &avoid_channel_freq,
706 		       sizeof(int));
707 		size = sizeof(u32) + sizeof(int);
708 		nan_debug_command_config(0, global_interface_handle,
709 					 cfg_debug, size);
710 	}
711 
712 	if (invalid_nan_schedule) {
713 		int invalid_nan_schedule_type = 0;
714 
715 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
716 		invalid_nan_schedule_type = atoi(invalid_nan_schedule);
717 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_TYPE;
718 		memcpy(cfg_debug.debug_cmd_data,
719 		       &invalid_nan_schedule_type, sizeof(int));
720 		size = sizeof(u32) + sizeof(int);
721 		sigma_dut_print(dut, DUT_MSG_INFO,
722 				"%s: invalid schedule type: cmd type = %d and command data = %d",
723 				__func__, cfg_debug.cmd,
724 				invalid_nan_schedule_type);
725 		nan_debug_command_config(0, global_interface_handle,
726 					 cfg_debug, size);
727 	}
728 
729 	if (map_order) {
730 		int map_order_val = 0;
731 
732 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
733 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_AVAILABILITY_MAP_ORDER;
734 		map_order_val = atoi(map_order);
735 		memcpy(cfg_debug.debug_cmd_data, &map_order_val, sizeof(int));
736 		size = sizeof(u32) + sizeof(int);
737 		sigma_dut_print(dut, DUT_MSG_INFO,
738 				"%s: map order: cmd type = %d and command data = %d",
739 				__func__,
740 				cfg_debug.cmd, map_order_val);
741 		nan_debug_command_config(0, global_interface_handle,
742 					 cfg_debug, size);
743 	}
744 
745 #if NAN_CERT_VERSION >= 3
746 	if (qos_config) {
747 		u32 qos_config_val = 0;
748 
749 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
750 		cfg_debug.cmd = NAN_TEST_MODE_CMD_CONFIG_QOS;
751 		qos_config_val = atoi(qos_config);
752 		memcpy(cfg_debug.debug_cmd_data, &qos_config_val, sizeof(u32));
753 		size = sizeof(u32) + sizeof(u32);
754 		sigma_dut_print(dut, DUT_MSG_INFO,
755 				"%s: qos config: cmd type = %d and command data = %d",
756 				__func__, cfg_debug.cmd, qos_config_val);
757 		nan_debug_command_config(0, global_interface_handle,
758 					 cfg_debug, size);
759 	}
760 #endif
761 
762 	/*
763 	 * Setting this flag, so that interface for ping6 command
764 	 * is set appropriately in traffic_send_ping().
765 	 */
766 	dut->ndp_enable = 1;
767 
768 	/*
769 	 * Intended sleep after NAN data interface create
770 	 * before the NAN data request
771 	 */
772 	sleep(4);
773 
774 	init_req.requestor_instance_id = global_match_handle;
775 	strlcpy((char *) init_req.ndp_iface, "nan0",
776 		sizeof(init_req.ndp_iface));
777 
778 	if (ndp_resp_mac) {
779 		nan_parse_mac_address(dut, ndp_resp_mac,
780 				      init_req.peer_disc_mac_addr);
781 		sigma_dut_print(
782 			dut, DUT_MSG_INFO, "PEER MAC ADDR: " MAC_ADDR_STR,
783 			MAC_ADDR_ARRAY(init_req.peer_disc_mac_addr));
784 	} else {
785 		memcpy(init_req.peer_disc_mac_addr, global_peer_mac_addr,
786 		       sizeof(init_req.peer_disc_mac_addr));
787 	}
788 
789 	/* Not requesting the channel and letting FW decide */
790 	if (dut->sta_channel == 0) {
791 		init_req.channel_request_type = NAN_DP_CHANNEL_NOT_REQUESTED;
792 		init_req.channel = 0;
793 	} else {
794 		init_req.channel_request_type = NAN_DP_FORCE_CHANNEL_SETUP;
795 		init_req.channel = channel_to_freq(dut->sta_channel);
796 	}
797 	sigma_dut_print(dut, DUT_MSG_INFO,
798 			"%s: Initiator Request: Channel = %d  Channel Request Type = %d",
799 			__func__, init_req.channel,
800 			init_req.channel_request_type);
801 
802 	if (dut->nan_pmk_len == NAN_PMK_INFO_LEN) {
803 		init_req.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
804 		memcpy(&init_req.key_info.body.pmk_info.pmk[0],
805 		       &dut->nan_pmk[0], NAN_PMK_INFO_LEN);
806 		init_req.key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN;
807 		sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d",
808 				__func__,
809 				init_req.key_info.body.pmk_info.pmk_len);
810 	}
811 
812 	ret = nan_data_request_initiator(0, global_interface_handle, &init_req);
813 	if (ret != WIFI_SUCCESS) {
814 		send_resp(dut, conn, SIGMA_ERROR,
815 			  "Unable to initiate nan data request");
816 		return 0;
817 	}
818 
819 	return 0;
820 }
821 
822 
823 static int sigma_nan_data_response(struct sigma_dut *dut,
824 				   struct sigma_conn *conn,
825 				   struct sigma_cmd *cmd)
826 {
827 	const char *ndl_response = get_param(cmd, "NDLresponse");
828 	const char *m4_response_type = get_param(cmd, "M4ResponseType");
829 	wifi_error ret;
830 	NanDebugParams cfg_debug;
831 	int size;
832 
833 	if (ndl_response) {
834 		int auto_responder_mode_val = 0;
835 
836 		sigma_dut_print(dut, DUT_MSG_INFO,
837 				"%s: ndl_response = (%s) is passed",
838 				__func__, ndl_response);
839 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
840 		cfg_debug.cmd = NAN_TEST_MODE_CMD_AUTO_RESPONDER_MODE;
841 		if (strcasecmp(ndl_response, "Auto") == 0) {
842 			auto_responder_mode_val = NAN_DATA_RESPONDER_MODE_AUTO;
843 		} else if (strcasecmp(ndl_response, "Reject") == 0) {
844 			auto_responder_mode_val =
845 				NAN_DATA_RESPONDER_MODE_REJECT;
846 		} else if (strcasecmp(ndl_response, "Accept") == 0) {
847 			auto_responder_mode_val =
848 				NAN_DATA_RESPONDER_MODE_ACCEPT;
849 		} else if (strcasecmp(ndl_response, "Counter") == 0) {
850 			auto_responder_mode_val =
851 				NAN_DATA_RESPONDER_MODE_COUNTER;
852 		} else {
853 			sigma_dut_print(dut, DUT_MSG_ERROR,
854 					"%s: Invalid ndl_response",
855 					__func__);
856 			return 0;
857 		}
858 		memcpy(cfg_debug.debug_cmd_data, &auto_responder_mode_val,
859 		       sizeof(int));
860 		size = sizeof(u32) + sizeof(int);
861 		ret = nan_debug_command_config(0, global_interface_handle,
862 					       cfg_debug, size);
863 		if (ret != WIFI_SUCCESS) {
864 			send_resp(dut, conn, SIGMA_ERROR,
865 				  "Nan config request failed");
866 		}
867 	}
868 
869 	if (m4_response_type) {
870 		int m4_response_type_val = 0;
871 
872 		sigma_dut_print(dut, DUT_MSG_INFO,
873 				"%s: m4_response_type = (%s) is passed",
874 				__func__, m4_response_type);
875 		memset(&cfg_debug, 0, sizeof(NanDebugParams));
876 		cfg_debug.cmd = NAN_TEST_MODE_CMD_M4_RESPONSE_TYPE;
877 		if (strcasecmp(m4_response_type, "Accept") == 0)
878 			m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_ACCEPT;
879 		else if (strcasecmp(m4_response_type, "Reject") == 0)
880 			m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_REJECT;
881 		else if (strcasecmp(m4_response_type, "BadMic") == 0)
882 			m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_BADMIC;
883 
884 		memcpy(cfg_debug.debug_cmd_data, &m4_response_type_val,
885 		       sizeof(int));
886 		size = sizeof(u32) + sizeof(int);
887 		ret = nan_debug_command_config(0, global_interface_handle,
888 					       cfg_debug, size);
889 		if (ret != WIFI_SUCCESS) {
890 			send_resp(dut, conn, SIGMA_ERROR,
891 				  "Nan config request failed");
892 		}
893 	}
894 
895 	return 0;
896 }
897 
898 
899 static int sigma_nan_data_end(struct sigma_dut *dut, struct sigma_cmd *cmd)
900 {
901 	const char *nmf_security_config = get_param(cmd, "Security");
902 	NanDataPathEndRequest req;
903 	NanDebugParams cfg_debug;
904 	int size;
905 
906 	memset(&req, 0, sizeof(NanDataPathEndRequest));
907 	memset(&cfg_debug, 0, sizeof(NanDebugParams));
908 	if (nmf_security_config) {
909 		int nmf_security_config_val = 0;
910 
911 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_NMF_CLEAR_CONFIG;
912 		if (strcasecmp(nmf_security_config, "open") == 0)
913 			nmf_security_config_val = NAN_NMF_CLEAR_ENABLE;
914 		else if (strcasecmp(nmf_security_config, "secure") == 0)
915 			nmf_security_config_val = NAN_NMF_CLEAR_DISABLE;
916 		memcpy(cfg_debug.debug_cmd_data,
917 			&nmf_security_config_val, sizeof(int));
918 		size = sizeof(u32) + sizeof(int);
919 		sigma_dut_print(dut, DUT_MSG_INFO,
920 				"%s: nmf_security_config_val -- cmd type = %d and command data = %d",
921 				__func__, cfg_debug.cmd,
922 				nmf_security_config_val);
923 		nan_debug_command_config(0, global_interface_handle,
924 					 cfg_debug, size);
925 	}
926 
927 	req.num_ndp_instances = 1;
928 	req.ndp_instance_id[0] = global_ndp_instance_id;
929 
930 	nan_data_end(0, global_interface_handle, &req);
931 	return 0;
932 }
933 
934 
935 static int sigma_nan_range_request(struct sigma_dut *dut,
936 				   struct sigma_cmd *cmd)
937 {
938 	const char *dest_mac = get_param(cmd, "destmac");
939 	NanSubscribeRequest req;
940 
941 	memset(&req, 0, sizeof(NanSubscribeRequest));
942 	req.period = 1;
943 	req.subscribe_type = NAN_SUBSCRIBE_TYPE_ACTIVE;
944 	req.serviceResponseFilter = NAN_SRF_ATTR_BLOOM_FILTER;
945 	req.serviceResponseInclude = NAN_SRF_INCLUDE_RESPOND;
946 	req.ssiRequiredForMatchIndication = NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
947 	req.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS;
948 	req.subscribe_count = 0;
949 	strlcpy((char *) req.service_name, DEFAULT_SVC,
950 		NAN_MAX_SERVICE_NAME_LEN);
951 	req.service_name_len = strlen((char *) req.service_name);
952 
953 	req.subscribe_id = global_subscribe_id;
954 	req.sdea_params.ranging_state = 1;
955 	req.sdea_params.range_report = NAN_ENABLE_RANGE_REPORT;
956 	req.range_response_cfg.requestor_instance_id = global_match_handle;
957 	req.range_response_cfg.ranging_response = NAN_RANGE_REQUEST_ACCEPT;
958 	req.ranging_cfg.config_ranging_indications =
959 		NAN_RANGING_INDICATE_CONTINUOUS_MASK;
960 	if (dest_mac) {
961 		nan_parse_mac_address(dut, dest_mac,
962 				      req.range_response_cfg.peer_addr);
963 		sigma_dut_print(
964 			dut, DUT_MSG_INFO, "peer mac addr: " MAC_ADDR_STR,
965 			MAC_ADDR_ARRAY(req.range_response_cfg.peer_addr));
966 	}
967 	nan_subscribe_request(0, global_interface_handle, &req);
968 
969 	return 0;
970 }
971 
972 
973 static int sigma_nan_cancel_range(struct sigma_dut *dut,
974 				  struct sigma_cmd *cmd)
975 {
976 	const char *dest_mac = get_param(cmd, "destmac");
977 	NanPublishRequest req;
978 
979 	memset(&req, 0, sizeof(NanPublishRequest));
980 	req.ttl = 0;
981 	req.period = 1;
982 	req.publish_match_indicator = 1;
983 	req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED;
984 	req.tx_type = NAN_TX_TYPE_BROADCAST;
985 	req.publish_count = 0;
986 	strlcpy((char *) req.service_name, DEFAULT_SVC,
987 		NAN_MAX_SERVICE_NAME_LEN);
988 	req.service_name_len = strlen((char *) req.service_name);
989 	req.publish_id = global_publish_id;
990 	req.range_response_cfg.ranging_response = NAN_RANGE_REQUEST_CANCEL;
991 	if (dest_mac) {
992 		nan_parse_mac_address(dut, dest_mac,
993 				      req.range_response_cfg.peer_addr);
994 		sigma_dut_print(
995 			dut, DUT_MSG_INFO, "peer mac addr: " MAC_ADDR_STR,
996 			MAC_ADDR_ARRAY(req.range_response_cfg.peer_addr));
997 	}
998 	nan_publish_request(0, global_interface_handle, &req);
999 
1000 	return 0;
1001 }
1002 
1003 
1004 static int sigma_nan_schedule_update(struct sigma_dut *dut,
1005 				     struct sigma_cmd *cmd)
1006 {
1007 	const char *schedule_update_type = get_param(cmd, "type");
1008 	const char *channel_availability = get_param(cmd,
1009 						     "ChannelAvailability");
1010 	const char *responder_nmi_mac = get_param(cmd, "ResponderNMI");
1011 	NanDebugParams cfg_debug;
1012 	int size = 0;
1013 
1014 	memset(&cfg_debug, 0, sizeof(NanDebugParams));
1015 
1016 	if (!schedule_update_type)
1017 		return 0;
1018 
1019 	if (strcasecmp(schedule_update_type, "ULWnotify") == 0) {
1020 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_ULW_NOTIFY;
1021 		size = sizeof(u32);
1022 		sigma_dut_print(dut, DUT_MSG_INFO,
1023 				"%s: Schedule Update cmd type = %d", __func__,
1024 				cfg_debug.cmd);
1025 		if (channel_availability) {
1026 			int channel_availability_val;
1027 
1028 			channel_availability_val = atoi(channel_availability);
1029 			size += sizeof(int);
1030 			memcpy(cfg_debug.debug_cmd_data,
1031 			       &channel_availability_val, sizeof(int));
1032 			sigma_dut_print(dut, DUT_MSG_INFO,
1033 					"%s: Schedule Update cmd data = %d size = %d",
1034 					__func__, channel_availability_val,
1035 					size);
1036 		}
1037 	} else if (strcasecmp(schedule_update_type, "NDLnegotiate") == 0) {
1038 		cfg_debug.cmd =
1039 			NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NEGOTIATE;
1040 		size = sizeof(u32);
1041 		sigma_dut_print(dut, DUT_MSG_INFO,
1042 				"%s: Schedule Update cmd type = %d", __func__,
1043 				cfg_debug.cmd);
1044 		if (responder_nmi_mac) {
1045 			u8 responder_nmi_mac_addr[NAN_MAC_ADDR_LEN];
1046 
1047 			nan_parse_mac_address(dut, responder_nmi_mac,
1048 					      responder_nmi_mac_addr);
1049 			size += NAN_MAC_ADDR_LEN;
1050 			memcpy(cfg_debug.debug_cmd_data, responder_nmi_mac_addr,
1051 			       NAN_MAC_ADDR_LEN);
1052 			sigma_dut_print(dut, DUT_MSG_INFO,
1053 					"%s: RESPONDER NMI MAC: "MAC_ADDR_STR,
1054 					__func__,
1055 					MAC_ADDR_ARRAY(responder_nmi_mac_addr));
1056 			sigma_dut_print(dut, DUT_MSG_INFO,
1057 					"%s: Schedule Update: cmd size = %d",
1058 					__func__, size);
1059 		}
1060 	} else if (strcasecmp(schedule_update_type, "NDLnotify") == 0) {
1061 		cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NOTIFY;
1062 		size = sizeof(u32);
1063 		sigma_dut_print(dut, DUT_MSG_INFO,
1064 				"%s: Schedule Update cmd type = %d", __func__,
1065 				cfg_debug.cmd);
1066 	}
1067 
1068 	nan_debug_command_config(0, global_interface_handle, cfg_debug, size);
1069 
1070 	return 0;
1071 }
1072 
1073 
1074 int config_post_disc_attr(void)
1075 {
1076 	wifi_error ret;
1077 	NanConfigRequest configReq;
1078 
1079 	memset(&configReq, 0, sizeof(NanConfigRequest));
1080 
1081 	/* Configure Post disc attr */
1082 	/* Make these defines and use correct enum */
1083 	configReq.num_config_discovery_attr = 1;
1084 	configReq.discovery_attr_val[0].type = 4; /* Further Nan discovery */
1085 	configReq.discovery_attr_val[0].role = 0;
1086 	configReq.discovery_attr_val[0].transmit_freq = 1;
1087 	configReq.discovery_attr_val[0].duration = 0;
1088 	configReq.discovery_attr_val[0].avail_interval_bitmap = 0x00000008;
1089 
1090 	ret = nan_config_request(0, global_interface_handle, &configReq);
1091 	if (ret != WIFI_SUCCESS) {
1092 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1093 				"NAN config request failed while configuring post discovery attribute");
1094 	}
1095 
1096 	return 0;
1097 }
1098 
1099 
1100 int sigma_nan_publish_request(struct sigma_dut *dut, struct sigma_conn *conn,
1101 			      struct sigma_cmd *cmd)
1102 {
1103 	const char *publish_type = get_param(cmd, "PublishType");
1104 	const char *service_name = get_param(cmd, "ServiceName");
1105 	const char *disc_range = get_param(cmd, "DiscoveryRange");
1106 	const char *rx_match_filter = get_param(cmd, "rxMatchFilter");
1107 	const char *tx_match_filter = get_param(cmd, "txMatchFilter");
1108 	const char *sdftx_dw = get_param(cmd, "SDFTxDW");
1109 	const char *discrange_ltd = get_param(cmd, "DiscRangeLtd");
1110 	const char *ndp_enable = get_param(cmd, "DataPathFlag");
1111 	const char *ndp_type = get_param(cmd, "DataPathType");
1112 	const char *data_path_security = get_param(cmd, "datapathsecurity");
1113 	const char *range_required = get_param(cmd, "rangerequired");
1114 	const char *awake_dw_interval = get_param(cmd, "awakeDWint");
1115 #if NAN_CERT_VERSION >= 3
1116 	const char *qos_config = get_param(cmd, "QoS");
1117 #endif
1118 	NanPublishRequest req;
1119 	NanConfigRequest config_req;
1120 	int filter_len_rx = 0, filter_len_tx = 0;
1121 	u8 input_rx[NAN_MAX_MATCH_FILTER_LEN];
1122 	u8 input_tx[NAN_MAX_MATCH_FILTER_LEN];
1123 	wifi_error ret;
1124 
1125 	memset(&req, 0, sizeof(NanPublishRequest));
1126 	memset(&config_req, 0, sizeof(NanConfigRequest));
1127 	req.ttl = 0;
1128 	req.period = 1;
1129 	req.publish_match_indicator = 1;
1130 	req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED;
1131 	req.tx_type = NAN_TX_TYPE_BROADCAST;
1132 	req.publish_count = 0;
1133 	req.service_responder_policy = NAN_SERVICE_ACCEPT_POLICY_ALL;
1134 
1135 	if (global_publish_service_name_len &&
1136 	    service_name &&
1137 	    strcasecmp((char *) global_publish_service_name,
1138 		       service_name) == 0 &&
1139 	    global_publish_id) {
1140 		req.publish_id = global_publish_id;
1141 		sigma_dut_print(dut, DUT_MSG_INFO,
1142 				"%s: updating publish_id = %d in publish request",
1143 				__func__, req.publish_id);
1144 	}
1145 
1146 	if (service_name) {
1147 		strlcpy((char *) req.service_name, service_name,
1148 			sizeof(req.service_name));
1149 		req.service_name_len = strlen((char *) req.service_name);
1150 		strlcpy((char *) global_publish_service_name, service_name,
1151 			sizeof(global_publish_service_name));
1152 		global_publish_service_name_len =
1153 			strlen((char *) global_publish_service_name);
1154 	}
1155 
1156 	if (publish_type) {
1157 		if (strcasecmp(publish_type, "Solicited") == 0) {
1158 			req.publish_type = NAN_PUBLISH_TYPE_SOLICITED;
1159 		} else if (strcasecmp(publish_type, "Unsolicited") == 0) {
1160 			req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED;
1161 		} else if (strcasecmp(publish_type, "Cancel") == 0) {
1162 			NanPublishCancelRequest req;
1163 
1164 			memset(&req, 0, sizeof(NanPublishCancelRequest));
1165 			ret = nan_publish_cancel_request(
1166 				0, global_interface_handle, &req);
1167 			if (ret != WIFI_SUCCESS) {
1168 				send_resp(dut, conn, SIGMA_ERROR,
1169 					  "Unable to cancel nan publish request");
1170 			}
1171 			return 0;
1172 		}
1173 	}
1174 
1175 	if (disc_range)
1176 		req.rssi_threshold_flag = atoi(disc_range);
1177 
1178 	if (sdftx_dw)
1179 		req.publish_count = atoi(sdftx_dw);
1180 
1181 	if (discrange_ltd)
1182 		req.rssi_threshold_flag = atoi(discrange_ltd);
1183 
1184 	memset(input_rx, 0, sizeof(input_rx));
1185 	memset(input_tx, 0, sizeof(input_tx));
1186 	if (rx_match_filter) {
1187 		nan_parse_token(rx_match_filter, input_rx, &filter_len_rx);
1188 		sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d",
1189 				filter_len_rx);
1190 	}
1191 	if (tx_match_filter) {
1192 		nan_parse_token(tx_match_filter, input_tx, &filter_len_tx);
1193 		sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d",
1194 				filter_len_tx);
1195 	}
1196 
1197 	if (is_fam == 1) {
1198 		config_post_disc_attr();
1199 		/*
1200 		 * 8-bit bitmap which allows the Host to associate this publish
1201 		 * with a particular Post-NAN Connectivity attribute which has
1202 		 * been sent down in a NanConfigureRequest/NanEnableRequest
1203 		 * message. If the DE fails to find a configured Post-NAN
1204 		 * connectivity attributes referenced by the bitmap, the DE will
1205 		 * return an error code to the Host. If the Publish is
1206 		 * configured to use a Post-NAN Connectivity attribute and the
1207 		 * Host does not refresh the Post-NAN Connectivity attribute the
1208 		 * Publish will be canceled and the Host will be sent a
1209 		 * PublishTerminatedIndication message.
1210 		 */
1211 		req.connmap = 0x10;
1212 	}
1213 
1214 	if (tx_match_filter) {
1215 		req.tx_match_filter_len = filter_len_tx;
1216 		memcpy(req.tx_match_filter, input_tx, filter_len_tx);
1217 		nan_hex_dump(dut, req.tx_match_filter, filter_len_tx);
1218 	}
1219 
1220 	if (rx_match_filter) {
1221 		req.rx_match_filter_len = filter_len_rx;
1222 		memcpy(req.rx_match_filter, input_rx, filter_len_rx);
1223 		nan_hex_dump(dut, req.rx_match_filter, filter_len_rx);
1224 	}
1225 
1226 	if (service_name) {
1227 		strlcpy((char *) req.service_name, service_name,
1228 			strlen(service_name) + 1);
1229 		req.service_name_len = strlen(service_name);
1230 	}
1231 
1232 	if (ndp_enable) {
1233 		if (strcasecmp(ndp_enable, "enable") == 0)
1234 			req.sdea_params.config_nan_data_path = 1;
1235 		else
1236 			req.sdea_params.config_nan_data_path = 0;
1237 
1238 		if (ndp_type)
1239 			req.sdea_params.ndp_type = atoi(ndp_type);
1240 
1241 		if (data_path_security) {
1242 			if (strcasecmp(data_path_security, "secure") == 0) {
1243 				req.sdea_params.security_cfg =
1244 					NAN_DP_CONFIG_SECURITY;
1245 			} else if (strcasecmp(data_path_security, "open") ==
1246 				   0) {
1247 				req.sdea_params.security_cfg =
1248 					NAN_DP_CONFIG_NO_SECURITY;
1249 			}
1250 		}
1251 
1252 		if (dut->nan_pmk_len == NAN_PMK_INFO_LEN) {
1253 			req.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK;
1254 			memcpy(&req.key_info.body.pmk_info.pmk[0],
1255 				&dut->nan_pmk[0], NAN_PMK_INFO_LEN);
1256 			req.key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN;
1257 			sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d",
1258 			__func__, req.key_info.body.pmk_info.pmk_len);
1259 		}
1260 	}
1261 	if (range_required && strcasecmp(range_required, "enable") == 0) {
1262 		req.sdea_params.ranging_state = NAN_RANGING_ENABLE;
1263 		req.sdea_params.range_report = NAN_ENABLE_RANGE_REPORT;
1264 	}
1265 
1266 	if (awake_dw_interval) {
1267 		int input_dw_interval_val = atoi(awake_dw_interval);
1268 		int awake_dw_int = 0;
1269 
1270 		if (input_dw_interval_val > NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL) {
1271 			sigma_dut_print(dut, DUT_MSG_INFO,
1272 					"%s: input active dw interval = %d overwritting dw interval to Max allowed dw interval 16",
1273 					__func__, input_dw_interval_val);
1274 			input_dw_interval_val =
1275 				NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL;
1276 		}
1277 		sigma_dut_print(dut, DUT_MSG_INFO,
1278 				"%s: input active DW interval = %d",
1279 				__func__, input_dw_interval_val);
1280 		/*
1281 		 * Indicates the interval for Sync beacons and SDF's in 2.4 GHz
1282 		 * or 5 GHz band. Valid values of DW Interval are: 1, 2, 3, 4,
1283 		 * and 5; 0 is reserved. The SDF includes in OTA when enabled.
1284 		 * The publish/subscribe period. values don't override the
1285 		 * device level configurations.
1286 		 * input_dw_interval_val is provided by the user are in the
1287 		 * format 2^n-1 = 1/2/4/8/16. Internal implementation expects n
1288 		 * to be passed to indicate the awake_dw_interval.
1289 		 */
1290 		if (input_dw_interval_val == 1 ||
1291 		    input_dw_interval_val % 2 == 0) {
1292 			while (input_dw_interval_val > 0) {
1293 				input_dw_interval_val >>= 1;
1294 				awake_dw_int++;
1295 			}
1296 		}
1297 		sigma_dut_print(dut, DUT_MSG_INFO,
1298 				"%s:converted active DW interval = %d",
1299 				__func__, awake_dw_int);
1300 		config_req.config_dw.config_2dot4g_dw_band = 1;
1301 		config_req.config_dw.dw_2dot4g_interval_val = awake_dw_int;
1302 		config_req.config_dw.config_5g_dw_band = 1;
1303 		config_req.config_dw.dw_5g_interval_val = awake_dw_int;
1304 		ret = nan_config_request(0, global_interface_handle,
1305 					 &config_req);
1306 		if (ret != WIFI_SUCCESS) {
1307 			sigma_dut_print(dut, DUT_MSG_ERROR,
1308 					"%s:NAN config request failed",
1309 					__func__);
1310 			return -2;
1311 		}
1312 	}
1313 
1314 #if NAN_CERT_VERSION >= 3
1315 	if (qos_config)
1316 		req.sdea_params.qos_cfg = (NanQosCfgStatus) atoi(qos_config);
1317 #endif
1318 
1319 	ret = nan_publish_request(0, global_interface_handle, &req);
1320 	if (ret != WIFI_SUCCESS)
1321 		send_resp(dut, conn, SIGMA_ERROR, "Unable to publish");
1322 
1323 	if (ndp_enable)
1324 		dut->ndp_enable = 1;
1325 
1326 	return 0;
1327 }
1328 
1329 
1330 static int nan_further_availability_rx(struct sigma_dut *dut,
1331 				       struct sigma_conn *conn,
1332 				       struct sigma_cmd *cmd)
1333 {
1334 	const char *master_pref = get_param(cmd, "MasterPref");
1335 	const char *rand_fac = get_param(cmd, "RandFactor");
1336 	const char *hop_count = get_param(cmd, "HopCount");
1337 	wifi_error ret;
1338 	struct timespec abstime;
1339 
1340 	NanEnableRequest req;
1341 
1342 	memset(&req, 0, sizeof(NanEnableRequest));
1343 	req.cluster_low = 0;
1344 	req.cluster_high = 0xFFFF;
1345 	req.master_pref = 30;
1346 
1347 	if (master_pref)
1348 		req.master_pref = strtoul(master_pref, NULL, 0);
1349 
1350 	if (rand_fac) {
1351 		int rand_fac_val = strtoul(rand_fac, NULL, 0);
1352 
1353 		req.config_random_factor_force = 1;
1354 		req.random_factor_force_val = rand_fac_val;
1355 	}
1356 
1357 	if (hop_count) {
1358 		int hop_count_val = strtoul(hop_count, NULL, 0);
1359 
1360 		req.config_hop_count_force = 1;
1361 		req.hop_count_force_val = hop_count_val;
1362 	}
1363 
1364 	ret = nan_enable_request(0, global_interface_handle, &req);
1365 	if (ret != WIFI_SUCCESS) {
1366 		send_resp(dut, conn, SIGMA_ERROR, "Unable to enable nan");
1367 		return 0;
1368 	}
1369 
1370 	abstime.tv_sec = 4;
1371 	abstime.tv_nsec = 0;
1372 	wait(abstime);
1373 
1374 	return 0;
1375 }
1376 
1377 
1378 static int nan_further_availability_tx(struct sigma_dut *dut,
1379 				       struct sigma_conn *conn,
1380 				       struct sigma_cmd *cmd)
1381 {
1382 	const char *master_pref = get_param(cmd, "MasterPref");
1383 	const char *rand_fac = get_param(cmd, "RandFactor");
1384 	const char *hop_count = get_param(cmd, "HopCount");
1385 	wifi_error ret;
1386 
1387 	NanEnableRequest req;
1388 	NanConfigRequest configReq;
1389 
1390 	memset(&req, 0, sizeof(NanEnableRequest));
1391 	req.cluster_low = 0;
1392 	req.cluster_high = 0xFFFF;
1393 	req.master_pref = 30;
1394 
1395 	if (master_pref)
1396 		req.master_pref = strtoul(master_pref, NULL, 0);
1397 
1398 	if (rand_fac) {
1399 		int rand_fac_val = strtoul(rand_fac, NULL, 0);
1400 
1401 		req.config_random_factor_force = 1;
1402 		req.random_factor_force_val = rand_fac_val;
1403 	}
1404 
1405 	if (hop_count) {
1406 		int hop_count_val = strtoul(hop_count, NULL, 0);
1407 
1408 		req.config_hop_count_force = 1;
1409 		req.hop_count_force_val = hop_count_val;
1410 	}
1411 
1412 	ret = nan_enable_request(0, global_interface_handle, &req);
1413 	if (ret != WIFI_SUCCESS) {
1414 		send_resp(dut, conn, SIGMA_ERROR, "Unable to enable nan");
1415 		return 0;
1416 	}
1417 
1418 	/* Start the config of fam */
1419 
1420 	memset(&configReq, 0, sizeof(NanConfigRequest));
1421 
1422 	configReq.config_fam = 1;
1423 	configReq.fam_val.numchans = 1;
1424 	configReq.fam_val.famchan[0].entry_control = 0;
1425 	configReq.fam_val.famchan[0].class_val = 81;
1426 	configReq.fam_val.famchan[0].channel = 6;
1427 	configReq.fam_val.famchan[0].mapid = 0;
1428 	configReq.fam_val.famchan[0].avail_interval_bitmap = 0x7ffffffe;
1429 
1430 	ret = nan_config_request(0, global_interface_handle, &configReq);
1431 	if (ret != WIFI_SUCCESS)
1432 		send_resp(dut, conn, SIGMA_ERROR, "Nan config request failed");
1433 
1434 	return 0;
1435 }
1436 
1437 
1438 int sigma_nan_transmit_followup(struct sigma_dut *dut,
1439 				struct sigma_conn *conn,
1440 				struct sigma_cmd *cmd)
1441 {
1442 	const char *mac = get_param(cmd, "mac");
1443 	const char *requestor_id = get_param(cmd, "RemoteInstanceId");
1444 	const char *local_id = get_param(cmd, "LocalInstanceId");
1445 	const char *service_name = get_param(cmd, "servicename");
1446 	wifi_error ret;
1447 	NanTransmitFollowupRequest req;
1448 
1449 	memset(&req, 0, sizeof(NanTransmitFollowupRequest));
1450 	req.requestor_instance_id = global_match_handle;
1451 	req.addr[0] = 0xFF;
1452 	req.addr[1] = 0xFF;
1453 	req.addr[2] = 0xFF;
1454 	req.addr[3] = 0xFF;
1455 	req.addr[4] = 0xFF;
1456 	req.addr[5] = 0xFF;
1457 	req.priority = NAN_TX_PRIORITY_NORMAL;
1458 	req.dw_or_faw = 0;
1459 
1460 	if (service_name)
1461 		req.service_specific_info_len = strlen(service_name);
1462 
1463 	if (requestor_id) {
1464 		/* int requestor_id_val = atoi(requestor_id); */
1465 		req.requestor_instance_id = global_match_handle;
1466 	}
1467 	if (local_id) {
1468 		/* int local_id_val = atoi(local_id); */
1469 		req.publish_subscribe_id = global_header_handle;
1470 	}
1471 
1472 	if (mac == NULL) {
1473 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid MAC Address");
1474 		return -1;
1475 	}
1476 	nan_parse_mac_address(dut, mac, req.addr);
1477 
1478 	if (requestor_id)
1479 		req.requestor_instance_id = strtoul(requestor_id, NULL, 0);
1480 
1481 	ret = nan_transmit_followup_request(0, global_interface_handle, &req);
1482 	if (ret != WIFI_SUCCESS) {
1483 		send_resp(dut, conn, SIGMA_ERROR,
1484 			  "Unable to complete nan transmit followup");
1485 	}
1486 
1487 	return 0;
1488 }
1489 
1490 
1491 /* NotifyResponse invoked to notify the status of the Request */
1492 void nan_notify_response(transaction_id id, NanResponseMsg *rsp_data)
1493 {
1494 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1495 			"%s: status %d response_type %d",
1496 			__func__, rsp_data->status, rsp_data->response_type);
1497 	if (rsp_data->response_type == NAN_RESPONSE_STATS &&
1498 	    rsp_data->body.stats_response.stats_type ==
1499 	    NAN_STATS_ID_DE_TIMING_SYNC) {
1500 		NanSyncStats *pSyncStats;
1501 
1502 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1503 				"%s: stats_type %d", __func__,
1504 				rsp_data->body.stats_response.stats_type);
1505 		pSyncStats = &rsp_data->body.stats_response.data.sync_stats;
1506 		memcpy(&global_nan_sync_stats, pSyncStats,
1507 		       sizeof(NanSyncStats));
1508 		pthread_cond_signal(&gCondition);
1509 	} else if (rsp_data->response_type == NAN_RESPONSE_PUBLISH) {
1510 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1511 				"%s: publish_id %d\n",
1512 				__func__,
1513 				rsp_data->body.publish_response.publish_id);
1514 		global_publish_id = rsp_data->body.publish_response.publish_id;
1515 	} else if (rsp_data->response_type == NAN_RESPONSE_SUBSCRIBE) {
1516 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1517 				"%s: subscribe_id %d\n",
1518 				__func__,
1519 				rsp_data->body.subscribe_response.subscribe_id);
1520 		global_subscribe_id =
1521 			rsp_data->body.subscribe_response.subscribe_id;
1522 	}
1523 }
1524 
1525 
1526 /* Events Callback */
1527 void nan_event_publish_replied(NanPublishRepliedInd *event)
1528 {
1529 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1530 			"%s: handle %d " MAC_ADDR_STR " rssi:%d",
1531 			__func__, event->requestor_instance_id,
1532 			MAC_ADDR_ARRAY(event->addr), event->rssi_value);
1533 	event_anyresponse = 1;
1534 	snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
1535 		 "EventName,Replied,RemoteInstanceID %d,mac," MAC_ADDR_STR,
1536 		 (event->requestor_instance_id >> 24),
1537 		 MAC_ADDR_ARRAY(event->addr));
1538 }
1539 
1540 
1541 /* Events Callback */
1542 void nan_event_publish_terminated(NanPublishTerminatedInd *event)
1543 {
1544 	sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: publish_id %d reason %d",
1545 			__func__, event->publish_id, event->reason);
1546 }
1547 
1548 
1549 /* Events Callback */
1550 void nan_event_match(NanMatchInd *event)
1551 {
1552 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1553 			"%s: Pub/Sub Id %d remote_requestor_id %08x "
1554 			MAC_ADDR_STR
1555 			" rssi:%d",
1556 			__func__,
1557 			event->publish_subscribe_id,
1558 			event->requestor_instance_id,
1559 			MAC_ADDR_ARRAY(event->addr),
1560 			event->rssi_value);
1561 	event_anyresponse = 1;
1562 	global_header_handle = event->publish_subscribe_id;
1563 	global_match_handle = event->requestor_instance_id;
1564 	memcpy(global_peer_mac_addr, event->addr, sizeof(global_peer_mac_addr));
1565 
1566 	/* memset(event_resp_buf, 0, sizeof(event_resp_buf)); */
1567 	/* global_pub_sub_handle = event->header.handle; */
1568 	/* Print the SSI */
1569 	sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing SSI:");
1570 	nan_hex_dump(global_dut, event->service_specific_info,
1571 		event->service_specific_info_len);
1572 	snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
1573 		 "EventName,DiscoveryResult,RemoteInstanceID,%d,LocalInstanceID,%d,mac,"
1574 		 MAC_ADDR_STR " ", (event->requestor_instance_id >> 24),
1575 		 event->publish_subscribe_id, MAC_ADDR_ARRAY(event->addr));
1576 
1577 	/* Print the match filter */
1578 	sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing sdf match filter:");
1579 	nan_hex_dump(global_dut, event->sdf_match_filter,
1580 		     event->sdf_match_filter_len);
1581 
1582 	/* Print the conn_capability */
1583 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1584 			"Printing PostConnectivity Capability");
1585 	if (event->is_conn_capability_valid) {
1586 		sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfd supported:%s",
1587 				event->conn_capability.is_wfd_supported ?
1588 				"yes" : "no");
1589 		sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfds supported:%s",
1590 				(event->conn_capability.is_wfds_supported ?
1591 				 "yes" : "no"));
1592 		sigma_dut_print(global_dut, DUT_MSG_INFO, "TDLS supported:%s",
1593 				(event->conn_capability.is_tdls_supported ?
1594 				 "yes" : "no"));
1595 		sigma_dut_print(global_dut, DUT_MSG_INFO, "IBSS supported:%s",
1596 				(event->conn_capability.is_ibss_supported ?
1597 				 "yes" : "no"));
1598 		sigma_dut_print(global_dut, DUT_MSG_INFO, "Mesh supported:%s",
1599 				(event->conn_capability.is_mesh_supported ?
1600 				 "yes" : "no"));
1601 		sigma_dut_print(global_dut, DUT_MSG_INFO, "Infra Field:%d",
1602 				event->conn_capability.wlan_infra_field);
1603 	} else {
1604 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1605 				"PostConnectivity Capability not present");
1606 	}
1607 
1608 	/* Print the discovery_attr */
1609 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1610 			"Printing PostDiscovery Attribute");
1611 	if (event->num_rx_discovery_attr) {
1612 		int idx;
1613 
1614 		for (idx = 0; idx < event->num_rx_discovery_attr; idx++) {
1615 			sigma_dut_print(global_dut, DUT_MSG_INFO,
1616 					"PostDiscovery Attribute - %d", idx);
1617 			sigma_dut_print(global_dut, DUT_MSG_INFO,
1618 					"Conn Type:%d Device Role:%d"
1619 					MAC_ADDR_STR,
1620 					event->discovery_attr[idx].type,
1621 					event->discovery_attr[idx].role,
1622 					MAC_ADDR_ARRAY(event->discovery_attr[idx].addr));
1623 			sigma_dut_print(global_dut, DUT_MSG_INFO,
1624 					"Duration:%d MapId:%d "
1625 					"avail_interval_bitmap:%04x",
1626 					event->discovery_attr[idx].duration,
1627 					event->discovery_attr[idx].mapid,
1628 					event->discovery_attr[idx].avail_interval_bitmap);
1629 			sigma_dut_print(global_dut, DUT_MSG_INFO,
1630 					"Printing Mesh Id:");
1631 			nan_hex_dump(global_dut,
1632 				     event->discovery_attr[idx].mesh_id,
1633 				     event->discovery_attr[idx].mesh_id_len);
1634 			sigma_dut_print(global_dut, DUT_MSG_INFO,
1635 					"Printing Infrastructure Ssid:");
1636 			nan_hex_dump(global_dut,
1637 				     event->discovery_attr[idx].infrastructure_ssid_val,
1638 				     event->discovery_attr[idx].infrastructure_ssid_len);
1639 		}
1640 	} else {
1641 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1642 				"PostDiscovery attribute not present");
1643 	}
1644 
1645 	/* Print the fam */
1646 	if (event->num_chans) {
1647 		nan_print_further_availability_chan(global_dut,
1648 						    event->num_chans,
1649 						    &event->famchan[0]);
1650 	} else {
1651 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1652 				"Further Availability Map not present");
1653 	}
1654 	if (event->cluster_attribute_len) {
1655 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1656 				"Printing Cluster Attribute:");
1657 		nan_hex_dump(global_dut, event->cluster_attribute,
1658 			     event->cluster_attribute_len);
1659 	} else {
1660 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1661 				"Cluster Attribute not present");
1662 	}
1663 }
1664 
1665 
1666 /* Events Callback */
1667 void nan_event_match_expired(NanMatchExpiredInd *event)
1668 {
1669 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1670 			"%s: publish_subscribe_id %d match_handle %08x",
1671 			__func__, event->publish_subscribe_id,
1672 			event->requestor_instance_id);
1673 }
1674 
1675 
1676 /* Events Callback */
1677 void nan_event_subscribe_terminated(NanSubscribeTerminatedInd *event)
1678 {
1679 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1680 			"%s: Subscribe Id %d reason %d",
1681 			__func__, event->subscribe_id, event->reason);
1682 }
1683 
1684 
1685 /* Events Callback */
1686 void nan_event_followup(NanFollowupInd *event)
1687 {
1688 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1689 			"%s: Publish/Subscribe Id %d match_handle 0x%08x dw_or_faw %d "
1690 			MAC_ADDR_STR, __func__, event->publish_subscribe_id,
1691 			event->requestor_instance_id, event->dw_or_faw,
1692 			MAC_ADDR_ARRAY(event->addr));
1693 
1694 	global_match_handle = event->publish_subscribe_id;
1695 	global_header_handle = event->requestor_instance_id;
1696 	sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Printing SSI", __func__);
1697 	nan_hex_dump(global_dut, event->service_specific_info,
1698 		     event->service_specific_info_len);
1699 	event_anyresponse = 1;
1700 	snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
1701 		 "EventName,FollowUp,RemoteInstanceID,%d,LocalInstanceID,%d,mac,"
1702 		 MAC_ADDR_STR " ", event->requestor_instance_id >> 24,
1703 		 event->publish_subscribe_id, MAC_ADDR_ARRAY(event->addr));
1704 }
1705 
1706 
1707 /* Events Callback */
1708 void nan_event_disceng_event(NanDiscEngEventInd *event)
1709 {
1710 	sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: event_type %d",
1711 			__func__, event->event_type);
1712 
1713 	if (event->event_type == NAN_EVENT_ID_JOINED_CLUSTER) {
1714 		sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Joined cluster "
1715 				MAC_ADDR_STR,
1716 				__func__,
1717 				MAC_ADDR_ARRAY(event->data.cluster.addr));
1718 		/* To ensure sta_get_events to get the events
1719 		 * only after joining the NAN cluster. */
1720 		pthread_cond_signal(&gCondition);
1721 	}
1722 	if (event->event_type == NAN_EVENT_ID_STARTED_CLUSTER) {
1723 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1724 				"%s: Started cluster " MAC_ADDR_STR,
1725 				__func__,
1726 				MAC_ADDR_ARRAY(event->data.cluster.addr));
1727 	}
1728 	if (event->event_type == NAN_EVENT_ID_DISC_MAC_ADDR) {
1729 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1730 				"%s: Discovery Mac Address "
1731 				MAC_ADDR_STR,
1732 				__func__,
1733 				MAC_ADDR_ARRAY(event->data.mac_addr.addr));
1734 		memcpy(global_nan_mac_addr, event->data.mac_addr.addr,
1735 		       sizeof(global_nan_mac_addr));
1736 	}
1737 }
1738 
1739 
1740 /* Events Callback */
1741 void nan_event_disabled(NanDisabledInd *event)
1742 {
1743 	sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: reason %d",
1744 			__func__, event->reason);
1745 	/* pthread_cond_signal(&gCondition); */
1746 }
1747 
1748 
1749 /* Events callback */
1750 static void ndp_event_data_indication(NanDataPathRequestInd *event)
1751 {
1752 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1753 			"%s: Service Instance Id: %d  Peer Discovery MAC ADDR "
1754 			MAC_ADDR_STR
1755 			" NDP Instance Id: %d App Info  len %d App Info %s",
1756 			__func__,
1757 			event->service_instance_id,
1758 			MAC_ADDR_ARRAY(event->peer_disc_mac_addr),
1759 			event->ndp_instance_id,
1760 			event->app_info.ndp_app_info_len,
1761 			event->app_info.ndp_app_info);
1762 
1763 	global_ndp_instance_id = event->ndp_instance_id;
1764 }
1765 
1766 
1767 /* Events callback */
1768 static void ndp_event_data_confirm(NanDataPathConfirmInd *event)
1769 {
1770 	char cmd[200];
1771 	char ipv6_buf[100];
1772 
1773 	sigma_dut_print(global_dut, DUT_MSG_INFO,
1774 			"Received NDP Confirm Indication");
1775 
1776 	memset(cmd, 0, sizeof(cmd));
1777 	memset(ipv6_buf, 0, sizeof(ipv6_buf));
1778 
1779 	global_ndp_instance_id = event->ndp_instance_id;
1780 
1781 	if (event->rsp_code == NAN_DP_REQUEST_ACCEPT) {
1782 		if (system("ifconfig nan0 up") != 0) {
1783 			sigma_dut_print(global_dut, DUT_MSG_ERROR,
1784 					"Failed to set nan interface up");
1785 			return;
1786 		}
1787 		if (system("ip -6 route add fe80::/64 dev nan0 table local") !=
1788 		    0) {
1789 			sigma_dut_print(global_dut, DUT_MSG_ERROR,
1790 					"Failed to run:ip -6 route replace fe80::/64 dev nan0 table local");
1791 		}
1792 		convert_mac_addr_to_ipv6_lladdr(event->peer_ndi_mac_addr,
1793 						ipv6_buf, sizeof(ipv6_buf));
1794 		snprintf(cmd, sizeof(cmd),
1795 			 "ip -6 neighbor replace %s lladdr %02x:%02x:%02x:%02x:%02x:%02x nud permanent dev nan0",
1796 			 ipv6_buf, event->peer_ndi_mac_addr[0],
1797 			 event->peer_ndi_mac_addr[1],
1798 			 event->peer_ndi_mac_addr[2],
1799 			 event->peer_ndi_mac_addr[3],
1800 			 event->peer_ndi_mac_addr[4],
1801 			 event->peer_ndi_mac_addr[5]);
1802 		sigma_dut_print(global_dut, DUT_MSG_INFO,
1803 				"neighbor replace cmd = %s", cmd);
1804 		if (system(cmd) != 0) {
1805 			sigma_dut_print(global_dut, DUT_MSG_ERROR,
1806 					"Failed to run: ip -6 neighbor replace");
1807 			return;
1808 		}
1809 	}
1810 }
1811 
1812 
1813 void * my_thread_function(void *ptr)
1814 {
1815 	wifi_event_loop(global_wifi_handle);
1816 	pthread_exit(0);
1817 	return (void *) NULL;
1818 }
1819 
1820 
1821 static NanCallbackHandler callbackHandler = {
1822 	.NotifyResponse = nan_notify_response,
1823 	.EventPublishReplied = nan_event_publish_replied,
1824 	.EventPublishTerminated = nan_event_publish_terminated,
1825 	.EventMatch = nan_event_match,
1826 	.EventMatchExpired = nan_event_match_expired,
1827 	.EventSubscribeTerminated = nan_event_subscribe_terminated,
1828 	.EventFollowup = nan_event_followup,
1829 	.EventDiscEngEvent = nan_event_disceng_event,
1830 	.EventDisabled = nan_event_disabled,
1831 	.EventDataRequest = ndp_event_data_indication,
1832 	.EventDataConfirm = ndp_event_data_confirm,
1833 };
1834 
1835 
1836 void nan_init(struct sigma_dut *dut)
1837 {
1838 	pthread_t thread1;	/* thread variables */
1839 	wifi_error err = wifi_initialize(&global_wifi_handle);
1840 
1841 	if (err) {
1842 		printf("wifi hal initialize failed\n");
1843 		return;
1844 	}
1845 
1846 	global_interface_handle = wifi_get_iface_handle(global_wifi_handle,
1847 							(char *) "wlan0");
1848 	/* create threads 1 */
1849 	pthread_create(&thread1, NULL, &my_thread_function, NULL);
1850 
1851 	pthread_mutex_init(&gMutex, NULL);
1852 	pthread_cond_init(&gCondition, NULL);
1853 	if (global_interface_handle)
1854 		nan_register_handler(global_interface_handle, callbackHandler);
1855 }
1856 
1857 
1858 void nan_cmd_sta_reset_default(struct sigma_dut *dut, struct sigma_conn *conn,
1859 			       struct sigma_cmd *cmd)
1860 {
1861 	sigma_dut_print(dut, DUT_MSG_INFO, "NAN sta_reset_default");
1862 
1863 	if (nan_state == 0) {
1864 		nan_init(dut);
1865 		nan_state = 1;
1866 	}
1867 	is_fam = 0;
1868 	event_anyresponse = 0;
1869 	global_dut = dut;
1870 	memset(&dut->nan_pmk[0], 0, NAN_PMK_INFO_LEN);
1871 	dut->nan_pmk_len = 0;
1872 	dut->sta_channel = 0;
1873 	memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
1874 	memset(&global_nan_sync_stats, 0, sizeof(global_nan_sync_stats));
1875 	memset(global_publish_service_name, 0,
1876 	       sizeof(global_publish_service_name));
1877 	global_publish_service_name_len = 0;
1878 	global_publish_id = 0;
1879 	global_subscribe_id = 0;
1880 
1881 	sigma_nan_data_end(dut, cmd);
1882 	nan_data_interface_delete(0, global_interface_handle, (char *) "nan0");
1883 	sigma_nan_disable(dut, conn, cmd);
1884 }
1885 
1886 
1887 int nan_cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
1888 			    struct sigma_cmd *cmd)
1889 {
1890 	const char *program = get_param(cmd, "Prog");
1891 	const char *nan_op = get_param(cmd, "NANOp");
1892 	const char *method_type = get_param(cmd, "MethodType");
1893 	const char *band = get_param(cmd, "band");
1894 	char resp_buf[100];
1895 	wifi_error ret;
1896 
1897 	if (program == NULL)
1898 		return -1;
1899 
1900 	if (strcasecmp(program, "NAN") != 0) {
1901 		send_resp(dut, conn, SIGMA_ERROR,
1902 			  "ErrorCode,Unsupported program");
1903 		return 0;
1904 	}
1905 
1906 	if (nan_op) {
1907 		/*
1908 		 * NANOp has been specified.
1909 		 * We will build a nan_enable or nan_disable command.
1910 		*/
1911 		if (strcasecmp(nan_op, "On") == 0) {
1912 			if (sigma_nan_enable(dut, conn, cmd) == 0) {
1913 				ret = nan_data_interface_create(
1914 					0, global_interface_handle,
1915 					(char *) "nan0");
1916 				if (ret != WIFI_SUCCESS) {
1917 					sigma_dut_print(
1918 						global_dut, DUT_MSG_ERROR,
1919 						"Unable to create NAN data interface");
1920 				}
1921 				snprintf(resp_buf, sizeof(resp_buf), "mac,"
1922 					 MAC_ADDR_STR,
1923 					 MAC_ADDR_ARRAY(global_nan_mac_addr));
1924 				send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
1925 			} else {
1926 				send_resp(dut, conn, SIGMA_ERROR,
1927 					  "NAN_ENABLE_FAILED");
1928 				return -1;
1929 			}
1930 
1931 			if (band && strcasecmp(band, "24g") == 0) {
1932 				sigma_dut_print(dut, DUT_MSG_INFO,
1933 						"%s: Setting band to 2G Only",
1934 						__func__);
1935 				sigma_ndp_configure_band(
1936 					dut, conn, cmd,
1937 					NAN_DATA_PATH_SUPPORTED_BAND_2G);
1938 			} else if (band && dut->sta_channel > 12) {
1939 				sigma_ndp_configure_band(
1940 					dut, conn, cmd,
1941 					NAN_DATA_PATH_SUPPORT_DUAL_BAND);
1942 			}
1943 		} else if (strcasecmp(nan_op, "Off") == 0) {
1944 			sigma_nan_disable(dut, conn, cmd);
1945 			memset(global_publish_service_name, 0,
1946 			       sizeof(global_publish_service_name));
1947 			global_publish_service_name_len = 0;
1948 			global_publish_id = 0;
1949 			global_subscribe_id = 0;
1950 			send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1951 		}
1952 	}
1953 	if (nan_state && nan_op == NULL) {
1954 		if (method_type) {
1955 			if (strcasecmp(method_type, "Publish") == 0) {
1956 				sigma_nan_publish_request(dut, conn, cmd);
1957 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1958 			}
1959 			if (strcasecmp(method_type, "Subscribe") == 0) {
1960 				sigma_nan_subscribe_request(dut, conn, cmd);
1961 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1962 			}
1963 			if (strcasecmp(method_type, "Followup") == 0) {
1964 				sigma_nan_transmit_followup(dut, conn, cmd);
1965 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1966 			}
1967 			if (strcasecmp(method_type, "DataRequest") == 0) {
1968 				sigma_nan_data_request(dut, conn, cmd);
1969 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1970 			}
1971 			if (strcasecmp(method_type, "DataResponse") == 0) {
1972 				sigma_dut_print(dut, DUT_MSG_INFO,
1973 						"%s: method_type is DataResponse",
1974 						__func__);
1975 				sigma_nan_data_response(dut, conn, cmd);
1976 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1977 			}
1978 			if (strcasecmp(method_type, "DataEnd") == 0) {
1979 				sigma_nan_data_end(dut, cmd);
1980 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1981 			}
1982 			if (strcasecmp(method_type, "rangerequest") == 0) {
1983 				sigma_dut_print(dut, DUT_MSG_INFO,
1984 						"%s: method_type is rangerequest",
1985 						__func__);
1986 				sigma_nan_range_request(dut, cmd);
1987 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1988 			}
1989 			if (strcasecmp(method_type, "cancelrange") == 0) {
1990 				sigma_dut_print(dut, DUT_MSG_INFO,
1991 						"%s: method_type is cancelrange",
1992 						__func__);
1993 				sigma_nan_cancel_range(dut, cmd);
1994 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1995 			}
1996 			if (strcasecmp(method_type, "SchedUpdate") == 0) {
1997 				sigma_dut_print(dut, DUT_MSG_INFO,
1998 						"%s: method_type is SchedUpdate",
1999 						__func__);
2000 				sigma_nan_schedule_update(dut, cmd);
2001 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
2002 			}
2003 		} else {
2004 			sigma_nan_config_enable(dut, conn, cmd);
2005 			snprintf(resp_buf, sizeof(resp_buf), "mac,"
2006 				 MAC_ADDR_STR,
2007 				 MAC_ADDR_ARRAY(global_nan_mac_addr));
2008 			send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
2009 		}
2010 	}
2011 
2012 	return 0;
2013 }
2014 
2015 
2016 int nan_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
2017 			      struct sigma_cmd *cmd)
2018 {
2019 
2020 	const char *program = get_param(cmd, "Program");
2021 	const char *parameter = get_param(cmd, "Parameter");
2022 	char resp_buf[100];
2023 	NanStatsRequest req;
2024 	struct timespec abstime;
2025 	u64 master_rank;
2026 	u8 master_pref;
2027 	u8 random_factor;
2028 	u8 hop_count;
2029 	u32 beacon_transmit_time;
2030 	u32 ndp_channel_freq;
2031 	u32 ndp_channel_freq2;
2032 
2033 	if (program == NULL) {
2034 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Program Name");
2035 		return -1;
2036 	}
2037 	if (strcasecmp(program, "NAN") != 0) {
2038 		send_resp(dut, conn, SIGMA_ERROR,
2039 			  "ErrorCode,Unsupported program");
2040 		return 0;
2041 	}
2042 
2043 	if (parameter == NULL) {
2044 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Parameter");
2045 		return -1;
2046 	}
2047 
2048 	memset(&req, 0, sizeof(NanStatsRequest));
2049 	req.stats_type = (NanStatsType) NAN_STATS_ID_DE_TIMING_SYNC;
2050 	nan_stats_request(0, global_interface_handle, &req);
2051 	/*
2052 	 * To ensure sta_get_events to get the events
2053 	 * only after joining the NAN cluster
2054 	 */
2055 	abstime.tv_sec = 4;
2056 	abstime.tv_nsec = 0;
2057 	wait(abstime);
2058 
2059 	master_rank = global_nan_sync_stats.myRank;
2060 	master_pref = (global_nan_sync_stats.myRank & 0xFF00000000000000) >> 56;
2061 	random_factor = (global_nan_sync_stats.myRank & 0x00FF000000000000) >>
2062 		48;
2063 	hop_count = global_nan_sync_stats.currAmHopCount;
2064 	beacon_transmit_time = global_nan_sync_stats.currAmBTT;
2065 	ndp_channel_freq = global_nan_sync_stats.ndpChannelFreq;
2066 	ndp_channel_freq2 = global_nan_sync_stats.ndpChannelFreq2;
2067 
2068 	sigma_dut_print(dut, DUT_MSG_INFO,
2069 			"%s: NanStatsRequest Master_pref:%02x, Random_factor:%02x, hop_count:%02x beacon_transmit_time:%d ndp_channel_freq:%d ndp_channel_freq2:%d",
2070 			__func__, master_pref, random_factor,
2071 			hop_count, beacon_transmit_time,
2072 			ndp_channel_freq, ndp_channel_freq2);
2073 
2074 	if (strcasecmp(parameter, "MasterPref") == 0) {
2075 		snprintf(resp_buf, sizeof(resp_buf), "MasterPref,0x%x",
2076 			 master_pref);
2077 	} else if (strcasecmp(parameter, "MasterRank") == 0) {
2078 		snprintf(resp_buf, sizeof(resp_buf), "MasterRank,0x%lx",
2079 			 master_rank);
2080 	} else if (strcasecmp(parameter, "RandFactor") == 0) {
2081 		snprintf(resp_buf, sizeof(resp_buf), "RandFactor,0x%x",
2082 			 random_factor);
2083 	} else if (strcasecmp(parameter, "HopCount") == 0) {
2084 		snprintf(resp_buf, sizeof(resp_buf), "HopCount,0x%x",
2085 			 hop_count);
2086 	} else if (strcasecmp(parameter, "BeaconTransTime") == 0) {
2087 		snprintf(resp_buf, sizeof(resp_buf), "BeaconTransTime 0x%x",
2088 			 beacon_transmit_time);
2089 	} else if (strcasecmp(parameter, "NANStatus") == 0) {
2090 		if (nan_state == 1)
2091 			snprintf(resp_buf, sizeof(resp_buf), "On");
2092 		else
2093 			snprintf(resp_buf, sizeof(resp_buf), "Off");
2094 	} else if (strcasecmp(parameter, "NDPChannel") == 0) {
2095 		if (ndp_channel_freq != 0 && ndp_channel_freq2 != 0) {
2096 			snprintf(resp_buf, sizeof(resp_buf),
2097 				 "ndpchannel,%d,ndpchannel,%d",
2098 				 freq_to_channel(ndp_channel_freq),
2099 				 freq_to_channel(ndp_channel_freq2));
2100 		} else if (ndp_channel_freq != 0) {
2101 			snprintf(resp_buf, sizeof(resp_buf), "ndpchannel,%d",
2102 				 freq_to_channel(ndp_channel_freq));
2103 		} else if (ndp_channel_freq2 != 0) {
2104 			snprintf(resp_buf, sizeof(resp_buf), "ndpchannel,%d",
2105 				 freq_to_channel(ndp_channel_freq2));
2106 		} else {
2107 			sigma_dut_print(dut, DUT_MSG_ERROR,
2108 				"%s: No Negotiated NDP Channels", __func__);
2109 		}
2110 	} else {
2111 		send_resp(dut, conn, SIGMA_ERROR, "Invalid Parameter");
2112 		return 0;
2113 	}
2114 
2115 	send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
2116 	return 0;
2117 }
2118 
2119 
2120 int nan_cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
2121 			   struct sigma_cmd *cmd)
2122 {
2123 	const char *action = get_param(cmd, "Action");
2124 
2125 	if (!action)
2126 		return 0;
2127 
2128 	/* Check action for start, stop and get events. */
2129 	if (strcasecmp(action, "Start") == 0) {
2130 		memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
2131 		send_resp(dut, conn, SIGMA_COMPLETE, NULL);
2132 	} else if (strcasecmp(action, "Stop") == 0) {
2133 		event_anyresponse = 0;
2134 		memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
2135 		send_resp(dut, conn, SIGMA_COMPLETE, NULL);
2136 	} else if (strcasecmp(action, "Get") == 0) {
2137 		if (event_anyresponse == 1) {
2138 			send_resp(dut, conn, SIGMA_COMPLETE,
2139 				  global_event_resp_buf);
2140 		} else {
2141 			send_resp(dut, conn, SIGMA_COMPLETE, "EventList,NONE");
2142 		}
2143 	}
2144 	return 0;
2145 }
2146 
2147 #else /* #if NAN_CERT_VERSION */
2148 
2149 int nan_cmd_sta_preset_testparameters(struct sigma_dut *dut,
2150 				      struct sigma_conn *conn,
2151 				      struct sigma_cmd *cmd)
2152 {
2153 	return 1;
2154 }
2155 
2156 
2157 int nan_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
2158 			      struct sigma_cmd *cmd)
2159 {
2160 	return 0;
2161 
2162 }
2163 
2164 
2165 void nan_cmd_sta_reset_default(struct sigma_dut *dut, struct sigma_conn *conn,
2166 			       struct sigma_cmd *cmd)
2167 {
2168 	return;
2169 }
2170 
2171 
2172 int nan_cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
2173 			   struct sigma_cmd *cmd)
2174 {
2175 	return 0;
2176 }
2177 
2178 
2179 int nan_cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
2180 			    struct sigma_cmd *cmd)
2181 {
2182 	return 0;
2183 }
2184 
2185 #endif /* #if NAN_CERT_VERSION */
2186