1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: shell cmds APIs implementation about ping and ping6
15 * Author: none
16 * Create: 2020
17 */
18
19 #include "lwip/nettool/ping.h"
20 #include "lwip/icmp.h"
21 #include "lwip/icmp6.h"
22 #include "lwip/sockets.h"
23 #include "lwip/ip.h"
24 #include "lwip/inet_chksum.h"
25 #include "lwip/nettool/utility.h"
26 #include "lwip/netdb.h"
27 #include "netif/ifaddrs.h"
28 #include "lwip/sys.h"
29 #if LWIP_LITEOS_COMPAT
30 #include "los_config.h"
31 #include <td_base.h>
32 #endif
33
34
35 #if LWIP_ENABLE_BASIC_SHELL_CMD
36
37 /** LWIP_SHELL_CMD_PING_TIMEOUT: Ping cmd waiting timeout max(in millisec) to receive ping response */
38 #if !defined LWIP_SHELL_CMD_PING_TIMEOUT_MAX || defined __DOXYGEN__
39 #define LWIP_SHELL_CMD_PING_TIMEOUT_MAX 10000
40 #endif
41
42 /** LWIP_SHELL_CMD_PING_TIMEOUT: Ping cmd waiting timeout min(in millisec) to receive ping response */
43 #if !defined LWIP_SHELL_CMD_PING_TIMEOUT_MIN || defined __DOXYGEN__
44 #define LWIP_SHELL_CMD_PING_TIMEOUT_MIN 1000
45 #endif
46
47 #ifdef CUSTOM_AT_COMMAND
48 #define LWIP_PING_TASK_PRIO 5
49 #define LWIP_PING_MAX_PKT_LEN 7360
50 #else
51 #define LWIP_PING_TASK_PRIO 4
52 #endif
53
54 #define LWIP_PING_INTERFACE_ARG 1
55 #define LWIP_PING_HOSTNAME_ARG 2
56 #define LWIP_PING_DEFAULT_SOCKET 4
57 #define PERCENT 100
58
59 /* Maximum tick value that can be generated by sys_now() */
60 #define LWIP_MAX_TICK 0xFFFFFFFF
61 #define LWIP_MAX_TICK_U64 0xFFFFFFFFFFFFFFFFLLU
62 #define LWIP_DEFAULT_PING_TASK_ID 0xFFFFFFFF
63
64 static uint32_t ping_taskid = LWIP_DEFAULT_PING_TASK_ID;
65 static int ping_kill = 0;
66 static u8_t ping_task_running = 0;
67 #define PING_ZERO_DATA_LEN 8
68 #define SEC_TO_US 1000000
69 #define US_TO_NSEC 1000
70
71 static void
lwip_ping_usage(u32_t is_v6)72 lwip_ping_usage(u32_t is_v6)
73 {
74 #ifndef CUSTOM_AT_COMMAND
75 char *ping = is_v6 ? "ping6" : "ping";
76 LWIP_PLATFORM_PRINT("Usage:"\
77 CRLF" %s"
78 CRLF" %s [-6] [-n cnt] [-w interval] [-l len] dest"
79 CRLF" %s [-I iface/ipaddr] [-t] [-w interval] [-W timeout] dest"
80 CRLF" %s -k use -k to stop"
81 CRLF" %s -t ping forever"CRLF, ping, ping, ping, ping, ping);
82 #else
83 (void)is_v6;
84 #endif
85 }
86
87 #if LWIP_LITEOS_TASK
88 /* help convert ptr to u32 array(if 64bit platfrom) */
89 union los_ptr_args {
90 void *ptr;
91 u32_t args[2];
92 };
93 #endif
94
95 struct ping_run_ctx {
96 int sfd;
97 u32_t is_v6;
98 struct sockaddr_storage to;
99 struct icmp_echo_hdr *iecho;
100 struct icmp_echo_hdr *iecho_resp;
101 struct ip_hdr *iphdr_resp;
102 u32_t iecho_len;
103 s16_t ip_hlen;
104 u16_t i;
105 u32_t forever;
106 u32_t succ_cnt;
107 u32_t failed_cnt;
108 #if LWIP_LITEOS_TASK
109 u64_t start_us;
110 u64_t end_us;
111 u64_t timout_end_us;
112 #else
113 u32_t start_ms;
114 u32_t end_ms;
115 u32_t timout_end_ms;
116 #endif
117
118 #ifdef CUSTOM_AT_COMMAND
119 s32_t rtt_sum;
120 s32_t rtt_min;
121 s32_t rtt_max;
122 #endif
123
124 s32_t timout_ms;
125 #if LWIP_SOCKET_POLL && !LWIP_EXT_POLL_SUPPORT
126 struct pollfd pfd;
127 #else
128 fd_set read_set;
129 struct timeval time_val;
130 #endif
131 s32_t rtt;
132 u32_t intrvl;
133 char *data_buf;
134 struct sockaddr_storage dst;
135 u32_t socklen;
136 u32_t cnt;
137 u32_t timout;
138 u32_t interval;
139 u32_t data_len;
140 };
141
142 #define PING_ADDR_STR_LEN IPADDR_STRLEN_MAX
143
144 struct ping_cfg {
145 u32_t count;
146 u32_t interval;
147 u32_t timeout;
148 u32_t data_len;
149 struct sockaddr_storage dst;
150 u8_t src_type;
151 u32_t is_v6;
152 char src_iface[NETIF_NAMESIZE];
153 struct sockaddr_storage src;
154 };
155
156 #ifdef CONFIG_SIGMA_SUPPORT
157 ping_result_callback upload_ping_result = NULL;
ping_add_ext_callback(ping_result_callback func)158 void ping_add_ext_callback(ping_result_callback func)
159 {
160 upload_ping_result = func;
161 }
162 #endif
163
164 LWIP_STATIC void
ping_req_init(struct ping_run_ctx * ctx)165 ping_req_init(struct ping_run_ctx *ctx)
166 {
167 u32_t i;
168 if (ctx->data_len > PING_ZERO_DATA_LEN) {
169 (void)memset_s(ctx->iecho, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN, 0,
170 sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN);
171 ctx->data_buf = (char *)ctx->iecho + sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN;
172 for (i = 0; i < ctx->data_len - PING_ZERO_DATA_LEN; i++) {
173 *(ctx->data_buf + i) = i + 0x10;
174 }
175 } else {
176 (void)memset_s(ctx->iecho, sizeof(struct icmp_echo_hdr) + ctx->data_len, 0,
177 sizeof(struct icmp_echo_hdr) + ctx->data_len);
178 }
179 ctx->iecho->id = LWIP_RAND();
180
181 #if LWIP_IPV6
182 if (ctx->is_v6) {
183 ICMPH_TYPE_SET(ctx->iecho, (u8_t)ICMP6_TYPE_EREQ);
184 } else
185 #endif
186 {
187 ICMPH_TYPE_SET(ctx->iecho, (u8_t)ICMP_ECHO);
188 }
189 }
190
191 LWIP_STATIC int
ping_ctx_init(struct ping_run_ctx * ctx,struct ping_cfg * cfg)192 ping_ctx_init(struct ping_run_ctx *ctx, struct ping_cfg *cfg)
193 {
194 ctx->sfd = -1;
195 ctx->is_v6 = cfg->is_v6;
196 ctx->iecho = NULL;
197 ctx->iecho_resp = NULL;
198 ctx->iphdr_resp = NULL;
199 ctx->succ_cnt = 0;
200 ctx->failed_cnt = 0;
201
202 #ifdef CUSTOM_AT_COMMAND
203 ctx->rtt_sum = 0;
204 ctx->rtt_min = 0;
205 ctx->rtt_max = 0;
206 #endif
207 ctx->data_buf = NULL;
208 ctx->dst = cfg->dst;
209 #if LWIP_IPV6
210 ctx->socklen = (ctx->dst.ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
211 #else
212 ctx->socklen = sizeof(struct sockaddr_in);
213 #endif
214 ctx->cnt = cfg->count;
215 ctx->interval = cfg->interval;
216 ctx->timout = cfg->timeout;
217 ctx->data_len = cfg->data_len;
218
219 ctx->iecho_len = sizeof(struct icmp_echo_hdr) + ctx->data_len;
220 ctx->iphdr_resp = (struct ip_hdr *)mem_malloc(ctx->iecho_len + IP_HLEN_MAX);
221 if (ctx->iphdr_resp == NULL) {
222 #ifdef CUSTOM_AT_COMMAND
223 (void)uapi_at_printf("Ping: malloc fail"CRLF);
224 #else
225 LWIP_PLATFORM_PRINT("Ping: malloc fail"CRLF);
226 #endif
227 return -1;
228 }
229 ctx->iecho = (struct icmp_echo_hdr *)mem_malloc(ctx->iecho_len);
230 if (ctx->iecho == NULL) {
231 #ifdef CUSTOM_AT_COMMAND
232 (void)uapi_at_printf("Ping: request malloc fail"CRLF);
233 #else
234 LWIP_PLATFORM_PRINT("Ping: request malloc fail"CRLF);
235 #endif
236 return -1;
237 }
238 ctx->to = cfg->dst;
239 ctx->forever = (ctx->cnt ? 0 : 1);
240 ctx->i = 0;
241 ping_req_init(ctx);
242 return 0;
243 }
244
245
246 LWIP_STATIC void
ping_resp_code_print(u8_t iecho_resp)247 ping_resp_code_print(u8_t iecho_resp)
248 {
249 const char *printstr = NULL;
250 LWIP_STATIC const char *icmp_code_str[] = {
251 "icmp reply", /* ICMP_ER */
252 NULL,
253 NULL,
254 "destination host unreachable", /* ICMP_DUR */
255 "source quench", /* ICMP_SQ */
256 "redirect", /* ICMP_RD */
257 NULL,
258 NULL,
259 NULL,
260 NULL,
261 NULL,
262 "time exceeded", /* ICMP_TE */
263 "parameter problem" /* ICMP_PP */
264 };
265
266 if (iecho_resp < LWIP_ARRAYSIZE(icmp_code_str)) {
267 printstr = icmp_code_str[iecho_resp];
268 }
269
270 if (printstr == NULL) {
271 printstr = "unknow error";
272 }
273 #ifdef CUSTOM_AT_COMMAND
274 (void)uapi_at_printf("Ping: %s: "CRLF, printstr);
275 #else
276 LWIP_PLATFORM_PRINT("Ping: %s: "CRLF, printstr);
277 #endif
278 }
279
280 LWIP_STATIC void
ping_resp_process(struct ping_run_ctx * ctx)281 ping_resp_process(struct ping_run_ctx *ctx)
282 {
283 u8_t af = AF_INET;
284 const char *ipstr = NULL;
285 char str_buf[PING_ADDR_STR_LEN];
286 const void *src = &(((struct sockaddr_in *)&ctx->to)->sin_addr);
287
288 #if LWIP_IPV6
289 if (ctx->is_v6) {
290 af = AF_INET6;
291 src = &(((struct sockaddr_in6 *)&ctx->to)->sin6_addr);
292 }
293 #endif
294 ipstr = lwip_inet_ntop(af, src, str_buf, PING_ADDR_STR_LEN);
295 if (ipstr == NULL) {
296 ipstr = "****";
297 }
298
299 #ifdef CUSTOM_AT_COMMAND
300 #if LWIP_IPV6
301 if (ctx->is_v6) {
302 (void)uapi_at_printf("%u bytes from %s: icmp_seq=%u ", ctx->data_len, ipstr, ctx->i);
303 if (ctx->rtt < 1) {
304 (void)uapi_at_printf("time<1ms"CRLF);
305 } else {
306 (void)uapi_at_printf("time=%ims"CRLF, ctx->rtt);
307 }
308 } else
309 #endif
310 {
311 (void)uapi_at_printf("[%u]Reply from %s:", ctx->i, ipstr);
312 if (ctx->rtt < 1) {
313 (void)uapi_at_printf("time<1ms ");
314 } else {
315 (void)uapi_at_printf("time=%dms ", ctx->rtt);
316 }
317 (void)uapi_at_printf("TTL=%u"CRLF, ctx->iphdr_resp->_ttl);
318 }
319 #else
320 LWIP_PLATFORM_PRINT("[%u]Reply from %s: ", ctx->i, ipstr);
321 if (ctx->rtt < 1) {
322 LWIP_PLATFORM_PRINT("time<1 ms ");
323 } else {
324 LWIP_PLATFORM_PRINT("time=%i ms ", ctx->rtt);
325 }
326 if (ctx->is_v6 == 0) {
327 LWIP_PLATFORM_PRINT("TTL=%u"CRLF, ctx->iphdr_resp->_ttl);
328 } else {
329 LWIP_PLATFORM_PRINT(CRLF);
330 }
331 #endif
332
333 /* delay 1s for every successful ping */
334 ctx->intrvl = ctx->interval;
335 if (((ctx->succ_cnt + ctx->failed_cnt + 1) < ctx->cnt) || ctx->forever) {
336 do {
337 if (ctx->intrvl < MS_PER_SECOND) {
338 sys_msleep(ctx->intrvl);
339 break;
340 }
341 ctx->intrvl -= MS_PER_SECOND;
342 sys_msleep(MS_PER_SECOND);
343 if (ping_kill == 1) {
344 break;
345 }
346 } while (ctx->intrvl > 0);
347 }
348 ctx->succ_cnt++;
349 #ifdef CUSTOM_AT_COMMAND
350 if (ctx->rtt >= 1) {
351 ctx->rtt_sum += ctx->rtt;
352 }
353 if ((ctx->rtt < ctx->rtt_min) || (ctx->succ_cnt == 1)) {
354 ctx->rtt_min = ctx->rtt;
355 }
356 if ((ctx->rtt > ctx->rtt_max) || (ctx->succ_cnt == 1)) {
357 ctx->rtt_max = ctx->rtt;
358 }
359 #endif
360 }
361
362 #if LWIP_LITEOS_TASK
uapi_get_us(td_void)363 td_u64 uapi_get_us(td_void)
364 {
365 struct timespec tp;
366
367 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
368 return (td_u64)(td_u32)tp.tv_sec * SEC_TO_US + (td_u32)tp.tv_nsec / US_TO_NSEC;
369 } else {
370 return (td_u64)(EXT_ERR_FAILURE);
371 }
372 }
373 #endif
374
375 LWIP_STATIC void
ping_rcv_rtt_calc(struct ping_run_ctx * ctx)376 ping_rcv_rtt_calc(struct ping_run_ctx *ctx)
377 {
378 #if LWIP_LITEOS_TASK
379 ctx->timout_end_us = uapi_get_us();
380 if (ctx->timout_end_us < ctx->start_us) {
381 /* Incase of wraparoud of ticks */
382 ctx->rtt = (s32_t)(ctx->timout_end_us / US_PER_MSECOND + ((LWIP_MAX_TICK_U64 - ctx->start_us) / US_PER_MSECOND));
383 } else {
384 ctx->rtt = (s32_t)(ctx->timout_end_us / US_PER_MSECOND - ctx->start_us / US_PER_MSECOND);
385 }
386 #else
387 ctx->timout_end_ms = sys_now();
388 ctx->rtt = (s32_t)(ctx->timout_end_ms - ctx->start_ms);
389 if (ctx->rtt < 0) {
390 ctx->rtt = (s32_t)(ctx->timout_end_ms + (LWIP_MAX_TICK - ctx->start_ms));
391 }
392 #endif
393 }
394
395 #if LWIP_IPV6
convert_icmpv6_err_to_string(u8_t err_type)396 LWIP_STATIC const char *convert_icmpv6_err_to_string(u8_t err_type)
397 {
398 switch (err_type) {
399 case ICMP6_TYPE_DUR:
400 return "Destination Unreachable";
401 case ICMP6_TYPE_PTB:
402 return "Packet too big";
403 case ICMP6_TYPE_TE:
404 return "Time Exceeded";
405 case ICMP6_TYPE_PP:
406 return "Parameter Problem";
407 default:
408 break;
409 }
410 return NULL;
411 }
412 #endif
413
414 LWIP_STATIC int
ping_rcv_check(struct ping_run_ctx * ctx,int len)415 ping_rcv_check(struct ping_run_ctx *ctx, int len)
416 {
417 #if LWIP_IPV6
418 int ip_hlen_min = ctx->is_v6 ? 0 : IP_HLEN;
419 #else
420 int ip_hlen_min = IP_HLEN;
421 #endif
422
423 if ((u32_t)len < sizeof(struct icmp_echo_hdr) + ip_hlen_min) {
424 #ifdef CUSTOM_AT_COMMAND
425 /* Drop the packet if its too short [Doesnot contain even the header !!] */
426 (void)uapi_at_printf("ping: received ICMP echo response too short for less icmp header\n");
427 #else
428 LWIP_PLATFORM_PRINT("Ping: received ICMP echo response too short for less icmp header\n");
429 #endif
430 return -1;
431 }
432
433 /* Accessing ip header and icmp header */
434 #if LWIP_IPV6
435 ctx->ip_hlen = ctx->is_v6 ? 0 : (IPH_HL(ctx->iphdr_resp) << 2);
436 #else
437 ctx->ip_hlen = (IPH_HL(ctx->iphdr_resp) << 2);
438 #endif
439 if ((u32_t)len < sizeof(struct icmp_echo_hdr) + ctx->ip_hlen) {
440 #ifdef CUSTOM_AT_COMMAND
441 /* Drop the packet if its too short [Doesnot contain send len !!] */
442 (void)uapi_at_printf("ping : received ICMP echo response too short for not equal send len\n");
443 #else
444 LWIP_PLATFORM_PRINT("Ping: received ICMP echo response too short for not equal send len\n");
445 #endif
446 return -1;
447 }
448
449 #if LWIP_IPV6
450 if (ctx->is_v6) {
451 ctx->iecho_resp = (struct icmp_echo_hdr *)((char *)ctx->iphdr_resp);
452 } else
453 #endif
454 {
455 struct sockaddr_in *sin = (struct sockaddr_in *)&ctx->to;
456 if (sin->sin_addr.s_addr != ctx->iphdr_resp->src.addr) {
457 return -1;
458 }
459 ctx->iecho_resp = (struct icmp_echo_hdr *)((char *)ctx->iphdr_resp + ctx->ip_hlen);
460 }
461
462 #if LWIP_IPV6
463 if (ctx->is_v6) {
464 if (ICMPH_TYPE(ctx->iecho_resp) != ICMP6_TYPE_EREP) {
465 const char *err_str = convert_icmpv6_err_to_string(ICMPH_TYPE(ctx->iecho_resp));
466 if (err_str != NULL) {
467 #ifdef CUSTOM_AT_COMMAND
468 (void)uapi_at_printf("ping: %s"CRLF, err_str);
469 #else
470 LWIP_PLATFORM_PRINT("ping: %s"CRLF, err_str);
471 #endif
472 }
473 return -1;
474 }
475 } else
476 #endif
477 {
478 if (ICMPH_TYPE(ctx->iecho_resp) == ICMP_ECHO) {
479 /* skip loopback ICMP_ECHO */
480 return -1;
481 } else if (ICMPH_TYPE(ctx->iecho_resp) != ICMP_ER) {
482 ping_resp_code_print(ICMPH_TYPE(ctx->iecho_resp));
483 return -1;
484 }
485 }
486
487 if (ctx->iecho_resp->id != ctx->iecho->id) {
488 #ifdef CUSTOM_AT_COMMAND
489 (void)uapi_at_printf("Ping : recv id unmatch"CRLF);
490 #else
491 LWIP_PLATFORM_PRINT("Ping: recv id unmatch %u %u"CRLF, ctx->iecho_resp->id, ctx->iecho->id);
492 #endif
493 return -1;
494 }
495
496 if (ntohs(ctx->iecho_resp->seqno) != ctx->i) {
497 #ifndef CUSTOM_AT_COMMAND
498 LWIP_PLATFORM_PRINT("Ping: recv seqno unmatch"CRLF);
499 #endif
500 return -1;
501 }
502
503 return 0;
504 }
505
506 LWIP_STATIC int
ping_rcv_poll(struct ping_run_ctx * ctx)507 ping_rcv_poll(struct ping_run_ctx *ctx)
508 {
509 #if LWIP_SOCKET_POLL && !LWIP_EXT_POLL_SUPPORT
510 /* poll for ICMP echo response msg */
511 ctx->pfd.fd = ctx->sfd;
512 ctx->pfd.events = POLLIN;
513 ctx->pfd.revents = 0;
514 return poll(&ctx->pfd, 1, ctx->timout_ms);
515 #else
516 /* Wait in select for ICMP response msg */
517 FD_ZERO(&ctx->read_set);
518 FD_SET(ctx->sfd, &ctx->read_set);
519 ctx->time_val.tv_sec = ctx->timout_ms / MS_PER_SECOND;
520 ctx->time_val.tv_usec = (ctx->timout_ms % MS_PER_SECOND) * US_PER_MSECOND;
521 return lwip_select(ctx->sfd + 1, &ctx->read_set, 0, 0, &ctx->time_val);
522 #endif
523 }
524
525 LWIP_STATIC int
ping_rcv(struct ping_run_ctx * ctx)526 ping_rcv(struct ping_run_ctx *ctx)
527 {
528 int ret;
529 /* capture the start ms to calculate RTT */
530 #if LWIP_LITEOS_TASK
531 ctx->start_us = uapi_get_us();
532 #else
533 ctx->start_ms = sys_now();
534 #endif
535 ctx->timout_ms = (s32_t)ctx->timout;
536
537 do {
538 ret = ping_rcv_poll(ctx);
539 if (ret < 0) {
540 #ifdef CUSTOM_AT_COMMAND
541 (void)uapi_at_printf("ping : poll/select failure, errno = %d"CRLF, errno);
542 #else
543 LWIP_PLATFORM_PRINT("ping : poll/select failure, errno = %d"CRLF, errno);
544 #endif
545 return -1;
546 } else if (ret == 0) {
547 /* first type timeout event */
548 break;
549 }
550
551 /* construct timeout event if poll lose efficacy when other host ping us */
552 ret = recv(ctx->sfd, ctx->iphdr_resp, ctx->iecho_len + IP_HLEN_MAX, MSG_DONTWAIT);
553 if (ret < 0) {
554 #ifdef CUSTOM_AT_COMMAND
555 (void)uapi_at_printf(CRLF"Recv failed errno = %d"CRLF, errno);
556 #else
557 LWIP_PLATFORM_PRINT(CRLF"Recv failed errno = %d"CRLF, errno);
558 #endif
559 return -1;
560 }
561 ping_rcv_rtt_calc(ctx);
562 ctx->timout_ms = ctx->timout - ctx->rtt;
563 if (ping_rcv_check(ctx, ret) == 0) {
564 ping_resp_process(ctx);
565 ctx->i++;
566 return 0;
567 }
568 } while (ctx->timout_ms > 0);
569
570 /* all timeout events are true timeout */
571 ctx->i++;
572 ctx->failed_cnt++;
573 #ifdef CUSTOM_AT_COMMAND
574 (void)uapi_at_printf(CRLF"Ping: destination unreachable"CRLF);
575 #else
576 LWIP_PLATFORM_PRINT("Ping: destination unreachable"CRLF);
577 #endif
578 return 0;
579 }
580
581 LWIP_STATIC void
ping_result_print(struct ping_run_ctx * ctx)582 ping_result_print(struct ping_run_ctx *ctx)
583 {
584 #ifdef CUSTOM_AT_COMMAND
585 (void)uapi_at_printf("%u packets transmitted, %u received, ", ctx->succ_cnt + ctx->failed_cnt, ctx->succ_cnt);
586 #if LWIP_IPV6
587 if (ctx->is_v6) {
588 float loss = ((float)ctx->failed_cnt * PERCENT) / (ctx->succ_cnt + ctx->failed_cnt);
589 (void)uapi_at_printf("%.2f%% loss", loss);
590 } else
591 #endif
592 {
593 (void)uapi_at_printf("%u loss", ctx->failed_cnt);
594 }
595
596 if (ctx->succ_cnt > 0) {
597 s32_t rtt_ave = ctx->rtt_sum / (s32_t)ctx->succ_cnt;
598 (void)uapi_at_printf(", rtt min/avg/max = %d/%d/%d ms"CRLF, ctx->rtt_min, rtt_ave, ctx->rtt_max);
599 (void)uapi_at_printf(CRLF"OK"CRLF);
600 } else {
601 (void)uapi_at_printf(CRLF"ERROR"CRLF);
602 }
603 #else
604 u8_t af = AF_INET;
605 const char *ipstr = NULL;
606 char str_buf[PING_ADDR_STR_LEN];
607 const void *src = &(((struct sockaddr_in *)&ctx->to)->sin_addr);
608
609 #if LWIP_IPV6
610 if (ctx->is_v6) {
611 af = AF_INET6;
612 src = &(((struct sockaddr_in6 *)&ctx->to)->sin6_addr);
613 }
614 #endif
615 ipstr = lwip_inet_ntop(af, src, str_buf, PING_ADDR_STR_LEN);
616 if (ipstr == NULL) {
617 ipstr = "****";
618 }
619
620 LWIP_PLATFORM_PRINT(CRLF"--- %s ping statistics ---"CRLF, ipstr);
621 LWIP_PLATFORM_PRINT("%u packets transmitted, %u received, %u loss"CRLF, ctx->succ_cnt + ctx->failed_cnt,
622 ctx->succ_cnt, ctx->failed_cnt);
623 LWIP_PLATFORM_PRINT(CRLF"OK"CRLF);
624 #endif
625 }
626
ping_setsockopt(struct ping_run_ctx * ctx,struct ping_cfg * cfg)627 LWIP_STATIC int ping_setsockopt(struct ping_run_ctx *ctx, struct ping_cfg *cfg)
628 {
629 int ret;
630 if (cfg->src_type == LWIP_PING_HOSTNAME_ARG) {
631 ret = lwip_bind(ctx->sfd, (struct sockaddr *)&cfg->src, (socklen_t)ctx->socklen);
632 if (ret == -1) {
633 #if CUSTOM_AT_COMMAND
634 (void)uapi_at_printf("ping bind fail errno = %d"CRLF, errno);
635 #else
636 LWIP_PLATFORM_PRINT("ping bind fail errno = %d"CRLF, errno);
637 #endif
638 return -1;
639 }
640 } else if (cfg->src_type == LWIP_PING_INTERFACE_ARG) {
641 struct ifreq req;
642 (void)memset_s(&req, sizeof(req), 0, sizeof(req));
643 ret = memcpy_s(req.ifr_ifrn.ifrn_name, sizeof(req.ifr_ifrn.ifrn_name) - 1, cfg->src_iface, strlen(cfg->src_iface));
644 if (ret != EOK) {
645 (void)lwip_close(ctx->sfd);
646 return -1;
647 }
648
649 /* Binding socket to the provided netif */
650 ret = lwip_setsockopt(ctx->sfd, SOL_SOCKET, SO_BINDTODEVICE, &req, sizeof(req));
651 if (ret == -1) {
652 LWIP_PLATFORM_PRINT("ping: unknown iface %s errno %d"CRLF, cfg->src_iface, errno);
653 return -1;
654 }
655 }
656
657 #if LWIP_IPV6 && LWIP_SOCK_OPT_ICMP6_FILTER
658 if (ctx->is_v6) {
659 struct icmp6_filter icmp6_sock_filter;
660 /* Setting socket filter since we are interested only in ECHO REPLY and ERROR messages */
661 ICMP6_FILTER_SETBLOCKALL(&icmp6_sock_filter);
662 ICMP6_FILTER_SETPASS(ICMP6_TYPE_EREP, &icmp6_sock_filter);
663 ICMP6_FILTER_SETPASS(ICMP6_TYPE_DUR, &icmp6_sock_filter);
664 ICMP6_FILTER_SETPASS(ICMP6_TYPE_PTB, &icmp6_sock_filter);
665 ICMP6_FILTER_SETPASS(ICMP6_TYPE_TE, &icmp6_sock_filter);
666
667 ret = lwip_setsockopt(ctx->sfd, IPPROTO_ICMPV6, ICMP6_FILTER, &icmp6_sock_filter, sizeof(struct icmp6_filter));
668 if (ret == -1) {
669 LWIP_PLATFORM_PRINT("ping : setsockopt: errno %d"CRLF, errno);
670 return -1;
671 }
672 }
673 #endif /* LWIP_SOCK_OPT_ICMP6_FILTER */
674 return 0;
675 }
676
677 /* as this is not an internal function removing static keyword */
678 LWIP_STATIC void
os_ping_func(void * para)679 os_ping_func(void* para)
680 {
681 LWIP_ERROR("os_ping_func para is null\n", para != NULL, return;);
682 struct ping_cfg *cfg = (struct ping_cfg *)para;
683
684 struct ping_run_ctx ctx;
685 int ret = -1;
686
687 if (ping_ctx_init(&ctx, cfg) != 0) {
688 mem_free(cfg);
689 goto FAILURE;
690 }
691
692 if (ctx.is_v6 == 0) {
693 ctx.sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
694 }
695 #if LWIP_IPV6
696 else {
697 ctx.sfd = lwip_socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
698 }
699 #endif
700 if (ctx.sfd < 0) {
701 #ifdef CUSTOM_AT_COMMAND
702 (void)uapi_at_printf("Ping socket create fail, errno = %d"CRLF, errno);
703 #else
704 LWIP_PLATFORM_PRINT("Ping socket create fail, errno = %d"CRLF, errno);
705 #endif
706 mem_free(cfg);
707 goto FAILURE;
708 }
709
710 if (ping_setsockopt(&ctx, cfg) == -1) {
711 mem_free(cfg);
712 goto FAILURE;
713 }
714
715 mem_free(cfg);
716 #ifdef CUSTOM_AT_COMMAND
717 if (ctx.is_v6 == 0) {
718 (void)uapi_at_printf("+PING:"CRLF);
719 } else {
720 (void)uapi_at_printf("+PING6:"CRLF);
721 }
722 #endif
723 ping_task_running = 1;
724 while ((ping_kill == 0) && ((ctx.forever != 0) || ((ctx.succ_cnt + ctx.failed_cnt) < ctx.cnt))) {
725 ctx.iecho->seqno = htons((u16_t)ctx.i);
726 ctx.iecho->chksum = 0;
727 ctx.iecho->chksum = inet_chksum((void *)ctx.iecho, ctx.iecho_len);
728 ret = sendto(ctx.sfd, ctx.iecho, ctx.iecho_len, 0, (struct sockaddr *)&ctx.to, (socklen_t)ctx.socklen);
729 if (ret < 0) {
730 #ifdef CUSTOM_AT_COMMAND
731 (void)uapi_at_printf("Ping: sending ICMP echo request fail errno %d"CRLF, errno);
732 #else
733 LWIP_PLATFORM_PRINT("Ping: sending ICMP echo request fail errno %d"CRLF, errno);
734 #endif
735 goto FAILURE;
736 }
737
738 if (ping_rcv(&ctx) != 0) {
739 break;
740 }
741 }
742
743 ping_result_print(&ctx);
744 #ifdef CONFIG_SIGMA_SUPPORT
745 if(upload_ping_result) {
746 upload_ping_result(ctx.succ_cnt, ctx.failed_cnt);
747 }
748 #endif
749 ret = (ctx.succ_cnt > 0) ? 0 : -1;
750 FAILURE:
751 ping_kill = 0;
752 ping_taskid = LWIP_DEFAULT_PING_TASK_ID;
753 ping_task_running = 0;
754 if (ctx.sfd >= 0) {
755 (void)lwip_close(ctx.sfd);
756 }
757 if (ctx.iphdr_resp != NULL) {
758 mem_free(ctx.iphdr_resp);
759 }
760 if (ctx.iecho != NULL) {
761 mem_free(ctx.iecho);
762 }
763 }
764
765 #if LWIP_LITEOS_TASK
766 static void
ping_cmd(unsigned int p0,unsigned int p1,unsigned int p2,unsigned int p3)767 ping_cmd(unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3)
768 {
769 union los_ptr_args ptr_args;
770
771 ptr_args.args[0] = p0;
772 ptr_args.args[1] = p1;
773 os_ping_func((struct ping_cfg *)ptr_args.ptr);
774
775 ping_taskid = LWIP_DEFAULT_PING_TASK_ID;
776 (void)p2;
777 (void)p3;
778 }
779 #endif
780
781 struct ping_cfg_handle {
782 const char *key;
783 u32_t *data;
784 int min;
785 int max;
786 int arg_num;
787 int (*handle)(struct ping_cfg_handle *src_handle, const char *arg);
788 };
789
790 LWIP_STATIC int
ping_cfg_parse_daddr(const char * daddr,struct sockaddr_storage * dst_ipaddr,u32_t is_v6)791 ping_cfg_parse_daddr(const char *daddr, struct sockaddr_storage *dst_ipaddr, u32_t is_v6)
792 {
793 dst_ipaddr->ss_family = AF_INET;
794 #if LWIP_IPV6
795 if (is_v6) {
796 dst_ipaddr->ss_family = AF_INET6;
797 }
798 #endif
799 /* initialize dst IP address */
800 #if LWIP_DNS
801 struct addrinfo hints_structure;
802 struct addrinfo *res = NULL;
803
804 /* Resolve the given hostname */
805 hints_structure.ai_family = dst_ipaddr->ss_family;
806 hints_structure.ai_flags = 0;
807 if (lwip_getaddrinfo(daddr, NULL, &hints_structure, &res) != ERR_OK) {
808 goto fail;
809 }
810
811 #if LWIP_IPV6
812 if (is_v6) {
813 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)dst_ipaddr;
814 sin6->sin6_addr = ((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr;
815 sin6->sin6_family = AF_INET6;
816 sin6->sin6_port = 0;
817 sin6->sin6_scope_id = 0;
818 sin6->sin6_flowinfo = 0;
819 } else
820 #endif
821 {
822 struct sockaddr_in *sin = (struct sockaddr_in *)dst_ipaddr;
823 sin->sin_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr;
824 sin->sin_family = AF_INET;
825 sin->sin_port = 0;
826 }
827 lwip_freeaddrinfo(res);
828 #else /* LWIP_DNS */
829 void *buf = NULL;
830 #if LWIP_IPV6
831 if (is_v6) {
832 buf = &(((struct sockaddr_in6 *)dst_ipaddr)->sin6_addr);
833 } else
834 #endif
835 {
836 buf = &(((struct sockaddr_in *)dst_ipaddr)->sin_addr);
837 }
838
839 if (lwip_inet_pton(dst_ipaddr->ss_family, daddr, buf) != 1) {
840 goto fail;
841 }
842 #endif /* LWIP_DNS */
843
844 #if LWIP_IPV6
845 if (is_v6) {
846 ip6_addr_t ip6;
847 inet6_addr_to_ip6addr(&ip6, &((struct sockaddr_in6 *)dst_ipaddr)->sin6_addr);
848 if (ip6_addr_isany(&ip6) || ip6_addr_isnone(&ip6)) {
849 goto fail;
850 }
851 } else
852 #endif
853 {
854 ip4_addr_t ip4;
855 ip4.addr = ((struct sockaddr_in *)dst_ipaddr)->sin_addr.s_addr;
856 if ((ip4.addr == IPADDR_NONE) || (ip4.addr == IPADDR_ANY)) {
857 goto fail;
858 }
859 }
860 return 0;
861
862 fail:
863 #ifdef CUSTOM_AT_COMMAND
864 (void)uapi_at_printf("Host:%s can't be resolved to IP"CRLF, daddr);
865 #else
866 LWIP_PLATFORM_PRINT("Host:%s can't be resolved to IP"CRLF, daddr);
867 #endif
868 return -1;
869 }
870
ping_cfg_handle_src_addr(struct ping_cfg_handle * src_handle,const char * arg)871 LWIP_STATIC int ping_cfg_handle_src_addr(struct ping_cfg_handle *src_handle, const char *arg)
872 {
873 struct ping_cfg *cfg = (struct ping_cfg *)src_handle->data;
874 u16_t family = AF_INET;
875 void *buf = &(((struct sockaddr_in *)&cfg->src)->sin_addr);
876
877 #if LWIP_IPV6
878 if (cfg->is_v6) {
879 family = AF_INET6;
880 buf = &(((struct sockaddr_in6 *)&cfg->src)->sin6_addr);
881 }
882 #endif
883 if (lwip_inet_pton(family, arg, buf) != 1) {
884 if (strcpy_s(cfg->src_iface, NETIF_NAMESIZE, arg) != EOK) {
885 return -1;
886 }
887
888 cfg->src_type = LWIP_PING_INTERFACE_ARG;
889 return 0;
890 }
891
892 struct sockaddr_in *sin = (struct sockaddr_in *)&cfg->src;
893 sin->sin_family = family;
894 cfg->src_type = LWIP_PING_HOSTNAME_ARG;
895 return 0;
896 }
897
898 LWIP_STATIC int
ping_cfg_parse(int argc,const char ** argv,struct ping_cfg * cfg,u32_t * ping_kill_flag)899 ping_cfg_parse(int argc, const char **argv, struct ping_cfg *cfg, u32_t *ping_kill_flag)
900 {
901 u32_t ping_forever = 0;
902 u32_t i = 0;
903 u32_t j = 0;
904 s64_t ret;
905 struct ping_cfg_handle handle[] = {
906 {
907 .key = "-k",
908 .data = ping_kill_flag,
909 .min = 0,
910 .max = INT_MAX,
911 .arg_num = 0,
912 .handle = NULL,
913 },
914 {
915 .key = "-n",
916 .data = &cfg->count,
917 .min = 1,
918 .max = INT_MAX,
919 .arg_num = 1,
920 .handle = NULL,
921 },
922 {
923 .key = "-c",
924 .data = &cfg->count,
925 .min = 1,
926 .max = INT_MAX,
927 .arg_num = 1,
928 .handle = NULL,
929 },
930 {
931 .key = "-t",
932 .data = &ping_forever,
933 .min = 0,
934 .max = INT_MAX,
935 .arg_num = 0,
936 .handle = NULL,
937 },
938 {
939 .key = "-w",
940 .data = &cfg->interval,
941 .min = 1,
942 .max = INT_MAX,
943 .arg_num = 1,
944 .handle = NULL,
945 },
946 {
947 .key = "-W",
948 .data = &cfg->timeout,
949 .min = LWIP_SHELL_CMD_PING_TIMEOUT_MIN,
950 .max = LWIP_SHELL_CMD_PING_TIMEOUT_MAX,
951 .arg_num = 1,
952 .handle = NULL,
953 },
954 {
955 .key = "-l",
956 .data = &cfg->data_len,
957 .min = 0,
958 #ifndef CUSTOM_AT_COMMAND
959 .max = (int)(LWIP_MAX_UDP_RAW_SEND_SIZE - sizeof(struct icmp_echo_hdr)) - PBUF_ZERO_COPY_RESERVE,
960 #else
961 .max = LWIP_PING_MAX_PKT_LEN,
962 #endif
963 .arg_num = 1,
964 .handle = NULL,
965 },
966 {
967 .key = "-6",
968 .data = &cfg->is_v6,
969 .min = 0,
970 .max = INT_MAX,
971 .arg_num = 0,
972 .handle = NULL,
973 },
974 {
975 .key = "-I",
976 .data = (u32_t *)cfg,
977 .min = 0,
978 .max = INT_MAX,
979 .arg_num = 1,
980 .handle = ping_cfg_handle_src_addr,
981 },
982 };
983 cfg->count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
984 cfg->is_v6 = 0;
985 /* could add more param support */
986 while (argc > 0) {
987 u8_t match = 0;
988 for (j = 0; j < LWIP_ARRAYSIZE(handle); j++) {
989 if (strcmp(argv[i], handle[j].key) == 0) {
990 if ((handle[j].arg_num + 1) > argc) {
991 goto param_error;
992 }
993
994 if (handle[j].arg_num == 0) {
995 *(handle[j].data) = 1;
996 if (ping_kill_flag == handle[j].data) {
997 return 0;
998 }
999 } else if (handle[j].handle != NULL) {
1000 ret = (*handle[j].handle)(&handle[j], argv[i + 1]);
1001 if (ret != 0) {
1002 #ifdef CUSTOM_AT_COMMAND
1003 (void)uapi_at_printf("Ping %s arg error"CRLF, handle[j].key);
1004 #else
1005 LWIP_PLATFORM_PRINT("Ping %s arg error"CRLF, handle[j].key);
1006 #endif
1007 return -1;
1008 }
1009 } else {
1010 char *invalid_ptr;
1011 ret = strtoll(argv[i + 1], &invalid_ptr, 10);
1012 if(invalid_ptr && strlen(invalid_ptr) != 0) {
1013 LWIP_PLATFORM_PRINT("Invalid parameter: |%s|\n", argv[i + 1]);
1014 return -1;
1015 }
1016
1017 if ((ret < (s64_t)handle[j].min) || (ret > (s64_t)handle[j].max)) {
1018 #ifdef CUSTOM_AT_COMMAND
1019 (void)uapi_at_printf("Ping %s arg error, range:[%d, %d] "CRLF,
1020 handle[j].key, handle[j].min, handle[j].max);
1021 #else
1022 LWIP_PLATFORM_PRINT("Ping %s arg error, range:[%d, %d] "CRLF,
1023 handle[j].key, handle[j].min, handle[j].max);
1024 #endif
1025 return -1;
1026 }
1027 *(handle[j].data) = (u32_t)ret;
1028 }
1029 i += handle[j].arg_num + 1;
1030 argc -= handle[j].arg_num + 1;
1031 match = 1;
1032 break;
1033 }
1034 }
1035
1036 if (match == 0) {
1037 break;
1038 }
1039 }
1040
1041 if (argc != 1) {
1042 param_error:
1043 #ifdef CUSTOM_AT_COMMAND
1044 (void)uapi_at_printf("Invalid param"CRLF);
1045 #else
1046 LWIP_PLATFORM_PRINT("Invalid param"CRLF);
1047 #endif
1048 return -1;
1049 }
1050
1051 if (ping_cfg_parse_daddr(argv[i], &cfg->dst, cfg->is_v6) == -1) {
1052 return -1;
1053 }
1054
1055 if (ping_forever == 1) {
1056 cfg->count = 0;
1057 }
1058 return 0;
1059 }
1060
1061 #if LWIP_LITEOS_TASK
ping_task_create(struct ping_cfg * cfg,u16_t prio)1062 LWIP_STATIC u32_t ping_task_create(struct ping_cfg *cfg, u16_t prio)
1063 {
1064 UINT32 los_ret;
1065 TSK_INIT_PARAM_S st_ping_task;
1066 union los_ptr_args ptr_args = {0};
1067
1068 /* start one task if ping forever or ping count greater than 60 */
1069 if (ping_taskid != LWIP_DEFAULT_PING_TASK_ID) {
1070 #ifdef CUSTOM_AT_COMMAND
1071 (void)uapi_at_printf("Ping task is running"CRLF);
1072 #else
1073 LWIP_PLATFORM_PRINT("Ping task is running"CRLF);
1074 #endif
1075 return OS_NOK;
1076 }
1077 ptr_args.ptr = cfg;
1078
1079 st_ping_task.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd;
1080 st_ping_task.uwStackSize = 4096;
1081 st_ping_task.pcName = "ping_task";
1082 st_ping_task.usTaskPrio = prio; /* equal lwip */
1083 st_ping_task.uwResved = LOS_TASK_STATUS_DETACHED;
1084 #ifdef LOSCFG_OBSOLETE_API
1085 st_ping_task.auwArgs[0] = ptr_args.args[0];
1086 st_ping_task.auwArgs[1] = ptr_args.args[1];
1087 st_ping_task.auwArgs[2] = 0;
1088 st_ping_task.auwArgs[3] = 0;
1089 #else
1090 st_ping_task.pArgs=(void*)(ptr_args.args[0]);
1091 #endif
1092 los_ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &st_ping_task);
1093 if (los_ret != OS_OK) {
1094 #ifdef CUSTOM_AT_COMMAND
1095 (void)uapi_at_printf("ping_task create fail 0x%08x."CRLF, los_ret);
1096 #else
1097 LWIP_PLATFORM_PRINT("ping_task create fail 0x%08x."CRLF, los_ret);
1098 #endif
1099 return OS_NOK;
1100 }
1101 return OS_OK;
1102 }
1103 #endif
1104
ping_exec(struct ping_cfg * cfg)1105 LWIP_STATIC u32_t ping_exec(struct ping_cfg *cfg)
1106 {
1107 #ifdef CUSTOM_AT_COMMAND
1108 #if LWIP_LITEOS_TASK
1109 u32_t ret = ping_task_create(cfg, LWIP_PING_TASK_PRIO);
1110 if (ret != OS_OK) {
1111 mem_free(cfg);
1112 }
1113 return ret;
1114 #endif
1115 #else
1116 #if LWIP_LITEOS_TASK
1117 /* start one task if ping forever or ping count greater than 60 */
1118 if ((cfg->count == 0) || (cfg->count > LWIP_SHELL_CMD_PING_RETRY_TIMES)) {
1119 u32_t ret = ping_task_create(cfg, LWIP_PING_TASK_PRIO);
1120 if ((ret == OS_NOK) || (ping_taskid == LWIP_DEFAULT_PING_TASK_ID)) {
1121 cfg->count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
1122 } else {
1123 return OS_OK;
1124 }
1125 }
1126 #endif
1127 /* Use threads to perform ping operations. */
1128 ping_taskid = sys_thread_new("ping_thread", os_ping_func, (void*)cfg, TCPIP_THREAD_STACKSIZE, 8);
1129 #if !LWIP_FREERTOS_COMPAT
1130 /* Bugfix: The processing of the thread return is slower than that of the os_ping_func function. */
1131 ping_taskid = ping_task_running == 0 ? LWIP_DEFAULT_PING_TASK_ID : ping_taskid;
1132 #endif
1133 return OS_OK;
1134 #endif
1135 }
1136
1137 u32_t
os_shell_ping(int argc,const char ** argv)1138 os_shell_ping(int argc, const char **argv)
1139 {
1140 struct ping_cfg *cfg = NULL;
1141 u32_t ping_kill_flag = 0;
1142
1143 if (tcpip_init_finish == 0) {
1144 #ifdef CUSTOM_AT_COMMAND
1145 (void)uapi_at_printf("shell_ping tcpip_init have not been called"CRLF);
1146 #else
1147 LWIP_PLATFORM_PRINT("shell_ping tcpip_init have not been called"CRLF);
1148 #endif
1149 return OS_NOK;
1150 }
1151
1152 cfg = mem_malloc(sizeof(struct ping_cfg));
1153 if (cfg == NULL) {
1154 #ifdef CUSTOM_AT_COMMAND
1155 (void)uapi_at_printf("shell_ping malloc fail"CRLF);
1156 #else
1157 LWIP_PLATFORM_PRINT("shell_ping malloc fail"CRLF);
1158 #endif
1159 return OS_NOK;
1160 }
1161 cfg->count = 0;
1162 cfg->interval = 1000; /* default ping interval */
1163 cfg->timeout = LWIP_SHELL_CMD_PING_TIMEOUT;
1164 cfg->data_len = 48; /* default data length */
1165 cfg->src_type = LWIP_PING_DEFAULT_SOCKET;
1166 cfg->is_v6 = 0;
1167
1168 if ((argc < 1) || (argv == NULL)) {
1169 #ifdef CUSTOM_AT_COMMAND
1170 (void)uapi_at_printf("Ping: require dest ipaddr at least "CRLF);
1171 #else
1172 LWIP_PLATFORM_PRINT("Ping: require dest ipaddr at least "CRLF);
1173 #endif
1174 goto ping_error;
1175 }
1176 if (ping_cfg_parse(argc, argv, cfg, &ping_kill_flag) == -1) {
1177 goto ping_error;
1178 }
1179
1180 if (ping_kill_flag == 1) {
1181 u32_t is_v6 = cfg->is_v6;
1182 mem_free(cfg);
1183 if (ping_taskid != LWIP_DEFAULT_PING_TASK_ID) {
1184 ping_kill = 1; /* stop the current ping task */
1185 #ifdef CUSTOM_AT_COMMAND
1186 (void)uapi_at_printf("+PING%s:"CRLF"OK"CRLF, is_v6 ? "6" : "");
1187 #else
1188 LWIP_UNUSED_ARG(is_v6);
1189 #endif
1190 return (int)OS_OK;
1191 } else {
1192 LWIP_PLATFORM_PRINT("No ping task running"CRLF);
1193 return (int)OS_NOK;
1194 }
1195 }
1196
1197 if(ping_task_running == 1) {
1198 LWIP_PLATFORM_PRINT("Now ping task is running"CRLF);
1199 mem_free(cfg);
1200 return OS_NOK;
1201 }
1202
1203 return ping_exec(cfg);
1204 ping_error:
1205 lwip_ping_usage(cfg->is_v6);
1206 mem_free(cfg);
1207 return OS_NOK;
1208 }
1209
1210 #if LWIP_IPV6
os_shell_ping6(int argc,const char ** argv)1211 u32_t os_shell_ping6(int argc, const char **argv)
1212 {
1213 int i;
1214 u32_t ret;
1215 const char **argv6 = mem_malloc(sizeof(char *) * (argc + 1));
1216 if (argv6 == NULL) {
1217 #ifdef CUSTOM_AT_COMMAND
1218 (void)uapi_at_printf("ping6 malloc fail"CRLF);
1219 #else
1220 LWIP_PLATFORM_PRINT("ping6 malloc fail"CRLF);
1221 #endif
1222 return OS_NOK;
1223 }
1224
1225 argv6[0] = "-6";
1226 for (i = 0; i < argc; i++) {
1227 argv6[i + 1] = argv[i];
1228 }
1229 argc++;
1230 ret = os_shell_ping(argc, argv6);
1231 mem_free(argv6);
1232 return ret;
1233 }
1234 #endif /* LWIP_IPV6 */
1235
1236 #endif /* LWIP_ENABLE_BASIC_SHELL_CMD */
1237