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