1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "../core/ipv4/etharp.c" /* for arp_table */ 33#define icmp6_hdr netinet_icmp6_hdr 34#include <netinet/icmp6.h> 35#undef icmp6_hdr 36#include "lwip/fixme.h" 37#include "lwip/opt.h" 38 39#if LWIP_ENABLE_LOS_SHELL_CMD 40#include "lwip/api.h" 41#include "lwip/tcpip.h" 42#include "lwip/netif.h" 43#include "lwip/netdb.h" 44#include "lwip/stats.h" 45#include "lwip/err.h" 46#include "lwip/inet.h" 47#include "netif/etharp.h" 48#include "lwip/ip_addr.h" 49#include "lwip/ip6_addr.h" 50#include "lwip/icmp.h" 51#include "lwip/priv/nd6_priv.h" 52#include "lwip/sockets.h" 53#include "lwip/inet_chksum.h" 54#include "lwip/raw.h" 55#include "los_config.h" 56#include <string.h> 57#include "limits.h" 58#include <stdlib.h> 59#include <stdio.h> 60#include <errno.h> 61#include <time.h> 62#include <ctype.h> 63#include <poll.h> 64 65#include "lwip/api_shell.h" 66 67#include "lwip/dns.h" 68#include "lwip/udp.h" 69#include "lwip/priv/tcp_priv.h" 70 71#include "lwip/dhcp.h" 72#include "lwip/netifapi.h" 73#include "los_strnlen_user.h" 74#include "linux/kernel.h" 75#ifdef LOSCFG_SHELL 76#include "shcmd.h" 77#include "shell.h" 78#endif 79 80#define LWIP_STATIC static 81 82#if LWIP_ARP 83extern sys_sem_t ip_conflict_detect; 84#endif 85extern volatile int tcpip_init_finish; 86extern const char *const tcp_state_str[]; 87extern int get_unused_socket_num(void); 88 89#if LWIP_IPV6 90#define LWIP_MAX_PING6_ARG_COUNT 64 91#define LWIP_PING6_STANDARD_PKT_SIZE 56 92#define LWIP_PING6_STARTING_SEQ_NUM 0x2255 93#define LWIP_PING6_OUT_OF_ORDER_MAGNITUDE 1 94 95#define LWIP_PING6_COUNT_ARG 1 96#define LWIP_PING6_SOURCE_ADDRESS_ARG 2 97#define LWIP_PING6_INTERFACE_ARG 4 98#define LWIP_PING6_HOSTNAME_ARG 8 99#define LWIP_PING6_DEFAULT_SOCKET 16 100#endif 101 102/* Forward Declarations [START] */ 103#ifndef LWIP_TESTBED 104LWIP_STATIC 105#endif 106int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len); 107 108#ifndef LWIP_TESTBED 109LWIP_STATIC 110#endif 111void lwip_ifconfig_show_internal(void *arg); 112 113#ifndef LWIP_TESTBED 114LWIP_STATIC 115#endif 116void lwip_ifconfig_internal(void *arg); 117 118void lwip_printsize(size_t size); 119LWIP_STATIC void lwip_ifconfig_usage(const char *cmd); 120 121#ifndef LWIP_TESTBED 122LWIP_STATIC 123#endif 124void lwip_arp_show_internal(struct netif *netif, char *printf_buf, unsigned int buf_len); 125 126#ifndef LWIP_TESTBED 127LWIP_STATIC 128#endif 129void lwip_arp_internal(void *arg); 130 131LWIP_STATIC void lwip_arp_usage(const char *cmd); 132void ifup_internal(void *arg); 133void ifdown_internal(void *arg); 134 135#if LWIP_DNS 136LWIP_STATIC unsigned int get_hostip(const char *hname); 137 138#ifndef LWIP_TESTBED 139LWIP_STATIC 140#endif 141struct hostent *gethostnameinfo(const char *host); 142 143#endif /* LWIP_DNS */ 144 145#ifdef LWIP_DEBUG_INFO 146LWIP_STATIC u32_t netdebug_memp(int argc, const char **argv); 147LWIP_STATIC u32_t netdebug_sock(int argc, const char **argv); 148u32_t osShellNetDebug(int argc, const char **argv); 149u32_t osShellIpDebug(int argc, const char **argv); 150#endif /* LWIP_DEBUG_INFO */ 151#if LWIP_IPV6 152/* Holds params for ping6 task */ 153typedef struct ping6_args { 154 u8_t args_found; 155 u8_t interface_index; 156 u8_t host_index; 157 u8_t pad; 158 u32_t pingcount; 159 ip6_addr_t src_addr; 160 ip6_addr_t dst_addr; 161} ping6_args_t; 162 163/* Holds stats for ongoing ping6 task */ 164typedef struct ping6_stats { 165 u32_t flag; 166 u32_t min_rtt; 167 u32_t max_rtt; 168 float avg_rtt; 169} ping6_stats_t; 170LWIP_STATIC void update_ping6_stats(ping6_stats_t *ping6_stats, u32_t rtt, u32_t nreceived); 171LWIP_STATIC int parse_args_ping6(int argc, const char **argv, ping6_args_t *ping6_params); 172 173u32_t osShellPing6(int argc, const char **argv); 174LWIP_STATIC int create_ping6_socket(u8_t type, const void *param); 175LWIP_STATIC const char *convert_icmpv6_err_to_string(u8_t err_type); 176#endif /* LWIP_IPV6 */ 177u32_t osTcpserver(int argc, const char **argv); 178void udpserver(int argc, const char **argv); 179void tcp_access(int sockfd); 180#if LWIP_IPV6 181int netstat_get_udp_sendQLen6(struct udp_pcb *udppcb, struct pbuf *udpbuf); 182int netstat_udp_sendq6(struct udp_pcb *upcb); 183#endif 184#if LWIP_IPV4 185int netstat_get_udp_sendQLen(struct udp_pcb *udppcb, struct pbuf *udpbuf); 186#endif 187int netstat_tcp_sendq(struct tcp_pcb *tpcb); 188int netstat_tcp_recvq(struct tcp_pcb *tpcb); 189int netstat_netconn_recvq(const struct netconn *conn); 190 191int netstat_udp_sendq(struct udp_pcb *upcb); 192int netstat_netconn_sendq(struct netconn *conn); 193/* Forward Declarations [END] */ 194 195#define IFCONFIG_OPTION_SET_IP (1) 196#define IFCONFIG_OPTION_SET_NETMASK (1 << 1) 197#define IFCONFIG_OPTION_SET_GW (1 << 2) 198#define IFCONFIG_OPTION_SET_HW (1 << 3) 199#define IFCONFIG_OPTION_SET_UP (1 << 4) 200#define IFCONFIG_OPTION_SET_DOWN (1 << 5) 201#define IFCONFIG_OPTION_SET_MTU (1 << 6) 202#define IFCONFIG_OPTION_DEL_IP (1 << 7) 203 204#define NETSTAT_ENTRY_SIZE 120 205#define MAX_NETSTAT_ENTRY (NETSTAT_ENTRY_SIZE * (MEMP_NUM_TCP_PCB + MEMP_NUM_UDP_PCB + MEMP_NUM_TCP_PCB_LISTEN + 1)) 206 207#define PRINT_BUF_LEN 1024 208#define MAX_MACADDR_STRING_LENGTH 18 /* including NULL */ 209 210#define CONVERT_STRING_TO_HEX(_src, _dest) \ 211{ \ 212 const char *_srcString = (char *)_src; \ 213 _dest = 0; \ 214 while (*_srcString) { \ 215 _dest = (unsigned char)((_dest << 4) & 0xFF); \ 216 if ((*_srcString >= 48) && (*_srcString <= 57)) /* between 0 to 9 */ \ 217 _dest |= (unsigned char)(*_srcString - 48); \ 218 else if ((*_srcString >= 65 && *_srcString <= 70)) /* between A to F */ \ 219 _dest |= (unsigned char)((*_srcString - 65) + 10); \ 220 else if ((*_srcString >= 97 && *_srcString <= 102)) /* between a to f */ \ 221 _dest |= (unsigned char)((*_srcString - 97) + 10); \ 222 else break; \ 223 ++_srcString; \ 224 } \ 225} 226 227#define ERR_IFCONFIG_STRING_PUT(ret, str) \ 228 do { \ 229 (ret) = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, \ 230 PRINT_BUF_LEN - ifconfig_cmd->print_len, \ 231 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), (str)); \ 232 if (((ret) > 0) && ((unsigned int)(ret) < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) \ 233 ifconfig_cmd->print_len += (unsigned int)(ret); \ 234 } while (0) \ 235 236#define LWIP_MSECS_TO_SECS(time_in_msecs) (time_in_msecs / 1000) 237struct ifconfig_option { 238 char iface[IFNAMSIZ]; 239 unsigned int option; 240 ip_addr_t ip_addr; 241 ip_addr_t netmask; 242 ip_addr_t gw; 243 unsigned char ethaddr[6]; 244 u16_t mtu; 245 /* when using telnet, print to the telnet socket will result in system */ 246 /* deadlock. So we cache the print data to a buf, and when the tcpip */ 247 /* callback returns, then print the data out to the telnet socket */ 248 sys_sem_t cb_completed; 249 char cb_print_buf[PRINT_BUF_LEN]; 250 unsigned int print_len; 251}; 252 253struct netstat_data { 254 s8_t *netstat_out_buf; 255 u32_t netstat_out_buf_len; 256 u32_t netstat_out_buf_updated_len; 257 sys_sem_t cb_completed; 258}; 259 260struct if_cmd_data { 261 char *if_name; 262 err_t err; 263 sys_sem_t cb_completed; 264}; 265 266#ifndef LWIP_TESTBED 267LWIP_STATIC 268#endif 269int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len) 270{ 271 int i, ret; 272 char *tmp = print_buf; 273#if LWIP_IPV6 274 char *addr = NULL; 275#endif 276#ifdef LOSCFG_NET_CONTAINER 277 struct net_group *group = get_net_group_from_netif(netif); 278#endif 279 if (buf_len < 1) { 280 goto out; 281 } 282 if (netif->link_layer_type == LOOPBACK_IF) { 283 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%.2s\t", netif->name); 284 } else { 285 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%s\t", netif_get_name(netif)); 286 } 287 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 288 goto out; 289 tmp += ret; 290 buf_len -= (unsigned int)ret; 291#if LWIP_IPV4 292 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "ip:%s ", ipaddr_ntoa(&netif->ip_addr)); 293 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 294 goto out; 295 tmp += ret; 296 buf_len -= (unsigned int)ret; 297 298 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "netmask:%s ", ipaddr_ntoa(&netif->netmask)); 299 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 300 goto out; 301 tmp += ret; 302 buf_len -= (unsigned int)ret; 303 304 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "gateway:%s\n", ipaddr_ntoa(&netif->gw)); 305 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 306 goto out; 307 tmp += ret; 308 buf_len -= (unsigned int)ret; 309#endif 310 311#if LWIP_IPV6 312 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 313 /* only PREFERRED addresses are displyaed */ 314 if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) { 315 continue; 316 } 317 addr = ip6addr_ntoa((const ip6_addr_t *)&netif->ip6_addr[i]); 318 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tip6: %s/64\n", addr ? addr : "::"); 319 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 320 goto out; 321 tmp += ret; 322 buf_len -= (unsigned int)ret; 323 } 324#endif 325 326 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tHWaddr "); 327 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 328 goto out; 329 tmp += ret; 330 buf_len -= (unsigned int)ret; 331 332 for (i = 0; i < netif->hwaddr_len - 1; i++) { 333 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x:", netif->hwaddr[i]); 334 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 335 goto out; 336 tmp += ret; 337 buf_len -= (unsigned int)ret; 338 } 339 340 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x", netif->hwaddr[i]); 341 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 342 goto out; 343 tmp += ret; 344 buf_len -= (unsigned int)ret; 345 346 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " MTU:%d %s", netif->mtu, 347 (netif->flags & NETIF_FLAG_UP) ? "Running" : "Stop"); 348 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 349 goto out; 350 tmp += ret; 351 buf_len -= (unsigned int)ret; 352 353#ifdef LOSCFG_NET_CONTAINER 354 if ((group->netif_default == netif) && (netif_is_up(netif))) { 355#else 356 if (netif_default == netif && netif_is_up(netif)) { 357#endif 358 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s", "Default"); 359 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 360 goto out; 361 tmp += ret; 362 buf_len -= (unsigned int)ret; 363 } 364 365 ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s\n", 366 (netif->flags & NETIF_FLAG_LINK_UP) ? "Link UP" : "Link Down"); 367 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 368 goto out; 369 tmp += ret; 370 371#if MIB2_STATS 372 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tRX packets:%u ", 373 netif->mib2_counters.ifinucastpkts + netif->mib2_counters.ifinnucastpkts); 374 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 375 goto out; 376 tmp += ret; 377 buf_len -= (unsigned int)ret; 378 379 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "errors:%u ", netif->mib2_counters.ifinerrors); 380 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 381 goto out; 382 tmp += ret; 383 buf_len -= (unsigned int)ret; 384 385 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "dropped:%u ", netif->mib2_counters.ifindiscards); 386 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 387 goto out; 388 tmp += ret; 389 buf_len -= (unsigned int)ret; 390 391 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "overruns:%u\n", netif->mib2_counters.ifinoverruns); 392 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 393 goto out; 394 tmp += ret; 395 buf_len -= (unsigned int)ret; 396 397 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tTX packets:%u ", 398 netif->mib2_counters.ifoutucastpkts + netif->mib2_counters.ifoutnucastpkts); 399 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 400 goto out; 401 tmp += ret; 402 buf_len -= (unsigned int)ret; 403 404 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "errors:%u ", netif->mib2_counters.ifouterrors); 405 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 406 goto out; 407 tmp += ret; 408 buf_len -= (unsigned int)ret; 409 410 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "dropped:%u\n", netif->mib2_counters.ifoutdiscards); 411 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 412 goto out; 413 tmp += ret; 414 buf_len -= (unsigned int)ret; 415 416 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tRX bytes:%u ", netif->mib2_counters.ifinoctets); 417 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 418 goto out; 419 tmp += ret; 420 buf_len -= (unsigned int)ret; 421 422 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "TX bytes:%u\n", netif->mib2_counters.ifoutoctets); 423 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 424 goto out; 425 tmp += ret; 426 buf_len -= (unsigned int)ret; 427#endif 428 429out: 430 return (int)(tmp - print_buf); 431} 432 433#ifndef LWIP_TESTBED 434LWIP_STATIC 435#endif 436void lwip_ifconfig_show_internal(void *arg) 437{ 438 struct netif *netif = NULL; 439 struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg; 440 int ret; 441#ifdef LOSCFG_NET_CONTAINER 442 struct net_group *group = get_curr_process_net_group(); 443 if (group->netif_list == NULL) { 444#else 445 if (netif_list == NULL) { 446#endif 447 ret = snprintf_s(ifconfig_cmd->cb_print_buf, PRINT_BUF_LEN - ifconfig_cmd->print_len, 448 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not init\n"); 449 if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) { 450 ifconfig_cmd->print_len += (unsigned int)ret; 451 } 452 sys_sem_signal(&ifconfig_cmd->cb_completed); 453 return; 454 } 455 456 if (ifconfig_cmd->iface[0] == '\0') { 457 /* display all netif */ 458#ifdef LOSCFG_NET_CONTAINER 459 for (netif = group->netif_list; netif != NULL; netif = netif->next) { 460#else 461 for (netif = netif_list; netif != NULL; netif = netif->next) { 462#endif 463 ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, 464 PRINT_BUF_LEN - ifconfig_cmd->print_len); 465 ifconfig_cmd->print_len += (unsigned int)ret; 466 } 467 } else { 468 netif = netif_find(ifconfig_cmd->iface); 469 if (netif == NULL) { 470 ret = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, 471 (PRINT_BUF_LEN - ifconfig_cmd->print_len), 472 ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not found\n"); 473 if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) { 474 ifconfig_cmd->print_len += (unsigned int)ret; 475 } 476 477 sys_sem_signal(&ifconfig_cmd->cb_completed); 478 return; 479 } 480 481 ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, 482 PRINT_BUF_LEN - ifconfig_cmd->print_len); 483 ifconfig_cmd->print_len += (unsigned int)ret; 484 } 485 sys_sem_signal(&ifconfig_cmd->cb_completed); 486} 487 488#ifndef LWIP_TESTBED 489LWIP_STATIC 490#endif 491void lwip_ifconfig_internal(void *arg) 492{ 493 struct ifconfig_option *ifconfig_cmd = NULL; 494 struct netif *netif = NULL; 495 ip_addr_t ip_addr; 496 ip_addr_t netmask; 497 ip_addr_t gw; 498 unsigned short mtu; 499 struct netif *loc_netif = NULL; 500 int ret; 501 s8_t idx; 502 err_t err; 503#ifdef LOSCFG_NET_CONTAINER 504 struct net_group *group = get_curr_process_net_group(); 505#endif 506 ifconfig_cmd = (struct ifconfig_option *)arg; 507 netif = netif_find(ifconfig_cmd->iface); 508 if (netif == NULL) { 509 ERR_IFCONFIG_STRING_PUT(ret, "Device not found\n"); 510 goto out; 511 } 512 513 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_UP) { 514 (void)netif_set_up(netif); 515 goto out; 516 } else if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_DOWN) { 517 (void)netif_set_down(netif); 518 goto out; 519 } 520 521 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) || 522 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) || 523 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW)) { 524 (void)netif_set_down(netif); 525 } 526 527 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) { 528 ip_addr_set_val(&ip_addr, &(ifconfig_cmd->ip_addr)); 529 if (IP_IS_V4_VAL(ifconfig_cmd->ip_addr)) { 530 /* check the address is not multicast/broadcast/0/loopback */ 531 if (ip_addr_ismulticast_val(&ip_addr) || ip_addr_isbroadcast_val(&ip_addr, netif) || 532 ip_addr_isany(&ip_addr) || ip_addr_isloopback(&ip_addr)) { 533 ERR_IFCONFIG_STRING_PUT(ret, "Don't set ip as a multicast/broadcast/0/loopback address!\n"); 534 goto out; 535 } 536 537 /* reset gateway if new and previous ipaddr not in same net */ 538 if (!ip_addr_netcmp_val(&ip_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask))) { 539 ip_addr_set_zero(&netif->gw); 540#ifdef LOSCFG_NET_CONTAINER 541 if (netif == group->netif_default) { 542 (void)netif_set_default(NULL, group); 543#else 544 if (netif == netif_default) { 545 (void)netif_set_default(NULL); 546#endif 547 } 548 } 549 550 /* lwip disallow two netif sit in same net at the same time */ 551#ifdef LOSCFG_NET_CONTAINER 552 loc_netif = group->netif_list; 553#else 554 loc_netif = netif_list; 555#endif 556 while (loc_netif != NULL) { 557 if (loc_netif == netif) { 558 loc_netif = loc_netif->next; 559 continue; 560 } 561 if (IP_IS_V4_VAL(ifconfig_cmd->ip_addr) && ip_addr_cmp(&netif->netmask, &loc_netif->netmask) && 562 ip_addr_netcmp_val(&loc_netif->ip_addr, &ip_addr, ip_2_ip4(&netif->netmask))) { 563 ERR_IFCONFIG_STRING_PUT(ret, "Duplicate network!\n"); 564 goto out; 565 } 566 loc_netif = loc_netif->next; 567 } 568 569#if LWIP_DHCP 570 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) { 571 (void)netif_dhcp_off(netif); 572 } 573#endif 574 netif_set_ipaddr(netif, ip_2_ip4(&ip_addr)); 575 } else if (IP_IS_V6_VAL(ifconfig_cmd->ip_addr)) { 576 idx = -1; 577 err = netif_add_ip6_address(netif, ip_2_ip6(&ip_addr), &idx); 578 if (err != ERR_OK || idx == -1) { 579 ERR_IFCONFIG_STRING_PUT(ret, "The IPv6 has reached the Global address limit, " 580 "you should delete one address before add!\n"); 581 goto out; 582 } 583 } 584 } 585 586 if (ifconfig_cmd->option & IFCONFIG_OPTION_DEL_IP) { 587 (void)netif_do_rmv_ipv6_addr(netif, &ifconfig_cmd->ip_addr); 588 } 589 590 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) { 591 ip_addr_set_val(&netmask, &(ifconfig_cmd->netmask)); 592 /* check data valid */ 593 if (!ip_addr_netmask_valid(ip_2_ip4(&netmask))) { 594 ERR_IFCONFIG_STRING_PUT(ret, "ifconfig: netmask is invalid!\n"); 595 goto out; 596 } 597 598#if LWIP_DHCP 599 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) { 600 (void)netif_dhcp_off(netif); 601 } 602#endif 603 if (netif_ip4_netmask(netif)->addr != ip_2_ip4(&netmask)->addr) { 604 /* lwip disallow two netif sit in same net at the same time */ 605#ifdef LOSCFG_NET_CONTAINER 606 loc_netif = group->netif_list; 607#else 608 loc_netif = netif_list; 609#endif 610 while (loc_netif != NULL) { 611 if (loc_netif == netif) { 612 loc_netif = loc_netif->next; 613 continue; 614 } 615 if (ip_addr_cmp(&loc_netif->netmask, &netmask) && 616 ip_addr_netcmp(&loc_netif->ip_addr, &netif->ip_addr, ip_2_ip4(&netmask))) { 617 ERR_IFCONFIG_STRING_PUT(ret, "Duplicate network!\n"); 618 goto out; 619 } 620 loc_netif = loc_netif->next; 621 } 622 netif_set_netmask(netif, ip_2_ip4(&netmask)); 623 /* check if gateway still reachable */ 624 if (!ip_addr_netcmp(&netif->gw, &netif->ip_addr, ip_2_ip4(&netmask))) { 625 ip_addr_set_zero(&(netif->gw)); 626#ifdef LOSCFG_NET_CONTAINER 627 if (netif == group->netif_default) { 628 (void)netif_set_default(NULL, group); 629#else 630 if (netif == netif_default) { 631 (void)netif_set_default(NULL); 632#endif 633 } 634 } 635 } 636 } 637 638 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW) && 639 netif_set_hwaddr(netif, ifconfig_cmd->ethaddr, NETIF_MAX_HWADDR_LEN) != ERR_OK) { 640 ERR_IFCONFIG_STRING_PUT(ret, "Failed to update the hwaddr of the device!\n"); 641 (void)netif_set_up(netif); 642 goto out; 643 } 644 645 if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) || 646 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) || 647 (ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW)) { 648 (void)netif_set_up(netif); 649 } 650 651 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_GW) { 652 ip_addr_set_val(&gw, &ifconfig_cmd->gw); 653 654 /* check the address multicast/0/loopback */ 655 if (ip_addr_ismulticast_val(&gw) || ip_addr_isbroadcast_val(&gw, netif) || 656 ip_addr_isany(&gw) || ip_addr_isloopback(&gw)) { 657 ERR_IFCONFIG_STRING_PUT(ret, "Don't set gateway as a multicast/broadcast/0/loopback address!\n"); 658 goto out; 659 } 660 661 /* check if reachable */ 662 if (!ip_addr_netcmp_val(&gw, &netif->ip_addr, ip_2_ip4(&netif->netmask))) { 663 ERR_IFCONFIG_STRING_PUT(ret, "The address is unreachable!\n"); 664 goto out; 665 } 666 667#ifdef LOSCFG_NET_CONTAINER 668 if (group->netif_default != netif) { 669 ip_addr_set_zero(&netif->gw); 670 (void)netif_set_default(netif, group); 671#else 672 if (netif_default != netif) { 673 ip_addr_set_zero(&netif->gw); 674 (void)netif_set_default(netif); 675#endif 676 } 677 678#if LWIP_DHCP 679 if (netif_dhcp_data(netif) && netif_dhcp_data(netif)->state != DHCP_STATE_OFF) { 680 (void)netif_dhcp_off(netif); 681 } 682#endif 683 netif_set_gw(netif, ip_2_ip4(&gw)); 684 } 685 686 if (ifconfig_cmd->option & IFCONFIG_OPTION_SET_MTU) { 687 mtu = ifconfig_cmd->mtu; 688 if (netif_set_mtu(netif, mtu) != ERR_OK) { 689 ERR_IFCONFIG_STRING_PUT(ret, "Invalid MTU\n"); 690 } 691 } 692out: 693 sys_sem_signal(&ifconfig_cmd->cb_completed); 694} 695 696 697void lwip_printsize(size_t size) 698{ 699 static const char *SIZES[] = {"B", "KB", "MB", "GB"}; 700 size_t divis = 0; 701 size_t rem = 0; 702 703 while ((size >= 1024) && (divis < ((sizeof(SIZES) / sizeof(char *)) - 1))) { 704 rem = (size % 1024); 705 divis++; 706 size /= 1024; 707 } 708 709 PRINTK("(%.1f %s) \r\n", (float)size + (float)rem / 1024.0, SIZES[divis]); 710} 711 712LWIP_STATIC void lwip_ifconfig_usage(const char *cmd) 713{ 714 PRINTK("Usage:"\ 715 "\n%s [-a] "\ 716 "\n[interface]"\ 717 "\n[interface ipaddr] <netmask mask> <gateway gw>"\ 718 "\n[interface inet6 add|del ipaddr]"\ 719 "\n[interface hw ether MAC]"\ 720 "\n[interface mtu NN]"\ 721 "\n[interface up|down]\n", 722 cmd); 723} 724 725u32_t lwip_ifconfig(int argc, const char **argv) 726{ 727 int i; 728 static struct ifconfig_option ifconfig_cmd; 729 err_t ret; 730 731#if LWIP_STATS 732 u32_t stat_err_cnt; 733 u32_t stat_drop_cnt; 734 u32_t stat_rx_or_tx_cnt; 735 u32_t stat_rx_or_tx_bytes; 736#endif 737 738#if LWIP_ARP 739 u32_t retval; 740 struct netif *netiftmp = NULL; 741#if LWIP_ENABLE_IP_CONFLICT_SIGNAL 742 u32_t old_ip4addr; 743 err_t err; 744 extern sys_sem_t ip_conflict_detect; 745 extern u32_t is_ip_conflict_signal; 746#endif /* LWIP_ENABLE_IP_CONFLICT_SIGNAL */ 747#endif /* LWIP_ARP */ 748#if LWIP_IPV6 749 extern sys_sem_t dup_addr_detect; 750 extern u32_t is_dup_detect_initialized; 751#endif 752 if (!tcpip_init_finish) { 753 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 754 return 2; 755 } 756 /* To support "ifconfig -a" command 757 RX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format) 758 TX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format) 759 760 Below is assumed for 'overrun' stat. 761 Linux Kernel: 762 RX: FIFO overrun 763 Data structure: net_device->stats->rx_fifo_errors 764 Flag which is marked when FIFO overrun: ENRSR_FO 765 766 Function: ei_receive->ENRSR_FO 767 768 TX: A "FIFO underrun" occurred during transmit. 769 Data structure: net_device->stats->tx_fifo_errors 770 Flag which is marked when FIFO underrun: ENTSR_FU 771 772 Function: ei_tx_intr->ENTSR_FU 773 774 LWIP: 775 So in our case, 776 while receiving a packet RX case, if the buffer is full (trypost - it is sys_mbox_trypost) 777 the error will be returned, we can consider that an overflow has happened. 778 So this can be RX overrun. 779 780 But while transmitting a packet TX case, underrun cannot happen because it block on the 781 message Q if it is full (NOT trypost - it is sys_mbox_post). So TX overrun is always 0. 782 */ 783 if (argc) { 784 if (strcmp("-a", argv[0]) == 0) { 785#if LWIP_STATS 786 stat_rx_or_tx_cnt = lwip_stats.ip.recv; 787 stat_err_cnt = (u32_t)(lwip_stats.ip.ip_rx_err + 788 lwip_stats.ip.lenerr + 789 lwip_stats.ip.chkerr + 790 lwip_stats.ip.opterr + 791 lwip_stats.ip.proterr); 792 stat_drop_cnt = (u32_t)(lwip_stats.ip.drop + lwip_stats.link.link_rx_drop); 793 stat_rx_or_tx_bytes = lwip_stats.ip.ip_rx_bytes; 794 795 PRINTK("%18s:%u\t errors:%u\t ip dropped:%u\t link dropped:%u\t overrun:%d\t bytes:%u ", 796 "RX packets", 797 stat_rx_or_tx_cnt, 798 stat_err_cnt, 799 stat_drop_cnt, 800 lwip_stats.link.link_rx_drop, 801 lwip_stats.ip.link_rx_overrun, 802 stat_rx_or_tx_bytes); 803 804 /* Print in Human readable format of the incoming bytes */ 805 lwip_printsize(lwip_stats.ip.ip_rx_bytes); 806#if IP6_STATS 807 stat_rx_or_tx_cnt = lwip_stats.ip6.recv; 808 stat_err_cnt = (u32_t)(lwip_stats.ip6.ip_rx_err + 809 lwip_stats.ip6.lenerr + 810 lwip_stats.ip6.chkerr + 811 lwip_stats.ip6.opterr + 812 lwip_stats.ip6.proterr); 813 stat_drop_cnt = lwip_stats.ip6.drop; 814 stat_rx_or_tx_bytes = lwip_stats.ip6.ip_rx_bytes; 815 816 PRINTK("%18s:%u\t errors:%u\t dropped:%u\t overrun:%d\t bytes:%u ", 817 "RX packets(ip6)", 818 stat_rx_or_tx_cnt, 819 stat_err_cnt, 820 stat_drop_cnt, 821 lwip_stats.ip.link_rx_overrun, 822 stat_rx_or_tx_bytes); 823 824 /* Print in Human readable format of the incoming bytes */ 825 lwip_printsize(lwip_stats.ip6.ip_rx_bytes); 826#endif 827 stat_rx_or_tx_cnt = (u32_t)(lwip_stats.ip.fw + lwip_stats.ip.xmit); 828 stat_err_cnt = (u32_t)(lwip_stats.ip.rterr + lwip_stats.ip.ip_tx_err); 829 /* IP layer drop stat param is not maintained, failure at IP is considered in 'errors' stat */ 830 stat_drop_cnt = lwip_stats.link.link_tx_drop; 831 stat_rx_or_tx_bytes = lwip_stats.ip.ip_tx_bytes; 832 833 PRINTK("%18s:%u\t errors:%u\t link dropped:%u\t overrun:0\t bytes:%u", 834 "TX packets", 835 stat_rx_or_tx_cnt, 836 stat_err_cnt, 837 stat_drop_cnt, 838 stat_rx_or_tx_bytes); 839 840 /* Print in Human readable format of the outgoing bytes */ 841 lwip_printsize(lwip_stats.ip.ip_tx_bytes); 842 843 stat_rx_or_tx_cnt = (u32_t)(lwip_stats.ip6.fw + lwip_stats.ip6.xmit); 844 stat_err_cnt = (u32_t)(lwip_stats.ip6.rterr + lwip_stats.ip6.ip_tx_err); 845 stat_rx_or_tx_bytes = lwip_stats.ip6.ip_tx_bytes; 846 847 PRINTK("%18s:%u\t errors:%u\t overrun:0\t bytes:%u", 848 "TX packets(ip6)", 849 stat_rx_or_tx_cnt, 850 stat_err_cnt, 851 stat_rx_or_tx_bytes); 852 853 /* Print in Human readable format of the outgoing bytes */ 854 lwip_printsize(lwip_stats.ip6.ip_tx_bytes); 855#endif /* LWIP_STATS */ 856 return 0; 857 } 858 } 859 860 (void)memset_s(&ifconfig_cmd, sizeof(ifconfig_cmd), 0, sizeof(ifconfig_cmd)); 861 if (sys_sem_new(&ifconfig_cmd.cb_completed, 0) != ERR_OK) { 862 PRINTK("%s: sys_sem_new fail\n", __FUNCTION__); 863 return 1; 864 } 865 866 i = 0; 867 /* Get the interface */ 868 if (argc > 0) { 869 if (strlen(argv[i]) < IFNAMSIZ) { 870 if (strncpy_s(ifconfig_cmd.iface, IFNAMSIZ, argv[i], (strlen(argv[i]))) != EOK) { 871 sys_sem_free(&ifconfig_cmd.cb_completed); 872 PRINTK("ifconfig : strncpy_s error\n"); 873 return 1; 874 } 875 ifconfig_cmd.iface[IFNAMSIZ - 1] = '\0'; 876 } else { 877 sys_sem_free(&ifconfig_cmd.cb_completed); 878 PRINTK("ifconfig : interface name is too big\n"); 879 return 1; 880 } 881 i++; 882 argc--; 883 if (argc == 0) { 884 /* no more arguments, show the interface state. */ 885 ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd); 886 if (ret != ERR_OK) { 887 sys_sem_free(&ifconfig_cmd.cb_completed); 888 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret); 889 return 1; 890 } 891 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 892 sys_sem_free(&ifconfig_cmd.cb_completed); 893 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 894 PRINTK("%s", ifconfig_cmd.cb_print_buf); 895 return 0; 896 } 897 } else { 898 /* no more arguments, show all the interface state. */ 899 ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd); 900 if (ret != ERR_OK) { 901 sys_sem_free(&ifconfig_cmd.cb_completed); 902 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret); 903 return 1; 904 } 905 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 906 sys_sem_free(&ifconfig_cmd.cb_completed); 907 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 908 PRINTK("%s", ifconfig_cmd.cb_print_buf); 909 910 return 0; 911 } 912 913 /* ifup/ifdown */ 914 if (strcmp("up", argv[i]) == 0) { 915 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_UP; 916 /* setup the interface, other arguments is ignored. */ 917 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd); 918 if (ret != ERR_OK) { 919 sys_sem_free(&ifconfig_cmd.cb_completed); 920 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret); 921 return 1; 922 } 923 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 924 sys_sem_free(&ifconfig_cmd.cb_completed); 925 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 926 PRINTK("%s", ifconfig_cmd.cb_print_buf); 927 return 0; 928 } else if (strcmp("down", argv[i]) == 0) { 929 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_DOWN; 930 /* setdown the interface, other arguments is ignored. */ 931 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd); 932 if (ret != ERR_OK) { 933 sys_sem_free(&ifconfig_cmd.cb_completed); 934 PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret); 935 return 1; 936 } 937 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 938 sys_sem_free(&ifconfig_cmd.cb_completed); 939 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 940 PRINTK("%s", ifconfig_cmd.cb_print_buf); 941 return 0; 942 } 943 /* check if set the ip address. */ 944#if LWIP_ARP 945 netiftmp = netifapi_netif_find_by_name(ifconfig_cmd.iface); 946 if (netiftmp == NULL) { 947 sys_sem_free(&ifconfig_cmd.cb_completed); 948 PRINTK("ifconfig : Interface %s not found\n", ifconfig_cmd.iface); 949 return 1; 950 } 951#if LWIP_ENABLE_IP_CONFLICT_SIGNAL 952 old_ip4addr = ipaddr_addr(ipaddr_ntoa(&netiftmp->ip_addr)); 953#endif /* LWIP_ENABLE_IP_CONFLICT_SIGNAL */ 954#endif /* LWIP_ARP */ 955 if (!strcmp(argv[i], "inet") || ip4addr_aton(argv[i], ip_2_ip4(&ifconfig_cmd.ip_addr))) { 956 if (!strcmp(argv[i], "inet")) { 957 if (argc <= 1) { 958 sys_sem_free(&ifconfig_cmd.cb_completed); 959 goto ifconfig_error; 960 } 961 962 if (!ip4addr_aton(argv[i + 1], ip_2_ip4(&ifconfig_cmd.ip_addr))) { 963 sys_sem_free(&ifconfig_cmd.cb_completed); 964 PRINTK("ifconfig : Invalid IPv4 Address\n"); 965 return 1; 966 } 967 argc--; 968 i++; 969 } 970 IP_SET_TYPE_VAL((ifconfig_cmd.ip_addr), IPADDR_TYPE_V4); 971#if LWIP_ARP 972 if (!ip_addr_cmp(&ifconfig_cmd.ip_addr, &netiftmp->ip_addr)) { 973 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_IP; 974 } 975#else 976 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_IP; 977#endif /* LWIP_ARP */ 978 argc--; 979 i++; 980 } else if (!strcmp(argv[i], "inet6")) { 981 if (argc < 3) { 982 sys_sem_free(&ifconfig_cmd.cb_completed); 983 goto ifconfig_error; 984 } 985 if (strcmp(argv[i + 1], "add") && strcmp(argv[i + 1], "del")) { 986 sys_sem_free(&ifconfig_cmd.cb_completed); 987 goto ifconfig_error; 988 } 989 990 if (!ip6addr_aton(argv[i + 2], ip_2_ip6(&ifconfig_cmd.ip_addr))) { 991 sys_sem_free(&ifconfig_cmd.cb_completed); 992 PRINTK("ifconfig : Invalid IPv6 Address\n"); 993 return 1; 994 } 995 996 IP_SET_TYPE_VAL((ifconfig_cmd.ip_addr), IPADDR_TYPE_V6); 997 ifconfig_cmd.option |= (!strcmp(argv[i + 1], "add") ? IFCONFIG_OPTION_SET_IP : IFCONFIG_OPTION_DEL_IP); 998 argc -= 3; 999 i += 3; 1000 } 1001 1002 if (ifconfig_cmd.option & IFCONFIG_OPTION_DEL_IP) { 1003 if (argc != 0) { 1004 sys_sem_free(&ifconfig_cmd.cb_completed); 1005 goto ifconfig_error; 1006 } 1007 } 1008 1009 while (argc > 0) { 1010 if (strcmp("netmask", argv[i]) == 0 && (argc > 1) && (ipaddr_addr(argv[i + 1]) != IPADDR_NONE)) { 1011 /* if set netmask */ 1012 ip_addr_set_ip4_u32_val((ifconfig_cmd.netmask), ipaddr_addr(argv[i + 1])); 1013 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_NETMASK; 1014 i += 2; 1015 argc -= 2; 1016 } else if (strcmp("gateway", argv[i]) == 0 && (argc > 1) && (ipaddr_addr(argv[i + 1]) != IPADDR_NONE)) { 1017 /* if set gateway */ 1018 ip_addr_set_ip4_u32_val((ifconfig_cmd.gw), ipaddr_addr(argv[i + 1])); 1019 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_GW; 1020 i += 2; 1021 argc -= 2; 1022 } else if (strcmp("hw", argv[i]) == 0 && argc > 2 && strcmp("ether", argv[i + 1]) == 0) { 1023 /* if set HWaddr */ 1024 char *digit = NULL; 1025 u32_t macaddrlen = strlen(argv[i + 2]) + 1; 1026 char tmpStr[MAX_MACADDR_STRING_LENGTH]; 1027 char *tmpStr1 = NULL; 1028 char *saveptr = NULL; 1029 int j; 1030 1031 if (macaddrlen != MAX_MACADDR_STRING_LENGTH) { 1032 sys_sem_free(&ifconfig_cmd.cb_completed); 1033 PRINTK("ifconfig : wrong MAC address format\n"); 1034 return 1; 1035 } 1036 1037 if (strncpy_s(tmpStr, MAX_MACADDR_STRING_LENGTH, argv[i + 2], macaddrlen - 1) != 0) { 1038 sys_sem_free(&ifconfig_cmd.cb_completed); 1039 PRINTK("ifconfig : wrong MAC address\n"); 1040 return 1; 1041 } 1042 for (j = 0, tmpStr1 = tmpStr; j < 6; j++, tmpStr1 = NULL) { 1043 digit = strtok_r(tmpStr1, ":", &saveptr); 1044 if ((digit == NULL) || (strlen(digit) > 2)) { 1045 sys_sem_free(&ifconfig_cmd.cb_completed); 1046 PRINTK("ifconfig : wrong MAC address format\n"); 1047 return 1; 1048 } 1049 CONVERT_STRING_TO_HEX(digit, ifconfig_cmd.ethaddr[j]); 1050 } 1051 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_HW; 1052 i += 3; 1053 argc -= 3; 1054 } else if (!strcmp("mtu", argv[i]) && (argc > 1)) { 1055 /* if set mtu */ 1056 if ((atoi(argv[i + 1]) < 0) || (atoi(argv[i + 1]) > 0xFFFF)) { 1057 sys_sem_free(&ifconfig_cmd.cb_completed); 1058 PRINTK("\nifconfig: Invalid argument for mtu\n"); 1059 goto ifconfig_error; 1060 } 1061 1062 ifconfig_cmd.mtu = (u16_t)(atoi(argv[i + 1])); 1063 ifconfig_cmd.option |= IFCONFIG_OPTION_SET_MTU; 1064 i += 2; 1065 argc -= 2; 1066 } else { 1067 sys_sem_free(&ifconfig_cmd.cb_completed); 1068 goto ifconfig_error; 1069 } 1070 } 1071 1072#if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL 1073 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) { 1074 /* Create the semaphore for ip conflict detection. */ 1075 if (sys_sem_new(&ip_conflict_detect, 0) != ERR_OK) { 1076 sys_sem_free(&ifconfig_cmd.cb_completed); 1077 PRINTK("ifconfig: internal error\n"); 1078 return 1; 1079 } 1080 is_ip_conflict_signal = 1; 1081 } 1082#endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */ 1083 1084#if LWIP_IPV6 1085 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL((ifconfig_cmd.ip_addr))) { 1086 /* Create the semaphore for duplicate address detection. */ 1087 if (sys_sem_new(&dup_addr_detect, 0) != ERR_OK) { 1088 sys_sem_free(&ifconfig_cmd.cb_completed); 1089 PRINTK("ifconfig: internal error\n"); 1090 return 1; 1091 } 1092 is_dup_detect_initialized = 1; 1093 } 1094#endif /* LWIP_IPV6 */ 1095 1096 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd); 1097 if (ret != ERR_OK) { 1098 sys_sem_free(&ifconfig_cmd.cb_completed); 1099#if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL 1100 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) { 1101 is_ip_conflict_signal = 0; 1102 sys_sem_free(&ip_conflict_detect); 1103 } 1104#endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */ 1105 1106#if LWIP_IPV6 1107 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL((ifconfig_cmd.ip_addr))) { 1108 is_dup_detect_initialized = 0; 1109 sys_sem_free(&dup_addr_detect); 1110 } 1111#endif /* LWIP_IPV6 */ 1112 1113 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret); 1114 return 1; 1115 } 1116 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 1117 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 1118 PRINTK("%s", ifconfig_cmd.cb_print_buf); 1119#if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL 1120 /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */ 1121 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V4_VAL((ifconfig_cmd.ip_addr))) { 1122 err = (err_t)sys_arch_sem_wait(&ip_conflict_detect, DUP_ARP_DETECT_TIME); 1123 is_ip_conflict_signal = 0; 1124 sys_sem_free(&ip_conflict_detect); 1125 if (err < 0) { 1126 /* The result neither conflict nor timeout. */ 1127 PRINT_ERR("ifconfig: internal error\n"); 1128 sys_sem_free(&ifconfig_cmd.cb_completed); 1129 return 1; 1130 } else if (err < DUP_ARP_DETECT_TIME) { 1131 /* Duplicate use of new ip, restore it to the old one. */ 1132 PRINT_ERR("ifconfig: ip conflict!\n"); 1133 ip_addr_set_ip4_u32_val(ifconfig_cmd.ip_addr, old_ip4addr); 1134 ret = tcpip_callback(lwip_ifconfig_internal, &ifconfig_cmd); 1135 if (ret != ERR_OK) { 1136 sys_sem_free(&ifconfig_cmd.cb_completed); 1137 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret); 1138 return 1; 1139 } 1140 (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); 1141 sys_sem_free(&ifconfig_cmd.cb_completed); 1142 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 1143 PRINTK("%s", ifconfig_cmd.cb_print_buf); 1144 return 1; 1145 } 1146 } 1147#endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */ 1148#if LWIP_IPV6 1149 if ((ifconfig_cmd.option & IFCONFIG_OPTION_SET_IP) && IP_IS_V6_VAL(ifconfig_cmd.ip_addr)) { 1150 /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */ 1151 retval = sys_arch_sem_wait(&dup_addr_detect, DUP_ARP_DETECT_TIME); 1152 is_dup_detect_initialized = 0; 1153 sys_sem_free(&dup_addr_detect); 1154 if (retval == SYS_ARCH_ERROR) { 1155 sys_sem_free(&ifconfig_cmd.cb_completed); 1156 /* The result neither conflict nor timeout. */ 1157 PRINT_ERR("ifconfig: internal error\n"); 1158 return 1; 1159 } else if (retval < DUP_ARP_DETECT_TIME) { 1160 /* Duplicate use of new ip, restore it to the old one. */ 1161 struct netif *netif = NULL; 1162 PRINT_ERR("ifconfig: IP conflict!\n"); 1163 netif = netifapi_netif_find_by_name(ifconfig_cmd.iface); 1164 i = netif_get_ip6_addr_match(netif, &ifconfig_cmd.ip_addr.u_addr.ip6); 1165 if (i >= 0) { 1166 netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 1167 } 1168 1169 sys_sem_free(&ifconfig_cmd.cb_completed); 1170 ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 1171 PRINTK("%s", ifconfig_cmd.cb_print_buf); 1172 return 1; 1173 } 1174 } 1175#endif /* LWIP_IPV6 */ 1176 sys_sem_free(&ifconfig_cmd.cb_completed); 1177 return 0; 1178ifconfig_error: 1179 lwip_ifconfig_usage("ifconfig"); 1180 return 1; 1181} 1182 1183#ifdef LOSCFG_SHELL 1184SHELLCMD_ENTRY(ifconfig_shellcmd, CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig); 1185#endif /* LOSCFG_SHELL */ 1186/* add arp entry to arp cache */ 1187#define ARP_OPTION_ADD 1 1188/* delete arp entry to arp cache */ 1189#define ARP_OPTION_DEL 2 1190/* print all arp entry in arp cache */ 1191#define ARP_OPTION_SHOW 3 1192 1193struct arp_option { 1194 /* see the ARP_OPTION_ above */ 1195 int option; 1196 /* descriptive abbreviation of network interface */ 1197 char iface[IFNAMSIZ]; 1198 /* ip addr */ 1199 unsigned int ipaddr; 1200 /* hw addr */ 1201 unsigned char ethaddr[6]; 1202 /* when using telnet, print to the telnet socket will result in system */ 1203 /* deadlock.so don't do it. cache the data to print to a buf, and when */ 1204 /* callback returns, then print the data out to the telnet socket */ 1205 sys_sem_t cb_completed; 1206 char cb_print_buf[PRINT_BUF_LEN]; 1207 int print_buf_len; 1208}; 1209 1210#ifndef LWIP_TESTBED 1211LWIP_STATIC 1212#endif 1213void lwip_arp_show_internal(struct netif *netif, char *printf_buf, unsigned int buf_len) 1214{ 1215 u8_t state, i; 1216 int ret; 1217 char *tmp = printf_buf; 1218 if (buf_len < 1) { 1219 return; 1220 } 1221 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%-24s%-12s%-12s\n", "Address", "HWaddress", "Iface", "Type"); 1222 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 1223 return; 1224 tmp += ret; 1225 buf_len -= (unsigned int)ret; 1226 1227 if (netif != NULL) { 1228 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 1229 state = arp_table[i].state; 1230 if (((state == ETHARP_STATE_STABLE) 1231 #if ETHARP_SUPPORT_STATIC_ENTRIES 1232 || (state == ETHARP_STATE_STATIC) 1233#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 1234 ) && arp_table[i].netif) { 1235 if (strcmp(netif_get_name(netif), netif_get_name(arp_table[i].netif)) != 0) { 1236 continue; 1237 } 1238 1239 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%02X:%02X:%02X:%02X:%02X:%02X %s %s\n", 1240 ip4addr_ntoa(&arp_table[i].ipaddr), 1241 arp_table[i].ethaddr.addr[0], arp_table[i].ethaddr.addr[1], 1242 arp_table[i].ethaddr.addr[2], arp_table[i].ethaddr.addr[3], 1243 arp_table[i].ethaddr.addr[4], arp_table[i].ethaddr.addr[5], 1244 netif_get_name(netif), 1245#if ETHARP_SUPPORT_STATIC_ENTRIES 1246 ((state == ETHARP_STATE_STATIC) ? "static" : "dynamic") 1247#else 1248 "dynamic" 1249#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 1250 ); 1251 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 1252 return; 1253 tmp += ret; 1254 buf_len -= (unsigned int)ret; 1255 } 1256 } 1257 } else { 1258 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 1259 state = arp_table[i].state; 1260 if (((state == ETHARP_STATE_STABLE) 1261 #if ETHARP_SUPPORT_STATIC_ENTRIES 1262 || (state == ETHARP_STATE_STATIC) 1263#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 1264 ) && arp_table[i].netif) { 1265 ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%-24s%02X:%02X:%02X:%02X:%02X:%02X %s %s\n", 1266 ip4addr_ntoa(&arp_table[i].ipaddr), 1267 arp_table[i].ethaddr.addr[0], arp_table[i].ethaddr.addr[1], 1268 arp_table[i].ethaddr.addr[2], arp_table[i].ethaddr.addr[3], 1269 arp_table[i].ethaddr.addr[4], arp_table[i].ethaddr.addr[5], 1270 netif_get_name(arp_table[i].netif), 1271#if ETHARP_SUPPORT_STATIC_ENTRIES 1272 ((state == ETHARP_STATE_STATIC) ? "static" : "dynamic") 1273#else 1274 "dynamic" 1275#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 1276 ); 1277 if ((ret <= 0) || ((unsigned int)ret >= buf_len)) 1278 return; 1279 tmp += ret; 1280 buf_len -= (unsigned int)ret; 1281 } 1282 } 1283 } 1284} 1285 1286#ifndef LWIP_TESTBED 1287LWIP_STATIC 1288#endif 1289void lwip_arp_internal(void *arg) 1290{ 1291#if LWIP_IPV4 1292 struct arp_option *arp_cmd = (struct arp_option *)arg; 1293 struct netif *netif = NULL; 1294 struct eth_addr ethaddr; 1295 ip4_addr_t ipaddr; 1296 err_t ret = 0; 1297 int type = 0; 1298#ifdef LOSCFG_NET_CONTAINER 1299 struct net_group *group = get_curr_process_net_group(); 1300#endif 1301 if (arp_cmd->iface[0] == 'd' && arp_cmd->iface[1] == 'e') { 1302 netif = NULL; 1303 } else { 1304 /* find the specified netif by it's name */ 1305 netif = netif_find(arp_cmd->iface); 1306 if (netif == NULL) { 1307 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "No such device\n"); 1308 goto out; 1309 } 1310 } 1311 1312 type = arp_cmd->option; 1313 switch (type) { 1314 case ARP_OPTION_SHOW: 1315 if (netif != NULL) { 1316 lwip_arp_show_internal(netif, arp_cmd->cb_print_buf, PRINT_BUF_LEN); 1317 } else { 1318 lwip_arp_show_internal(NULL, arp_cmd->cb_print_buf, PRINT_BUF_LEN); 1319 } 1320 break; 1321 1322 case ARP_OPTION_ADD: 1323#if ETHARP_SUPPORT_STATIC_ENTRIES 1324 ipaddr.addr = arp_cmd->ipaddr; 1325 (void)memcpy_s(ethaddr.addr, sizeof(ethaddr.addr), arp_cmd->ethaddr, 6); 1326 if (netif != NULL) { 1327 if (ip4_addr_netcmp(&ipaddr, ip_2_ip4(&(netif->ip_addr)), ip_2_ip4(&(netif->netmask)))) { 1328 ret = etharp_update_arp_entry(netif, &ipaddr, ðaddr, 1329 ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); 1330 } else { 1331 ret = ERR_RTE; 1332 } 1333 } else { 1334 ret = etharp_add_static_entry(&ipaddr, ðaddr); 1335 } 1336#else 1337 ret = ERR_ARG; 1338#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 1339 break; 1340 1341 case ARP_OPTION_DEL: 1342 ipaddr.addr = arp_cmd->ipaddr; 1343 (void)memcpy_s(ethaddr.addr, sizeof(ethaddr.addr), arp_cmd->ethaddr, 6); 1344 if (netif != NULL) { 1345 ret = etharp_delete_arp_entry(netif, &ipaddr); 1346 } else { 1347#ifdef LOSCFG_NET_CONTAINER 1348 for (netif = group->netif_list; netif != NULL; netif = netif->next) { 1349#else 1350 for (netif = netif_list; netif != NULL; netif = netif->next) { 1351#endif 1352 ret = etharp_delete_arp_entry(netif, &ipaddr); 1353 if (ret == ERR_OK) { 1354 /* only can del success one time */ 1355 break; 1356 } 1357 } 1358 } 1359 break; 1360 1361 default: 1362 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Error\n"); 1363 goto out; 1364 } 1365 1366out: 1367 if (type == ARP_OPTION_ADD || type == ARP_OPTION_DEL) { 1368 if (ret == ERR_MEM) { 1369 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Out of memory error\n"); 1370 } else if (ret == ERR_ARG) { 1371 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Illegal argument\n"); 1372 } else if (ret == ERR_RTE) { 1373 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Network is unreachable\n"); 1374 } else { 1375 (void)snprintf_s(arp_cmd->cb_print_buf, PRINT_BUF_LEN, (PRINT_BUF_LEN - 1), "Succeeded\n"); 1376 } 1377 } 1378#endif 1379 1380 sys_sem_signal(&arp_cmd->cb_completed); 1381} 1382 1383 1384LWIP_STATIC void lwip_arp_usage(const char *cmd) 1385{ 1386 PRINTK("Usage:" 1387 "\n%s" 1388 "\n%s [-i IF] -s IPADDR HWADDR" 1389 "\n%s [-i IF] -d IPADDR\n", 1390 cmd, cmd, cmd); 1391} 1392 1393u32_t lwip_arp(int argc, const char **argv) 1394{ 1395 int i; 1396 struct arp_option arp_cmd; 1397 err_t ret; 1398 size_t interface_len = 0; 1399 1400 (void)memset_s(&arp_cmd, sizeof(struct arp_option), 0, sizeof(struct arp_option)); 1401 if (!tcpip_init_finish) { 1402 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 1403 return LOS_NOK; 1404 } 1405 1406 arp_cmd.iface[0] = 'd'; 1407 arp_cmd.iface[1] = 'e'; 1408 arp_cmd.iface[2] = '0'; 1409 arp_cmd.option = ARP_OPTION_SHOW; 1410 arp_cmd.print_buf_len = 0; 1411 if (sys_sem_new(&arp_cmd.cb_completed, 0) != ERR_OK) { 1412 PRINTK("%s: sys_sem_new fail\n", __FUNCTION__); 1413 return 1; 1414 } 1415 1416 i = 0; 1417 while (argc > 0) { 1418 if (strcmp("-i", argv[i]) == 0 && (argc > 1)) { 1419 /* get the network interface's name */ 1420 interface_len = strlen(argv[i + 1]); 1421 if (interface_len < IFNAMSIZ) { 1422 if (strncmp(argv[i + 1], "lo", (sizeof("lo") - 1)) == 0) { 1423 PRINTK("Illegal operation\n"); 1424 goto arp_error; 1425 } 1426 if (strncpy_s(arp_cmd.iface, IFNAMSIZ, argv[i + 1], interface_len) != EOK) { 1427 PRINTK("strncpy_s error\n"); 1428 goto arp_error; 1429 } 1430 arp_cmd.iface[interface_len] = '\0'; 1431 } else { 1432 PRINTK("Iface name is big \n"); 1433 goto arp_error; 1434 } 1435 i += 2; 1436 argc -= 2; // 2: number of used parameters 1437 } else if (strcmp("-d", argv[i]) == 0 && (argc > 1)) { 1438 /* arp delete */ 1439 arp_cmd.option = ARP_OPTION_DEL; 1440 arp_cmd.ipaddr = inet_addr(argv[i + 1]); 1441 1442 if (arp_cmd.ipaddr == IPADDR_NONE) { 1443 PRINTK("IP address is not correct!\n"); 1444 goto arp_error; 1445 } 1446 1447 i += 2; 1448 argc -= 2; // 2: number of used parameters 1449 } else if (strcmp("-s", argv[i]) == 0 && (argc > 2)) { // 2: require more than 2 parameters 1450 /* arp add */ 1451 char *digit = NULL; 1452 u32_t macaddrlen = strlen(argv[i + 2]) + 1; 1453 char tmpStr[MAX_MACADDR_STRING_LENGTH]; 1454 char *tmpStr1 = NULL; 1455 char *saveptr1 = NULL; 1456 char *temp = NULL; 1457 int j; 1458 1459 arp_cmd.option = ARP_OPTION_ADD; 1460 arp_cmd.ipaddr = inet_addr(argv[i + 1]); 1461 1462 if (arp_cmd.ipaddr == IPADDR_NONE) { 1463 PRINTK("IP address is not correct!\n"); 1464 goto arp_error; 1465 } 1466 1467 /* cannot add an arp entry of 127.*.*.* */ 1468 if ((arp_cmd.ipaddr & (u32_t)0x0000007fUL) == (u32_t)0x0000007fUL) { 1469 PRINTK("IP address is not correct!\n"); 1470 goto arp_error; 1471 } 1472 1473 if (macaddrlen != MAX_MACADDR_STRING_LENGTH) { 1474 PRINTK("Wrong MAC address length\n"); 1475 goto arp_error; 1476 } 1477 1478 if (strncpy_s(tmpStr, MAX_MACADDR_STRING_LENGTH, argv[i + 2], macaddrlen - 1) != 0) { 1479 PRINTK("Wrong MAC address\n"); 1480 goto arp_error; 1481 } 1482 1483 for (j = 0, tmpStr1 = tmpStr; j < 6; j++, tmpStr1 = NULL) { 1484 digit = strtok_r(tmpStr1, ":", &saveptr1); 1485 if ((digit == NULL) || (strlen(digit) > 2)) { 1486 PRINTK("MAC address is not correct\n"); 1487 goto arp_error; 1488 } 1489 1490 for (temp = digit; *temp != '\0'; temp++) { 1491 if (!isxdigit(*temp)) { 1492 PRINTK("MAC address is not correct\n"); 1493 goto arp_error; 1494 } 1495 } 1496 1497 CONVERT_STRING_TO_HEX(digit, arp_cmd.ethaddr[j]); 1498 } 1499 1500 i += 3; 1501 argc -= 3; // 3: number of used parameters 1502 } else { 1503 goto arp_error; 1504 } 1505 } 1506 1507 ret = tcpip_callback(lwip_arp_internal, &arp_cmd); 1508 if (ret != ERR_OK) { 1509 PRINTK("%s : tcpip_callback failed in line %d : errnu %d", __FUNCTION__, __LINE__, ret); 1510 sys_sem_free(&arp_cmd.cb_completed); 1511 return 1; 1512 } 1513 (void)sys_arch_sem_wait(&arp_cmd.cb_completed, 0); 1514 sys_sem_free(&arp_cmd.cb_completed); 1515 arp_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; 1516 PRINTK("%s", arp_cmd.cb_print_buf); 1517 return 0; 1518 1519arp_error: 1520 lwip_arp_usage("arp"); 1521 sys_sem_free(&arp_cmd.cb_completed); 1522 return 1; 1523} 1524 1525#ifdef LOSCFG_SHELL_CMD_DEBUG 1526SHELLCMD_ENTRY(arp_shellcmd, CMD_TYPE_EX, "arp", 1, (CmdCallBackFunc)lwip_arp); 1527#endif /* LOSCFG_SHELL_CMD_DEBUG */ 1528 1529void ifup_internal(void *arg) 1530{ 1531 struct netif *netif = NULL; 1532 struct if_cmd_data *ifcmd_data; 1533 1534 ifcmd_data = (struct if_cmd_data *)arg; 1535 if (ifcmd_data == NULL) { 1536 return; 1537 } 1538 netif = netif_find(ifcmd_data->if_name); 1539 if (netif == NULL) { 1540 ifcmd_data->err = ERR_VAL; 1541 } else { 1542 (void)netif_set_up(netif); 1543 ifcmd_data->err = ERR_OK; 1544 } 1545 1546 sys_sem_signal(&ifcmd_data->cb_completed); 1547} 1548 1549void ifdown_internal(void *arg) 1550{ 1551 struct netif *netif = NULL; 1552 struct if_cmd_data *ifcmd_data = NULL; 1553 1554 ifcmd_data = (struct if_cmd_data *)arg; 1555 if (ifcmd_data == NULL) { 1556 return; 1557 } 1558 netif = netif_find(ifcmd_data->if_name); 1559 if (netif == NULL) { 1560 ifcmd_data->err = ERR_VAL; 1561 } else { 1562 (void)netif_set_down(netif); 1563 ifcmd_data->err = ERR_OK; 1564 } 1565 1566 sys_sem_signal(&ifcmd_data->cb_completed); 1567} 1568 1569#if LWIP_DNS 1570#ifndef LWIP_TESTBED 1571LWIP_STATIC 1572#endif 1573struct hostent *gethostnameinfo(const char *host) 1574{ 1575 static struct hostent hostbuf; 1576 struct hostent *hp = NULL; 1577 const size_t hstbuflen = 1024; 1578 char tmphstbuf[1024]; 1579 int res; 1580 int herr; 1581 1582 res = lwip_gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr); 1583 /* Check for errors. */ 1584 if (res || hp == NULL) 1585 return NULL; 1586 return hp; 1587} 1588 1589LWIP_STATIC unsigned int get_hostip(const char *hname) 1590{ 1591 unsigned int ip = 0; 1592 int ret; 1593 1594 struct hostent *pent = gethostnameinfo(hname); 1595 if (pent == NULL || pent->h_addr == NULL) 1596 return 0; 1597 ret = memcpy_s(&ip, sizeof(ip), pent->h_addr, 4); 1598 if (ret != 0) { 1599 return 0; 1600 } 1601 return ip; 1602} 1603#endif 1604 1605#if LWIP_EXT_POLL_SUPPORT 1606static int ping_taskid = -1; 1607static int ping_kill = 0; 1608#define PING_ZERO_DATA_LEN 8 1609static void lwip_ping_usage(void) 1610{ 1611 PRINTK("Usage:"\ 1612 "\n ping" 1613 "\n ping [-n cnt] [-w interval] [-l data_len] destination" 1614 "\n ping [-t] [-w interval] destination" 1615 "\n ping -k"); 1616 PRINTK("\n -t means ping forever, user can use -k to stop the forever ping\n"); 1617} 1618 1619LWIP_STATIC int osPingFunc(u32_t destip, u32_t cnt, u32_t interval, u32_t data_len) 1620{ 1621 int sfd; 1622 struct sockaddr_in to; 1623 struct pbuf *pbuf_resp = NULL; 1624 struct icmp_echo_hdr *iecho = NULL; 1625 struct icmp_echo_hdr *iecho_resp = NULL; 1626 struct ip_hdr *iphdr_resp = NULL; 1627 u32_t iecho_len; 1628 s16_t ip_hlen; 1629 u32_t forever; 1630 u32_t i = 0; 1631 u32_t succ_cnt = 0; 1632 u32_t failed_cnt = 0; 1633 struct timespec start, end; 1634 long timout_ms = 0; 1635 struct pollfd pfd; 1636 long rtt; 1637 int ret = 0; 1638 u32_t intrvl = 0; 1639 char *data_buf = NULL; 1640 BOOL timeout_flag = false; 1641 char buf[50]; 1642 1643 iecho_len = sizeof(struct icmp_echo_hdr) + data_len; 1644 sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 1645 if (sfd < 0) { 1646 perror("Ping socket"); 1647 return -1; 1648 } 1649 pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM); 1650 if (pbuf_resp == NULL) { 1651 PRINTK("Ping: pbuf_resp malloc failed\n"); 1652 ret = -1; 1653 goto FAILURE; 1654 } 1655 iecho = (struct icmp_echo_hdr *)mem_malloc(iecho_len); 1656 if (iecho == NULL) { 1657 PRINTK("Ping: echo request malloc failed\n"); 1658 ret = -1; 1659 goto FAILURE; 1660 } 1661 1662 to.sin_family = AF_INET; 1663 to.sin_addr.s_addr = destip; /* already in network order */ 1664 to.sin_port = 0; 1665 1666 if (data_len > PING_ZERO_DATA_LEN) { 1667 (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN, 1668 0, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN); 1669 data_buf = (char *)iecho + sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN; 1670 for (i = 0; i < data_len - PING_ZERO_DATA_LEN; i++) { 1671 *(data_buf + i) = i + 0x10; 1672 } 1673 } else { 1674 (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + data_len, 0, sizeof(struct icmp_echo_hdr) + data_len); 1675 } 1676 iecho->id = htons((u16_t)LOS_CurTaskIDGet()); 1677 ICMPH_TYPE_SET(iecho, (u8_t)ICMP_ECHO); 1678 forever = (cnt ? 0 : 1); 1679 i = 0; 1680 while (!ping_kill && (forever || (i < cnt))) { 1681 iecho->seqno = htons((u16_t)i); 1682 iecho->chksum = 0; 1683 iecho->chksum = inet_chksum((void *)iecho, iecho_len); 1684 1685 ret = sendto(sfd, iecho, iecho_len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to)); 1686 if (ret < 0) { 1687 perror("Ping: sending ICMP echo request failed\n"); 1688 goto FAILURE; 1689 } 1690 1691 /* capture the start time to calculate RTT */ 1692 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start); 1693 1694 /* poll for ICMP echo response msg */ 1695 pfd.fd = sfd; 1696 1697 do { 1698 pfd.events = POLLIN; 1699 pfd.revents = 0; 1700 timeout_flag = false; 1701 ret = poll(&pfd, 1, LWIP_SHELL_CMD_PING_TIMEOUT); 1702 if (ret < 0) { 1703 perror("Ping: poll\n"); 1704 goto FAILURE; 1705 } else if (ret == 0) { 1706 /* first type timeout event */ 1707 timeout_flag = true; 1708 break; 1709 } 1710 1711 ret = recv(sfd, pbuf_resp->payload, pbuf_resp->len, MSG_DONTWAIT); 1712 if (ret < 0) { 1713 perror("Ping: recv echo reply failed\n"); 1714 goto FAILURE; 1715 } 1716 1717 /* Accessing ip header and icmp header */ 1718 iphdr_resp = pbuf_resp->payload; 1719 1720 ip_hlen = (IPH_HL(iphdr_resp) << 2); 1721 if (pbuf_header(pbuf_resp, -ip_hlen)) { 1722 /* this failure will never happen, but failure handle is written just to be in safe side */ 1723 PRINTK("Ping : memory management failure\n"); 1724 goto FAILURE; 1725 } 1726 iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload; 1727 /* Reverting back pbuf to its original state */ 1728 if (pbuf_header(pbuf_resp, ip_hlen)) { 1729 /* this failure will never happen, but failure handle is written just to be in safe side */ 1730 PRINTK("ping : memory management failure\n"); 1731 goto FAILURE; 1732 } 1733 1734 if ((iphdr_resp->src.addr != to.sin_addr.s_addr) || 1735 ((ICMPH_TYPE(iecho_resp) == ICMP_ECHO) && (iphdr_resp->src.addr == to.sin_addr.s_addr))) { 1736 /* second type timeout event */ 1737 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); 1738 timout_ms = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); 1739 timout_ms = LWIP_SHELL_CMD_PING_TIMEOUT - timout_ms; 1740 } else { 1741 timout_ms = 0; 1742 break; 1743 } 1744 } while (timout_ms >= 0); 1745 1746 /* all timeout events are true timeout */ 1747 if ((timout_ms < 0) || (timeout_flag == true)) { 1748 failed_cnt++; 1749 i++; 1750 PRINTK("\nPing: destination unreachable ..."); 1751 continue; 1752 } 1753 /* capture the end time to calculate round trip time */ 1754 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); 1755 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); 1756 1757 if (iphdr_resp->src.addr == to.sin_addr.s_addr) { 1758 switch (ICMPH_TYPE(iecho_resp)) { 1759 case ICMP_ER: 1760 PRINTK("\n[%u]Reply from %s: ", i, inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf))); 1761 if (rtt > 0) { 1762 PRINTK("time=%ims ", rtt); 1763 } else { 1764 PRINTK("time<1ms "); 1765 } 1766 PRINTK("TTL=%u", iphdr_resp->_ttl); 1767 1768 /* delay 1s for every successful ping */ 1769 intrvl = interval; 1770 do { 1771 if (intrvl < 1000) { 1772 sys_msleep(intrvl); 1773 break; 1774 } 1775 intrvl -= 1000; 1776 sys_msleep(1000); // 1000: delay 1 s 1777 if (ping_kill == 1) 1778 break; 1779 } while (intrvl > 0); 1780 succ_cnt++; 1781 break; 1782 case ICMP_DUR: 1783 PRINTK("\nPing: destination host unreachable ..."); 1784 break; 1785 case ICMP_SQ: 1786 PRINTK("\nPing: source quench ..."); 1787 break; 1788 case ICMP_RD: 1789 PRINTK("\nPing: redirect ..."); 1790 break; 1791 case ICMP_TE: 1792 PRINTK("\nPing: time exceeded ..."); 1793 break; 1794 case ICMP_PP: 1795 PRINTK("\nPing: parameter problem ..."); 1796 break; 1797 default : 1798 PRINTK("\nPing: unknown error ..."); 1799 break; 1800 } 1801 i++; 1802 } 1803 } 1804 1805 PRINTK("\n--- %s ping statistics ---\n", inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf))); 1806 PRINTK("%u packets transmitted, %u received, %u loss\n", i, succ_cnt, failed_cnt); 1807 1808FAILURE: 1809 ping_kill = 0; 1810 (void)lwip_close(sfd); 1811 if (pbuf_resp != NULL) { 1812 (void)pbuf_free(pbuf_resp); 1813 } 1814 if (iecho != NULL) { 1815 mem_free(iecho); 1816 } 1817 return ret; 1818} 1819 1820static void ping_cmd(unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3) 1821{ 1822 u32_t destip = p0; 1823 u32_t count = p1; 1824 u32_t interval = p2; 1825 u32_t data_len = p3; 1826 int ret; 1827 1828 ret = osPingFunc(destip, count, interval, data_len); 1829 if (ret < 0) { 1830 PRINTK("Ping cmd failed due to some errors\n"); 1831 } 1832 1833 ping_taskid = -1; 1834} 1835 1836u32_t osShellPing(int argc, const char **argv) 1837{ 1838 int ret; 1839 u32_t i = 0; 1840 u32_t count = 0; 1841 int count_set = 0; 1842 u32_t interval = 1000; /* default ping interval */ 1843 u32_t data_len = 48; /* default data length */ 1844 ip4_addr_t dst_ipaddr; 1845 TSK_INIT_PARAM_S stPingTask; 1846 1847 if (!tcpip_init_finish) { 1848 PRINTK("Ping: tcpip_init have not been called\n"); 1849 return LOS_NOK; 1850 } 1851 1852 if ((argc < 1) || (argv == NULL)) { 1853 PRINTK("Ping: require dest ipaddr at least\n"); 1854 goto ping_error; 1855 } 1856 1857 /* could add more param support */ 1858 while (argc > 0) { 1859 if (strcmp("-n", argv[i]) == 0 && (argc > 1)) { 1860 ret = atoi(argv[i + 1]); 1861 if (ret <= 0) { 1862 PRINTK("Ping count should be greater than 0 \n"); 1863 goto ping_error; 1864 } 1865 count = ret; 1866 count_set = 1; 1867 i += 2; 1868 argc -= 2; // 2: nuber of arguments that has been checked 1869 } else if (strcmp("-t", argv[i]) == 0) { 1870 count = 0; /* ping forerver */ 1871 count_set = 1; 1872 i++; 1873 argc--; 1874 } else if (strcmp("-w", argv[i]) == 0 && (argc > 1)) { 1875 ret = atoi(argv[i + 1]); 1876 if (ret <= 0) { 1877 PRINTK("Ping interval should be greater than 0 \n"); 1878 goto ping_error; 1879 } 1880 1881 interval = ret; 1882 i += 2; 1883 argc -= 2; // 2:number of arguments that has been checked 1884 } else if (strcmp("-l", argv[i]) == 0 && (argc > 1)) { 1885 ret = atoi(argv[i + 1]); 1886 if (ret < 0 || ret > (int)(LWIP_MAX_UDP_RAW_SEND_SIZE - sizeof(struct icmp_echo_hdr))) { 1887 PRINTK("Ping data length error, should be in range of [0, %d] \n", 1888 LWIP_MAX_UDP_RAW_SEND_SIZE - sizeof(struct icmp_echo_hdr)); 1889 goto ping_error; 1890 } 1891 data_len = ret; 1892 i += 2; 1893 argc -= 2; // 2: number of elements has been checked 1894 } else if (strcmp("-k", argv[i]) == 0) { 1895 if (ping_taskid > 0) { 1896 ping_kill = 1; /* stop the current ping task */ 1897 return LOS_OK; 1898 } else { 1899 PRINTK("No ping task running...\n"); 1900 return LOS_NOK; 1901 } 1902 } else { 1903 if (argc == 1) { 1904 break; 1905 } else { 1906 PRINTK("Invalid Ping param\n"); 1907 goto ping_error; 1908 } 1909 } 1910 } 1911 1912 if (!count_set) { 1913 count = LWIP_SHELL_CMD_PING_RETRY_TIMES; 1914 } 1915 1916 /* initialize dst IP address */ 1917 if (argc <= 0) { 1918 goto ping_error; 1919 } 1920#if LWIP_DNS 1921 dst_ipaddr.addr = get_hostip(argv[i]); 1922#else /* LWIP_DNS */ 1923 dst_ipaddr.addr = inet_addr(argv[i]); 1924#endif /* LWIP_DNS */ 1925 1926 if (dst_ipaddr.addr == IPADDR_NONE || dst_ipaddr.addr == IPADDR_ANY) { 1927 PRINTK("Invalid dest ipaddr: NONE or ANY\n"); 1928 return LOS_NOK; 1929 } 1930 1931 /* start one task if ping forever or ping count greater than 60 */ 1932 if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) { 1933 if (ping_taskid > 0) { 1934 PRINTK("Ping task already running and only support one now\n"); 1935 return LOS_NOK; 1936 } 1937 stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd; 1938 stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 1939 stPingTask.pcName = "ping_task"; 1940 stPingTask.usTaskPrio = 8; /* higher than shell */ 1941 stPingTask.uwResved = LOS_TASK_STATUS_DETACHED; 1942 stPingTask.auwArgs[0] = dst_ipaddr.addr; /* network order */ 1943 stPingTask.auwArgs[1] = count; 1944 stPingTask.auwArgs[2] = interval; 1945 stPingTask.auwArgs[3] = data_len; // 3: index of data length 1946 ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask); 1947 if (ret != LOS_OK) { 1948 PRINTK("ping_task create failed 0x%08x.\n", ret); 1949 count = LWIP_SHELL_CMD_PING_RETRY_TIMES; 1950 } else { 1951 return LOS_OK; 1952 } 1953 } 1954 1955 /* two cases: 1956 1, ping cout less than LWIP_SHELL_CMD_PING_RETRY_TIMES; 1957 2, ping task create failed; 1958 */ 1959 if (osPingFunc(dst_ipaddr.addr, count, interval, data_len) < 0) { 1960 PRINTK("Ping cmd failed due some errors\n"); 1961 } 1962 1963 return LOS_OK; 1964ping_error: 1965 lwip_ping_usage(); 1966 return LOS_NOK; 1967} 1968#ifdef LOSCFG_SHELL 1969SHELLCMD_ENTRY(ping_shellcmd, CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)osShellPing); 1970#endif /* LOSCFG_SHELL */ 1971 1972#else /* LWIP_EXT_POLL_SUPPORT */ 1973 1974u32_t osShellPing(int argc, const char **argv) 1975{ 1976 int sfd; 1977 struct sockaddr_in to; 1978 struct icmp_echo_hdr iecho; 1979 struct pbuf *pbuf_resp = NULL; 1980 struct icmp_echo_hdr *iecho_resp = NULL; 1981 struct ip_hdr *iphdr_resp = NULL; 1982 s16_t ip_hlen; 1983 ip_addr_t dst_ipaddr; 1984 fd_set fdReadSet; 1985 struct timeval stTimeVal; 1986 struct timespec start, end; 1987 int ret; 1988 s32_t i; 1989 long rtt; 1990 s32_t pingcount; 1991 char buf[50]; 1992 1993 if (!tcpip_init_finish) { 1994 PRINTK("ping: tcpip_init have not been called\n"); 1995 return LOS_NOK; 1996 } 1997 1998 if ((argc < 1) || (argv == NULL)) { 1999 PRINTK("ping : invalid arguments, ping command receives ip as command line argument \n"); 2000 return LOS_NOK; 2001 } 2002 2003 if (argc == 2) { 2004 pingcount = atoi(argv[1]); 2005 if (pingcount < 1) 2006 pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES; 2007 } else { 2008 pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES; 2009 } 2010 PRINTK("ping %u packets start.\n", pingcount); 2011 2012 /* initialize dst IP address */ 2013#if LWIP_DNS 2014 ip_2_ip4(&dst_ipaddr)->addr = get_hostip(argv[0]); 2015#else /* LWIP_DNS */ 2016 ip_2_ip4(&dst_ipaddr)->addr = inet_addr(argv[0]); 2017#endif /* LWIP_DNS */ 2018 2019 to.sin_family = AF_INET; 2020 to.sin_addr.s_addr = ip_2_ip4(&dst_ipaddr)->addr; 2021 to.sin_port = 0; 2022 2023 if (to.sin_addr.s_addr == IPADDR_NONE || to.sin_addr.s_addr == IPADDR_ANY) { 2024 PRINTK("ping : invalid ip address : NONE or ANY\n"); 2025 return LOS_NOK; 2026 } 2027 2028 sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 2029 if (sfd == -1) { 2030 PRINTK("ping : failed, socket creation failed\n"); 2031 return LOS_NOK; 2032 } 2033 2034 pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM); 2035 if (pbuf_resp == NULL) { 2036 PRINTK("ping : memory allocation failed\n"); 2037 goto FAILURE; 2038 } 2039 2040 for (i = 0; i < pingcount; i++) { 2041 (void)memset_s(&iecho, sizeof(iecho), 0, sizeof(iecho)); 2042 ICMPH_TYPE_SET(&iecho, (u8_t)ICMP_ECHO); 2043 iecho.chksum = inet_chksum(&iecho, sizeof(struct icmp_echo_hdr)); 2044 2045 ret = lwip_sendto(sfd, &iecho, sizeof(struct icmp_echo_hdr), 0, (struct sockaddr *)&to, (socklen_t)sizeof(to)); 2046 if (ret == -1) { 2047 PRINTK("ping : sending ICMP echo msg failed\n"); 2048 goto FAILURE; 2049 } 2050 2051 /* capture the start time to calculate round trip time */ 2052 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start); 2053 /* Wait in select for ICMP response msg */ 2054 FD_ZERO(&fdReadSet); 2055 FD_SET(sfd, &fdReadSet); 2056 stTimeVal.tv_sec = LWIP_SHELL_CMD_PING_TIMEOUT / 1000; 2057 stTimeVal.tv_usec = 0; 2058 2059DO_SELECT: 2060 ret = select(sfd + 1, &fdReadSet, 0, 0, &stTimeVal); 2061 if (ret < 0) { 2062 PRINTK("ping : select failure\n"); 2063 goto FAILURE; 2064 } else if (ret == 0) { 2065 PRINTK("Request timed out.\n"); 2066 continue; 2067 } 2068 2069 /* capture the end time to calculate round trip time */ 2070 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); 2071 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); 2072 2073 ret = lwip_recv(sfd, pbuf_resp->payload, pbuf_resp->len, 0); 2074 if (ret == -1) { 2075 PRINTK("ping : receiving ICMP echo response msg failed\n"); 2076 goto FAILURE; 2077 } 2078 2079 /* Accessing ip header and icmp header */ 2080 iphdr_resp = (struct ip_hdr *)(pbuf_resp->payload); 2081 ip_hlen = (s16_t)(IPH_HL(iphdr_resp) * 4); 2082 if (pbuf_header(pbuf_resp, (s16_t)(-ip_hlen))) { 2083 /* this failure will never happen, but failure handle is written just to be in safe side */ 2084 PRINTK("ping : memory management failure\n"); 2085 goto FAILURE; 2086 } 2087 iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload; 2088 2089 /* Reverting back pbuf to its original state */ 2090 if (pbuf_header(pbuf_resp, ip_hlen)) { 2091 /* this failure will never happen, but failure handle is written just to be in safe side */ 2092 PRINTK("ping : memory management failure\n"); 2093 goto FAILURE; 2094 } 2095 2096 if (iphdr_resp->src.addr == to.sin_addr.s_addr) { 2097 if (ICMPH_TYPE(iecho_resp) == ICMP_ER) { 2098 PRINTK("[%u]Reply from %s: time=%ims TTL=%u\n", i, 2099 inet_ntoa_r(to.sin_addr.s_addr, buf, sizeof(buf)), rtt, iphdr_resp->_ttl); 2100 } else if (ICMPH_TYPE(iecho_resp) == ICMP_ECHO) { 2101 /* If ping self, stack will receive a ICMP_ECHO request message flowing a ICMP_ER reply message, 2102 and we need reply only, do select again */ 2103 goto DO_SELECT; 2104 } 2105 } 2106 } 2107 2108 (void)lwip_close(sfd); 2109 (void)pbuf_free(pbuf_resp); 2110 return LOS_OK; 2111 2112FAILURE: 2113 (void)lwip_close(sfd); 2114 if (pbuf_resp != NULL) { 2115 (void)pbuf_free(pbuf_resp); 2116 } 2117 2118 return LOS_NOK; 2119} 2120 2121#ifdef LOSCFG_SHELL 2122SHELLCMD_ENTRY(ping_shellcmd, CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)osShellPing); 2123#endif /* LOSCFG_SHELL */ 2124 2125#endif /* LWIP_EXT_POLL_SUPPORT */ 2126 2127#if LWIP_IPV6 2128u32_t osShellPing6(int argc, const char **argv) 2129{ 2130 u16_t icmpv6_id; 2131 u16_t icmpv6_seq; 2132 u32_t nsent; 2133 u32_t nrecieve; 2134 u32_t last_received; 2135 struct timespec start, end, start_in_reply; 2136 struct timespec first, last; 2137 long rtt; 2138 int ret; 2139 fd_set fdReadSet; 2140 void *param = NULL; 2141 ping6_args_t ping6_params; 2142 ping6_stats_t ping6_stats; 2143 struct sockaddr_in6 to; 2144 struct icmp6_echo_hdr *iecho_resp = NULL; 2145 struct icmp6_echo_hdr *iecho = NULL; 2146 struct timeval stTimeVal; 2147 struct timeval deltaTimeVal; 2148 struct pbuf *pbuf_resp = NULL; 2149 struct pbuf *pbuf_req = NULL; 2150 int sfd = -1; 2151 u8_t type; 2152 u8_t select_on_socket = 0; 2153 char buf[INET6_ADDRSTRLEN]; 2154 2155 if (!tcpip_init_finish) { 2156 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 2157 ret = -1; 2158 goto exit; 2159 } 2160 2161 if ((argc < 1) || (argc > LWIP_MAX_PING6_ARG_COUNT) || (argv == NULL)) { 2162 goto usage; 2163 } 2164 2165 ret = parse_args_ping6(argc, argv, &ping6_params); 2166 if (ret == -1) { 2167 goto exit; 2168 } 2169 2170 if (ping6_params.args_found & LWIP_PING6_SOURCE_ADDRESS_ARG) { 2171 type = LWIP_PING6_SOURCE_ADDRESS_ARG; 2172 param = (void *)(&ping6_params.src_addr); 2173 } else if (ping6_params.args_found & LWIP_PING6_INTERFACE_ARG) { 2174 type = LWIP_PING6_INTERFACE_ARG; 2175 param = (void *)(argv[ping6_params.interface_index]); 2176 } else { 2177 type = LWIP_PING6_DEFAULT_SOCKET; 2178 param = NULL; 2179 } 2180 2181 /* Create a socket for sending and receiving pings with appropriate bindings */ 2182 sfd = create_ping6_socket(type, param); 2183 if (sfd == -1) { 2184 ret = -1; 2185 goto exit; 2186 } 2187 2188 pbuf_req = pbuf_alloc(PBUF_RAW, LWIP_PING6_STANDARD_PKT_SIZE, PBUF_RAM); 2189 pbuf_resp = pbuf_alloc(PBUF_RAW, LWIP_PING6_STANDARD_PKT_SIZE, PBUF_RAM); 2190 if ((pbuf_resp == NULL) || (pbuf_req == NULL)) { 2191 PRINTK("ping6 : Memory Allocation Failed\n"); 2192 ret = -1; 2193 goto exit; 2194 } 2195 2196 to.sin6_family = AF_INET6; 2197 inet6_addr_from_ip6addr(&to.sin6_addr, &(ping6_params.dst_addr)); 2198 to.sin6_port = htons(IPPROTO_ICMPV6); 2199 2200#if LWIP_DNS 2201 if (lwip_strnicmp(inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)), argv[ping6_params.host_index], 2202 sizeof(to.sin6_addr))) { 2203 /* If There Was A DNS Resolution */ 2204 PRINTK("PING %s (%s) with %d bytes of data.\n", 2205 argv[ping6_params.host_index], buf, LWIP_PING6_STANDARD_PKT_SIZE); 2206 } else { 2207 PRINTK("PING %s with %d bytes of data.\n", buf, LWIP_PING6_STANDARD_PKT_SIZE); 2208 } 2209#else 2210 PRINTK("PING %s with %d bytes of data\n", inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)), LWIP_PING6_STANDARD_PKT_SIZE); 2211#endif /* LWIP_DNS */ 2212 2213 nrecieve = 0; 2214 ping6_stats.flag = 0; 2215 ping6_stats.avg_rtt = 0; 2216 ping6_stats.max_rtt = 0; 2217 ping6_stats.min_rtt = 0; 2218 last_received = LWIP_PING6_STARTING_SEQ_NUM + LWIP_PING6_OUT_OF_ORDER_MAGNITUDE + 1; 2219 icmpv6_id = (u16_t)LWIP_RAND(); 2220 icmpv6_seq = LWIP_PING6_STARTING_SEQ_NUM; 2221 /* Setting the start time of the entire ping task for statistics */ 2222 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &first); 2223 2224 for (nsent = 0; nsent < ping6_params.pingcount; nsent++) { 2225 /* capture the start tick to calculate rtt */ 2226 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start); 2227 /* Initialize Memory To Prevent Uninitialized Memory Read Write Issues */ 2228 if (memset_s(pbuf_req->payload, pbuf_req->len, (int)(start.tv_nsec), pbuf_req->len) != 0) { 2229 goto exit; 2230 } 2231 2232 iecho = (struct icmp6_echo_hdr *)pbuf_req->payload; 2233 iecho->type = ICMP6_TYPE_EREQ; 2234 iecho->id = icmpv6_id; 2235 icmpv6_seq++; 2236 iecho->seqno = icmpv6_seq; 2237 iecho->code = 0; 2238 2239 /* Embedding the start_tick as data into the icmp_payload */ 2240 (void)pbuf_header(pbuf_req, (s16_t)(-(s16_t)(sizeof(struct icmp6_echo_hdr)))); 2241 if (memcpy_s(pbuf_req->payload, pbuf_req->len, (void *)&start, sizeof(start)) != 0) { 2242 goto exit; 2243 } 2244 (void)pbuf_header(pbuf_req, (s16_t)((s16_t)(sizeof(struct icmp6_echo_hdr)))); 2245 2246 ret = lwip_sendto(sfd, iecho, pbuf_req->len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to)); 2247 if (ret == -1) { 2248 PRINTK("ping6 : Sending ICMP Echo message failed\n"); 2249 goto exit; 2250 } 2251 2252 /* Wait in select for ICMP response msg */ 2253 FD_ZERO(&fdReadSet); 2254 FD_SET(sfd, &fdReadSet); 2255 stTimeVal.tv_sec = LWIP_MSECS_TO_SECS(LWIP_SHELL_CMD_PING_TIMEOUT); 2256 stTimeVal.tv_usec = 0; 2257 select_on_socket = 1; 2258 2259 while (select_on_socket) { 2260 select_on_socket = 0; 2261 ret = select(sfd + 1, &fdReadSet, 0, 0, &stTimeVal); 2262 if (ret < 0) { 2263 PRINTK("ping6 : select failure\n"); 2264 goto exit; 2265 } else if (ret == 0) { 2266 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); 2267 PRINTK("Request timed out\n"); 2268 continue; 2269 } 2270 2271 /* capture the end time to calculate round trip time */ 2272 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); 2273 2274 ret = lwip_recv(sfd, pbuf_resp->payload, pbuf_resp->len, 0); 2275 if (ret == -1) { 2276 PRINTK("ping6 : receiving ICMP echo response msg failed\n"); 2277 goto exit; 2278 } 2279 2280 if ((u32_t)ret < sizeof(struct icmp6_echo_hdr *)) { 2281 /* Drop the packet if its too short [Doesn't contain even the header !!] */ 2282 PRINTK("ping6 : received ICMP echo response too short\n"); 2283 goto REDUCE_SELECT_TIME; 2284 } 2285 2286 /* Acceping the ICMPv6 payload. */ 2287 /* Here, pbuf_resp->payload won't contain IPv6 Header since its an AF_INET6 RAW Socket */ 2288 iecho_resp = (struct icmp6_echo_hdr *)pbuf_resp->payload; 2289 2290 if (iecho_resp->id == icmpv6_id) { 2291 if (iecho_resp->type == ICMP6_TYPE_EREP) { 2292 if (ret < LWIP_PING6_STANDARD_PKT_SIZE) { 2293 /* Drop the packet if its too short */ 2294 PRINTK("ping6 : received ICMP echo response too short\n"); 2295 goto REDUCE_SELECT_TIME; 2296 } 2297 /* Accept and process only those delayed EREP only if its sequence num is within out-of-order magnitude */ 2298 if (nsent && iecho_resp->seqno != icmpv6_seq && 2299 (iecho_resp->seqno<(u16_t)(last_received - LWIP_PING6_OUT_OF_ORDER_MAGNITUDE) || 2300 iecho_resp->seqno>(u16_t)( 2301 last_received + LWIP_PING6_OUT_OF_ORDER_MAGNITUDE))) { 2302 /* Otherwise drop it and wait for more packets */ 2303 goto REDUCE_SELECT_TIME; 2304 } 2305 ++nrecieve; 2306 last_received = iecho_resp->seqno; 2307 /* Retrieving the start_tick from the packet which was embedded when the request was transmitted */ 2308 (void)pbuf_header(pbuf_resp, (s16_t)(-(s16_t)(sizeof(struct icmp6_echo_hdr)))); 2309 if (memcpy_s((void *)&start_in_reply, sizeof(start_in_reply), 2310 pbuf_resp->payload, sizeof(start_in_reply)) != EOK) { 2311 goto REDUCE_SELECT_TIME; 2312 } 2313 (void)pbuf_header(pbuf_resp, (s16_t)((s16_t)(sizeof(struct icmp6_echo_hdr)))); 2314 2315 rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); 2316 2317 PRINTK("%d bytes from %s : icmp_seq=%d time", ret, 2318 inet_ntop(AF_INET6, &to.sin6_addr, buf, sizeof(buf)), 2319 ((iecho_resp->seqno) - LWIP_PING6_STARTING_SEQ_NUM)); 2320 if (rtt < 1) { 2321 PRINTK("<1 ms\n"); 2322 } else { 2323 PRINTK("=%i ms\n", rtt); 2324 } 2325 2326 update_ping6_stats(&ping6_stats, (u32_t)(rtt), nrecieve); 2327 2328 /* Checking if its a delayed packet */ 2329 if ((iecho_resp->seqno != icmpv6_seq) && (nsent < ping6_params.pingcount)) { 2330 /* In case of delayed packet wait on socket for other response before sending a new PING */ 2331 /* We have to reduce the timeout value now when selecting on socket */ 2332 goto REDUCE_SELECT_TIME; 2333 } 2334 } else { 2335 PRINTK("[%u]ping6 : %s\n", nsent, convert_icmpv6_err_to_string(iecho_resp->type)); 2336 } 2337 } else { 2338 /* If incoming packet does not matches with icmp_id, it should be ignored */ 2339 /* Reduce the timeout for select on socket */ 2340REDUCE_SELECT_TIME: 2341 deltaTimeVal.tv_sec = (long)(end.tv_sec - start.tv_sec); 2342 deltaTimeVal.tv_usec = (long)((end.tv_nsec - start.tv_nsec) / 1000); 2343 /* Subtract deltaTime from stTime and store in stTime */ 2344 /* This will reduce the select time on the socket */ 2345 timersub(&stTimeVal, &deltaTimeVal, &stTimeVal); 2346 select_on_socket = 1; 2347 } 2348 } 2349 } 2350 2351 ret = ERR_OK; 2352 2353 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &last); 2354 /* Display ping stats */ 2355 PRINTK("--- %s ping statistics ---\n", argv[ping6_params.host_index]); 2356 PRINTK("%d packets transmitted, %d received, %.2f%% packet loss, time %dms\n", 2357 nsent, nrecieve, (float)(((float)(nsent - nrecieve)) * ((float)(100)) / ((float)(nsent))), 2358 /* 1000: convert seconds to milliseconds, 1000000: convert nanoseconds to milliseconds */ 2359 ((last.tv_sec - first.tv_sec) * 1000 + (last.tv_nsec - first.tv_nsec) / 1000000)); 2360 if (nrecieve) { 2361 /* Display rtt stats only if at least one packet is received */ 2362 PRINTK("rtt min/avg/max = %u/%.2f/%u ms\n", ping6_stats.min_rtt, ping6_stats.avg_rtt, ping6_stats.max_rtt); 2363 } 2364 2365exit: 2366 if (sfd != -1) { 2367 (void)lwip_close(sfd); 2368 } 2369 2370 if (pbuf_resp != NULL) { 2371 (void)pbuf_free(pbuf_resp); 2372 } 2373 2374 if (pbuf_req != NULL) { 2375 (void)pbuf_free(pbuf_req); 2376 } 2377 return (u32_t)((ret == (int)ERR_OK) ? LOS_OK : LOS_NOK); 2378 2379usage: 2380 PRINTK("Usage:\n"); 2381 PRINTK("\tping6 [-c count] [-I interface/sourceAddress] destination\n"); 2382 return LOS_NOK; 2383} 2384 2385LWIP_STATIC int create_ping6_socket(u8_t type, const void *param) 2386{ 2387 int sfd; 2388 int ret; 2389 struct sockaddr_in6 stHostAddr6; 2390 struct icmp6_filter icmp6_sock_filter; 2391 2392 sfd = lwip_socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 2393 if (sfd == -1) { 2394 PRINTK("ping6 : Failed, socket creation failed\n"); 2395 return -1; 2396 } 2397 2398 if (param != NULL) { 2399 if (type == LWIP_PING6_SOURCE_ADDRESS_ARG) { 2400 /* Binding socket to the provided source address */ 2401 (void)memset_s(&stHostAddr6, sizeof(stHostAddr6), 0, sizeof(stHostAddr6)); 2402 stHostAddr6.sin6_family = AF_INET6; 2403 inet6_addr_from_ip6addr(&stHostAddr6.sin6_addr, (ip6_addr_t *)param); 2404 stHostAddr6.sin6_port = htons(IPPROTO_ICMPV6); 2405 stHostAddr6.sin6_scope_id = 0; 2406 2407 ret = lwip_bind(sfd, (struct sockaddr *)&stHostAddr6, sizeof(stHostAddr6)); 2408 if (ret == -1) { 2409 (void)lwip_close(sfd); 2410 PRINTK("ping6 : bind icmp socket: cannot assign requested address\n"); 2411 return ret; 2412 } 2413 } else if (type == LWIP_PING6_INTERFACE_ARG) { 2414 /* Binding socket to the provided netif */ 2415 ret = lwip_setsockopt(sfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)(param), strlen((char *)(param))); 2416 if (ret == -1) { 2417 (void)lwip_close(sfd); 2418 PRINTK("ping6: unknownn iface %s\n", (char *)(param)); 2419 return ret; 2420 } 2421 } 2422 } 2423 2424 /* Setting socket filter since we are interested only in ECHO REPLY and ERROR messages */ 2425 ICMP6_FILTER_SETBLOCKALL(&icmp6_sock_filter); 2426 ICMP6_FILTER_SETPASS(ICMP6_TYPE_EREP, &icmp6_sock_filter); 2427 ICMP6_FILTER_SETPASS(ICMP6_TYPE_DUR, &icmp6_sock_filter); 2428 ICMP6_FILTER_SETPASS(ICMP6_TYPE_PTB, &icmp6_sock_filter); 2429 ICMP6_FILTER_SETPASS(ICMP6_TYPE_TE, &icmp6_sock_filter); 2430 2431 ret = lwip_setsockopt(sfd, IPPROTO_ICMPV6, ICMP6_FILTER, &icmp6_sock_filter, sizeof(struct icmp6_filter)); 2432 if (ret == -1) { 2433 (void)lwip_close(sfd); 2434 PRINTK("ping6 : setsockopt: Invalid Argument\n"); 2435 return -1; 2436 } 2437 2438 return sfd; 2439} 2440 2441/* 2442 * Function to parse the command line args for ping6 shell utility 2443 * @return: 2444 * Success: ERR_OK 2445 * Failure: -1 2446 */ 2447LWIP_STATIC int parse_args_ping6(int argc, const char **argv, ping6_args_t *ping6_params) 2448{ 2449 int pingcount; 2450 int ret = -1; 2451#if LWIP_DNS 2452 struct addrinfo *res = NULL; 2453 struct addrinfo hints_structure; 2454#endif 2455 u8_t i = 0; 2456 2457 IP6_ADDR(&(ping6_params->dst_addr), 0, 0, 0, 0); 2458 IP6_ADDR(&(ping6_params->src_addr), 0, 0, 0, 0); 2459 2460 ping6_params->pingcount = LWIP_SHELL_CMD_PING_RETRY_TIMES; 2461 ping6_params->host_index = 0; 2462 ping6_params->args_found = 0; 2463 2464 while (i < argc) { 2465 if (strcmp("-c", argv[i]) == 0) { 2466 /* Handle number of ICMP packets to transmit :: -c [number_of_packets] */ 2467 if (ping6_params->args_found & LWIP_PING6_COUNT_ARG) { 2468 PRINTK("ping6: -c option present multiple times \n"); 2469 ret = -1; 2470 goto exit; 2471 } 2472 2473 if (i + 2 > argc) { 2474 PRINTK("ping6: ping count(-c) should require an argument \n"); 2475 ret = -1; 2476 goto exit; 2477 } 2478 2479 pingcount = atoi(argv[i + 1]); 2480 if (pingcount <= 0) { 2481 PRINTK("ping6: bad number of packets to transmit \n"); 2482 ret = -1; 2483 goto exit; 2484 } 2485 2486 ping6_params->args_found |= LWIP_PING6_COUNT_ARG; 2487 ping6_params->pingcount = (u32_t)pingcount; 2488 i = (u8_t)(i + 2); 2489 } else if (strcmp("-I", argv[i]) == 0) { 2490 /* Handle interface ID / sourceAddress using which the ICMP Packets has to be transmitted :: -I [interface_id/source_address] */ 2491 2492 if ((ping6_params->args_found & LWIP_PING6_SOURCE_ADDRESS_ARG) || 2493 (ping6_params->args_found & LWIP_PING6_INTERFACE_ARG)) { 2494 PRINTK("ping6: -I option present multiple times \n"); 2495 ret = -1; 2496 goto exit; 2497 } 2498 2499 if (i + 2 > argc) { 2500 PRINTK("ping6: interface/source address(-I) should require an argument \n"); 2501 ret = -1; 2502 goto exit; 2503 } 2504 2505 /* Check whether the given argument to -I is source address */ 2506 if (ip6addr_aton(argv[i + 1], &(ping6_params->src_addr))) { 2507 ping6_params->args_found |= LWIP_PING6_SOURCE_ADDRESS_ARG; 2508 i = (u8_t)(i + 2); 2509 continue; 2510 } 2511 2512 /* Storing the index where interface name is found */ 2513 /* If this name is not valid, then it will fail later in setsockopt(BIND_TO_DEVICE) */ 2514 ping6_params->interface_index = (u8_t)(i + 1); 2515 ping6_params->args_found |= LWIP_PING6_INTERFACE_ARG; 2516 2517 i = (u8_t)(i + 2); 2518 } else { 2519 if (argv[i][0] == '-') { 2520 /* Check whether its a bad option */ 2521 PRINTK("ping6: bad option %s\n", argv[i]); 2522 ret = -1; 2523 goto exit; 2524 } else if (ping6_params->args_found & LWIP_PING6_HOSTNAME_ARG) { 2525 /* Check whether hostname is already found and there are extra arguments */ 2526 PRINTK("ping6: bad parameter %s\n", argv[i]); 2527 ret = -1; 2528 goto exit; 2529 } 2530 2531#if LWIP_DNS 2532 /* Resolve the given hostname */ 2533 hints_structure.ai_family = AF_INET6; 2534 hints_structure.ai_flags = 0; 2535 ret = lwip_getaddrinfo(argv[i], NULL, &hints_structure, &res); 2536 if (ret != ERR_OK) { 2537 PRINTK("ping6 : Host : %s can't be resolved to IPv6 address\n", argv[i]); 2538 ret = -1; 2539 goto exit; 2540 } 2541 2542 inet6_addr_to_ip6addr(&(ping6_params->dst_addr), 2543 &(((const struct sockaddr_in6 *)(res->ai_addr))->sin6_addr)); 2544#else 2545 /* Convert the string representation to network form */ 2546 if (!ip6addr_aton(argv[i], &(ping6_params->dst_addr))) { 2547 PRINTK("ping6 : Invalid IPv6 Address : %s\n", argv[i]); 2548 ret = -1; 2549 goto exit; 2550 } 2551#endif /* LWIP_DNS */ 2552 if (ip6_addr_isany(&(ping6_params->dst_addr)) || ip6_addr_isnone(&(ping6_params->dst_addr))) { 2553#if LWIP_DNS 2554 PRINTK("ping6 : IPv6 address of host : %s (%s) is invalid\n", argv[i], 2555 ip6addr_ntoa((const ip6_addr_t *)&(ping6_params->dst_addr))); 2556#else 2557 PRINTK("ping6 : Invalid IPv6 address : %s\n", argv[i]); 2558#endif /* LWIP_DNS */ 2559 goto exit; 2560 } 2561 /* Setting host_index to the index of argv[] where the host/IP is present */ 2562 ping6_params->args_found |= LWIP_PING6_HOSTNAME_ARG; 2563 ping6_params->host_index = (u8_t)(i); 2564 i = (u8_t)(i + 1); 2565 } 2566 } 2567 2568 if (!(ping6_params->args_found & LWIP_PING6_HOSTNAME_ARG)) { 2569 /* Hostname/IPv6 address not found */ 2570 PRINTK("ping6 : Hostname/IPv6 address to ping is not specified\n"); 2571 ret = -1; 2572 goto exit; 2573 } 2574 2575 if (ip6_addr_islinklocal(&(ping6_params->dst_addr)) && 2576 !(ping6_params->args_found & (LWIP_PING6_INTERFACE_ARG | LWIP_PING6_SOURCE_ADDRESS_ARG))) { 2577 /* For link-local addresses, -I is mandatory */ 2578 PRINTK("ping6 : Interface specification is mandatory for link-local addresses\n"); 2579 ret = -1; 2580 goto exit; 2581 } 2582 2583 ret = ERR_OK; 2584 2585exit: 2586#if LWIP_DNS 2587 lwip_freeaddrinfo(res); 2588#endif /* LWIP_DNS */ 2589 2590 return ret; 2591} 2592 2593/* 2594 * Function to update ping6_stats 2595 * stats is maintained in ping6_stats structure 2596 */ 2597LWIP_STATIC void update_ping6_stats(ping6_stats_t *ping6_stats, u32_t rtt, u32_t nreceived) 2598{ 2599 if (rtt > ping6_stats->max_rtt) { 2600 ping6_stats->max_rtt = rtt; 2601 } 2602 2603 if (ping6_stats->flag == 0 || rtt < ping6_stats->min_rtt) { 2604 ping6_stats->min_rtt = rtt; 2605 ping6_stats->flag = 1; 2606 } 2607 2608 ping6_stats->avg_rtt = (float)(ping6_stats->avg_rtt + 2609 (float)((float)((float)rtt - ping6_stats->avg_rtt) / (float)(nreceived))); 2610} 2611 2612LWIP_STATIC const char *convert_icmpv6_err_to_string(u8_t err_type) 2613{ 2614 switch (err_type) { 2615 case ICMP6_TYPE_DUR: 2616 return "Destination Unreachable"; 2617 case ICMP6_TYPE_PTB: 2618 return "Packet too big"; 2619 case ICMP6_TYPE_TE: 2620 return "Time Exceeded"; 2621 case ICMP6_TYPE_PP: 2622 return "Parameter Problem"; 2623 default: 2624 break; 2625 } 2626 return "Unknown Error"; 2627} 2628 2629#ifdef LOSCFG_SHELL_CMD_DEBUG 2630SHELLCMD_ENTRY(ping6_shellcmd, CMD_TYPE_EX, "ping6", XARGS, (CmdCallBackFunc)osShellPing6); 2631#endif /* LOSCFG_SHELL_CMD_DEBUG */ 2632#endif /* LWIP_IPV6 */ 2633 2634#if LWIP_SNTP 2635u32_t osShellNtpdate(int argc, const char **argv) 2636{ 2637 int server_num = 0; 2638 char *ret = NULL; 2639 struct timeval get_time; 2640 char buf[50]; 2641 2642 (void)memset_s(&get_time, sizeof(struct timeval), 0, sizeof(struct timeval)); 2643 2644 if (!tcpip_init_finish) { 2645 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 2646 return LOS_NOK; 2647 } 2648 2649 if (argc < 1 || argv == NULL) { 2650 goto usage; 2651 } 2652 2653 server_num = lwip_sntp_start(argc, (char **)argv, &get_time); 2654 if (server_num >= 0 && server_num < argc) { 2655 ret = ctime_r((time_t *)&get_time.tv_sec, buf); 2656 if (ret != NULL) { 2657 PRINTK("time server %s: %s\n", argv[server_num], ret); 2658 } else { 2659 PRINTK("ctime return null error\n"); 2660 } 2661 } else { 2662 PRINTK("no server suitable for synchronization found\n"); 2663 } 2664 2665 return LOS_OK; 2666 2667usage: 2668 PRINTK("\nUsage:\n"); 2669 PRINTK("ntpdate [SERVER_IP1] [SERVER_IP2] ...\n"); 2670 return LOS_NOK; 2671} 2672 2673#ifdef LOSCFG_SHELL_CMD_DEBUG 2674SHELLCMD_ENTRY(ntpdate_shellcmd, CMD_TYPE_EX, "ntpdate", XARGS, (CmdCallBackFunc)osShellNtpdate); 2675#endif /* LOSCFG_SHELL_CMD_DEBUG */ 2676 2677#endif /* LWIP_SNTP */ 2678 2679#if LWIP_DNS 2680u32_t osShellDns(int argc, const char **argv) 2681{ 2682 ip_addr_t dns = {0}; 2683 err_t err; 2684 int i; 2685 if (argc < 1 || argv == NULL) { 2686 goto usage; 2687 } 2688 2689 if (tcpip_init_finish == 0) { 2690 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 2691 return LOS_NOK; 2692 } 2693 2694 if (argc == 1 && (strcmp(argv[0], "-a") == 0)) { 2695 for (i = 0; i < DNS_MAX_SERVERS; i++) { 2696 err = lwip_dns_getserver((u8_t)i, &dns); 2697 if (err == ERR_OK) { 2698 PRINTK("dns %d: %s\n", i + 1, ipaddr_ntoa_unsafe(&dns)); 2699 } else { 2700 PRINTK("dns: failed\n"); 2701 return LOS_NOK; 2702 } 2703 } 2704 return LOS_OK; 2705 } else if (argc == 2) { 2706 i = atoi(argv[0]); 2707 if ((i <= 0) || (i > DNS_MAX_SERVERS)) 2708 goto usage; 2709#if LWIP_IPV6 2710 if (ip6addr_aton(argv[1], ((ip6_addr_t *)&dns))) { 2711#if LWIP_IPV4 && LWIP_IPV6 2712 dns.type = IPADDR_TYPE_V6; 2713#endif 2714 if (!ip6_addr_isglobal((ip6_addr_t *)&dns)) { 2715 PRINTK("ip address<%s> is wrong\n", argv[1]); 2716 return LOS_NOK; 2717 } 2718 } else 2719#endif 2720 { 2721#if LWIP_IPV4 2722 ((ip4_addr_t *)&dns)->addr = ipaddr_addr(argv[1]); 2723 if (((ip4_addr_t *)&dns)->addr == IPADDR_NONE) { 2724 PRINTK("ip address<%s> is wrong\n", argv[1]); 2725 return LOS_NOK; 2726 } 2727#if LWIP_IPV4 && LWIP_IPV6 2728 dns.type = IPADDR_TYPE_V4; 2729#endif 2730#endif 2731 } 2732 2733 err = lwip_dns_setserver((u8_t)(i - 1), &dns); 2734 if (err != ERR_OK) { 2735 PRINTK("dns : failed\n"); 2736 return LOS_NOK; 2737 } 2738 return LOS_OK; 2739 } 2740usage: 2741 PRINTK("usage:\n"); 2742 PRINTK("\tdns <1-%d> <IP>\n", DNS_MAX_SERVERS); 2743 PRINTK("\tdns -a\n"); 2744 return LOS_NOK; 2745} 2746 2747#ifdef LOSCFG_SHELL_CMD_DEBUG 2748SHELLCMD_ENTRY(dns_shellcmd, CMD_TYPE_EX, "dns", XARGS, (CmdCallBackFunc)osShellDns); 2749#endif /* LOSCFG_SHELL_CMD_DEBUG */ 2750#endif /* LWIP_DNS */ 2751#if LWIP_IPV6 2752extern struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; 2753#endif 2754#if LWIP_IPV6 2755int netstat_get_udp_sendQLen6(struct udp_pcb *udppcb, struct pbuf *udpbuf) 2756{ 2757 int sendLen = -1; 2758 u16_t offset = 0, len; 2759 struct ip6_hdr *iphdr = NULL; 2760 struct udp_hdr *udphdr = NULL; 2761 struct ip6_dest_hdr *dest_hdr = NULL; 2762 struct ip6_frag_hdr *frag_hdr = NULL; 2763 u8_t nexth; 2764 u16_t hlen = 0; 2765 2766 LWIP_ERROR("netstat_get_udp6_sendQLen: NULL pcb received\n", (udppcb != NULL), return -1); 2767 LWIP_ERROR("netstat_get_udp6_sendQLen: NULL pbuf received\n", (udpbuf != NULL), return -1); 2768 2769 iphdr = (struct ip6_hdr *)udpbuf->payload; 2770 2771 if (!(ip6_addr_cmp(&iphdr->dest, ip_2_ip6(&udppcb->remote_ip)) && 2772 (ip_addr_isany(&udppcb->local_ip) || 2773 ip6_addr_cmp(&iphdr->src, ip_2_ip6(&udppcb->local_ip))))) { 2774 goto FUNC_OUT; 2775 } 2776 2777 len = IP6_HLEN; 2778 if (pbuf_header(udpbuf, (s16_t)(-(s16_t)(len)))) { 2779 goto FUNC_OUT; 2780 } 2781 2782 offset = len; 2783 2784 nexth = IP6H_NEXTH(iphdr); 2785 while (offset < udpbuf->tot_len) { 2786 if (nexth == IP6_NEXTH_NONE || nexth == IP6_NEXTH_UDP || nexth == IP6_NEXTH_UDPLITE) { 2787 break; 2788 } 2789 switch (nexth) { 2790 case IP6_NEXTH_HOPBYHOP: 2791 case IP6_NEXTH_ROUTING: 2792 nexth = *((u8_t *)udpbuf->payload); 2793 hlen = (u16_t)(8 * (1 + *((u8_t *)udpbuf->payload + 1))); 2794 break; 2795 case IP6_NEXTH_DESTOPTS: 2796 nexth = *((u8_t *)udpbuf->payload); 2797 dest_hdr = (struct ip6_dest_hdr *)udpbuf->payload; 2798 hlen = (u16_t)(8 * (1 + dest_hdr->_hlen)); 2799 break; 2800 case IP6_NEXTH_FRAGMENT: 2801 frag_hdr = (struct ip6_frag_hdr *)udpbuf->payload; 2802 nexth = frag_hdr->_nexth; 2803 hlen = IP6_FRAG_HLEN; 2804 break; 2805 default: 2806 /* Unknown next_header */ 2807 goto FUNC_OUT; 2808 } 2809 2810 (void)pbuf_header(udpbuf, (s16_t)(-(s16_t)hlen)); 2811 offset = (u16_t)(offset + hlen); 2812 } 2813 2814 /* If the while loop test condition failed , then revert the last offset change */ 2815 if (offset >= udpbuf->tot_len) { 2816 offset = (u16_t)(offset - hlen); 2817 goto FUNC_OUT; 2818 } 2819 2820 LWIP_ERROR("Transport option should be UDP", (nexth == IP6_NEXTH_UDP || nexth == IP6_NEXTH_UDPLITE), goto FUNC_OUT); 2821 2822 if (offset > iphdr->_plen) { 2823 goto FUNC_OUT; 2824 } 2825 2826 /* check if there is enough space for at least udp header available */ 2827 if (udpbuf->tot_len < UDP_HLEN) { 2828 goto FUNC_OUT; 2829 } 2830 2831 udphdr = (struct udp_hdr *)udpbuf->payload; 2832 if ((ntohs(udphdr->dest) == udppcb->remote_port) && (ntohs(udphdr->src) == udppcb->local_port)) { 2833 if (ntohs(udphdr->len) > UDP_HLEN) { 2834 sendLen = ntohs(udphdr->len) - UDP_HLEN; 2835 } else { 2836 sendLen = udpbuf->tot_len - UDP_HLEN; 2837 } 2838 } 2839 2840FUNC_OUT: 2841 (void)pbuf_header(udpbuf, (s16_t)offset); // can not cross max limit of s16_t 2842 return sendLen; 2843} 2844#endif 2845 2846#if LWIP_IPV4 2847int netstat_get_udp_sendQLen(struct udp_pcb *udppcb, struct pbuf *udpbuf) 2848{ 2849 int sendLen = -1; 2850 u16_t offset = 0, len; 2851 struct ip_hdr *iphdr = NULL; 2852 struct udp_hdr *udphdr = NULL; 2853 2854 LWIP_ERROR("netstat_get_udp_sendQLen: NULL pcb received\n", (udppcb != NULL), return -1); 2855 LWIP_ERROR("netstat_get_udp_sendQLen: NULL pbuf received\n", (udpbuf != NULL), return -1); 2856 2857 iphdr = (struct ip_hdr *)udpbuf->payload; 2858 2859 if (!(ip4_addr_cmp(&iphdr->dest, ip_2_ip4(&udppcb->remote_ip)) && 2860 (ip_addr_isany(&udppcb->local_ip) || 2861 ip4_addr_cmp(&iphdr->src, ip_2_ip4(&udppcb->local_ip))))) { 2862 goto FUNC_OUT; 2863 } 2864#if LWIP_UDPLITE 2865 if ((IPH_PROTO(iphdr) != IP_PROTO_UDP) && (IPH_PROTO(iphdr) != IP_PROTO_UDPLITE)) { 2866#else 2867 if (IPH_PROTO(iphdr) != IP_PROTO_UDP) { 2868#endif 2869 goto FUNC_OUT; 2870 } 2871 2872 if ((ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK) != 0) { 2873 goto FUNC_OUT; 2874 } 2875 2876 len = (u16_t)(IPH_HL(iphdr) * 4); 2877 if (pbuf_header(udpbuf, (s16_t)(-len))) { 2878 goto FUNC_OUT; 2879 } 2880 2881 offset = (u16_t)(offset + len); 2882 2883 udphdr = (struct udp_hdr *)udpbuf->payload; 2884 if ((ntohs(udphdr->dest) == udppcb->remote_port) && (ntohs(udphdr->src) == udppcb->local_port)) { 2885 sendLen = ntohs(udphdr->len) - UDP_HLEN; 2886 } 2887 2888FUNC_OUT: 2889 (void)pbuf_header(udpbuf, (s16_t)offset); 2890 return sendLen; 2891} 2892#endif 2893 2894int netstat_tcp_recvq(struct tcp_pcb *tpcb) 2895{ 2896 unsigned int retVal = 0; 2897#if LWIP_SO_RCVBUF 2898 struct netconn *conn = NULL; 2899#endif 2900 2901 LWIP_ERROR("netstat_tcp_recvq: Received NULL pcb\n", (tpcb != NULL), return 0); 2902 2903#if LWIP_SO_RCVBUF 2904 conn = (struct netconn *)tpcb->callback_arg; 2905 if (conn != NULL) { 2906 switch (conn->type) { 2907 case NETCONN_TCP: 2908 case NETCONN_RAW: 2909#if LWIP_IPV6 2910 case NETCONN_RAW_IPV6: 2911 case NETCONN_UDP_IPV6: 2912#endif 2913 case NETCONN_UDP: 2914 SYS_ARCH_GET(((unsigned int)conn->recv_avail), retVal); // + conn->lrcv_left 2915 break; 2916 default: 2917 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */ 2918 } 2919 } 2920#endif 2921 2922 return (int)retVal; 2923} 2924 2925int netstat_tcp_sendq(struct tcp_pcb *tpcb) 2926{ 2927 int retVal = 0; 2928 struct tcp_seg *useg = NULL; 2929 2930 LWIP_ERROR("netstat_tcp_sendq: Received NULL pcb\n", (tpcb != NULL), return 0); 2931 2932 for (useg = tpcb->unacked; useg != NULL; useg = useg->next) { 2933 retVal = retVal + useg->len; 2934 } 2935 2936 return retVal; 2937} 2938 2939#if LWIP_IPV6 2940int netstat_udp_sendq6(struct udp_pcb *upcb) 2941{ 2942 int retLen = 0; 2943 int ret; 2944 int idx = 0; 2945 int i; 2946#if LWIP_ND6_QUEUEING 2947 struct nd6_q_entry *neibq = NULL; 2948#endif 2949 2950 LWIP_ERROR("netstat_udp_sendq6: Received NULL pcb\n", (upcb != NULL), return 0); 2951 2952 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 2953 if (neighbor_cache[i].state != ND6_NO_ENTRY) { 2954 if (ip6_addr_cmp(&upcb->remote_ip.u_addr.ip6, &neighbor_cache[i].next_hop_address)) { 2955 idx = i; 2956 break; 2957 } 2958 } 2959 } 2960#if LWIP_ND6_QUEUEING 2961 for (neibq = neighbor_cache[idx].q; neibq != NULL; neibq = neibq->next) { 2962 ret = netstat_get_udp_sendQLen6(upcb, neibq->p); 2963 if (ret >= 0) { 2964 retLen += ret; 2965 } 2966 } 2967#else 2968 ret = netstat_get_udp_sendQLen6(upcb, neighbor_cache[idx].q); 2969 if (ret >= 0) { 2970 retLen += ret; 2971 } 2972#endif 2973 return retLen; 2974} 2975#endif 2976 2977#if LWIP_IPV4 2978int netstat_udp_sendq(struct udp_pcb *upcb) 2979{ 2980 int retLen = 0; 2981 int ret; 2982 int arpidx = -1; 2983 int i; 2984#if ARP_QUEUEING 2985 struct etharp_q_entry *arpq = NULL; 2986#endif 2987 2988 LWIP_ERROR("netstat_udp_sendq: Received NULL pcb\n", (upcb != NULL), return 0); 2989 2990 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 2991 if (arp_table[i].state != ETHARP_STATE_EMPTY) { 2992 if (ip4_addr_cmp(ip_2_ip4(&upcb->remote_ip), &arp_table[i].ipaddr)) { 2993 arpidx = i; 2994 break; 2995 } 2996 } 2997 } 2998 2999 if (arpidx >= 0) { 3000#if ARP_QUEUEING 3001 for (arpq = arp_table[arpidx].q; arpq != NULL; arpq = arpq->next) { 3002 ret = netstat_get_udp_sendQLen(upcb, arpq->p); 3003 if (ret > 0) { 3004 retLen += ret; 3005 if (retLen <= 0) { // overflow, set rteLen = -1 to indicate 3006 retLen = -1; 3007 break; 3008 } 3009 } 3010 } 3011#else 3012 ret = netstat_get_udp_sendQLen(upcb, arp_table[arpidx].q); 3013 if (ret > 0) { 3014 retLen += ret; 3015 if (retLen <= 0) { // overflow, set rteLen = -1 to indicate 3016 retLen = -1; 3017 } 3018 } 3019#endif 3020 } 3021 return retLen; 3022} 3023#endif 3024int netstat_netconn_recvq(const struct netconn *conn) 3025{ 3026 unsigned int retVal = 0; 3027 3028#if LWIP_SO_RCVBUF 3029 if (conn == NULL) { 3030 return 0; 3031 } 3032 3033 switch (NETCONNTYPE_GROUP((unsigned int)(conn->type))) { 3034 case NETCONN_TCP: 3035 case NETCONN_RAW: 3036#if PF_PKT_SUPPORT 3037 case NETCONN_PKT_RAW: 3038#endif 3039 case NETCONN_UDP: 3040 SYS_ARCH_GET(((unsigned int)conn->recv_avail), retVal); // + conn->lrcv_left 3041 break; 3042 default: 3043 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */ 3044 } 3045#endif 3046 return (int)retVal; 3047} 3048 3049int netstat_netconn_sendq(struct netconn *conn) 3050{ 3051 int retVal = 0; 3052 3053 if (conn == NULL) { 3054 return 0; 3055 } 3056 3057 switch (NETCONNTYPE_GROUP((unsigned int)(conn->type))) { 3058 case NETCONN_TCP: 3059 retVal = netstat_tcp_sendq(conn->pcb.tcp); 3060 break; 3061 case NETCONN_RAW: 3062 retVal = 0; 3063 break; 3064#if PF_PKT_SUPPORT 3065 case NETCONN_PKT_RAW: 3066 retVal = 0; /* always be 0 as frame send to driver directly */ 3067 break; 3068#endif 3069 case NETCONN_UDP: 3070 retVal = netstat_udp_sendq(conn->pcb.udp); 3071 break; 3072 default: 3073 retVal = 0; /* ur... very ugly, damn DHCP DNS and SNTP */ 3074 } 3075 3076 return retVal; 3077} 3078void netstat_internal(void *ctx) 3079{ 3080 s8_t local_ip_port[64] = {0}; 3081 s8_t remote_ip_port[64] = {0}; 3082 struct tcp_pcb *tpcb = NULL; 3083 struct tcp_pcb_listen *lpcb = NULL; 3084 struct udp_pcb *upcb = NULL; 3085 struct raw_pcb *rpcb = NULL; 3086 s8_t *entry_buf = NULL; 3087 u32_t entry_buf_len; 3088 u32_t entry_buf_offset; 3089 struct netstat_data *ndata = (struct netstat_data *)ctx; 3090 int iRet; 3091 int recvQlen = 0; 3092 int sendQlen = 0; 3093 u_int proto; 3094#if PF_PKT_SUPPORT 3095 u8_t netif_name[IFNAMSIZ]; 3096 struct netif *netif = NULL; 3097#endif 3098 3099 if (ndata == NULL) { 3100 return; 3101 } 3102 entry_buf = ndata->netstat_out_buf; 3103 entry_buf_len = ndata->netstat_out_buf_len; 3104 entry_buf_offset = 0; 3105 3106 if (entry_buf == NULL) { 3107 goto out; 3108 } 3109 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3110 "========== total sockets %d ====== unused sockets %d ==========\n", 3111 LWIP_CONFIG_NUM_SOCKETS, get_unused_socket_num()); 3112 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3113 goto out; 3114 } 3115 entry_buf_len -= (u32_t)(iRet); 3116 entry_buf_offset += (u32_t)(iRet); 3117 3118#if LWIP_TCP 3119 if (tcp_active_pcbs != NULL || tcp_bound_pcbs != NULL || tcp_tw_pcbs != NULL || tcp_listen_pcbs.pcbs != NULL) { 3120 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3121 "%-8s%-12s%-12s%-24s%-24s%-16s\n", 3122 "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "State"); 3123 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3124 goto out; 3125 } 3126 entry_buf_len -= (u32_t)(iRet); 3127 entry_buf_offset += (u32_t)(iRet); 3128 3129 for (tpcb = tcp_active_pcbs; tpcb != NULL; tpcb = tpcb->next) { 3130 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3131 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port); 3132 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3133 goto out; 3134 } 3135 3136 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3137 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port); 3138 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3139 goto out; 3140 } 3141 if (tpcb->state == SYN_RCVD) { 3142 recvQlen = 0; 3143 sendQlen = 0; 3144 } else { 3145 recvQlen = netstat_netconn_recvq(tpcb->callback_arg); 3146 sendQlen = netstat_netconn_sendq(tpcb->callback_arg); 3147 } 3148 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3149 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" : 3150 "%-8s%-12d%-12d%-24s%-24s%-16s\n", 3151 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp", 3152 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]); 3153 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3154 goto out; 3155 } 3156 entry_buf_len -= (u32_t)(iRet); 3157 entry_buf_offset += (u32_t)(iRet); 3158 } 3159 3160 /* For bound PCBs */ 3161 sendQlen = 0; 3162 recvQlen = 0; 3163 3164 for (tpcb = tcp_bound_pcbs; tpcb != NULL; tpcb = tpcb->next) { 3165 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3166 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port); 3167 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3168 goto out; 3169 } 3170 3171 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3172 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port); 3173 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3174 goto out; 3175 } 3176 3177 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3178 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" : 3179 "%-8s%-12d%-12d%-24s%-24s%-16s\n", 3180 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp", 3181 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]); 3182 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3183 goto out; 3184 } 3185 entry_buf_len -= (u32_t)(iRet); 3186 entry_buf_offset += (u32_t)(iRet); 3187 } 3188 3189 for (tpcb = tcp_tw_pcbs; tpcb != NULL; tpcb = tpcb->next) { 3190 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3191 "%s:%d", ipaddr_ntoa(&tpcb->local_ip), tpcb->local_port); 3192 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3193 goto out; 3194 } 3195 3196 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3197 "%s:%d", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port); 3198 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3199 goto out; 3200 } 3201 3202 recvQlen = netstat_netconn_recvq(tpcb->callback_arg); 3203 sendQlen = netstat_netconn_sendq(tpcb->callback_arg); 3204 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3205 IP_IS_V6(&tpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" : 3206 "%-8s%-12d%-12d%-24s%-24s%-16s\n", 3207 IP_IS_V6(&tpcb->local_ip) ? "tcp-ip6" : "tcp", 3208 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[tpcb->state]); 3209 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3210 goto out; 3211 } 3212 entry_buf_len -= (u32_t)(iRet); 3213 entry_buf_offset += (u32_t)(iRet); 3214 } 3215 3216 /* For listen PCBs */ 3217 sendQlen = 0; 3218 3219 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 3220 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3221 "%s:%d", ipaddr_ntoa(&lpcb->local_ip), lpcb->local_port); 3222 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3223 goto out; 3224 } 3225 3226 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3227 "%s:%d", ipaddr_ntoa(&lpcb->remote_ip), 0); 3228 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3229 goto out; 3230 } 3231 3232 recvQlen = netstat_netconn_recvq(lpcb->callback_arg); 3233 3234 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3235 IP_IS_V6(&lpcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" : 3236 "%-8s%-12d%-12d%-24s%-24s%-16s\n", 3237 IP_IS_V6(&lpcb->local_ip) ? "tcp-ip6" : "tcp", 3238 recvQlen, sendQlen, local_ip_port, remote_ip_port, tcp_state_str[lpcb->state]); 3239 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3240 goto out; 3241 } 3242 entry_buf_len -= (u32_t)(iRet); 3243 entry_buf_offset += (u32_t)(iRet); 3244 } 3245 } 3246#endif 3247#if LWIP_UDP 3248 if (udp_pcbs != NULL) { 3249 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3250 "\n%-8s%-12s%-12s%-24s%-24s\n", 3251 "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address"); 3252 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3253 goto out; 3254 } 3255 entry_buf_len -= (u32_t)(iRet); 3256 entry_buf_offset += (u32_t)(iRet); 3257 3258 for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { 3259 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3260 "%s:%d", ipaddr_ntoa(&upcb->local_ip), upcb->local_port); 3261 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3262 goto out; 3263 } 3264 3265 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3266 "%s:%d", ipaddr_ntoa(&upcb->remote_ip), upcb->remote_port); 3267 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3268 goto out; 3269 } 3270 3271 recvQlen = netstat_netconn_recvq(upcb->recv_arg); 3272#if LWIP_IPV6 3273 sendQlen = IP_IS_V6(&upcb->local_ip) ? netstat_udp_sendq6(upcb) : netstat_netconn_sendq(upcb->recv_arg); 3274#else 3275 sendQlen = netstat_netconn_sendq(upcb->recv_arg); 3276#endif 3277 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3278 IP_IS_V6(&upcb->local_ip) ? "%-8s%-12d%-12d%-39s%-39s%-16s\n" : 3279 "%-8s%-12d%-12d%-24s%-24s%-16s\n", 3280 IP_IS_V6(&upcb->local_ip) ? "udp-ip6" : "udp", 3281 recvQlen, sendQlen, local_ip_port, remote_ip_port, " "); 3282 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3283 goto out; 3284 } 3285 entry_buf_len -= (u32_t)(iRet); 3286 entry_buf_offset += (u32_t)(iRet); 3287 } 3288 } 3289#endif 3290 3291#if LWIP_RAW 3292 if (raw_pcbs != NULL) { 3293 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3294 "\n%-8s%-12s%-12s%-20s%-20s%-16s%-16s\n", 3295 "Type", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "Protocol", "HDRINCL"); 3296 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3297 goto out; 3298 } 3299 entry_buf_len -= (u32_t)(iRet); 3300 entry_buf_offset += (u32_t)(iRet); 3301 3302 for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { 3303 iRet = snprintf_s((char *)local_ip_port, sizeof(local_ip_port), (sizeof(local_ip_port) - 1), 3304 "%s", ipaddr_ntoa(&rpcb->local_ip)); 3305 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(local_ip_port))) { 3306 goto out; 3307 } 3308 3309 iRet = snprintf_s((char *)remote_ip_port, sizeof(remote_ip_port), (sizeof(remote_ip_port) - 1), 3310 "%s", ipaddr_ntoa(&rpcb->remote_ip)); 3311 if ((iRet <= 0) || ((u32_t)(iRet) >= sizeof(remote_ip_port))) { 3312 goto out; 3313 } 3314 3315 recvQlen = netstat_netconn_recvq(rpcb->recv_arg); 3316 sendQlen = netstat_netconn_sendq(rpcb->recv_arg); 3317 3318 proto = rpcb->protocol; // raw_proto; 3319 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3320 "%-8s%-12d%-12d%-20s%-20s%-16u%-16d\n", 3321 "raw", recvQlen, sendQlen, local_ip_port, remote_ip_port, proto, 0); // rpcb->hdrincl 3322 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3323 goto out; 3324 } 3325 entry_buf_len -= (u32_t)(iRet); 3326 entry_buf_offset += (u32_t)(iRet); 3327 } 3328 } 3329#if PF_PKT_SUPPORT 3330 if (pkt_raw_pcbs != NULL) { 3331 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3332 "\n%-12s%-12s%-12s%-16s%-12s\n", "Type", "Recv-Q", "Send-Q", "Protocol", "netif"); 3333 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3334 goto out; 3335 } 3336 entry_buf_len -= (u32_t)(iRet); 3337 entry_buf_offset += (u32_t)(iRet); 3338 3339 for (rpcb = pkt_raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { 3340 recvQlen = netstat_netconn_recvq(rpcb->recv_arg); 3341 sendQlen = netstat_netconn_sendq(rpcb->recv_arg); 3342 3343 for (netif = netif_list; netif != NULL; netif = netif->next) { 3344 /* netif->ifindex and index */ 3345 if (netif_get_index(netif) == rpcb->netif_idx) { 3346 (void)snprintf_s((char *)netif_name, IFNAMSIZ, IFNAMSIZ - 1, "%s", netif_get_name(netif)); 3347 break; 3348 } 3349 } 3350 3351 if (netif == NULL) { 3352 (void)snprintf_s((char *)netif_name, IFNAMSIZ, IFNAMSIZ - 1, "%s", "None"); 3353 } 3354 3355 proto = rpcb->protocol; // ntohs(rpcb->proto.eth_proto); 3356 3357 iRet = snprintf_s((char *)(entry_buf + entry_buf_offset), entry_buf_len, entry_buf_len - 1, 3358 "%-12s%-12d%-12d%-16x%-12s\n", "pkt-raw", recvQlen, sendQlen, proto, netif_name); 3359 if ((iRet <= 0) || ((u32_t)(iRet) >= entry_buf_len)) { 3360 goto out; 3361 } 3362 entry_buf_len -= (u32_t)(iRet); 3363 entry_buf_offset += (u32_t)(iRet); 3364 } 3365 } 3366#endif 3367#endif 3368 3369out: 3370 ndata->netstat_out_buf_updated_len = entry_buf_offset; 3371 sys_sem_signal(&ndata->cb_completed); 3372 return; 3373} 3374 3375u32_t osShellNetstat(int argc, const char **argv) 3376{ 3377 struct netstat_data ndata; 3378 err_t err; 3379 3380 if (argc > 0) { 3381 PRINTK("\nUsage: netstat\n"); 3382 return LOS_NOK; 3383 } 3384 3385 if (tcpip_init_finish == 0) { 3386 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 3387 return LOS_NOK; 3388 } 3389 3390 ndata.netstat_out_buf = mem_malloc(MAX_NETSTAT_ENTRY); 3391 if (ndata.netstat_out_buf == NULL) { 3392 PRINTK("%s: no free mem\n", __FUNCTION__); 3393 return LOS_NOK; 3394 } 3395 ndata.netstat_out_buf_len = MAX_NETSTAT_ENTRY; 3396 ndata.netstat_out_buf_updated_len = 0; 3397 3398 if (sys_sem_new(&ndata.cb_completed, 0) != ERR_OK) { 3399 goto err_hand; 3400 } 3401 3402 err = tcpip_callback(netstat_internal, &ndata); 3403 if (err != ERR_OK) { 3404 sys_sem_free(&ndata.cb_completed); 3405 goto err_hand; 3406 } 3407 3408 (void)sys_arch_sem_wait(&ndata.cb_completed, 0); 3409 sys_sem_free(&ndata.cb_completed); 3410 if ((ndata.netstat_out_buf_updated_len > 0) && (ndata.netstat_out_buf_updated_len < MAX_NETSTAT_ENTRY)) { 3411 PRINTK("%s\n", (char *)(ndata.netstat_out_buf)); 3412 mem_free(ndata.netstat_out_buf); 3413 return LOS_OK; 3414 } 3415 3416err_hand: 3417 mem_free(ndata.netstat_out_buf); 3418 ndata.netstat_out_buf = NULL; 3419 (void)(argv); 3420 return LOS_NOK; 3421} 3422#ifdef LOSCFG_SHELL 3423SHELLCMD_ENTRY(netstat_shellcmd, CMD_TYPE_EX, "netstat", XARGS, (CmdCallBackFunc)osShellNetstat); 3424#endif /* LOSCFG_SHELL */ 3425 3426#define NETIF_NAME_LEN 10 3427STATIC VOID OsShellDhclientUsage(VOID) 3428{ 3429 PRINTK("<netif name>, start dhcp for netif name\n" 3430 "-x <netif name>, stop dhcp for netif name\n" 3431 "-h | --help, print dhclient command usage\n"); 3432} 3433 3434u32_t OsShellDhclient(int argc, const char **argv) 3435{ 3436 struct netif *netif = NULL; 3437 3438 if (argc == 0) { 3439 OsShellDhclientUsage(); 3440 } else if (argc == 1) { 3441 if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) { 3442 OsShellDhclientUsage(); 3443 } else { 3444 netif = netif_find(argv[0]); 3445 if (netif != NULL) { 3446 (VOID)netifapi_dhcp_start(netif); 3447 } else { 3448 PRINTK("dhclient: invalid option: %s\n", argv[0]); 3449 OsShellDhclientUsage(); 3450 } 3451 } 3452 } else if (argc == 2) { 3453 if (strcmp(argv[0], "-x") == 0) { 3454 netif = netif_find(argv[1]); 3455 if (netif != NULL) { 3456 (VOID)netifapi_dhcp_stop(netif); 3457 } else { 3458 PRINTK("dhclient: invalid option: %s\n", argv[1]); 3459 OsShellDhclientUsage(); 3460 } 3461 } else { 3462 PRINTK("dhclient: invalid option: %s\n", argv[0]); 3463 OsShellDhclientUsage(); 3464 } 3465 } else { 3466 OsShellDhclientUsage(); 3467 } 3468 3469 return 0; 3470} 3471 3472#ifdef LOSCFG_SHELL 3473SHELLCMD_ENTRY(dhclient_shellcmd, CMD_TYPE_EX, "dhclient", XARGS, (CmdCallBackFunc)OsShellDhclient); 3474#endif /* LOSCFG_SHELL */ 3475 3476#ifdef LWIP_DEBUG_TCPSERVER 3477 3478#define MAX_SIZE 1024 3479void tcp_access(int sockfd) 3480{ 3481 size_t n, i; 3482 ssize_t ret; 3483 char msg[MAX_SIZE] = {0}; 3484 while (1) { 3485 PRINTK("waiting for recv\n"); 3486 (void)memset_s(msg, MAX_SIZE, 0, MAX_SIZE); 3487 ret = recv(sockfd, msg, MAX_SIZE - 1, 0); 3488 if (ret < 0) { 3489 PRINTK("recv failed, %d.\n", (u32_t)ret); 3490 (void)closesocket(sockfd); 3491 return; 3492 } else if (ret == 0) { 3493 (void)closesocket(sockfd); 3494 PRINTK("client disconnect.\n"); 3495 return; 3496 } 3497 3498 n = strlen(msg); 3499 for (i = 0; i < n; ++i) { 3500 if (msg[i] >= 'a' && msg[i] <= 'z') { 3501 msg[i] = (char)(msg[i] + ('A' - 'a')); 3502 } else if (msg[i] >= 'A' && msg[i] <= 'Z') { 3503 msg[i] = (char)(msg[i] + ('a' - 'A')); 3504 } 3505 } 3506 3507 if (send(sockfd, msg, n, 0) < 0) { 3508 PRINTK("send failed!\r\n"); 3509 continue; 3510 } 3511 } 3512} 3513 3514u32_t osTcpserver(int argc, const char **argv) 3515{ 3516 uint16_t port; 3517 int sockfd = -1; 3518 int ret; 3519 struct sockaddr_in seraddr; 3520 struct sockaddr_in cliaddr; 3521 u32_t cliaddr_size = (u32_t)sizeof(cliaddr); 3522 int reuse, iPortVal; 3523 3524 if (tcpip_init_finish == 0) { 3525 PRINTK("tcpip_init have not been called\n"); 3526 return LOS_NOK; 3527 } 3528 3529 if (argc < 1 || argv == NULL) { 3530 PRINTK("\nUsage: tcpserver <port>\n"); 3531 return LOS_NOK; 3532 } 3533 3534 iPortVal = atoi(argv[0]); 3535 /* Port 0 not supported , negative values not supported , max port limit is 65535 */ 3536 if (iPortVal <= 0 || iPortVal > 65535) { 3537 PRINTK("\nUsage: Invalid port\n"); 3538 return LOS_NOK; 3539 } 3540 3541 port = (uint16_t)iPortVal; 3542 3543 /* removed the print of argv[1] as its accessing argv[1] without verifying argc and 3544 * argv[1] not used anywhere else */ 3545 PRINTK("argv[0]:%s, argc:%d\r\n", argv[0], argc); 3546 sockfd = socket(AF_INET, SOCK_STREAM, 0); 3547 if (sockfd < 0) { 3548 PRINTK("\nUsage: create socket fail!\n"); 3549 return LOS_NOK; 3550 } 3551 reuse = 1; 3552 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) != 0) { 3553 (void)closesocket(sockfd); 3554 PRINTK("set SO_REUSEADDR failed\n"); 3555 return LOS_NOK; 3556 } 3557 3558 (void)memset_s(&seraddr, sizeof(seraddr), 0, sizeof(seraddr)); 3559 seraddr.sin_family = AF_INET; 3560 seraddr.sin_addr.s_addr = htonl(INADDR_ANY); 3561 seraddr.sin_port = htons(port); 3562 3563 ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr)); 3564 if (ret < 0) { 3565 PRINTK("bind ip and port failed"); 3566 (void)closesocket(sockfd); 3567 return LOS_NOK; 3568 } 3569 3570 ret = listen(sockfd, 5); 3571 if (ret < 0) { 3572 (void)closesocket(sockfd); 3573 PRINTK("listen failed\n"); 3574 return LOS_NOK; 3575 } 3576 while (1) { 3577 PRINTK("waiting for accept\n"); 3578 (void)memset_s(&cliaddr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)); 3579 ret = (int)accept(sockfd, (struct sockaddr *)&cliaddr, &cliaddr_size); 3580 if (ret < 0) { 3581 (void)closesocket(sockfd); 3582 PRINTK("Accept failed, %d\n", ret); 3583 break; 3584 } 3585 tcp_access(ret); 3586 } 3587 return LOS_NOK; // Hits Only If Accept Fails 3588} 3589 3590#ifdef LOSCFG_SHELL_CMD_DEBUG 3591SHELLCMD_ENTRY(tcpserver_shellcmd, CMD_TYPE_EX, "tcpserver", XARGS, (CmdCallBackFunc)osTcpserver); 3592#endif /* LOSCFG_SHELL_CMD_DEBUG */ 3593#endif /* LWIP_DEBUG_TCPSERVER */ 3594 3595#ifdef LWIP_DEBUG_UDPSERVER 3596void udpserver(int argc, const char **argv) 3597{ 3598 int sockfd, fromlen; 3599 int ret, iPortVal; 3600 struct sockaddr_in seraddr; 3601 struct sockaddr_in cliaddr; 3602 size_t n, i; 3603 3604 char msg[MAX_SIZE] = {0}; 3605 uint16_t port; 3606 3607 if (argc < 1) { 3608 PRINTK("\nUsage: udpserver <port>\n"); 3609 return; 3610 } 3611 3612 iPortVal = atoi(argv[0]); 3613 /* Port 0 not supported , negative values not supported , max port limit is 65535 */ 3614 if (iPortVal <= 0 || iPortVal > 65535) { 3615 PRINTK("\nUsage: Invalid Port\n"); 3616 return; 3617 } 3618 3619 port = (uint16_t)iPortVal; 3620 3621 PRINTK("port:%d\r\n", port); 3622 3623 sockfd = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 3624 if (sockfd == -1) { 3625 PRINTK("\ncreate socket fail\n"); 3626 return; 3627 } 3628 3629 (void)memset_s(&seraddr, sizeof(seraddr), 0, sizeof(seraddr)); 3630 (void)memset_s(&cliaddr, sizeof(cliaddr), 0, sizeof(cliaddr)); 3631 seraddr.sin_family = AF_INET; 3632 seraddr.sin_addr.s_addr = htonl(INADDR_ANY); 3633 seraddr.sin_port = htons(port); 3634 ret = lwip_bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr)); 3635 if (ret < 0) { 3636 PRINTK("bind ip and port failed:%d\n", errno); 3637 (void)closesocket(sockfd); 3638 return; 3639 } 3640 3641 while (1) { 3642 ret = recvfrom(sockfd, msg, MAX_SIZE - 1, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&fromlen); 3643 if (ret >= 0) { 3644 n = strlen(msg); 3645 for (i = 0; i < n; ++i) { 3646 if (msg[i] >= 'a' && msg[i] <= 'z') { 3647 msg[i] = (char)(msg[i] + 'A' - 'a'); 3648 } else if (msg[i] >= 'A' && msg[i] <= 'Z') { 3649 msg[i] = (char)(msg[i] + 'a' - 'A'); 3650 } 3651 } 3652 ret = sendto(sockfd, msg, n + 1, 0, (struct sockaddr *)&cliaddr, (socklen_t)fromlen); 3653 if (ret <= 0 && errno == EPIPE) { 3654 break; 3655 } 3656 } else { 3657 break; 3658 } 3659 } 3660 3661 (void)closesocket(sockfd); 3662 return; 3663} 3664 3665#ifdef LOSCFG_SHELL_CMD_DEBUG 3666SHELLCMD_ENTRY(udpserver_shellcmd, CMD_TYPE_EX, "udpserver", XARGS, (CmdCallBackFunc)udpserver); 3667#endif /* LOSCFG_SHELL_CMD_DEBUG */ 3668#endif /* LWIP_DEBUG_UDPSERVER */ 3669 3670#ifdef LWIP_DEBUG_INFO 3671LWIP_STATIC 3672u32_t netdebug_memp(int argc, const char **argv) 3673{ 3674 u32_t ret = LOS_OK; 3675 int type; 3676 3677 if (argc == 2) { 3678 if (!strcmp("-i", argv[1])) { 3679 debug_memp_info(); 3680 } else if (!strcmp("-udp", argv[1])) { 3681 debug_memp_type_info(MEMP_UDP_PCB); 3682 } else if (!strcmp("-tcp", argv[1])) { 3683 debug_memp_type_info(MEMP_TCP_PCB); 3684 } else if (!strcmp("-raw", argv[1])) { 3685 debug_memp_type_info(MEMP_RAW_PCB); 3686 } else if (!strcmp("-conn", argv[1])) { 3687 debug_memp_type_info(MEMP_NETCONN); 3688 } else { 3689 ret = LOS_NOK; 3690 } 3691 } else if (argc == 3) { 3692 if (!strcmp("-d", argv[1])) { 3693 type = atoi(argv[2]); 3694 if (type >= 0) { 3695 debug_memp_detail(type); 3696 } else { 3697 PRINTK("Error: type < 0\n"); 3698 ret = LOS_NOK; 3699 } 3700 } else { 3701 ret = LOS_NOK; 3702 } 3703 } else { 3704 ret = LOS_NOK; 3705 } 3706 3707 return ret; 3708} 3709 3710LWIP_STATIC 3711u32_t netdebug_sock(int argc, const char **argv) 3712{ 3713 int idx; 3714 u32_t ret = LOS_NOK; 3715 3716 if (argc == 2) { /* 2: Number of command parameters */ 3717 if (!strcmp("-i", argv[1])) { 3718 /* netdebug sock -i */ 3719 for (idx = 0; idx < (int)LWIP_CONFIG_NUM_SOCKETS; idx++) { 3720 debug_socket_info(idx, 1, 0); 3721 } 3722 ret = LOS_OK; 3723 } 3724 } else if (argc == 3) { /* 3: Number of command parameters */ 3725 if (!strcmp("-d", argv[1])) { 3726 idx = atoi(argv[2]); /* 2: netdebug sock -d <idx> */ 3727 if (idx >= 0) { 3728 debug_socket_info(idx, 1, 1); 3729 ret = LOS_OK; 3730 } else { 3731 PRINTK("Error: idx < 0\n"); 3732 } 3733 } 3734 } 3735 3736 return ret; 3737} 3738 3739 3740u32_t osShellNetDebug(int argc, const char **argv) 3741{ 3742 u32_t ret = LOS_NOK; 3743 3744 if (argc < 1 || argv == NULL) { 3745 goto usage; 3746 } 3747 3748 if (!strcmp("memp", argv[0])) { 3749 ret = netdebug_memp(argc, argv); 3750 if (ret != LOS_OK) { 3751 goto usage_memp; 3752 } 3753 } else if (!strcmp("sock", argv[0])) { 3754 /* netdebug sock {-i | -d <idx>} */ 3755 ret = netdebug_sock(argc, argv); 3756 if (ret != LOS_OK) { 3757 goto usage_sock; 3758 } 3759 } else { 3760 goto usage; 3761 } 3762 return ret; 3763 3764usage: 3765 /* Cmd help */ 3766 PRINTK("\nUsage:\n"); 3767 PRINTK("netdebug memp {-i | -d <type> | -udp | -tcp | -raw |-conn}\n"); 3768 PRINTK("netdebug sock {-i | -d <idx>}\n"); 3769 return LOS_NOK; 3770 3771usage_memp: 3772 /* netdebug memp help */ 3773 PRINTK("\nUsage:\n"); 3774 PRINTK("netdebug memp {-i | -d <type> | -udp | -tcp | -raw |-conn}\n"); 3775 return LOS_NOK; 3776 3777usage_sock: 3778 /* netdebug sock help */ 3779 PRINTK("\nUsage:\n"); 3780 PRINTK("netdebug sock {-i | -d <idx>}\n"); 3781 return LOS_NOK; 3782} 3783#endif /* LWIP_DEBUG_INFO */ 3784 3785#if defined(LOSCFG_SHELL_CMD_DEBUG) && defined(LWIP_DEBUG_INFO) 3786SHELLCMD_ENTRY(netdebug_shellcmd, CMD_TYPE_EX, "netdebug", XARGS, (CmdCallBackFunc)osShellNetDebug); 3787#endif /* LOSCFG_SHELL_CMD_DEBUG && LWIP_DEBUG_INFO */ 3788 3789u32_t osShellIpDebug(int argc, const char **argv) 3790{ 3791 u8_t i = 0; 3792 char acIPv6Addr[IP6ADDR_STRLEN_MAX + 1] = {0}; 3793 char aclladdr[20] = {0}; 3794 const char *acStates[] = {"NO_ENTRY", "INCOMPLETE", "REACHABLE", "STALE", "DELAY", "PROBE"}; 3795 u8_t atleastOneEntry = 0; 3796 3797 if (!tcpip_init_finish) { 3798 PRINTK("%s: tcpip_init have not been called\n", __FUNCTION__); 3799 goto exit; 3800 } 3801 3802 /* Display prefix */ 3803 PRINTK("=================\n"); 3804 PRINTK("|| Prefix List ||\n"); 3805 PRINTK("=================\n"); 3806 PRINTK("%-50s %-16s %-20s\n", "Prefix", "netif", "validLifetime"); 3807 PRINTK("---------------------------------------------------------------------------------\n"); 3808 /* Display neighbour Cache Entry */ 3809 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 3810 if (prefix_list[i].netif != NULL && prefix_list[i].invalidation_timer > 0) { 3811 atleastOneEntry = 1; 3812 (void)ip6addr_ntoa_r((const ip6_addr_t *)(prefix_list[i].prefix.addr), (acIPv6Addr), sizeof(acIPv6Addr)); 3813 PRINTK("%-50s ", acIPv6Addr); 3814 PRINTK("%-16s ", netif_get_name(prefix_list[i].netif)); 3815 PRINTK("%-20u\n", prefix_list[i].invalidation_timer); 3816 } 3817 } 3818 3819 if (!atleastOneEntry) { 3820 PRINTK("**** NO VALID PREFIXES FOUND CONFIGURED ****\n"); 3821 } 3822 PRINTK("---------------------------------------------------------------------------------\n"); 3823 3824 atleastOneEntry = 0; 3825 3826 PRINTK("\n\n"); 3827 PRINTK("============================\n"); 3828 PRINTK("|| Neighbor Cache Entries ||\n"); 3829 PRINTK("============================\n"); 3830 PRINTK("%-50s %-25s %-16s %-15s %-10s\n", "Neighbor", "MAC", "netif", "state", "IsRouter"); 3831 PRINTK("------------------------------------------------------------" 3832 "----------------------------------------------------------\n"); 3833 3834 /* Display neighbour Cache Entry */ 3835 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 3836 if (neighbor_cache[i].state != ND6_NO_ENTRY) { 3837 atleastOneEntry = 1; 3838 (void)ip6addr_ntoa_r((const ip6_addr_t *)(neighbor_cache[i].next_hop_address.addr), (acIPv6Addr), 3839 sizeof(acIPv6Addr)); 3840 PRINTK("%-50s ", acIPv6Addr); 3841 3842 if (snprintf_s(aclladdr, sizeof(aclladdr), sizeof(aclladdr) - 1, "%02X:%02X:%02X:%02X:%02X:%02X", 3843 neighbor_cache[i].lladdr[0], neighbor_cache[i].lladdr[1], /* 0, 1, member number */ 3844 neighbor_cache[i].lladdr[2], neighbor_cache[i].lladdr[3], /* 2, 3, member number */ 3845 neighbor_cache[i].lladdr[4], neighbor_cache[i].lladdr[5]) < 0) { /* 4, 5, member number */ 3846 return LOS_NOK; 3847 } 3848 PRINTK("%-25s ", aclladdr); 3849 PRINTK("%-16s ", netif_get_name(neighbor_cache[i].netif)); 3850 PRINTK("%-15s ", acStates[neighbor_cache[i].state]); 3851 PRINTK("%-10s\n", (neighbor_cache[i].isrouter ? "Yes" : "No")); 3852 } 3853 } 3854 if (!atleastOneEntry) { 3855 PRINTK("**** NO NEIGHBOURS FOUND ****\n"); 3856 } 3857 PRINTK("------------------------------------------------------------" 3858 "----------------------------------------------------------\n"); 3859 3860 atleastOneEntry = 0; 3861 3862 PRINTK("\n\n"); 3863 PRINTK("===============================\n"); 3864 PRINTK("|| Destination Cache Entries ||\n"); 3865 PRINTK("===============================\n"); 3866 PRINTK("%-50s %-50s %-10s %-10s\n", "Destination", "NextHop", "PMTU", "age"); 3867 PRINTK("------------------------------------------------------------" 3868 "--------------------------------------------------------\n"); 3869 /* Display destination Cache Entry */ 3870 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 3871 if (!ip6_addr_isany(&(destination_cache[i].destination_addr))) { 3872 atleastOneEntry = 1; 3873 (void)ip6addr_ntoa_r((const ip6_addr_t *)(destination_cache[i].destination_addr.addr), (acIPv6Addr), 3874 sizeof(acIPv6Addr)); 3875 PRINTK("%-50s ", acIPv6Addr); 3876 (void)ip6addr_ntoa_r((const ip6_addr_t *)(destination_cache[i].next_hop_addr.addr), (acIPv6Addr), 3877 sizeof(acIPv6Addr)); 3878 PRINTK("%-50s ", acIPv6Addr); 3879 PRINTK("%-10u ", destination_cache[i].pmtu); 3880 PRINTK("%-10u\n", destination_cache[i].age); 3881 } 3882 } 3883 if (!atleastOneEntry) { 3884 PRINTK("**** NO DESTINATION CACHE FOUND ****\n"); 3885 } 3886 PRINTK("------------------------------------------------------------" 3887 "--------------------------------------------------------\n"); 3888 3889 atleastOneEntry = 0; 3890 PRINTK("\n\n"); 3891 PRINTK("============================\n"); 3892 PRINTK("|| Default Router Entries ||\n"); 3893 PRINTK("============================\n"); 3894 PRINTK("%-50s %-20s %-10s\n", "Router", "invalidation_timer", "flags"); 3895 PRINTK("-----------------------------------------------------------------------------\n"); 3896 /* Display Default Router Cache Entry */ 3897 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 3898 if (default_router_list[i].neighbor_entry) { 3899 atleastOneEntry = 1; 3900 (void)ip6addr_ntoa_r((const ip6_addr_t *)((default_router_list[i].neighbor_entry)->next_hop_address.addr), 3901 (acIPv6Addr), sizeof(acIPv6Addr)); 3902 PRINTK("%-50s ", acIPv6Addr); 3903 PRINTK("%-20u ", default_router_list[i].invalidation_timer); 3904 PRINTK("%-10u\n", default_router_list[i].flags); 3905 } 3906 } 3907 if (!atleastOneEntry) { 3908 PRINTK("**** NO DEFAULT ROUTERS FOUND ****\n"); 3909 } 3910 PRINTK("-----------------------------------------------------------------------------\n"); 3911 3912exit: 3913 return LOS_OK; 3914} 3915 3916#ifdef LOSCFG_SHELL_CMD_DEBUG 3917SHELLCMD_ENTRY(ipdebug_shellcmd, CMD_TYPE_EX, "ipdebug", XARGS, (CmdCallBackFunc)osShellIpDebug); 3918#endif 3919#ifdef LWIP_TESTBED 3920extern void cmd_reset(void); 3921 3922void osShellReboot(int argc, const char **argv) 3923{ 3924 cmd_reset(); 3925} 3926 3927#ifdef LOSCFG_SHELL_CMD_DEBUG 3928SHELLCMD_ENTRY(reboot_shellcmd, CMD_TYPE_EX, "reboot", XARGS, (CmdCallBackFunc)osShellReboot); 3929#endif /* LOSCFG_SHELL_CMD_DEBUG */ 3930#endif 3931 3932#endif // LWIP_ENABLE_LOS_SHELL_CMD 3933