Import the initial version of sigma_dut open source project

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
diff --git a/sniffer.c b/sniffer.c
new file mode 100644
index 0000000..72d0e59
--- /dev/null
+++ b/sniffer.c
@@ -0,0 +1,385 @@
+/*
+ * Sigma Control API DUT (sniffer)
+ * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
+ * All Rights Reserved.
+ * Licensed under the Clear BSD license. See README for more details.
+ */
+
+#include "sigma_dut.h"
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+
+static void capture_process(const char *ifname, const char *filename)
+{
+	char *env[] = { NULL };
+	char *argv[] = { "sigma_dut[capture]", "-i", strdup(ifname),
+			 "-w", strdup(filename), NULL };
+	execve("/usr/bin/dumpcap", argv, env);
+	perror("execve");
+	exit(EXIT_FAILURE);
+}
+
+
+static int cmd_sniffer_control_start(struct sigma_dut *dut,
+				     struct sigma_conn *conn,
+				     struct sigma_cmd *cmd)
+{
+	const char *filename = get_param(cmd, "filename");
+	int res;
+	pid_t pid;
+
+	if (dut->sniffer_pid) {
+		sigma_dut_print(dut, DUT_MSG_INFO, "Sniffer was already capturing - restart based on new parameters");
+		sniffer_close(dut);
+	}
+
+	if (filename == NULL) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Missing filename argument");
+		return 0;
+	}
+	if (strchr(filename, '/')) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Invalid filename");
+		return 0;
+	}
+
+	res = cmd_wlantest_set_channel(dut, conn, cmd);
+	if (res != 1)
+		return res;
+
+	mkdir("Captures", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+
+	sigma_dut_print(dut, DUT_MSG_INFO, "Starting sniffer process");
+	snprintf(dut->sniffer_filename, sizeof(dut->sniffer_filename),
+		 "Captures/%s", filename);
+	pid = fork();
+	if (pid < 0) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed to fork sniffer process");
+		return 0;
+	}
+
+	if (pid == 0) {
+		capture_process(dut->sniffer_ifname, dut->sniffer_filename);
+		return 0;
+	}
+
+	dut->sniffer_pid = pid;
+
+	return 1;
+}
+
+
+void sniffer_close(struct sigma_dut *dut)
+{
+	if (!dut->sniffer_pid)
+		return;
+
+	if (kill(dut->sniffer_pid, SIGTERM) < 0) {
+		printf("Failed to kill sniffer process: %s\n", strerror(errno));
+		dut->sniffer_pid = 0;
+		return;
+	}
+	waitpid(dut->sniffer_pid, NULL, 0);
+
+	if (dut->sniffer_filename[0]) {
+		chmod(dut->sniffer_filename,
+		      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+		dut->sniffer_filename[0] = '\0';
+	}
+
+	dut->sniffer_pid = 0;
+}
+
+
+static int cmd_sniffer_control_stop(struct sigma_dut *dut,
+				    struct sigma_conn *conn,
+				    struct sigma_cmd *cmd)
+{
+	if (!dut->sniffer_pid) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Sniffer was not capturing");
+		return 0;
+	}
+
+	sniffer_close(dut);
+	return 1;
+}
+
+
+static int cmd_sniffer_control_field_check(struct sigma_dut *dut,
+					   struct sigma_conn *conn,
+					   struct sigma_cmd *cmd)
+{
+	const char *filename = get_param(cmd, "filename");
+	const char *framename = get_param(cmd, "framename");
+	const char *srcmac = get_param(cmd, "srcmac");
+	const char *wsc_state = get_param(cmd, "WSC_State");
+	const char *pvb_bit = get_param(cmd, "pvb_bit");
+	const char *moredata_bit = get_param(cmd, "MoreData_bit");
+	const char *eosp_bit = get_param(cmd, "EOSP_bit");
+	char buf[2000], *pos;
+	FILE *f;
+
+	if (filename == NULL || srcmac == NULL)
+		return -1;
+
+	if (strchr(filename, '/')) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Invalid filename");
+		return 0;
+	}
+
+	if (!file_exists("sniffer-control-field-check.py")) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-control-field-check.py not found");
+		return 0;
+	}
+
+	snprintf(buf, sizeof(buf),
+		 "./sniffer-control-field-check.py FileName=Captures/%s SrcMac=%s%s%s%s%s%s%s%s%s%s%s",
+		 filename, srcmac,
+		 framename ? " FrameName=" : "", framename ? framename : "",
+		 wsc_state ? " WSC_State=" : "", wsc_state ? wsc_state : "",
+		 moredata_bit ? " MoreData_bit=" : "",
+		 moredata_bit ? moredata_bit : "",
+		 eosp_bit ? " EOSP_bit=" : "", eosp_bit ? eosp_bit : "",
+		 pvb_bit ? " pvb_bit=" : "", pvb_bit ? pvb_bit : "");
+	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
+	f = popen(buf, "r");
+	if (f == NULL) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed to run sniffer helper");
+		return 0;
+	}
+
+	if (!fgets(buf, sizeof(buf), f)) {
+		pclose(f);
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed extract response from sniffer helper");
+		return 0;
+	}
+	pos = strchr(buf, '\n');
+	if (pos)
+		*pos = '\0';
+
+	pclose(f);
+
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_get_info(struct sigma_dut *dut, struct sigma_conn *conn,
+				struct sigma_cmd *cmd)
+{
+	char buf[200];
+
+	snprintf(buf, sizeof(buf), "WfaSnifferVersion,SigmaSniffer-foo,SnifferSTA,foo,DeviceSwInfo,foo,WiresharkVersion,foo");
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_control_filter_capture(struct sigma_dut *dut,
+					      struct sigma_conn *conn,
+					      struct sigma_cmd *cmd)
+{
+	const char *infile = get_param(cmd, "InFile");
+	const char *outfile = get_param(cmd, "OutFile");
+	const char *srcmac = get_param(cmd, "SrcMac");
+	const char *framename = get_param(cmd, "FrameName");
+	const char *nframes = get_param(cmd, "Nframes");
+	const char *hasfield = get_param(cmd, "HasField");
+	const char *datalen = get_param(cmd, "Datalen");
+	char buf[500], *pos;
+	FILE *f;
+
+	if (infile == NULL || outfile == NULL || srcmac == NULL ||
+	    nframes == NULL)
+		return -1;
+
+	if (strchr(infile, '/') || strchr(outfile, '/'))
+		return -1;
+
+	if (!file_exists("sniffer-control-filter-capture.py")) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-control-filter-capture.py not found");
+		return 0;
+	}
+
+	snprintf(buf, sizeof(buf),
+		 "./sniffer-control-filter-capture.py InFile=Captures/%s OutFile=Captures/%s SrcMac=%s%s%s Nframes=%s%s%s%s%s",
+		 infile, outfile, srcmac,
+		 framename ? " FrameName=" : "", framename ? framename : "",
+		 nframes,
+		 hasfield ? " HasField=" : "", hasfield ? hasfield : "",
+		 datalen ? " Datalen=" : "", datalen ? datalen : "");
+	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
+	f = popen(buf, "r");
+	if (f == NULL) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed to run sniffer helper");
+		return 0;
+	}
+
+	if (!fgets(buf, sizeof(buf), f)) {
+		pclose(f);
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed extract response from sniffer helper");
+		return 0;
+	}
+	pos = strchr(buf, '\n');
+	if (pos)
+		*pos = '\0';
+
+	pclose(f);
+
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_get_field_value(struct sigma_dut *dut,
+				       struct sigma_conn *conn,
+				       struct sigma_cmd *cmd)
+{
+	const char *infile = get_param(cmd, "FileName");
+	const char *srcmac = get_param(cmd, "SrcMac");
+	const char *framename = get_param(cmd, "FrameName");
+	const char *fieldname = get_param(cmd, "FieldName");
+	char buf[500], *pos;
+	FILE *f;
+
+	if (infile == NULL || srcmac == NULL || framename == NULL ||
+	    fieldname == NULL)
+		return -1;
+
+	if (!file_exists("sniffer-get-field-value.py")) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-get-field-value.py not found");
+		return 0;
+	}
+
+	snprintf(buf, sizeof(buf),
+		 "./sniffer-get-field-value.py FileName=Captures/%s SrcMac=%s FrameName=%s FieldName=%s",
+		 infile, srcmac, framename, fieldname);
+	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
+	f = popen(buf, "r");
+	if (f == NULL) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed to run sniffer helper");
+		return 0;
+	}
+
+	if (!fgets(buf, sizeof(buf), f)) {
+		pclose(f);
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed extract response from sniffer helper");
+		return 0;
+	}
+	pos = strchr(buf, '\n');
+	if (pos)
+		*pos = '\0';
+
+	pclose(f);
+
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_check_p2p_noa_duration(struct sigma_dut *dut,
+					      struct sigma_conn *conn,
+					      struct sigma_cmd *cmd)
+{
+	FILE *f;
+	char buf[200], *pos;
+	const char *infile = get_param(cmd, "FileName");
+	const char *bssid = get_param(cmd, "bssid");
+	const char *srcmac = get_param(cmd, "srcmac");
+	const char *destmac = get_param(cmd, "destmac");
+
+	if (infile == NULL || bssid == NULL || srcmac == NULL ||
+	    destmac == NULL)
+		return -1;
+
+	if (!file_exists("sniffer-check-p2p-noa-duration.py")) {
+		send_resp(dut, conn, SIGMA_ERROR, "errorCode,sniffer-check-p2p-noa-duration.py not found");
+		return 0;
+	}
+
+	snprintf(buf, sizeof(buf),
+		 "./sniffer-check-p2p-noa-duration.py Captures/%s %s %s %s",
+		 infile, bssid, srcmac, destmac);
+	sigma_dut_print(dut, DUT_MSG_INFO, "Run: %s", buf);
+	f = popen(buf, "r");
+	if (f == NULL) {
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed to run sniffer check");
+		return 0;
+	}
+
+	if (!fgets(buf, sizeof(buf), f)) {
+		pclose(f);
+		send_resp(dut, conn, SIGMA_ERROR,
+			  "errorCode,Failed extract response from sniffer check");
+		return 0;
+	}
+	pos = strchr(buf, '\n');
+	if (pos)
+		*pos = '\0';
+
+	pclose(f);
+
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_check_p2p_opps_client(struct sigma_dut *dut,
+					     struct sigma_conn *conn,
+					     struct sigma_cmd *cmd)
+{
+	char buf[200];
+
+	/* TODO */
+	snprintf(buf, sizeof(buf), "FilterStatus,SUCCESS");
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+static int cmd_sniffer_check_frame_field(struct sigma_dut *dut,
+					 struct sigma_conn *conn,
+					 struct sigma_cmd *cmd)
+{
+	char buf[200];
+
+	/* TODO */
+	snprintf(buf, sizeof(buf), "FilterStatus,SUCCESS");
+	send_resp(dut, conn, SIGMA_COMPLETE, buf);
+	return 0;
+}
+
+
+void sniffer_register_cmds(void)
+{
+	sigma_dut_reg_cmd("sniffer_control_start", NULL,
+			  cmd_sniffer_control_start);
+	sigma_dut_reg_cmd("sniffer_control_stop", NULL,
+			  cmd_sniffer_control_stop);
+	sigma_dut_reg_cmd("sniffer_control_field_check", NULL,
+			  cmd_sniffer_control_field_check);
+	sigma_dut_reg_cmd("sniffer_get_info", NULL, cmd_sniffer_get_info);
+	sigma_dut_reg_cmd("sniffer_control_filter_capture", NULL,
+			  cmd_sniffer_control_filter_capture);
+	sigma_dut_reg_cmd("wfa_sniffer_control_filter_capture", NULL,
+			  cmd_sniffer_control_filter_capture);
+	sigma_dut_reg_cmd("sniffer_get_field_value", NULL,
+			  cmd_sniffer_get_field_value);
+	sigma_dut_reg_cmd("sniffer_check_p2p_NoA_duration", NULL,
+			  cmd_sniffer_check_p2p_noa_duration);
+	sigma_dut_reg_cmd("sniffer_check_p2p_opps_client", NULL,
+			  cmd_sniffer_check_p2p_opps_client);
+	sigma_dut_reg_cmd("sniffer_check_frame_field", NULL,
+			  cmd_sniffer_check_frame_field);
+}