• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description: ifconfig shell cmd API implementation
15  * Author: none
16  * Create: 2020
17  */
18 
19 #include "lwip/priv/nd6_priv.h"
20 #include "lwip/sockets.h"
21 #include "lwip/inet_chksum.h"
22 #include "lwip/raw.h"
23 #include "lwip/priv/api_msg.h"
24 #include "lwip/icmp.h"
25 #include "lwip/dns.h"
26 #include "lwip/netdb.h"
27 #include "lwip/ip.h"
28 #include "lwip/dhcp.h"
29 #include "lwip/prot/dhcp.h"
30 #include "lwip/nettool/ifconfig.h"
31 #include "lwip/netifapi.h"
32 #include "lwip/etharp.h"
33 #include "lwip/nettool/utility.h"
34 #if LWIP_LITEOS_COMPAT
35 #include "los_config.h"
36 #endif
37 
38 #ifndef LWIP_IFCONFIG_SHOW_SINGLE
39 #define LWIP_IFCONFIG_SHOW_SINGLE 1
40 #endif
41 
42 #if LWIP_ENABLE_BASIC_SHELL_CMD
43 
44 #define BYTE_CONVERT_UNIT 1024
45 
46 #define IFCONFIG_OPTION_SET_IP          1
47 #define IFCONFIG_OPTION_SET_NETMASK     (1 << 1)
48 #define IFCONFIG_OPTION_SET_GW          (1 << 2)
49 #define IFCONFIG_OPTION_SET_HW          (1 << 3)
50 #define IFCONFIG_OPTION_SET_UP          (1 << 4)
51 #define IFCONFIG_OPTION_SET_DOWN        (1 << 5)
52 #define IFCONFIG_OPTION_SET_MTU         (1 << 6)
53 #define IFCONFIG_OPTION_DEL_IP          (1 << 7)
54 
55 struct ifconfig_option {
56   char            iface[NETIF_NAMESIZE];
57   unsigned int    option;
58   ip_addr_t       ip_addr;
59   ip_addr_t       netmask;
60   ip_addr_t       gw;
61   unsigned char   ethaddr[NETIF_MAX_HWADDR_LEN];
62   u16_t           mtu;
63   u8_t            result;
64   /*
65    * when using telnet, print to the telnet socket will result in system deadlock.
66    * So we cahe the prinf data to a buf, and when the tcpip callback returns,
67    * then print the data out to the telnet socket
68    */
69   sys_sem_t       cb_completed;
70   char            cb_print_buf[PRINT_BUF_LEN];
71   unsigned int    print_len;
72 };
73 
74 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
75 extern sys_sem_t ip_conflict_detect;
76 extern u32_t is_ip_conflict_signal;
77 LWIP_STATIC u32_t g_old_ip4addr;
78 LWIP_STATIC u32_t g_old_ip4mask;
79 LWIP_STATIC u32_t g_old_ip4gw;
80 #endif
81 #if LWIP_IPV6
82 extern sys_sem_t dup_addr_detect;
83 extern u32_t is_dup_detect_initialized;
84 #endif
85 
86 #ifndef CUSTOM_AT_COMMAND
87 LWIP_STATIC void
err_ifconfig_string_put(struct ifconfig_option * ifconfig_cmd,char * errcode)88 err_ifconfig_string_put(struct ifconfig_option *ifconfig_cmd, char* errcode)
89 {
90   int ret;
91   ret = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
92                    PRINT_BUF_LEN - ifconfig_cmd->print_len,
93                    ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "ERR:%s\n", errcode);
94   if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) {
95     ifconfig_cmd->print_len += (unsigned int)ret;
96   }
97 }
98 #endif
99 
100 #ifndef LWIP_TESTBED
101 LWIP_STATIC
102 #endif
print_netif_ip(struct netif * netif,char * print_buf,unsigned int buf_len)103 int print_netif_ip(struct netif *netif, char *print_buf, unsigned int buf_len)
104 {
105   int ret;
106   char *tmp = print_buf;
107 
108   if (buf_len <= 1) {
109     return -1;
110   }
111 
112 #if LWIP_IPV4
113   char ip_str[IPADDR_STRLEN_MAX];
114   char netmask_str[IPADDR_STRLEN_MAX];
115   char gateway_str[IPADDR_STRLEN_MAX];
116 
117   (void)ipaddr_ntoa_r(&netif->ip_addr, ip_str, IPADDR_STRLEN_MAX);
118   (void)ipaddr_ntoa_r(&netif->netmask, netmask_str, IPADDR_STRLEN_MAX);
119   (void)ipaddr_ntoa_r(&netif->gw, gateway_str, IPADDR_STRLEN_MAX);
120 #ifdef CUSTOM_AT_COMMAND
121   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "ip=%s,netmask=%s,gateway=%s,",
122                    ip_str, netmask_str, gateway_str);
123 #else
124   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "ip:%s netmask:%s gateway:%s"CRLF,
125                    ip_str, netmask_str, gateway_str);
126 #endif
127   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
128     return -1;
129   }
130   tmp += ret;
131   buf_len -= (unsigned int)ret;
132 #endif
133 
134 #if LWIP_IPV6
135   char ip6_str[IPADDR_STRLEN_MAX];
136   char *addr = NULL;
137   int i;
138   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
139     /* only PREFERRED addresses are displyaed */
140     if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
141       continue;
142     }
143     addr = ip6addr_ntoa_r((const ip6_addr_t *)&netif->ip6_addr[i], ip6_str, IPADDR_STRLEN_MAX);
144 #ifdef CUSTOM_AT_COMMAND
145     if (addr != NULL) {
146       ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "ip6=%s,", ip6_str);
147     }
148 #else
149     (void)addr;
150     ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "\tip6: %s/64"CRLF, ip6_str);
151 #endif
152     if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
153       return -1;
154     }
155     tmp += ret;
156     buf_len -= (unsigned int)ret;
157   }
158 #endif
159 
160   return (tmp - print_buf);
161 }
162 
163 LWIP_STATIC int
print_netif_hw(struct netif * netif,char * print_buf,unsigned int buf_len)164 print_netif_hw(struct netif *netif, char *print_buf, unsigned int buf_len)
165 {
166   int ret, i;
167   char *tmp = print_buf;
168   if (buf_len <= 1) {
169     return -1;
170   }
171 #ifdef CUSTOM_AT_COMMAND
172   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s", "HWaddr=");
173 #else
174   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s", "\tHWaddr ");
175 #endif
176   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
177     return -1;
178   }
179   tmp += ret;
180   buf_len -= (unsigned int)ret;
181 
182   for (i = 0; i < netif->hwaddr_len - 1; i++) {
183     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x:", netif->hwaddr[i]);
184     if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
185       return -1;
186     }
187     tmp += ret;
188     buf_len -= (unsigned int)ret;
189   }
190 
191 #ifdef CUSTOM_AT_COMMAND
192   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%02x,", netif->hwaddr[i]);
193 #else
194   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%02x", netif->hwaddr[i]);
195 #endif
196   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
197     return -1;
198   }
199   tmp += ret;
200 
201   return (tmp - print_buf);
202 }
203 
204 LWIP_STATIC int
print_netif_link(struct netif * netif,char * print_buf,unsigned int buf_len)205 print_netif_link(struct netif *netif, char *print_buf, unsigned int buf_len)
206 {
207   int ret;
208   char *tmp = print_buf;
209   if (buf_len <= 1) {
210     return -1;
211   }
212 #ifdef CUSTOM_AT_COMMAND
213   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "MTU=%hu,LinkStatus=%d,RunStatus=%d"CRLF,
214                    netif->mtu,
215                    ((netif->flags & NETIF_FLAG_LINK_UP) != 0) ? 1 : 0,
216                    ((netif->flags & NETIF_FLAG_UP) != 0) ? 1 : 0);
217 
218 #else
219   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), " MTU:%hu %s %s %s"CRLF,
220                    netif->mtu,
221                    ((netif->flags & NETIF_FLAG_UP) != 0) ? "Running" : "Stop",
222                    "Default",
223                    ((netif->flags & NETIF_FLAG_LINK_UP) != 0) ? "Link UP" : "Link Down");
224 #endif
225   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
226     return -1;
227   }
228   tmp += ret;
229 
230   return (tmp - print_buf);
231 }
232 
233 #if MIB2_STATS
234 LWIP_STATIC int
print_netif_mib(struct netif * netif,char * print_buf,unsigned int buf_len)235 print_netif_mib(struct netif *netif, char *print_buf, unsigned int buf_len)
236 {
237   int ret;
238   char *tmp = print_buf;
239 
240   if (buf_len <= 1) {
241     return -1;
242   }
243 
244   ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1),
245                    "\tRX packets:%u errors:%u dropped:%u overruns:%u"CRLF
246                    "\tTX packets:%u errors:%u dropped:%u"CRLF"\tRX bytes:%u TX bytes:%u"CRLF,
247                    netif->mib2_counters.ifinucastpkts + netif->mib2_counters.ifinnucastpkts,
248                    netif->mib2_counters.ifinerrors,
249                    netif->mib2_counters.ifindiscards,
250                    netif->mib2_counters.ifinoverruns,
251                    netif->mib2_counters.ifoutucastpkts + netif->mib2_counters.ifoutnucastpkts,
252                    netif->mib2_counters.ifouterrors,
253                    netif->mib2_counters.ifoutdiscards,
254                    netif->mib2_counters.ifinoctets,
255                    netif->mib2_counters.ifoutoctets);
256 
257   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
258     return -1;
259   }
260   tmp += ret;
261   return (tmp - print_buf);
262 }
263 #endif
264 
265 #ifndef LWIP_TESTBED
266 LWIP_STATIC
267 #endif
268 int
print_netif(struct netif * netif,char * print_buf,unsigned int buf_len)269 print_netif(struct netif *netif, char *print_buf, unsigned int buf_len)
270 {
271   int ret;
272   char *tmp = print_buf;
273 
274   if (buf_len <= 1) {
275     return -1;
276   }
277 #ifdef CUSTOM_AT_COMMAND
278   /* printf +IFCFG */
279   (void)uapi_at_printf("+IFCFG:");
280 #endif
281 
282   if (netif->link_layer_type == LOOPBACK_IF) {
283 #ifdef CUSTOM_AT_COMMAND
284     ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s,", netif->name);
285 #else
286     ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s\t", netif->name);
287 #endif
288   } else {
289 #ifdef CUSTOM_AT_COMMAND
290     ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s%u,", netif->name, netif->num);
291 #else
292     ret = snprintf_s(tmp, buf_len, (unsigned int)(buf_len - 1), "%s%u\t", netif->name, netif->num);
293 #endif
294   }
295   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
296     goto out;
297   }
298   tmp += ret;
299   buf_len -= (unsigned int)ret;
300 
301   ret = print_netif_ip(netif, tmp, buf_len);
302   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
303     goto out;
304   }
305   tmp += ret;
306   buf_len -= (unsigned int)ret;
307 
308   ret = print_netif_hw(netif, tmp, buf_len);
309   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
310     goto out;
311   }
312   tmp += ret;
313   buf_len -= (unsigned int)ret;
314 
315   ret = print_netif_link(netif, tmp, buf_len);
316   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
317     goto out;
318   }
319   tmp += ret;
320   buf_len -= (unsigned int)ret;
321 
322 #if MIB2_STATS
323   ret = print_netif_mib(netif, tmp, buf_len);
324   if ((ret <= 0) || ((unsigned int)ret >= buf_len)) {
325     goto out;
326   }
327   tmp += ret;
328   buf_len -= (unsigned int)ret;
329 #endif
330 
331 #if LWIP_IFCONFIG_SHOW_SINGLE
332 #ifdef CUSTOM_AT_COMMAND
333   (void)uapi_at_printf("%s", print_buf);
334 #else
335   LWIP_PLATFORM_PRINT("%s", print_buf);
336 #endif
337 #endif
338 out:
339   return (int)(tmp - print_buf);
340 }
341 
342 #ifndef LWIP_TESTBED
343 LWIP_STATIC
344 #endif
345 void
lwip_ifconfig_show_internal(void * arg)346 lwip_ifconfig_show_internal(void *arg)
347 {
348   struct netif *netif = NULL;
349   struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg;
350   int ret;
351 
352   if (netif_list == NULL) {
353 #ifndef CUSTOM_AT_COMMAND
354     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DEV_NOT_READY);
355 #endif
356     sys_sem_signal(&ifconfig_cmd->cb_completed);
357 #ifdef CUSTOM_AT_COMMAND
358     (void)uapi_at_printf("ERROR"CRLF);
359 #endif
360     return;
361   }
362 
363   if (ifconfig_cmd->iface[0] == '\0') {
364     /* display all netif */
365     for (netif = netif_list; netif != NULL; netif = netif->next) {
366       ret = print_netif(netif,
367                         ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
368                         PRINT_BUF_LEN - ifconfig_cmd->print_len);
369       if (ret == -1) {
370         sys_sem_signal(&ifconfig_cmd->cb_completed);
371         return;
372       }
373       ifconfig_cmd->print_len += (unsigned int)ret;
374     }
375   } else {
376     netif = netif_find(ifconfig_cmd->iface);
377     if (netif == NULL) {
378 #ifndef CUSTOM_AT_COMMAND
379       err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DEV_NOT_FOUND);
380 #endif
381       sys_sem_signal(&ifconfig_cmd->cb_completed);
382 #ifdef CUSTOM_AT_COMMAND
383       (void)uapi_at_printf("ERROR"CRLF);
384 #endif
385       PRINT_ERRCODE(API_SHELL_ERRCODE_DEV_NOT_FOUND);
386       return;
387     }
388 
389     ret = print_netif(netif,
390                       ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
391                       PRINT_BUF_LEN - ifconfig_cmd->print_len);
392     if (ret == -1) {
393       sys_sem_signal(&ifconfig_cmd->cb_completed);
394       return;
395     }
396     ifconfig_cmd->print_len += (unsigned int)ret;
397   }
398   sys_sem_signal(&ifconfig_cmd->cb_completed);
399 
400 #ifdef CUSTOM_AT_COMMAND
401   (void)uapi_at_printf("OK"CRLF);
402 #endif
403 }
404 
405 LWIP_STATIC int
lwip_ifconfig_ip(struct netif * netif,struct ifconfig_option * ifconfig_cmd)406 lwip_ifconfig_ip(struct netif *netif, struct ifconfig_option *ifconfig_cmd)
407 {
408   ip_addr_t ip_addr;
409   struct netif *loc_netif = NULL;
410 
411   ip_addr_set_val(ip_addr, (ifconfig_cmd->ip_addr));
412   if (IP_IS_V4_VAL(ifconfig_cmd->ip_addr)) {
413     /* check the address is not multicast/broadcast/0/loopback */
414     if (ip_addr_ismulticast_val(ip_addr) || ip_addr_isbroadcast_val(ip_addr, netif) ||
415         (ip_addr_isany(&ip_addr) && (g_old_ip4addr != IPADDR_ANY)) || ip_addr_isloopback(&ip_addr)) {
416 #ifndef CUSTOM_AT_COMMAND
417       err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_INVALID);
418 #endif
419       return -1;
420     }
421     /* lwip disallow two netif sit in same net at the same time */
422     loc_netif = netif_list;
423     while (loc_netif != NULL) {
424       if ((loc_netif == netif) || (ip4_addr_isany_val(*ip_2_ip4(&loc_netif->netmask)))) {
425         loc_netif = loc_netif->next;
426         continue;
427       }
428       if (ip_addr_cmp(&netif->netmask, &loc_netif->netmask) &&
429           ip_addr_netcmp_val(loc_netif->ip_addr, ip_addr, ip_2_ip4(&netif->netmask))) {
430 #ifndef CUSTOM_AT_COMMAND
431         err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DUPLICATE_NETWORK);
432 #endif
433         return -1;
434       }
435       loc_netif = loc_netif->next;
436     }
437     /* reset gateway if new and previous ipaddr not in same net */
438     if (!ip_addr_netcmp_val(ip_addr, netif->ip_addr, ip_2_ip4(&netif->netmask))) {
439       ip_addr_set_zero_val(netif->gw);
440       if (netif == netif_default) {
441         (void)netif_set_default(NULL);
442       }
443     }
444 
445 #if LWIP_DHCP
446     if ((netif_dhcp_data(netif) != NULL) &&
447         (netif_dhcp_data(netif)->client.states[LWIP_DHCP_NATIVE_IDX].state != DHCP_STATE_OFF)) {
448       (void)netif_dhcp_off(netif);
449     }
450 #endif
451     netif_set_ipaddr(netif, ip_2_ip4(&ip_addr));
452   }
453 #if LWIP_IPV6
454   else if (IP_IS_V6_VAL(ifconfig_cmd->ip_addr)) {
455     s8_t idx;
456     err_t err;
457     idx = -1;
458     err = netif_add_ip6_address(netif, ip_2_ip6(&ip_addr), &idx);
459     if ((err != ERR_OK) || (idx == -1)) {
460 #ifndef CUSTOM_AT_COMMAND
461       err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_MEM_ERR);
462 #endif
463       return -1;
464     }
465   }
466 #endif /* LWIP_IPV6 */
467   else {
468 #ifndef CUSTOM_AT_COMMAND
469     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_INVALID);
470 #endif
471     return -1;
472   }
473   return 0;
474 }
475 
476 LWIP_STATIC int
lwip_ifconfig_netmask(struct netif * netif,struct ifconfig_option * ifconfig_cmd)477 lwip_ifconfig_netmask(struct netif *netif, struct ifconfig_option *ifconfig_cmd)
478 {
479   ip_addr_t netmask;
480   struct netif *loc_netif = NULL;
481   ip_addr_set_val(netmask, (ifconfig_cmd->netmask));
482   /* check data valid */
483   if (ip_addr_netmask_valid(ip_2_ip4(&netmask)) == 0) {
484 #ifndef CUSTOM_AT_COMMAND
485     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_INVALID);
486 #endif
487     return -1;
488   }
489 
490 #if LWIP_DHCP
491   if ((netif_dhcp_data(netif) != NULL) &&
492       (netif_dhcp_data(netif)->client.states[LWIP_DHCP_NATIVE_IDX].state != DHCP_STATE_OFF)) {
493     (void)netif_dhcp_off(netif);
494   }
495 #endif
496   if (netif_ip4_netmask(netif)->addr != ip_2_ip4(&netmask)->addr) {
497     /* lwip disallow two netif sit in same net at the same time */
498     loc_netif = netif_list;
499     while (loc_netif != NULL) {
500       if (loc_netif == netif) {
501         loc_netif = loc_netif->next;
502         continue;
503       }
504       if (ip_addr_cmp(&loc_netif->netmask, &netmask) &&
505           ip_addr_netcmp(&loc_netif->ip_addr,
506                          &netif->ip_addr, ip_2_ip4(&netmask))) {
507 #ifndef CUSTOM_AT_COMMAND
508         err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DUPLICATE_NETWORK);
509 #endif
510         return -1;
511       }
512       loc_netif = loc_netif->next;
513     }
514     netif_set_netmask(netif, ip_2_ip4(&netmask));
515     /* check if gateway still reachable */
516     if (!ip_addr_netcmp(&netif->gw,
517                         &netif->ip_addr, ip_2_ip4(&netmask))) {
518       ip_addr_set_zero_val(netif->gw);
519       if (netif == netif_default) {
520         (void)netif_set_default(NULL);
521       }
522     }
523   }
524   return 0;
525 }
526 
527 LWIP_STATIC int
lwip_ifconfig_gw(struct netif * netif,struct ifconfig_option * ifconfig_cmd)528 lwip_ifconfig_gw(struct netif *netif, struct ifconfig_option *ifconfig_cmd)
529 {
530   ip_addr_t gw;
531 
532   ip_addr_set_val(gw, ifconfig_cmd->gw);
533 
534   /* check the address multicast/0/loopback */
535   if (ip_addr_ismulticast_val(gw) || ip_addr_isbroadcast_val(gw, netif) ||
536       ip_addr_isany(&gw) || ip_addr_isloopback(&gw)) {
537 #ifndef CUSTOM_AT_COMMAND
538     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DUPLICATE_NETWORK);
539 #endif
540     return -1;
541   }
542 
543   /* check if reachable */
544   if (!ip_addr_netcmp_val(gw, netif->ip_addr, ip_2_ip4(&netif->netmask))) {
545 #ifndef CUSTOM_AT_COMMAND
546     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_NO_ROUTE);
547 #endif
548     return -1;
549   }
550 
551   if (netif_default != netif) {
552     ip_addr_set_zero_val(netif->gw);
553     (void)netif_set_default(netif);
554   }
555 
556 #if LWIP_DHCP
557   if ((netif_dhcp_data(netif) != NULL) &&
558       (netif_dhcp_data(netif)->client.states[LWIP_DHCP_NATIVE_IDX].state != DHCP_STATE_OFF)) {
559     (void)netif_dhcp_off(netif);
560   }
561 #endif
562   netif_set_gw(netif, ip_2_ip4(&gw));
563   return 0;
564 }
565 
566 #ifndef LWIP_TESTBED
567 LWIP_STATIC
568 #endif
569 void
lwip_ifconfig_internal(void * arg)570 lwip_ifconfig_internal(void *arg)
571 {
572   struct ifconfig_option *ifconfig_cmd = NULL;
573   struct netif *netif = NULL;
574 
575   ifconfig_cmd = (struct ifconfig_option *)arg;
576   netif = netif_find(ifconfig_cmd->iface);
577   if (netif == NULL) {
578 #ifndef CUSTOM_AT_COMMAND
579     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_DEV_NOT_FOUND);
580 #endif
581     ifconfig_cmd->result = OS_NOK;
582     PRINT_ERRCODE(API_SHELL_ERRCODE_DEV_NOT_FOUND);
583     goto out;
584   }
585 
586   /* Saves the current address information of the NetIF interface. */
587   struct ifconfig_option ori_ifconfig_cmd;
588   ori_ifconfig_cmd.ip_addr = netif->ip_addr;
589   ori_ifconfig_cmd.netmask = netif->netmask;
590   ori_ifconfig_cmd.gw = netif->gw;
591 
592   if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_UP) != 0) {
593     (void)netif_set_up(netif);
594     goto out;
595   } else if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_DOWN) != 0) {
596     (void)netif_set_down(netif);
597     goto out;
598   }
599 
600   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) ||
601       ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) != 0) ||
602       ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW) != 0)) {
603     (void)netif_set_down(netif);
604   }
605 
606   if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) {
607     if (lwip_ifconfig_ip(netif, ifconfig_cmd) != 0) {
608       (void)netif_set_up(netif);
609       ifconfig_cmd->result = OS_NOK;
610       goto out;
611     }
612   }
613 
614 #if LWIP_IPV6
615   if ((ifconfig_cmd->option & IFCONFIG_OPTION_DEL_IP) != 0) {
616     (void)netif_do_rmv_ipv6_addr(netif, &ifconfig_cmd->ip_addr);
617   }
618 #endif
619 
620   if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) != 0) {
621     if (lwip_ifconfig_netmask(netif, ifconfig_cmd) != 0) {
622       (void)netif_set_up(netif);
623       ifconfig_cmd->result = OS_NOK;
624       goto out;
625     }
626   }
627 
628   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW) != 0) &&
629       (netif_set_hwaddr(netif, ifconfig_cmd->ethaddr, NETIF_MAX_HWADDR_LEN) != ERR_OK)) {
630 #ifndef CUSTOM_AT_COMMAND
631     err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_SERVICE_FAILURE);
632 #endif
633     (void)netif_set_up(netif);
634     ifconfig_cmd->result = OS_NOK;
635     goto out;
636   }
637 
638   if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_GW) != 0) {
639     if (lwip_ifconfig_gw(netif, ifconfig_cmd) != 0) {
640       ifconfig_cmd->result = OS_NOK;
641       goto out;
642     }
643   }
644 
645   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) ||
646       ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_NETMASK) != 0) ||
647       ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_HW) != 0)) {
648     (void)netif_set_up(netif);
649   }
650 
651   if ((ifconfig_cmd->option & IFCONFIG_OPTION_SET_MTU) != 0) {
652     if (netif_set_mtu(netif, ifconfig_cmd->mtu) != ERR_OK) {
653 #ifndef CUSTOM_AT_COMMAND
654       err_ifconfig_string_put(ifconfig_cmd, API_SHELL_ERRCODE_INVALID);
655 #endif
656       ifconfig_cmd->result = OS_NOK;
657     }
658   }
659 out:
660 
661   if(netif && ifconfig_cmd->result == OS_NOK) {
662     (void)lwip_ifconfig_ip(netif, &ori_ifconfig_cmd);
663     (void)lwip_ifconfig_netmask(netif, &ori_ifconfig_cmd);
664     (void)lwip_ifconfig_gw(netif, &ori_ifconfig_cmd);
665     (void)netif_set_down(netif);
666   }
667 
668   sys_sem_signal(&ifconfig_cmd->cb_completed);
669 }
670 
671 void
lwip_printsize(size_t size)672 lwip_printsize(size_t size)
673 {
674   static const char *sizes[] = { "", "K", "M", "G" };
675   size_t divis = 0;
676   size_t rem = 0;
677   while ((size >= BYTE_CONVERT_UNIT) && (divis < ((sizeof(sizes) / sizeof(char *)) - 1))) {
678     rem = (size % BYTE_CONVERT_UNIT);
679     divis++;
680     size /= BYTE_CONVERT_UNIT;
681   }
682   /* 1024.0 : byte in float unit */
683   LWIP_PLATFORM_PRINT("(%.1f %sB) \r\n", (float)size + (float)rem / 1024.0, sizes[divis]);
684 }
685 
686 #ifndef CUSTOM_AT_COMMAND
687 LWIP_STATIC void
lwip_ifconfig_usage(const char * cmd)688 lwip_ifconfig_usage(const char *cmd)
689 {
690   LWIP_PLATFORM_PRINT("Usage:"\
691                       CRLF"%s [-a] "\
692                       CRLF"[interface]"\
693                       CRLF"[interface ipaddr] <netmask mask> <gateway gw>"\
694                       CRLF"[interface inet6 add|del ipaddr]"\
695                       CRLF"[interface hw ether MAC]"\
696                       CRLF"[interface mtu NN]"\
697                       CRLF"[interface up|down]"CRLF,
698                       cmd);
699 }
700 #endif
701 
702 
703 #ifndef CUSTOM_AT_COMMAND
lwip_ifconfig_all(int argc,const char ** argv)704 LWIP_STATIC u32_t lwip_ifconfig_all(int argc, const char **argv)
705 {
706   LWIP_UNUSED_ARG(argc);
707   LWIP_UNUSED_ARG(argv);
708   /* To support "ifconfig -a" command
709    *   RX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format)
710    *   TX packets:XXXX errors:X dropped:X overruns:X bytes:XXXX (Human readable format)
711    *
712    *   Below is assumed for 'overrun' stat.
713    *   Linux Kernel:
714    *          RX: FIFO overrun
715    *              Data structure: net_device->stats->rx_fifo_errors
716    *              Flag which is marked when FIFO overrun: ENRSR_FO
717    *
718    *          Function: ei_receive->ENRSR_FO
719    *
720    *          TX: A "FIFO underrun" occurred during transmit.
721    *              Data structure: net_device->stats->tx_fifo_errors
722    *              Flag which is marked when FIFO underrun: ENTSR_FU
723    *
724    *          Function: ei_tx_intr->ENTSR_FU
725    *
726    *  LWIP:
727    *      So in our case,
728    *      while receiving a packet RX case, if the buffer is full (trypost - it is sys_mbox_trypost)
729    *      the error will be returned, we can consider that an overflow has happend.
730    *      So this can be RX overrun.
731    *
732    *      But while transmitting a packet TX case, underrun cannot happen because it block on the
733    *      message Q if it is full (NOT trypost - it is sys_mbox_post). So TX overrun is always 0.
734    */
735 #if LWIP_STATS
736   u32_t stat_err_cnt;
737   u32_t stat_drop_cnt;
738   u32_t stat_rx_or_tx_cnt;
739   u32_t stat_rx_or_tx_bytes;
740 
741   stat_rx_or_tx_cnt     = lwip_stats.ip.recv;
742   stat_err_cnt          = (u32_t)(lwip_stats.ip.ip_rx_err
743                                   + lwip_stats.ip.lenerr
744                                   + lwip_stats.ip.chkerr
745                                   + lwip_stats.ip.opterr
746                                   + lwip_stats.ip.proterr);
747   stat_drop_cnt         = (u32_t)(lwip_stats.ip.drop + lwip_stats.link.link_rx_drop);
748   stat_rx_or_tx_bytes = lwip_stats.ip.ip_rx_bytes;
749 
750   LWIP_PLATFORM_PRINT("%18s:%u\t errors:%u\t ip dropped:%u\t link dropped:%u\t overrun:%hu\t bytes:%u ",
751                       "RX packets",
752                       stat_rx_or_tx_cnt,
753                       stat_err_cnt,
754                       stat_drop_cnt,
755                       lwip_stats.link.link_rx_drop,
756                       lwip_stats.ip.link_rx_overrun,
757                       stat_rx_or_tx_bytes);
758 
759   /* Print in Human readable format of the incoming bytes */
760   lwip_printsize(lwip_stats.ip.ip_rx_bytes);
761 #if IP6_STATS
762   stat_rx_or_tx_cnt     = lwip_stats.ip6.recv;
763   stat_err_cnt          = (u32_t)(lwip_stats.ip6.ip_rx_err
764                                   + lwip_stats.ip6.lenerr
765                                   + lwip_stats.ip6.chkerr
766                                   + lwip_stats.ip6.opterr
767                                   + lwip_stats.ip6.proterr);
768   stat_drop_cnt         = lwip_stats.ip6.drop;
769   stat_rx_or_tx_bytes = lwip_stats.ip6.ip_rx_bytes;
770 
771   LWIP_PLATFORM_PRINT("%18s:%u\t errors:%u\t dropped:%u\t overrun:%hu\t bytes:%u ",
772                       "RX packets(ip6)",
773                       stat_rx_or_tx_cnt,
774                       stat_err_cnt,
775                       stat_drop_cnt,
776                       lwip_stats.ip.link_rx_overrun,
777                       stat_rx_or_tx_bytes);
778 
779   /* Print in Human readable format of the incoming bytes */
780   lwip_printsize(lwip_stats.ip6.ip_rx_bytes);
781 #endif
782   stat_rx_or_tx_cnt     = (u32_t)(lwip_stats.ip.fw + lwip_stats.ip.xmit);
783   stat_err_cnt          = (u32_t)(lwip_stats.ip.rterr + lwip_stats.ip.ip_tx_err);
784   /* IP layer drop stat param is not maintained, failure at IP is considered in 'errors' stat */
785   stat_drop_cnt         = lwip_stats.link.link_tx_drop;
786   stat_rx_or_tx_bytes   = lwip_stats.ip.ip_tx_bytes;
787 
788   LWIP_PLATFORM_PRINT("%18s:%u\t errors:%u\t link dropped:%u\t overrun:0\t bytes:%u",
789                       "TX packets",
790                       stat_rx_or_tx_cnt,
791                       stat_err_cnt,
792                       stat_drop_cnt,
793                       stat_rx_or_tx_bytes);
794 
795   /* Print in Human readable format of the outgoing bytes */
796   lwip_printsize(lwip_stats.ip.ip_tx_bytes);
797 
798 #if IP6_STATS
799   stat_rx_or_tx_cnt     = (u32_t)(lwip_stats.ip6.fw + lwip_stats.ip6.xmit);
800   stat_err_cnt          = (u32_t)(lwip_stats.ip6.rterr + lwip_stats.ip6.ip_tx_err);
801   stat_rx_or_tx_bytes   = lwip_stats.ip6.ip_tx_bytes;
802 
803   LWIP_PLATFORM_PRINT("%18s:%u\t errors:%u\t overrun:0\t bytes:%u",
804                       "TX packets(ip6)",
805                       stat_rx_or_tx_cnt,
806                       stat_err_cnt,
807                       stat_rx_or_tx_bytes);
808 
809   /* Print in Human readable format of the outgoing bytes */
810   lwip_printsize(lwip_stats.ip6.ip_tx_bytes);
811 #endif /* IP6_STATS */
812 #endif /* LWIP_STATS */
813   return 0;
814 }
815 #endif
816 
lwip_ifconfig_callback(tcpip_callback_fn function,struct ifconfig_option * ifconfig_cmd)817 LWIP_STATIC u32_t lwip_ifconfig_callback(tcpip_callback_fn function, struct ifconfig_option *ifconfig_cmd)
818 {
819   if (tcpip_callback(function, ifconfig_cmd) != ERR_OK) {
820     sys_sem_free(&ifconfig_cmd->cb_completed);
821     PRINT_ERRCODE(API_SHELL_ERRCODE_SERVICE_FAILURE);
822     return OS_NOK;
823   }
824   (void)sys_arch_sem_wait(&ifconfig_cmd->cb_completed, 0);
825   sys_sem_free(&ifconfig_cmd->cb_completed);
826 
827   ifconfig_cmd->cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
828   if (ifconfig_cmd->result != OS_OK) {
829     return OS_NOK;
830   }
831   return OS_OK;
832 }
833 
lwip_ifconfig_print_all(struct ifconfig_option * ifconfig_cmd)834 LWIP_STATIC u32_t lwip_ifconfig_print_all(struct ifconfig_option *ifconfig_cmd)
835 {
836   u32_t ret = lwip_ifconfig_callback(lwip_ifconfig_show_internal, ifconfig_cmd);
837   if (ret != 0) {
838     return ret;
839   }
840 
841 #if (LWIP_IFCONFIG_SHOW_SINGLE != lwIP_TRUE)
842 #ifdef CUSTOM_AT_COMMAND
843   (void)uapi_at_printf("+IFCONFIG:");
844   (void)uapi_at_printf("%s", ifconfig_cmd->cb_print_buf);
845   (void)uapi_at_printf("OK"CRLF);
846 #else
847   LWIP_PLATFORM_PRINT("%s", ifconfig_cmd->cb_print_buf);
848 #endif
849 #endif
850   return OS_OK;
851 }
852 
lwip_ifconfig_up_down(struct ifconfig_option * ifconfig_cmd)853 LWIP_STATIC u32_t lwip_ifconfig_up_down(struct ifconfig_option *ifconfig_cmd)
854 {
855   u32_t ret = lwip_ifconfig_callback(lwip_ifconfig_internal, ifconfig_cmd);
856   if (ret != 0) {
857     return ret;
858   }
859 
860 #ifndef CUSTOM_AT_COMMAND
861   LWIP_PLATFORM_PRINT("%s", ifconfig_cmd->cb_print_buf);
862   return 0;
863 #else
864   return OS_NOK;
865 #endif
866 }
867 
868 LWIP_STATIC u32_t
lwip_ifconfig_prase_inet(int * argc,const char ** argv,int * idx,struct ifconfig_option * ifconfig_cmd)869 lwip_ifconfig_prase_inet(int *argc, const char **argv, int *idx,
870                          struct ifconfig_option *ifconfig_cmd)
871 {
872 #if LWIP_ARP
873   struct netif *netiftmp = NULL;
874 #endif /* LWIP_ARP */
875 
876   /* check if set the ip address. */
877 #if LWIP_ARP
878   char buf[IPADDR_STRLEN_MAX] = {0};
879   netiftmp = netif_find(ifconfig_cmd->iface);
880   if (netiftmp == NULL) {
881     PRINT_ERRCODE(API_SHELL_ERRCODE_DEV_NOT_FOUND);
882     return EINVAL;
883   }
884   (void)ipaddr_ntoa_r(&netiftmp->netmask, buf, IPADDR_STRLEN_MAX);
885   g_old_ip4mask = ipaddr_addr(buf);
886   (void)memset_s(buf, IPADDR_STRLEN_MAX, 0x0, IPADDR_STRLEN_MAX);
887   (void)ipaddr_ntoa_r(&netiftmp->gw, buf, IPADDR_STRLEN_MAX);
888   g_old_ip4gw = ipaddr_addr(buf);
889   (void)memset_s(buf, IPADDR_STRLEN_MAX, 0x0, IPADDR_STRLEN_MAX);
890   (void)ipaddr_ntoa_r(&netiftmp->ip_addr, buf, IPADDR_STRLEN_MAX);
891   g_old_ip4addr = ipaddr_addr(buf);
892 #endif /* LWIP_ARP */
893   if ((strcmp(argv[*idx], "inet") == 0) || (ip4addr_aton(argv[*idx], ip_2_ip4(&ifconfig_cmd->ip_addr)) != 0)) {
894     if (strcmp(argv[*idx], "inet") == 0) {
895       if (*argc <= 1) {
896         return EINVAL;
897       }
898 
899       if (ip4addr_aton(argv[*idx + 1], ip_2_ip4(&ifconfig_cmd->ip_addr)) == 0) {
900         PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
901         return EINVAL;
902       }
903       (*argc)--;
904       (*idx)++;
905     }
906     IP_SET_TYPE_VAL((ifconfig_cmd->ip_addr), IPADDR_TYPE_V4);
907 #if LWIP_ARP
908     if (!ip_addr_cmp(&ifconfig_cmd->ip_addr, &netiftmp->ip_addr)) {
909       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_IP;
910     }
911 #else
912     ifconfig_cmd->option |= IFCONFIG_OPTION_SET_IP;
913 #endif /* LWIP_ARP */
914     (*argc)--;
915     (*idx)++;
916   }
917 #if LWIP_IPV6
918   else if (strcmp(argv[*idx], "inet6") == 0) {
919     /* 3 : min argc parameter num from command line */
920     if (*argc < 3) {
921       return OS_NOK;
922     }
923     if ((strcmp(argv[*idx + 1], "add") != 0) && (strcmp(argv[*idx + 1], "del") != 0)) {
924       return OS_NOK;
925     }
926 
927     /* 2 : skip two argv index */
928     if (ip6addr_aton(argv[*idx + 2], ip_2_ip6(&ifconfig_cmd->ip_addr)) == 0) {
929       PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
930       return EINVAL;
931     }
932 
933     IP_SET_TYPE_VAL((ifconfig_cmd->ip_addr), IPADDR_TYPE_V6);
934     ifconfig_cmd->option |= (!strcmp(argv[*idx + 1], "add") ? IFCONFIG_OPTION_SET_IP : IFCONFIG_OPTION_DEL_IP);
935     *argc -= 3; /* 3: skip already check three parameter */
936     (*idx) += 3; /* 3: skip three argv index */
937   }
938 #endif /* LWIP_IPV6 */
939   else {
940     PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
941     return EINVAL;
942   }
943 
944   if (((ifconfig_cmd->option & IFCONFIG_OPTION_DEL_IP) != 0) && (*argc != 0)) {
945     return OS_NOK;
946   }
947 
948   return OS_OK;
949 }
950 
951 LWIP_STATIC u32_t
lwip_ifconfig_prase_additional(int * argc,const char ** argv,int * idx,struct ifconfig_option * ifconfig_cmd)952 lwip_ifconfig_prase_additional(int *argc, const char **argv, int *idx,
953                                struct ifconfig_option *ifconfig_cmd)
954 {
955   while (*argc > 0) {
956     /* if set netmask */
957     if ((strcmp("netmask", argv[*idx]) == 0) && (*argc > 1) &&
958         (ipaddr_addr(argv[*idx + 1]) != IPADDR_NONE)) {
959       ip_addr_set_ip4_u32_val((ifconfig_cmd->netmask), ipaddr_addr(argv[*idx + 1]));
960       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_NETMASK;
961       *idx += 2; /* 2: skip two argv index */
962       *argc -= 2; /* 2: skip already check two parameter */
963     } else if ((strcmp("gateway", argv[*idx]) == 0) && (*argc > 1) && /* if set gateway */
964                (ipaddr_addr(argv[*idx + 1]) != IPADDR_NONE)) {
965       ip_addr_set_ip4_u32_val((ifconfig_cmd->gw), ipaddr_addr(argv[*idx + 1]));
966       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_GW;
967       *idx += 2; /* 2: skip two argv index */
968       *argc -= 2; /* 2: skip already check two parameter */
969     } else if ((strcmp("hw", argv[*idx]) == 0) && (*argc > 2) && /* 2 : if set HWaddr and more than two parameter */
970                (strcmp("ether", argv[*idx + 1]) == 0)) {
971       char *digit = NULL;
972       u32_t macaddrlen = strlen(argv[*idx + 2]) + 1; /* 2: skip two argv index */
973       char tmp_str[MAX_MACADDR_STRING_LENGTH];
974       char *tmp_str1 = NULL;
975       char *saveptr = NULL;
976       int j;
977 
978       if (macaddrlen != MAX_MACADDR_STRING_LENGTH) {
979         PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
980         return EINVAL;
981       }
982       /* 2: skip two argv index */
983       if (strncpy_s(tmp_str, MAX_MACADDR_STRING_LENGTH, argv[*idx + 2], macaddrlen - 1) != EOK) {
984         PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
985         return EINVAL;
986       }
987       /* 6 : max ':' num */
988       for (j = 0, tmp_str1 = tmp_str; j < 6; j++, tmp_str1 = NULL) {
989         digit = strtok_r(tmp_str1, ":", &saveptr);
990         if ((digit == NULL) || (strlen(digit) > 2)) { /* 2 : char len */
991           PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
992           return EINVAL;
993         }
994         if(convert_string_to_hex(digit, &ifconfig_cmd->ethaddr[j]) != 0) {
995           LWIP_PLATFORM_PRINT("MAC address is not correct"CRLF);
996           return EINVAL;
997         }
998       }
999       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_HW;
1000       *idx += 3; /* 3: skip already check three parameter */
1001       *argc -= 3; /* 3: skip three argv index */
1002     } else if ((strcmp("mtu", argv[*idx]) == 0) && (*argc > 1)) { /* if set mtu */
1003       if ((atoi(argv[*idx + 1]) < 0) || (atoi(argv[*idx + 1]) > 0xFFFF)) { /* 0xFFFF : max argv num */
1004         PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
1005         return EINVAL;
1006       }
1007 
1008       ifconfig_cmd->mtu = (u16_t)(atoi(argv[*idx + 1]));
1009       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_MTU;
1010       *idx += 2; /* 2: skip two argv index */
1011       *argc -= 2; /* 2: skip already check two parameter */
1012     } else {
1013       return OS_NOK;
1014     }
1015   }
1016 
1017   return OS_OK;
1018 }
1019 
1020 #if LWIP_DHCP && LWIP_DHCP_SUBSTITUTE
1021 LWIP_STATIC err_t
lwip_ifconfig_dhcp_addr_clients_check_fn(struct netif * nif,void * arg)1022 lwip_ifconfig_dhcp_addr_clients_check_fn(struct netif *nif, void *arg)
1023 {
1024   struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg;
1025   struct netif *netif = netif_find(ifconfig_cmd->iface);
1026   s32_t ret;
1027   (void)nif;
1028 
1029   if (netif == NULL) {
1030     ifconfig_cmd->result = lwIP_FALSE;
1031     PRINT_ERRCODE(API_SHELL_ERRCODE_DEV_NOT_FOUND);
1032     return ERR_OK;
1033   }
1034   ret = dhcp_netif_addr_clients_check(netif, ip_2_ip4(&ifconfig_cmd->ip_addr));
1035   if ((ret == lwIP_TRUE) && (!ip_addr_cmp(&ifconfig_cmd->ip_addr, &netif->ip_addr))) {
1036     ifconfig_cmd->result = lwIP_TRUE;
1037   } else {
1038     ifconfig_cmd->result = lwIP_FALSE;
1039   }
1040 
1041   return ERR_OK;
1042 }
1043 
1044 LWIP_STATIC u8_t
lwip_ifconfig_dhcp_addr_clients_check(struct ifconfig_option * ifconfig_cmd)1045 lwip_ifconfig_dhcp_addr_clients_check(struct ifconfig_option *ifconfig_cmd)
1046 {
1047   (void)netifapi_call_argcb(lwip_ifconfig_dhcp_addr_clients_check_fn, (void *)ifconfig_cmd);
1048   return ifconfig_cmd->result;
1049 }
1050 #endif
1051 
1052 LWIP_STATIC u32_t
lwip_ifconfig_prase_args(int * argc,const char ** argv,int * idx,struct ifconfig_option * ifconfig_cmd)1053 lwip_ifconfig_prase_args(int *argc, const char **argv, int *idx,
1054                          struct ifconfig_option *ifconfig_cmd)
1055 {
1056   u32_t ret = lwip_ifconfig_prase_inet(argc, argv, idx, ifconfig_cmd);
1057   if (ret != 0) {
1058     return ret;
1059   }
1060 
1061   ret = lwip_ifconfig_prase_additional(argc, argv, idx, ifconfig_cmd);
1062   if (ret != 0) {
1063     return ret;
1064   }
1065 
1066 #if LWIP_DHCP && LWIP_DHCP_SUBSTITUTE
1067   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V4_VAL((ifconfig_cmd->ip_addr))) {
1068     if (lwip_ifconfig_dhcp_addr_clients_check(ifconfig_cmd) == lwIP_TRUE) {
1069       PRINT_ERRCODE(API_SHELL_ERRCODE_IP_CONFLICT);
1070       return EINVAL;
1071     }
1072   }
1073 #endif
1074 
1075 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1076   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V4_VAL((ifconfig_cmd->ip_addr))) {
1077     /* Create the semaphore for ip conflict detection. */
1078     if (sys_sem_new(&ip_conflict_detect, 0) != ERR_OK) {
1079       PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
1080       return EINVAL;
1081     }
1082     is_ip_conflict_signal = 1;
1083   }
1084 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1085 
1086 #if LWIP_IPV6
1087   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V6_VAL((ifconfig_cmd->ip_addr))) {
1088     /* Create the semaphore for duplicate address detection. */
1089     if (sys_sem_new(&dup_addr_detect, 0) != ERR_OK) {
1090       PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
1091       return EINVAL;
1092     }
1093     is_dup_detect_initialized = 1;
1094   }
1095 #endif /* LWIP_IPV6 */
1096   return OS_OK;
1097 }
1098 
1099 LWIP_STATIC void
lwip_ifconfig_conflict_res_free(struct ifconfig_option * ifconfig_cmd)1100 lwip_ifconfig_conflict_res_free(struct ifconfig_option *ifconfig_cmd)
1101 {
1102 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1103     if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V4_VAL((ifconfig_cmd->ip_addr))) {
1104       is_ip_conflict_signal = 0;
1105       sys_sem_free(&ip_conflict_detect);
1106     }
1107 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1108 
1109 #if LWIP_IPV6
1110     if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V6_VAL((ifconfig_cmd->ip_addr))) {
1111       is_dup_detect_initialized = 0;
1112       sys_sem_free(&dup_addr_detect);
1113     }
1114 #endif /* LWIP_IPV6 */
1115 }
1116 
1117 LWIP_STATIC u32_t
lwip_ifconfig_conflict_process(struct ifconfig_option * ifconfig_cmd)1118 lwip_ifconfig_conflict_process(struct ifconfig_option *ifconfig_cmd)
1119 {
1120 #if LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL
1121   u32_t err;
1122   /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */
1123   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V4_VAL((ifconfig_cmd->ip_addr))) {
1124     err = sys_arch_sem_wait(&ip_conflict_detect, DUP_ARP_DETECT_TIME);
1125     is_ip_conflict_signal = 0;
1126     sys_sem_free(&ip_conflict_detect);
1127     if (err == SYS_ARCH_ERROR) {
1128       /* The result neither conflict nor timeout. */
1129       PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
1130       return OS_NOK;
1131     }
1132     if (err != SYS_ARCH_TIMEOUT) {
1133       /* Duplicate use of new ip, restore it to the old one. */
1134       PRINT_ERRCODE(API_SHELL_ERRCODE_IP_CONFLICT);
1135       ip_addr_set_ip4_u32_val(ifconfig_cmd->ip_addr, g_old_ip4addr);
1136       ip_addr_set_ip4_u32_val(ifconfig_cmd->netmask, g_old_ip4mask);
1137       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_NETMASK;
1138       ip_addr_set_ip4_u32_val(ifconfig_cmd->gw, g_old_ip4gw);
1139       ifconfig_cmd->option |= IFCONFIG_OPTION_SET_GW;
1140       if (sys_sem_new(&ifconfig_cmd->cb_completed, 0) != ERR_OK) {
1141         PRINT_ERRCODE(API_SHELL_ERRCODE_SEM_ERR);
1142         return OS_NOK;
1143       }
1144       if (tcpip_callback(lwip_ifconfig_internal, ifconfig_cmd) != ERR_OK) {
1145         PRINT_ERRCODE(API_SHELL_ERRCODE_SERVICE_FAILURE);
1146         return OS_NOK;
1147       }
1148       (void)sys_arch_sem_wait(&ifconfig_cmd->cb_completed, 0);
1149       ifconfig_cmd->cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1150 #ifndef CUSTOM_AT_COMMAND
1151       LWIP_PLATFORM_PRINT("%s", ifconfig_cmd->cb_print_buf);
1152 #endif
1153       return OS_NOK;
1154     }
1155   }
1156 #endif /* LWIP_ARP && LWIP_ENABLE_IP_CONFLICT_SIGNAL */
1157 #if LWIP_IPV6
1158   if (((ifconfig_cmd->option & IFCONFIG_OPTION_SET_IP) != 0) && IP_IS_V6_VAL(ifconfig_cmd->ip_addr)) {
1159     /* Pend 2 seconds for waiting the arp reply if the ip is already in use. */
1160     u32_t retval = sys_arch_sem_wait(&dup_addr_detect, DUP_ARP_DETECT_TIME);
1161     is_dup_detect_initialized = 0;
1162     sys_sem_free(&dup_addr_detect);
1163 
1164     if (retval == SYS_ARCH_ERROR) {
1165       /* The result neither conflict nor timeout. */
1166       PRINT_ERRCODE(API_SHELL_ERRCODE_SERVICE_FAILURE);
1167       return OS_NOK;
1168     }
1169     if (retval != SYS_ARCH_TIMEOUT) {
1170       /* Duplicate use of new ip, restore it to the old one. */
1171       struct netif *netif = NULL;
1172       PRINT_ERRCODE(API_SHELL_ERRCODE_IP_CONFLICT);
1173       netif = netif_find(ifconfig_cmd->iface);
1174       s8_t i = netif_get_ip6_addr_match(netif, &ifconfig_cmd->ip_addr.u_addr.ip6);
1175       if (i >= 0) {
1176         netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
1177       }
1178 
1179       ifconfig_cmd->cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
1180 #ifndef CUSTOM_AT_COMMAND
1181       LWIP_PLATFORM_PRINT("%s", ifconfig_cmd->cb_print_buf);
1182 #endif
1183       return OS_NOK;
1184     }
1185   }
1186 #endif /* LWIP_IPV6 */
1187 
1188   return OS_OK;
1189 }
1190 
1191 LWIP_STATIC u32_t
lwip_ifconfig_basic(int * argc,const char ** argv,int * idx,struct ifconfig_option * ifconfig_cmd)1192 lwip_ifconfig_basic(int *argc, const char **argv, int *idx,
1193                     struct ifconfig_option *ifconfig_cmd)
1194 {
1195   /* Get the interface */
1196   if (*argc > 0) {
1197     if (strlen(argv[*idx]) < NETIF_NAMESIZE) {
1198       (void)strncpy_s(ifconfig_cmd->iface, NETIF_NAMESIZE, argv[*idx], (strlen(argv[*idx])));
1199       ifconfig_cmd->iface[NETIF_NAMESIZE - 1] = '\0';
1200     } else {
1201       sys_sem_free(&ifconfig_cmd->cb_completed);
1202       PRINT_ERRCODE(API_SHELL_ERRCODE_INVALID);
1203       return 1;
1204     }
1205     (*idx)++;
1206     (*argc)--;
1207   }
1208 
1209   if (*argc == 0) {
1210     return lwip_ifconfig_print_all(ifconfig_cmd);
1211   }
1212 
1213   /* ifup/ifdown */
1214   if (strcmp("up", argv[*idx]) == 0) {
1215     ifconfig_cmd->option |= IFCONFIG_OPTION_SET_UP;
1216   } else if (strcmp("down", argv[*idx]) == 0) {
1217     ifconfig_cmd->option |= IFCONFIG_OPTION_SET_DOWN;
1218   }
1219 
1220   if ((ifconfig_cmd->option & (IFCONFIG_OPTION_SET_UP | IFCONFIG_OPTION_SET_DOWN)) != 0) {
1221     return lwip_ifconfig_up_down(ifconfig_cmd);
1222   }
1223 
1224   /* not a basic process, continue next process */
1225   return (u32_t)(-1);
1226 }
1227 
1228 u32_t
lwip_ifconfig(int argc,const char ** argv)1229 lwip_ifconfig(int argc, const char **argv)
1230 {
1231   int i;
1232   u32_t ret;
1233   if (argv == NULL) {
1234     return OS_NOK;
1235   }
1236 
1237   if (!tcpip_init_finish) {
1238     PRINT_ERRCODE(API_SHELL_ERRCODE_TCPIP_UNINTED);
1239     return OS_NOK;
1240   }
1241 
1242 #ifndef CUSTOM_AT_COMMAND
1243   if (argc != 0 && strcmp("-a", argv[0]) == 0) {
1244     return lwip_ifconfig_all(argc, argv);
1245   }
1246 #endif
1247 
1248   struct ifconfig_option *ifconfig_cmd = mem_malloc(sizeof(struct ifconfig_option));
1249   if (ifconfig_cmd == NULL) {
1250     PRINT_ERRCODE(API_SHELL_ERRCODE_MEM_ERR);
1251     return OS_NOK;
1252   }
1253   (void)memset_s(ifconfig_cmd, sizeof(struct ifconfig_option), 0, sizeof(struct ifconfig_option));
1254   if (sys_sem_new(&ifconfig_cmd->cb_completed, 0) != ERR_OK) {
1255     PRINT_ERRCODE(API_SHELL_ERRCODE_SEM_ERR);
1256     ret = OS_NOK;
1257     goto ifconfig_free_and_return;
1258   }
1259 
1260   i = 0;
1261   ret = lwip_ifconfig_basic(&argc, argv, &i, ifconfig_cmd);
1262   if (ret != (u32_t)(-1)) {
1263     goto ifconfig_free_and_return;
1264   }
1265 
1266   ret = lwip_ifconfig_prase_args(&argc, argv, &i, ifconfig_cmd);
1267   if (ret != 0) {
1268 #ifndef CUSTOM_AT_COMMAND
1269     if (ret != EINVAL) {
1270       lwip_ifconfig_usage("ifconfig");
1271     }
1272 #endif
1273     sys_sem_free(&ifconfig_cmd->cb_completed);
1274     ret = OS_NOK;
1275     goto ifconfig_free_and_return;
1276   }
1277 
1278   ret = lwip_ifconfig_callback(lwip_ifconfig_internal, ifconfig_cmd);
1279   if (ret != 0) {
1280     lwip_ifconfig_conflict_res_free(ifconfig_cmd);
1281     PRINT_ERRCODE(API_SHELL_ERRCODE_SERVICE_FAILURE);
1282     goto ifconfig_free_and_return;
1283   }
1284 #ifndef CUSTOM_AT_COMMAND
1285   LWIP_PLATFORM_PRINT("%s", ifconfig_cmd->cb_print_buf);
1286 #endif
1287 
1288   ret = lwip_ifconfig_conflict_process(ifconfig_cmd);
1289 #ifdef CUSTOM_AT_COMMAND
1290   if (ret == OS_OK) {
1291     (void)uapi_at_printf("OK"CRLF);
1292   }
1293 #endif
1294 
1295 ifconfig_free_and_return:
1296   mem_free(ifconfig_cmd);
1297   return ret;
1298 }
1299 
1300 u32_t
os_shell_netif(int argc,const char ** argv)1301 os_shell_netif(int argc, const char **argv)
1302 {
1303   struct netif *netif = NULL;
1304   if (argv == NULL) {
1305     return OS_NOK;
1306   }
1307   if (argc < 1) {
1308     LWIP_PLATFORM_PRINT("netif_default wlan0"CRLF);
1309     return OS_NOK;
1310   }
1311 
1312   netif = netif_find(argv[0]);
1313   if (netif == NULL) {
1314     LWIP_PLATFORM_PRINT("not find %s"CRLF, argv[0]);
1315     return OS_NOK;
1316   }
1317 
1318   (void)netifapi_netif_set_default(netif);
1319   return OS_OK;
1320 }
1321 
1322 #endif /* LWIP_ENABLE_BASIC_SHELL_CMD */
1323