| /* |
| * 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); |
| } |