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