1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2010-07-07     Bernard      fix send mail to mailbox issue.
9  * 2011-07-30     mbbill       port lwIP 1.4.0 to RT-Thread
10  * 2012-04-10     Bernard      add more compatible with RT-Thread.
11  * 2012-11-12     Bernard      The network interface can be initialized
12  *                             after lwIP initialization.
13  * 2013-02-28     aozima       fixed list_tcps bug: ipaddr_ntoa isn't reentrant.
14  * 2016-08-18     Bernard      port to lwIP 2.0.0
15  * 2018-11-02     MurphyZhao   port to lwIP 2.1.0
16  * 2021-09-07     Grissiom     fix eth_tx_msg ack bug
17  * 2022-02-22     xiangxistu   integrate v1.4.1 v2.0.3 and v2.1.2 porting layer
18  * 2024-09-12     Evlers       add support for independent dns services for multiple network devices
19  */
20 
21 /*
22  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms, with or without modification,
26  * are permitted provided that the following conditions are met:
27  *
28  * 1. Redistributions of source code must retain the above copyright notice,
29  *    this list of conditions and the following disclaimer.
30  * 2. Redistributions in binary form must reproduce the above copyright notice,
31  *    this list of conditions and the following disclaimer in the documentation
32  *    and/or other materials provided with the distribution.
33  * 3. The name of the author may not be used to endorse or promote products
34  *    derived from this software without specific prior written permission.
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
39  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
41  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
44  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
45  * OF SUCH DAMAGE.
46  *
47  * This file is part of the lwIP TCP/IP stack.
48  *
49  * Author: Adam Dunkels <adam@sics.se>
50  */
51 
52 #include <string.h>
53 
54 #include <lwip/init.h>
55 #include <lwip/opt.h>
56 #include <lwip/debug.h>
57 #include <lwip/def.h>
58 #include <lwip/mem.h>
59 #include <lwip/pbuf.h>
60 #include <lwip/sys.h>
61 #include <lwip/netif.h>
62 #include <lwip/stats.h>
63 #include <lwip/tcpip.h>
64 #include <lwip/dhcp.h>
65 #include <lwip/netifapi.h>
66 #include <lwip/inet.h>
67 #include <netif/etharp.h>
68 #include <netif/ethernetif.h>
69 
70 #include <ipc/completion.h>
71 
72 #if LWIP_IPV6
73 #include "lwip/ethip6.h"
74 #endif /* LWIP_IPV6 */
75 
76 #if LWIP_NETIF_HOSTNAME
77 #define LWIP_HOSTNAME_LEN 16
78 #endif
79 
80 #define netifapi_netif_set_link_up(n)      netifapi_netif_common(n, netif_set_link_up, NULL)
81 #define netifapi_netif_set_link_down(n)    netifapi_netif_common(n, netif_set_link_down, NULL)
82 
83 #ifndef RT_LWIP_ETHTHREAD_PRIORITY
84 #define RT_ETHERNETIF_THREAD_PREORITY   0x90
85 #else
86 #define RT_ETHERNETIF_THREAD_PREORITY   RT_LWIP_ETHTHREAD_PRIORITY
87 #endif
88 
89 #ifndef LWIP_NO_TX_THREAD
90 /**
91  * Tx message structure for Ethernet interface
92  */
93 struct eth_tx_msg
94 {
95     struct netif    *netif;
96     struct pbuf     *buf;
97     struct rt_completion ack;
98 };
99 
100 static struct rt_mailbox eth_tx_thread_mb;
101 static struct rt_thread eth_tx_thread;
102 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE
103 static char eth_tx_thread_mb_pool[32 * sizeof(rt_ubase_t)];
104 static char eth_tx_thread_stack[512];
105 #else
106 static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)];
107 static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];
108 #endif
109 #endif
110 
111 #ifndef LWIP_NO_RX_THREAD
112 static struct rt_mailbox eth_rx_thread_mb;
113 static struct rt_thread eth_rx_thread;
114 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE
115 static char eth_rx_thread_mb_pool[48 * sizeof(rt_ubase_t)];
116 static char eth_rx_thread_stack[1024];
117 #else
118 static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)];
119 static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];
120 #endif
121 #endif
122 
123 #ifdef RT_USING_NETDEV
124 
125 #include "lwip/ip.h"
126 #include "lwip/init.h"
127 #include "lwip/netdb.h"
128 #include <netdev.h>
129 
lwip_netdev_set_up(struct netdev * netif)130 static int lwip_netdev_set_up(struct netdev *netif)
131 {
132     netif_set_up((struct netif *)netif->user_data);
133     return ERR_OK;
134 }
135 
lwip_netdev_set_down(struct netdev * netif)136 static int lwip_netdev_set_down(struct netdev *netif)
137 {
138     netif_set_down((struct netif *)netif->user_data);
139     return ERR_OK;
140 }
141 
142 #ifndef ip_2_ip4
143 #define ip_2_ip4(ipaddr) (ipaddr)
144 #endif
lwip_netdev_set_addr_info(struct netdev * netif,ip_addr_t * ip_addr,ip_addr_t * netmask,ip_addr_t * gw)145 static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw)
146 {
147     if (ip_addr && netmask && gw)
148     {
149         netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
150     }
151     else
152     {
153         if (ip_addr)
154         {
155             netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr));
156         }
157 
158         if (netmask)
159         {
160             netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask));
161         }
162 
163         if (gw)
164         {
165             netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw));
166         }
167     }
168 
169     return ERR_OK;
170 }
171 
172 #ifdef RT_LWIP_DNS
lwip_netdev_set_dns_server(struct netdev * netdev,uint8_t dns_num,ip_addr_t * dns_server)173 static int lwip_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
174 {
175 #if RT_USING_LWIP_VER_NUM >= 0x20102
176     netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
177 #else
178 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
179     extern void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
180 #else /* >=2.x */
181     extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server);
182 #endif /* LWIP_VERSION_MAJOR == 1U */
183 
184     dns_setserver(dns_num, dns_server);
185 #endif /* RT_USING_LWIP_VER_NUM >= 0x20102 */
186     return ERR_OK;
187 }
188 #endif /* RT_LWIP_DNS */
189 
190 #ifdef RT_LWIP_DHCP
lwip_netdev_set_dhcp(struct netdev * netif,rt_bool_t is_enabled)191 static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled)
192 {
193     netdev_low_level_set_dhcp_status(netif, is_enabled);
194 
195     if(RT_TRUE == is_enabled)
196     {
197         dhcp_start((struct netif *)netif->user_data);
198     }
199     else
200     {
201         dhcp_stop((struct netif *)netif->user_data);
202     }
203 
204     return ERR_OK;
205 }
206 #endif /* RT_LWIP_DHCP */
207 
208 #ifdef RT_USING_FINSH
209 #ifdef RT_LWIP_USING_PING
210 extern int lwip_ping_recv(int s, int *ttl);
211 extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size);
212 
lwip_netdev_ping(struct netdev * netif,const char * host,size_t data_len,uint32_t timeout,struct netdev_ping_resp * ping_resp,rt_bool_t isbind)213 int lwip_netdev_ping(struct netdev *netif, const char *host, size_t data_len,
214                         uint32_t timeout, struct netdev_ping_resp *ping_resp, rt_bool_t isbind)
215 {
216     int s, ttl, recv_len, result = 0;
217     int elapsed_time;
218     rt_tick_t recv_start_tick;
219 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
220     int recv_timeout = timeout;
221 #else /* >= v2.x */
222     struct timeval recv_timeout = { timeout / 1000UL, timeout % 1000UL * 1000 };
223 #endif
224     ip_addr_t target_addr;
225     struct addrinfo hint, *res = RT_NULL;
226     struct sockaddr_in *h = RT_NULL;
227     struct in_addr ina;
228     struct sockaddr_in local;
229 
230     RT_ASSERT(netif);
231     RT_ASSERT(host);
232     RT_ASSERT(ping_resp);
233 
234     rt_memset(&hint, 0x00, sizeof(hint));
235     /* convert URL to IP */
236     if (lwip_getaddrinfo(host, RT_NULL, &hint, &res) != 0)
237     {
238         return -RT_ERROR;
239     }
240     SMEMCPY(&h, &res->ai_addr, sizeof(struct sockaddr_in *));
241     SMEMCPY(&ina, &h->sin_addr, sizeof(ina));
242     lwip_freeaddrinfo(res);
243     if (inet_aton(inet_ntoa(ina), &target_addr) == 0)
244     {
245         return -RT_ERROR;
246     }
247     SMEMCPY(&(ping_resp->ip_addr), &target_addr, sizeof(ip_addr_t));
248 
249     /* new a socket */
250     if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
251     {
252         return -RT_ERROR;
253     }
254 
255     local.sin_len = sizeof(local);
256     local.sin_family = AF_INET;
257     local.sin_port = 0;
258 #ifndef NETDEV_USING_IPV6
259     local.sin_addr.s_addr = (netif->ip_addr.addr);
260 #else
261     local.sin_addr.s_addr = (netif->ip_addr.u_addr.ip4.addr);
262 #endif
263     if (isbind) {
264         lwip_bind(s, (struct sockaddr *)&local, sizeof(struct sockaddr_in));
265     }
266 
267     lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout));
268 
269     if (lwip_ping_send(s, &target_addr, data_len) == ERR_OK)
270     {
271         recv_start_tick = rt_tick_get();
272         if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0)
273         {
274             elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND;
275             ping_resp->data_len = recv_len;
276             ping_resp->ttl = ttl;
277             ping_resp->ticks = elapsed_time;
278         }
279         else
280         {
281             result = -RT_ETIMEOUT;
282             goto __exit;
283         }
284     }
285     else
286     {
287         result = -RT_ETIMEOUT;
288         goto __exit;
289     }
290 
291 __exit:
292     lwip_close(s);
293 
294     return result;
295 }
296 #endif /* RT_LWIP_USING_PING */
297 
298 #if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP)
lwip_netdev_netstat(struct netdev * netif)299 void lwip_netdev_netstat(struct netdev *netif)
300 {
301     extern void list_tcps(void);
302     extern void list_udps(void);
303 
304 #ifdef RT_LWIP_TCP
305     list_tcps();
306 #endif
307 #ifdef RT_LWIP_UDP
308     list_udps();
309 #endif
310 }
311 #endif /* RT_LWIP_TCP || RT_LWIP_UDP */
312 #endif /* RT_USING_FINSH */
313 
lwip_netdev_set_default(struct netdev * netif)314 static int lwip_netdev_set_default(struct netdev *netif)
315 {
316     netif_set_default((struct netif *)netif->user_data);
317     return ERR_OK;
318 }
319 
320 const struct netdev_ops lwip_netdev_ops =
321 {
322     lwip_netdev_set_up,
323     lwip_netdev_set_down,
324 
325     lwip_netdev_set_addr_info,
326 #ifdef RT_LWIP_DNS
327     lwip_netdev_set_dns_server,
328 #else
329     NULL,
330 #endif /* RT_LWIP_DNS */
331 
332 #ifdef RT_LWIP_DHCP
333     lwip_netdev_set_dhcp,
334 #else
335     NULL,
336 #endif /* RT_LWIP_DHCP */
337 
338 #ifdef RT_USING_FINSH
339 #ifdef RT_LWIP_USING_PING
340     lwip_netdev_ping,
341 #else
342     NULL,
343 #endif /* RT_LWIP_USING_PING */
344 
345 #if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP)
346     lwip_netdev_netstat,
347 #endif /* RT_LWIP_TCP || RT_LWIP_UDP */
348 #endif /* RT_USING_FINSH */
349 
350     lwip_netdev_set_default,
351 };
352 
353 /* synchronize lwIP network interface device and network interface device flags */
netdev_flags_sync(struct netif * lwip_netif)354 static int netdev_flags_sync(struct netif *lwip_netif)
355 {
356     struct netdev *netdev = NULL;
357 
358     RT_ASSERT(lwip_netif);
359 
360     netdev = netdev_get_by_name(lwip_netif->name);
361     if (netdev == RT_NULL)
362     {
363         return -ERR_IF;
364     }
365 
366     netdev->mtu = lwip_netif->mtu;
367 
368     /* the macro definition is different from lwip-1.4.1 and lwip-2.x.x about 'flags'. */
369     if(lwip_netif->flags & NETIF_FLAG_BROADCAST)
370     {
371         netdev->flags |= NETDEV_FLAG_BROADCAST;
372     }
373     if(lwip_netif->flags & NETIF_FLAG_ETHARP)
374     {
375         netdev->flags |= NETDEV_FLAG_ETHARP;
376     }
377     if(lwip_netif->flags & NETIF_FLAG_IGMP)
378     {
379         netdev->flags |= NETDEV_FLAG_IGMP;
380     }
381 #if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
382     if(lwip_netif->flags & NETIF_FLAG_MLD6)
383     {
384         netdev->flags |= NETDEV_FLAG_MLD6;
385     }
386 #endif /* LWIP_VERSION_MAJOR >= 2U */
387 
388 #if LWIP_DHCP
389     netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
390 #else
391     netdev_low_level_set_dhcp_status(netdev, RT_FALSE);
392 #endif
393 
394     return ERR_OK;
395 }
396 
netdev_add(struct netif * lwip_netif)397 static int netdev_add(struct netif *lwip_netif)
398 {
399     int result = 0;
400     struct netdev *netdev = RT_NULL;
401     char name[NETIF_NAMESIZE] = {0};
402 
403     RT_ASSERT(lwip_netif);
404 
405     netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev));
406     if (netdev == RT_NULL)
407     {
408         return -ERR_IF;
409     }
410 
411 #ifdef SAL_USING_LWIP
412     extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev);
413     /* set the lwIP network interface device protocol family information */
414     sal_lwip_netdev_set_pf_info(netdev);
415 #endif /* SAL_USING_LWIP */
416 
417     rt_strncpy(name, lwip_netif->name, NETIF_NAMESIZE);
418     result = netdev_register(netdev, name, (void *)lwip_netif);
419 
420     /* Update netdev info after registered */
421     netdev_flags_sync(lwip_netif);
422     netdev->ops = &lwip_netdev_ops;
423     netdev->hwaddr_len =  lwip_netif->hwaddr_len;
424     SMEMCPY(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
425     netdev->ip_addr = lwip_netif->ip_addr;
426     netdev->gw = lwip_netif->gw;
427     netdev->netmask = lwip_netif->netmask;
428 
429 #ifdef NETDEV_USING_LINK_STATUS_CALLBACK
430     extern void netdev_status_change(struct netdev *netdev, enum netdev_cb_type type);
431     netdev_set_status_callback(netdev, netdev_status_change);
432 #endif
433 
434     return result;
435 }
436 
netdev_del(struct netif * lwip_netif)437 static void netdev_del(struct netif *lwip_netif)
438 {
439     char name[NETIF_NAMESIZE];
440     struct netdev *netdev;
441 
442     RT_ASSERT(lwip_netif);
443 
444     rt_strncpy(name, lwip_netif->name, NETIF_NAMESIZE);
445     netdev = netdev_get_by_name(name);
446     netdev_unregister(netdev);
447     rt_free(netdev);
448 }
449 #endif /* RT_USING_NETDEV */
450 
ethernetif_linkoutput(struct netif * netif,struct pbuf * p)451 static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
452 {
453 #ifndef LWIP_NO_TX_THREAD
454     struct eth_tx_msg msg;
455 
456     RT_ASSERT(netif != RT_NULL);
457 
458     /* send a message to eth tx thread */
459     msg.netif = netif;
460     msg.buf   = p;
461     rt_completion_init(&msg.ack);
462     if (rt_mb_send(&eth_tx_thread_mb, (rt_ubase_t) &msg) == RT_EOK)
463     {
464         /* waiting for ack */
465         rt_completion_wait(&msg.ack, RT_WAITING_FOREVER);
466     }
467 #else
468     struct eth_device* enetif;
469 
470     RT_ASSERT(netif != RT_NULL);
471     enetif = (struct eth_device*)netif->state;
472 
473     if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK)
474     {
475         return ERR_IF;
476     }
477 #endif
478     return ERR_OK;
479 }
480 
eth_netif_device_init(struct netif * netif)481 static err_t eth_netif_device_init(struct netif *netif)
482 {
483     struct eth_device *ethif;
484 
485     ethif = (struct eth_device*)netif->state;
486     if (ethif != RT_NULL)
487     {
488         rt_device_t device;
489 
490 #ifdef RT_USING_NETDEV
491         /* network interface device register */
492         netdev_add(netif);
493 #endif /* RT_USING_NETDEV */
494 
495         /* get device object */
496         device = (rt_device_t) ethif;
497         if (rt_device_init(device) != RT_EOK)
498         {
499             return ERR_IF;
500         }
501         if (rt_device_open(device, RT_DEVICE_FLAG_RDWR) != RT_EOK)
502         {
503             return ERR_IF;
504         }
505 
506         /* copy device flags to netif flags */
507         netif->flags = (ethif->flags & 0xff);
508         netif->mtu = ETHERNET_MTU;
509 
510         /* set output */
511         netif->output       = etharp_output;
512 
513 #if LWIP_IPV6
514         netif->output_ip6 = ethip6_output;
515         netif->ip6_autoconfig_enabled = 1;
516         netif_create_ip6_linklocal_address(netif, 1);
517 
518 #if LWIP_IPV6_MLD
519         netif->flags |= NETIF_FLAG_MLD6;
520 
521         /*
522         * For hardware/netifs that implement MAC filtering.
523         * All-nodes link-local is handled by default, so we must let the hardware know
524         * to allow multicast packets in.
525         * Should set mld_mac_filter previously. */
526         if (netif->mld_mac_filter != NULL)
527         {
528             ip6_addr_t ip6_allnodes_ll;
529             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
530             netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
531         }
532 #endif /* LWIP_IPV6_MLD */
533 
534 #endif /* LWIP_IPV6 */
535 
536         /* set default netif */
537         if (netif_default == RT_NULL)
538             netif_set_default(netif);
539 
540         /* set interface up */
541         netif_set_up(netif);
542 
543 #if LWIP_DHCP
544         /* if this interface uses DHCP, start the DHCP client */
545         dhcp_start(netif);
546 #endif
547 
548         if (ethif->flags & ETHIF_LINK_PHYUP)
549         {
550             /* set link_up for this netif */
551             netif_set_link_up(netif);
552         }
553 
554 #ifdef RT_USING_NETDEV
555         /* network interface device flags synchronize */
556         netdev_flags_sync(netif);
557 #endif /* RT_USING_NETDEV */
558 
559         return ERR_OK;
560     }
561 
562     return ERR_IF;
563 }
564 
565 /* Keep old drivers compatible in RT-Thread */
eth_device_init_with_flag(struct eth_device * dev,const char * name,rt_uint16_t flags)566 rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flags)
567 {
568     struct netif* netif;
569 #if LWIP_NETIF_HOSTNAME
570     char *hostname = RT_NULL;
571     netif = (struct netif*) rt_calloc (1, sizeof(struct netif) + LWIP_HOSTNAME_LEN);
572 #else
573     netif = (struct netif*) rt_calloc (1, sizeof(struct netif));
574 #endif
575     if (netif == RT_NULL)
576     {
577         rt_kprintf("malloc netif failed\n");
578         return -RT_ERROR;
579     }
580 
581     rt_spin_lock_init(&(dev->spinlock));
582     /* set netif */
583     dev->netif = netif;
584     dev->flags = flags;
585     /* link changed status of device */
586     dev->link_changed = 0x00;
587     /* avoid send the same mail to mailbox */
588     dev->rx_notice = 0x00;
589     dev->parent.type = RT_Device_Class_NetIf;
590     /* register to RT-Thread device manager */
591     rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR);
592 
593     /* set name */
594     rt_strncpy(netif->name, name, NETIF_NAMESIZE);
595 
596     /* set hw address to 6 */
597     netif->hwaddr_len   = 6;
598     /* maximum transfer unit */
599     netif->mtu          = ETHERNET_MTU;
600 
601     /* set linkoutput */
602     netif->linkoutput   = ethernetif_linkoutput;
603 
604     /* get hardware MAC address */
605     rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr);
606 
607 #if LWIP_NETIF_HOSTNAME
608     /* Initialize interface hostname */
609     hostname = (char *)netif + sizeof(struct netif);
610     rt_sprintf(hostname, "rtthread_%02x%02x", name[0], name[1]);
611     netif->hostname = hostname;
612 #endif /* LWIP_NETIF_HOSTNAME */
613 
614     /* if tcp thread has been started up, we add this netif to the system */
615     if (rt_thread_find("tcpip") != RT_NULL)
616     {
617 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
618         struct ip_addr ipaddr, netmask, gw;
619 #else /* >= v2.x */
620         ip4_addr_t ipaddr, netmask, gw;
621 #endif /* LWIP_VERSION_MAJOR == 1U */
622 
623 #if !LWIP_DHCP
624         ipaddr.addr = inet_addr(RT_LWIP_IPADDR);
625         gw.addr = inet_addr(RT_LWIP_GWADDR);
626         netmask.addr = inet_addr(RT_LWIP_MSKADDR);
627 #else
628         IP4_ADDR(&ipaddr, 0, 0, 0, 0);
629         IP4_ADDR(&gw, 0, 0, 0, 0);
630         IP4_ADDR(&netmask, 0, 0, 0, 0);
631 #endif
632         netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input);
633     }
634 
635     return RT_EOK;
636 }
637 
eth_device_init(struct eth_device * dev,const char * name)638 rt_err_t eth_device_init(struct eth_device * dev, const char *name)
639 {
640     rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
641 
642 #if LWIP_IGMP
643     /* IGMP support */
644     flags |= NETIF_FLAG_IGMP;
645 #endif
646 
647     return eth_device_init_with_flag(dev, name, flags);
648 }
649 
eth_device_deinit(struct eth_device * dev)650 void eth_device_deinit(struct eth_device *dev)
651 {
652     struct netif* netif = dev->netif;
653 
654 #if LWIP_DHCP
655     dhcp_stop(netif);
656     dhcp_cleanup(netif);
657 #endif
658     netif_set_down(netif);
659     netif_remove(netif);
660 #ifdef RT_USING_NETDEV
661     netdev_del(netif);
662 #endif
663     rt_device_close(&(dev->parent));
664     rt_device_unregister(&(dev->parent));
665     rt_free(netif);
666 }
667 
668 #ifdef SAL_USING_AF_UNIX /* create loopback netdev */
af_unix_eth_netif_device_init(struct netif * netif)669 static err_t af_unix_eth_netif_device_init(struct netif *netif)
670 {
671     struct eth_device *ethif;
672 
673     ethif = (struct eth_device*)netif->state;
674     if (ethif != RT_NULL)
675     {
676         rt_device_t device;
677 
678 #ifdef RT_USING_NETDEV
679         /* network interface device register */
680         netdev_add(netif);
681 #endif /* RT_USING_NETDEV */
682 
683         /* get device object */
684         device = (rt_device_t) ethif;
685         if (rt_device_init(device) != RT_EOK)
686         {
687             return ERR_IF;
688         }
689         if (rt_device_open(device, RT_DEVICE_FLAG_RDWR) != RT_EOK)
690         {
691             return ERR_IF;
692         }
693 
694         /* copy device flags to netif flags */
695         netif->flags = (ethif->flags & 0xff);
696         netif->mtu = ETHERNET_MTU;
697 
698         /* set output */
699         netif->output       = etharp_output;
700 
701 #if LWIP_IPV6
702         netif->output_ip6 = ethip6_output;
703         netif->ip6_autoconfig_enabled = 1;
704         netif_create_ip6_linklocal_address(netif, 1);
705 
706 #if LWIP_IPV6_MLD
707         netif->flags |= NETIF_FLAG_MLD6;
708 
709         /*
710         * For hardware/netifs that implement MAC filtering.
711         * All-nodes link-local is handled by default, so we must let the hardware know
712         * to allow multicast packets in.
713         * Should set mld_mac_filter previously. */
714         if (netif->mld_mac_filter != NULL)
715         {
716             ip6_addr_t ip6_allnodes_ll;
717             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
718             netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
719         }
720 #endif /* LWIP_IPV6_MLD */
721 
722 #endif /* LWIP_IPV6 */
723 
724         /* set default netif */
725         if (netif_default == RT_NULL)
726             netif_set_default(netif);
727 
728         /* set interface up */
729         netif_set_up(netif);
730 
731         if (ethif->flags & ETHIF_LINK_PHYUP)
732         {
733             /* set link_up for this netif */
734             netif_set_link_up(netif);
735         }
736 
737 #ifdef RT_USING_NETDEV
738         /* network interface device flags synchronize */
739         netdev_flags_sync(netif);
740 #endif /* RT_USING_NETDEV */
741 
742         return ERR_OK;
743     }
744 
745     return ERR_IF;
746 }
747 
748 /* Keep old drivers compatible in RT-Thread */
af_unix_eth_device_init_with_flag(struct eth_device * dev,const char * name,rt_uint16_t flags)749 rt_err_t af_unix_eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flags)
750 {
751     struct netif* netif;
752 #if LWIP_NETIF_HOSTNAME
753     char *hostname = RT_NULL;
754     netif = (struct netif*) rt_calloc (1, sizeof(struct netif) + LWIP_HOSTNAME_LEN);
755 #else
756     netif = (struct netif*) rt_calloc (1, sizeof(struct netif));
757 #endif
758     if (netif == RT_NULL)
759     {
760         rt_kprintf("malloc netif failed\n");
761         return -RT_ERROR;
762     }
763 
764     /* set netif */
765     dev->netif = netif;
766     dev->flags = flags;
767     /* link changed status of device */
768     dev->link_changed = 0x00;
769     /* avoid send the same mail to mailbox */
770     dev->rx_notice = 0x00;
771     dev->parent.type = RT_Device_Class_NetIf;
772     /* register to RT-Thread device manager */
773     rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR);
774 
775     /* set name */
776     netif->name[0] = name[0];
777     netif->name[1] = name[1];
778 
779     /* set hw address to 6 */
780     netif->hwaddr_len   = 6;
781     /* maximum transfer unit */
782     netif->mtu          = ETHERNET_MTU;
783 
784     /* set linkoutput */
785     netif->linkoutput   = ethernetif_linkoutput;
786 
787     /* get hardware MAC address */
788     rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr);
789 
790 #if LWIP_NETIF_HOSTNAME
791     /* Initialize interface hostname */
792     hostname = (char *)netif + sizeof(struct netif);
793     rt_sprintf(hostname, "rtthread_%02x%02x", name[0], name[1]);
794     netif->hostname = hostname;
795 #endif /* LWIP_NETIF_HOSTNAME */
796 
797     /* if tcp thread has been started up, we add this netif to the system */
798     if (rt_thread_find("tcpip") != RT_NULL)
799     {
800 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
801         struct ip_addr ipaddr, netmask, gw;
802 #else /* >= v2.x */
803         ip4_addr_t ipaddr, netmask, gw;
804 #endif /* LWIP_VERSION_MAJOR == 1U */
805 
806         ipaddr.addr = inet_addr("127.0.0.1");
807         gw.addr = inet_addr("255.0.0.0");
808         netmask.addr = inet_addr("127.0.0.1");
809 
810         netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, af_unix_eth_netif_device_init, tcpip_input);
811     }
812 
813     return RT_EOK;
814 }
815 
af_unix_eth_device_init(struct eth_device * dev,const char * name)816 rt_err_t af_unix_eth_device_init(struct eth_device * dev, const char *name)
817 {
818     rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
819 
820 #if LWIP_IGMP
821     /* IGMP support */
822     flags |= NETIF_FLAG_IGMP;
823 #endif
824 
825     return af_unix_eth_device_init_with_flag(dev, name, flags);
826 }
827 #endif /* SAL_USING_AF_UNIX */
828 
829 #ifndef LWIP_NO_RX_THREAD
eth_device_ready(struct eth_device * dev)830 rt_err_t eth_device_ready(struct eth_device* dev)
831 {
832     if (dev->netif)
833     {
834         if(dev->rx_notice == RT_FALSE)
835         {
836             dev->rx_notice = RT_TRUE;
837             return rt_mb_send(&eth_rx_thread_mb, (rt_ubase_t)dev);
838         }
839         else
840             return RT_EOK;
841         /* post message to Ethernet thread */
842     }
843     else
844         return -RT_ERROR; /* netif is not initialized yet, just return. */
845 }
846 
eth_device_linkchange(struct eth_device * dev,rt_bool_t up)847 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up)
848 {
849     rt_base_t level;
850 
851     RT_ASSERT(dev != RT_NULL);
852 
853     level = rt_spin_lock_irqsave(&(dev->spinlock));
854     dev->link_changed = 0x01;
855     if (up == RT_TRUE)
856         dev->link_status = 0x01;
857     else
858         dev->link_status = 0x00;
859     rt_spin_unlock_irqrestore(&(dev->spinlock), level);
860 
861     /* post message to ethernet thread */
862     return rt_mb_send(&eth_rx_thread_mb, (rt_ubase_t)dev);
863 }
864 #else
865 /* NOTE: please not use it in interrupt when no RxThread exist */
eth_device_linkchange(struct eth_device * dev,rt_bool_t up)866 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up)
867 {
868     if (up == RT_TRUE)
869         netifapi_netif_set_link_up(dev->netif);
870     else
871         netifapi_netif_set_link_down(dev->netif);
872 
873     return RT_EOK;
874 }
875 #endif
876 
877 #ifndef LWIP_NO_TX_THREAD
878 /* Ethernet Tx Thread */
eth_tx_thread_entry(void * parameter)879 static void eth_tx_thread_entry(void* parameter)
880 {
881     struct eth_tx_msg* msg;
882 
883     while (1)
884     {
885         if (rt_mb_recv(&eth_tx_thread_mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK)
886         {
887             struct eth_device* enetif;
888 
889             RT_ASSERT(msg->netif != RT_NULL);
890             RT_ASSERT(msg->buf   != RT_NULL);
891 
892             enetif = (struct eth_device*)msg->netif->state;
893             if (enetif != RT_NULL)
894             {
895                 /* call driver's interface */
896                 if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)
897                 {
898                     /* transmit eth packet failed */
899                 }
900             }
901 
902             /* send ACK */
903             rt_completion_done(&msg->ack);
904         }
905     }
906 }
907 #endif
908 
909 #ifndef LWIP_NO_RX_THREAD
910 /* Ethernet Rx Thread */
eth_rx_thread_entry(void * parameter)911 static void eth_rx_thread_entry(void* parameter)
912 {
913     struct eth_device* device;
914 
915     while (1)
916     {
917         if (rt_mb_recv(&eth_rx_thread_mb, (rt_ubase_t *)&device, RT_WAITING_FOREVER) == RT_EOK)
918         {
919             rt_base_t level;
920             struct pbuf *p;
921 
922             /* check link status */
923             if (device->link_changed)
924             {
925                 int status;
926 
927                 level = rt_spin_lock_irqsave(&(device->spinlock));
928                 status = device->link_status;
929                 device->link_changed = 0x00;
930                 rt_spin_unlock_irqrestore(&(device->spinlock), level);
931 
932                 if (status)
933                     netifapi_netif_set_link_up(device->netif);
934                 else
935                     netifapi_netif_set_link_down(device->netif);
936             }
937 
938             level = rt_spin_lock_irqsave(&(device->spinlock));
939             /* 'rx_notice' will be modify in the interrupt or here */
940             device->rx_notice = RT_FALSE;
941             rt_spin_unlock_irqrestore(&(device->spinlock), level);
942 
943             /* receive all of buffer */
944             while (1)
945             {
946                 if(device->eth_rx == RT_NULL) break;
947 
948                 p = device->eth_rx(&(device->parent));
949                 if (p != RT_NULL)
950                 {
951                     /* notify to upper layer */
952                     if( device->netif->input(p, device->netif) != ERR_OK )
953                     {
954                         LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n"));
955                         pbuf_free(p);
956                         p = NULL;
957                     }
958                 }
959                 else break;
960             }
961         }
962         else
963         {
964             LWIP_ASSERT("Should not happen!\n",0);
965         }
966     }
967 }
968 #endif
969 
970 /* this function does not need,
971  * use eth_system_device_init_private()
972  * call by lwip_system_init().
973  */
eth_system_device_init(void)974 int eth_system_device_init(void)
975 {
976     return 0;
977 }
978 
eth_system_device_init_private(void)979 int eth_system_device_init_private(void)
980 {
981     rt_err_t result = RT_EOK;
982 
983     /* initialize Rx thread. */
984 #ifndef LWIP_NO_RX_THREAD
985     /* initialize mailbox and create Ethernet Rx thread */
986     result = rt_mb_init(&eth_rx_thread_mb, "erxmb",
987                         &eth_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/sizeof(rt_ubase_t),
988                         RT_IPC_FLAG_FIFO);
989     RT_ASSERT(result == RT_EOK);
990 
991     result = rt_thread_init(&eth_rx_thread, "erx", eth_rx_thread_entry, RT_NULL,
992                             &eth_rx_thread_stack[0], sizeof(eth_rx_thread_stack),
993                             RT_ETHERNETIF_THREAD_PREORITY, 16);
994     RT_ASSERT(result == RT_EOK);
995     result = rt_thread_startup(&eth_rx_thread);
996     RT_ASSERT(result == RT_EOK);
997 #endif
998 
999     /* initialize Tx thread */
1000 #ifndef LWIP_NO_TX_THREAD
1001     /* initialize mailbox and create Ethernet Tx thread */
1002     result = rt_mb_init(&eth_tx_thread_mb, "etxmb",
1003                         &eth_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/sizeof(rt_ubase_t),
1004                         RT_IPC_FLAG_FIFO);
1005     RT_ASSERT(result == RT_EOK);
1006 
1007     result = rt_thread_init(&eth_tx_thread, "etx", eth_tx_thread_entry, RT_NULL,
1008                             &eth_tx_thread_stack[0], sizeof(eth_tx_thread_stack),
1009                             RT_ETHERNETIF_THREAD_PREORITY, 16);
1010     RT_ASSERT(result == RT_EOK);
1011 
1012     result = rt_thread_startup(&eth_tx_thread);
1013     RT_ASSERT(result == RT_EOK);
1014 #endif
1015 
1016     return (int)result;
1017 }
1018 
set_if(char * netif_name,char * ip_addr,char * gw_addr,char * nm_addr)1019 void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr)
1020 {
1021 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
1022     struct ip_addr *ip;
1023     struct ip_addr addr;
1024 #else /* >= v2.x */
1025     ip4_addr_t *ip;
1026     ip4_addr_t addr;
1027 #endif /* LWIP_VERSION_MAJOR == 1U */
1028 
1029     struct netif * netif = netif_list;
1030 
1031     if(strlen(netif_name) > sizeof(netif->name))
1032     {
1033         rt_kprintf("network interface name too long!\r\n");
1034         return;
1035     }
1036 
1037     while(netif != RT_NULL)
1038     {
1039         if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
1040             break;
1041 
1042         netif = netif->next;
1043         if( netif == RT_NULL )
1044         {
1045             rt_kprintf("network interface: %s not found!\r\n", netif_name);
1046             return;
1047         }
1048     }
1049 
1050 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
1051     ip = (struct ip_addr *)&addr;
1052 #else /* >= v2.x */
1053     ip = (ip4_addr_t *)&addr;
1054 #endif /* LWIP_VERSION_MAJOR == 1U */
1055 
1056 
1057     /* set ip address */
1058     if ((ip_addr != RT_NULL) && inet_aton(ip_addr, &addr))
1059     {
1060         netif_set_ipaddr(netif, ip);
1061     }
1062 
1063     /* set gateway address */
1064     if ((gw_addr != RT_NULL) && inet_aton(gw_addr, &addr))
1065     {
1066         netif_set_gw(netif, ip);
1067     }
1068 
1069     /* set netmask address */
1070     if ((nm_addr != RT_NULL) && inet_aton(nm_addr, &addr))
1071     {
1072         netif_set_netmask(netif, ip);
1073     }
1074 }
1075 
1076 #ifdef RT_USING_FINSH
1077 #include <finsh.h>
1078 FINSH_FUNCTION_EXPORT(set_if, set network interface address);
1079 
1080 #if LWIP_DNS
1081 #include <lwip/dns.h>
set_dns(uint8_t dns_num,char * dns_server)1082 void set_dns(uint8_t dns_num, char* dns_server)
1083 {
1084     ip_addr_t addr;
1085 
1086     if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr))
1087     {
1088         dns_setserver(dns_num, &addr);
1089     }
1090 }
1091 FINSH_FUNCTION_EXPORT(set_dns, set DNS server address);
1092 #endif
1093 
list_if(void)1094 void list_if(void)
1095 {
1096     rt_uint8_t index;
1097     struct netif * netif;
1098 
1099     rt_enter_critical();
1100 
1101     netif = netif_list;
1102 
1103     while( netif != RT_NULL )
1104     {
1105         rt_kprintf("network interface: %c%c%s\n",
1106                    netif->name[0],
1107                    netif->name[1],
1108                    (netif == netif_default)?" (Default)":"");
1109         rt_kprintf("MTU: %d\n", netif->mtu);
1110         rt_kprintf("MAC: ");
1111         for (index = 0; index < netif->hwaddr_len; index ++)
1112             rt_kprintf("%02x ", netif->hwaddr[index]);
1113         rt_kprintf("\nFLAGS:");
1114         if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP");
1115         else rt_kprintf(" DOWN");
1116         if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP");
1117         else rt_kprintf(" LINK_DOWN");
1118         if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP");
1119         if (netif->flags & NETIF_FLAG_BROADCAST) rt_kprintf(" BROADCAST");
1120         if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP");
1121         rt_kprintf("\n");
1122         rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr)));
1123         rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw)));
1124         rt_kprintf("net mask  : %s\n", ipaddr_ntoa(&(netif->netmask)));
1125 #if LWIP_IPV6
1126         {
1127             ip6_addr_t *addr;
1128             int addr_state;
1129             int i;
1130 
1131             addr = (ip6_addr_t *)&netif->ip6_addr[0];
1132             addr_state = netif->ip6_addr_state[0];
1133 
1134             rt_kprintf("\nipv6 link-local: %s state:%02X %s\n", ip6addr_ntoa(addr),
1135             addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID");
1136 
1137             for(i=1; i<LWIP_IPV6_NUM_ADDRESSES; i++)
1138             {
1139                 addr = (ip6_addr_t *)&netif->ip6_addr[i];
1140                 addr_state = netif->ip6_addr_state[i];
1141 
1142                 rt_kprintf("ipv6[%d] address: %s state:%02X %s\n", i, ip6addr_ntoa(addr),
1143                 addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID");
1144             }
1145 
1146         }
1147         rt_kprintf("\r\n");
1148 #endif /* LWIP_IPV6 */
1149         netif = netif->next;
1150     }
1151 
1152 #if LWIP_DNS
1153     {
1154 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
1155         struct ip_addr ip_addr;
1156 
1157         for(index=0; index<DNS_MAX_SERVERS; index++)
1158         {
1159             ip_addr = dns_getserver(index);
1160             rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(&(ip_addr)));
1161         }
1162 #else /* >= v2.x */
1163         const ip_addr_t *ip_addr;
1164 
1165         for(index=0; index<DNS_MAX_SERVERS; index++)
1166         {
1167             ip_addr = dns_getserver(index);
1168             rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(ip_addr));
1169         }
1170 #endif /* LWIP_VERSION_MAJOR == 1U */
1171 
1172     }
1173 #endif /**< #if LWIP_DNS */
1174 
1175     rt_exit_critical();
1176 }
1177 FINSH_FUNCTION_EXPORT(list_if, list network interface information);
1178 
1179 #if LWIP_TCP
1180 #include <lwip/tcp.h>
1181 #if LWIP_VERSION_MAJOR == 1U /* v1.x */
1182 #include <lwip/tcp_impl.h>
1183 #else /* >= v2.x */
1184 #include <lwip/priv/tcp_priv.h>
1185 #endif /* LWIP_VERSION_MAJOR == 1U */
1186 
list_tcps(void)1187 void list_tcps(void)
1188 {
1189     rt_uint32_t num = 0;
1190     struct tcp_pcb *pcb;
1191     char local_ip_str[16];
1192     char remote_ip_str[16];
1193 
1194     extern struct tcp_pcb *tcp_active_pcbs;
1195     extern union tcp_listen_pcbs_t tcp_listen_pcbs;
1196     extern struct tcp_pcb *tcp_tw_pcbs;
1197 
1198     rt_enter_critical();
1199     rt_kprintf("Active PCB states:\n");
1200     for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next)
1201     {
1202         strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip)));
1203         strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip)));
1204 
1205         rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ",
1206                    num++,
1207                    local_ip_str,
1208                    pcb->local_port,
1209                    remote_ip_str,
1210                    pcb->remote_port,
1211                    pcb->snd_nxt,
1212                    pcb->rcv_nxt);
1213         rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state));
1214     }
1215 
1216     rt_kprintf("Listen PCB states:\n");
1217     num = 0;
1218     for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next)
1219     {
1220         rt_kprintf("#%d local port %d ", num++, pcb->local_port);
1221         rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state));
1222     }
1223 
1224     rt_kprintf("TIME-WAIT PCB states:\n");
1225     num = 0;
1226     for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next)
1227     {
1228         strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip)));
1229         strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip)));
1230 
1231         rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ",
1232                    num++,
1233                    local_ip_str,
1234                    pcb->local_port,
1235                    remote_ip_str,
1236                    pcb->remote_port,
1237                    pcb->snd_nxt,
1238                    pcb->rcv_nxt);
1239         rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state));
1240     }
1241     rt_exit_critical();
1242 }
1243 FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections);
1244 #endif /* LWIP_TCP */
1245 
1246 #if LWIP_UDP
1247 #include "lwip/udp.h"
list_udps(void)1248 void list_udps(void)
1249 {
1250     struct udp_pcb *pcb;
1251     rt_uint32_t num = 0;
1252     char local_ip_str[16];
1253     char remote_ip_str[16];
1254 
1255     rt_enter_critical();
1256     rt_kprintf("Active UDP PCB states:\n");
1257     for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next)
1258     {
1259         strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip)));
1260         strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip)));
1261 
1262         rt_kprintf("#%d %d %s:%d <==> %s:%d \n",
1263                    num, (int)pcb->flags,
1264                    local_ip_str,
1265                    pcb->local_port,
1266                    remote_ip_str,
1267                    pcb->remote_port);
1268 
1269         num++;
1270     }
1271     rt_exit_critical();
1272 }
1273 FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections);
1274 #endif /* LWIP_UDP */
1275 
1276 #endif
1277