1 /* 2 * Sigma Control API DUT (station/AP) 3 * Copyright (c) 2010, Atheros Communications, Inc. 4 * Copyright (c) 2011-2013, 2016-2017 Qualcomm Atheros, Inc. 5 * All Rights Reserved. 6 * Licensed under the Clear BSD license. See README for more details. 7 */ 8 9 #include "sigma_dut.h" 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13 #include <signal.h> 14 #include <ctype.h> 15 16 #include "wpa_helpers.h" 17 18 #ifdef ANDROID 19 #define SHELL "/system/bin/sh" 20 #else /* ANDROID */ 21 #define SHELL "/bin/sh" 22 #endif /* ANDROID */ 23 24 25 static int cmd_traffic_send_ping(struct sigma_dut *dut, 26 struct sigma_conn *conn, 27 struct sigma_cmd *cmd) 28 { 29 const char *dst, *val; 30 int size, dur, pkts; 31 int id; 32 char resp[100]; 33 float interval; 34 double rate; 35 FILE *f; 36 char buf[100]; 37 int type = 1; 38 int dscp = 0, use_dscp = 0; 39 char extra[100], int_arg[100], intf_arg[100]; 40 41 val = get_param(cmd, "Type"); 42 if (!val) 43 val = get_param(cmd, "IPType"); 44 if (val) 45 type = atoi(val); 46 if (type != 1 && type != 2) { 47 send_resp(dut, conn, SIGMA_ERROR, 48 "ErrorCode,Unsupported address type"); 49 return 0; 50 } 51 52 dst = get_param(cmd, "destination"); 53 if (dst == NULL || (type == 1 && !is_ip_addr(dst)) || 54 (type == 2 && !is_ipv6_addr(dst))) 55 return -1; 56 57 val = get_param(cmd, "frameSize"); 58 if (val == NULL) 59 return -1; 60 size = atoi(val); 61 62 val = get_param(cmd, "frameRate"); 63 if (val == NULL) 64 return -1; 65 rate = atof(val); 66 if (rate <= 0) 67 return -1; 68 69 val = get_param(cmd, "duration"); 70 if (val == NULL) 71 return -1; 72 dur = atoi(val); 73 if (dur <= 0 || dur > 3600) 74 dur = 3600; 75 76 pkts = dur * rate; 77 interval = (float) 1 / rate; 78 if (interval > 100000) 79 return -1; 80 81 val = get_param(cmd, "DSCP"); 82 if (val) { 83 dscp = atoi(val); 84 if (dscp < 0 || dscp > 63) { 85 send_resp(dut, conn, SIGMA_ERROR, 86 "ErrorCode,Invalid DSCP value"); 87 return 0; 88 } 89 use_dscp = 1; 90 } 91 92 id = dut->next_streamid++; 93 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id); 94 unlink(buf); 95 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id); 96 unlink(buf); 97 98 sigma_dut_print(dut, DUT_MSG_DEBUG, "Send ping: pkts=%d interval=%f " 99 "streamid=%d", 100 pkts, interval, id); 101 102 f = fopen(SIGMA_TMPDIR "/sigma_dut-ping.sh", "w"); 103 if (f == NULL) 104 return -2; 105 106 extra[0] = '\0'; 107 if (use_dscp) { 108 snprintf(extra, sizeof(extra), " -Q 0x%02x", 109 dscp << 2); 110 } 111 112 int_arg[0] = '\0'; 113 if (rate != 1) 114 snprintf(int_arg, sizeof(int_arg), " -i %f", interval); 115 intf_arg[0] = '\0'; 116 if (dut->ndp_enable) 117 strlcpy(intf_arg, " -I nan0", sizeof(intf_arg)); 118 else if (type == 2) 119 snprintf(intf_arg, sizeof(intf_arg), " -I %s", 120 get_station_ifname()); 121 fprintf(f, "#!" SHELL "\n" 122 "ping%s -c %d%s -s %d%s -q%s %s > " SIGMA_TMPDIR 123 "/sigma_dut-ping.%d &\n" 124 "echo $! > " SIGMA_TMPDIR "/sigma_dut-ping-pid.%d\n", 125 type == 2 ? "6" : "", pkts, int_arg, size, extra, 126 intf_arg, dst, id, id); 127 128 fclose(f); 129 if (chmod(SIGMA_TMPDIR "/sigma_dut-ping.sh", 130 S_IRUSR | S_IWUSR | S_IXUSR) < 0) 131 return -2; 132 133 if (system(SIGMA_TMPDIR "/sigma_dut-ping.sh") != 0) { 134 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to start ping"); 135 return -2; 136 } 137 138 unlink(SIGMA_TMPDIR "/sigma_dut-ping.sh"); 139 140 snprintf(resp, sizeof(resp), "streamID,%d", id); 141 send_resp(dut, conn, SIGMA_COMPLETE, resp); 142 return 0; 143 } 144 145 146 static int cmd_traffic_stop_ping(struct sigma_dut *dut, 147 struct sigma_conn *conn, 148 struct sigma_cmd *cmd) 149 { 150 const char *val; 151 int id, pid; 152 FILE *f; 153 char buf[100]; 154 int res_found = 0, sent = 0, received = 0; 155 156 val = get_param(cmd, "streamID"); 157 if (val == NULL) 158 return -1; 159 id = atoi(val); 160 161 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id); 162 f = fopen(buf, "r"); 163 if (f == NULL) { 164 send_resp(dut, conn, SIGMA_ERROR, 165 "ErrorCode,Unknown streamID"); 166 return 0; 167 } 168 if (fscanf(f, "%d", &pid) != 1 || pid <= 0) { 169 sigma_dut_print(dut, DUT_MSG_ERROR, "No PID for ping process"); 170 fclose(f); 171 unlink(buf); 172 return -2; 173 } 174 175 fclose(f); 176 unlink(buf); 177 178 sigma_dut_print(dut, DUT_MSG_DEBUG, "Ping process pid %d", pid); 179 if (kill(pid, SIGINT) < 0 && errno != ESRCH) { 180 sigma_dut_print(dut, DUT_MSG_DEBUG, "kill failed: %s", 181 strerror(errno)); 182 } 183 usleep(250000); 184 185 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id); 186 f = fopen(buf, "r"); 187 if (f == NULL) { 188 sigma_dut_print(dut, DUT_MSG_DEBUG, 189 "No ping result file found"); 190 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0"); 191 return 0; 192 } 193 194 while (fgets(buf, sizeof(buf), f)) { 195 char *pos; 196 197 pos = strstr(buf, " packets transmitted"); 198 if (pos) { 199 pos--; 200 while (pos > buf && isdigit(pos[-1])) 201 pos--; 202 sent = atoi(pos); 203 res_found = 1; 204 } 205 206 pos = strstr(buf, " packets received"); 207 if (pos == NULL) 208 pos = strstr(buf, " received"); 209 if (pos) { 210 pos--; 211 while (pos > buf && isdigit(pos[-1])) 212 pos--; 213 received = atoi(pos); 214 res_found = 1; 215 } 216 } 217 fclose(f); 218 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id); 219 unlink(buf); 220 221 if (!res_found) { 222 sigma_dut_print(dut, DUT_MSG_DEBUG, 223 "No ping results found"); 224 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0"); 225 return 0; 226 } 227 228 snprintf(buf, sizeof(buf), "sent,%d,replies,%d", sent, received); 229 send_resp(dut, conn, SIGMA_COMPLETE, buf); 230 return 0; 231 } 232 233 234 void traffic_register_cmds(void) 235 { 236 sigma_dut_reg_cmd("traffic_send_ping", NULL, cmd_traffic_send_ping); 237 sigma_dut_reg_cmd("traffic_stop_ping", NULL, cmd_traffic_stop_ping); 238 } 239