1 /* 2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 3 * COPYRIGHT (C) 2006-2018, RT-Thread Development Team 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 26 * OF SUCH DAMAGE. 27 * 28 * This file is part of the lwIP TCP/IP stack. 29 * 30 * Author: Adam Dunkels <[email protected]> 31 * 32 * Change Logs: 33 * Date Author Notes 34 * 2010-07-07 Bernard fix send mail to mailbox issue. 35 * 2011-07-30 mbbill port lwIP 1.4.0 to RT-Thread 36 * 2012-04-10 Bernard add more compatible with RT-Thread. 37 * 2012-11-12 Bernard The network interface can be initialized 38 * after lwIP initialization. 39 * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. 40 * 2016-08-18 Bernard port to lwIP 2.0.0 41 * 2018-11-02 MurphyZhao port to lwIP 2.1.0 42 */ 43 44 #include "lwip/opt.h" 45 46 #include "lwip/opt.h" 47 #include "lwip/debug.h" 48 #include "lwip/def.h" 49 #include "lwip/mem.h" 50 #include "lwip/pbuf.h" 51 #include "lwip/sys.h" 52 #include "lwip/netif.h" 53 #include "lwip/stats.h" 54 #include "lwip/tcpip.h" 55 #include "lwip/dhcp.h" 56 #include "lwip/netifapi.h" 57 58 #include "netif/etharp.h" 59 #include "netif/ethernetif.h" 60 61 #include "lwip/inet.h" 62 63 #if LWIP_IPV6 64 #include "lwip/ethip6.h" 65 #endif /* LWIP_IPV6 */ 66 67 #define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) 68 #define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) 69 70 #ifndef RT_LWIP_ETHTHREAD_PRIORITY 71 #define RT_ETHERNETIF_THREAD_PREORITY 0x90 72 #else 73 #define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY 74 #endif 75 76 #ifndef LWIP_NO_TX_THREAD 77 /** 78 * Tx message structure for Ethernet interface 79 */ 80 struct eth_tx_msg 81 { 82 struct netif *netif; 83 struct pbuf *buf; 84 }; 85 86 static struct rt_mailbox eth_tx_thread_mb; 87 static struct rt_thread eth_tx_thread; 88 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE 89 static char eth_tx_thread_mb_pool[32 * 4]; 90 static char eth_tx_thread_stack[512]; 91 #else 92 static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; 93 static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; 94 #endif 95 #endif 96 97 #ifndef LWIP_NO_RX_THREAD 98 static struct rt_mailbox eth_rx_thread_mb; 99 static struct rt_thread eth_rx_thread; 100 #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE 101 static char eth_rx_thread_mb_pool[48 * 4]; 102 static char eth_rx_thread_stack[1024]; 103 #else 104 static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; 105 static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; 106 #endif 107 #endif 108 109 static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) 110 { 111 #ifndef LWIP_NO_TX_THREAD 112 struct eth_tx_msg msg; 113 struct eth_device* enetif; 114 115 RT_ASSERT(netif != RT_NULL); 116 enetif = (struct eth_device*)netif->state; 117 118 /* send a message to eth tx thread */ 119 msg.netif = netif; 120 msg.buf = p; 121 if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK) 122 { 123 /* waiting for ack */ 124 rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); 125 } 126 #else 127 struct eth_device* enetif; 128 129 RT_ASSERT(netif != RT_NULL); 130 enetif = (struct eth_device*)netif->state; 131 132 if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK) 133 { 134 return ERR_IF; 135 } 136 #endif 137 return ERR_OK; 138 } 139 140 static err_t eth_netif_device_init(struct netif *netif) 141 { 142 struct eth_device *ethif; 143 144 ethif = (struct eth_device*)netif->state; 145 if (ethif != RT_NULL) 146 { 147 rt_device_t device; 148 149 /* get device object */ 150 device = (rt_device_t) ethif; 151 if (rt_device_init(device) != RT_EOK) 152 { 153 return ERR_IF; 154 } 155 156 /* copy device flags to netif flags */ 157 netif->flags = (ethif->flags & 0xff); 158 netif->mtu = ETHERNET_MTU; 159 160 #if LWIP_IPV6 161 netif->output_ip6 = ethip6_output; 162 netif->ip6_autoconfig_enabled = 1; 163 netif_create_ip6_linklocal_address(netif, 1); 164 165 #if LWIP_IPV6_MLD 166 netif->flags |= NETIF_FLAG_MLD6; 167 168 /* 169 * For hardware/netifs that implement MAC filtering. 170 * All-nodes link-local is handled by default, so we must let the hardware know 171 * to allow multicast packets in. 172 * Should set mld_mac_filter previously. */ 173 if (netif->mld_mac_filter != NULL) 174 { 175 ip6_addr_t ip6_allnodes_ll; 176 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); 177 netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); 178 } 179 #endif /* LWIP_IPV6_MLD */ 180 181 #endif /* LWIP_IPV6 */ 182 183 /* set default netif */ 184 if (netif_default == RT_NULL) 185 netif_set_default(ethif->netif); 186 187 #if LWIP_DHCP 188 /* set interface up */ 189 netif_set_up(ethif->netif); 190 /* if this interface uses DHCP, start the DHCP client */ 191 dhcp_start(ethif->netif); 192 #else 193 /* set interface up */ 194 netif_set_up(ethif->netif); 195 #endif 196 197 if (ethif->flags & ETHIF_LINK_PHYUP) 198 { 199 /* set link_up for this netif */ 200 netif_set_link_up(ethif->netif); 201 } 202 203 return ERR_OK; 204 } 205 206 return ERR_IF; 207 } 208 209 /* Keep old drivers compatible in RT-Thread */ 210 rt_err_t eth_device_init_with_flag(struct eth_device *dev, char *name, rt_uint16_t flags) 211 { 212 struct netif* netif; 213 214 netif = (struct netif*) rt_malloc (sizeof(struct netif)); 215 if (netif == RT_NULL) 216 { 217 rt_kprintf("malloc netif failed\n"); 218 return -RT_ERROR; 219 } 220 rt_memset(netif, 0, sizeof(struct netif)); 221 222 /* set netif */ 223 dev->netif = netif; 224 /* device flags, which will be set to netif flags when initializing */ 225 dev->flags = flags; 226 /* link changed status of device */ 227 dev->link_changed = 0x00; 228 dev->parent.type = RT_Device_Class_NetIf; 229 /* register to RT-Thread device manager */ 230 rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR); 231 rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO); 232 233 /* set name */ 234 netif->name[0] = name[0]; 235 netif->name[1] = name[1]; 236 237 /* set hw address to 6 */ 238 netif->hwaddr_len = 6; 239 /* maximum transfer unit */ 240 netif->mtu = ETHERNET_MTU; 241 242 /* get hardware MAC address */ 243 rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr); 244 245 #if LWIP_NETIF_HOSTNAME 246 /* Initialize interface hostname */ 247 netif->hostname = "rtthread"; 248 #endif /* LWIP_NETIF_HOSTNAME */ 249 250 /* if tcp thread has been started up, we add this netif to the system */ 251 if (rt_thread_find("tcpip") != RT_NULL) 252 { 253 ip4_addr_t ipaddr, netmask, gw; 254 255 #if !LWIP_DHCP 256 ipaddr.addr = inet_addr(RT_LWIP_IPADDR); 257 gw.addr = inet_addr(RT_LWIP_GWADDR); 258 netmask.addr = inet_addr(RT_LWIP_MSKADDR); 259 #else 260 IP4_ADDR(&ipaddr, 0, 0, 0, 0); 261 IP4_ADDR(&gw, 0, 0, 0, 0); 262 IP4_ADDR(&netmask, 0, 0, 0, 0); 263 #endif 264 netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input); 265 266 /* set output */ 267 netif->output = etharp_output; 268 netif->linkoutput = ethernetif_linkoutput; 269 } 270 271 return RT_EOK; 272 } 273 274 rt_err_t eth_device_init(struct eth_device * dev, char *name) 275 { 276 rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; 277 278 #if LWIP_IGMP 279 /* IGMP support */ 280 flags |= NETIF_FLAG_IGMP; 281 #endif 282 283 return eth_device_init_with_flag(dev, name, flags); 284 } 285 286 #ifndef LWIP_NO_RX_THREAD 287 rt_err_t eth_device_ready(struct eth_device* dev) 288 { 289 if (dev->netif) 290 /* post message to Ethernet thread */ 291 return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); 292 else 293 return ERR_OK; /* netif is not initialized yet, just return. */ 294 } 295 296 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) 297 { 298 rt_uint32_t level; 299 300 RT_ASSERT(dev != RT_NULL); 301 302 level = rt_hw_interrupt_disable(); 303 dev->link_changed = 0x01; 304 if (up == RT_TRUE) 305 dev->link_status = 0x01; 306 else 307 dev->link_status = 0x00; 308 rt_hw_interrupt_enable(level); 309 310 /* post message to ethernet thread */ 311 return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); 312 } 313 #else 314 /* NOTE: please not use it in interrupt when no RxThread exist */ 315 rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) 316 { 317 if (up == RT_TRUE) 318 netifapi_netif_set_link_up(dev->netif); 319 else 320 netifapi_netif_set_link_down(dev->netif); 321 322 return RT_EOK; 323 } 324 #endif 325 326 #ifndef LWIP_NO_TX_THREAD 327 /* Ethernet Tx Thread */ 328 static void eth_tx_thread_entry(void* parameter) 329 { 330 struct eth_tx_msg* msg; 331 332 while (1) 333 { 334 if (rt_mb_recv(ð_tx_thread_mb, (rt_uint32_t*)&msg, RT_WAITING_FOREVER) == RT_EOK) 335 { 336 struct eth_device* enetif; 337 338 RT_ASSERT(msg->netif != RT_NULL); 339 RT_ASSERT(msg->buf != RT_NULL); 340 341 enetif = (struct eth_device*)msg->netif->state; 342 if (enetif != RT_NULL) 343 { 344 /* call driver's interface */ 345 if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK) 346 { 347 /* transmit eth packet failed */ 348 } 349 } 350 351 /* send ACK */ 352 rt_sem_release(&(enetif->tx_ack)); 353 } 354 } 355 } 356 #endif 357 358 #ifndef LWIP_NO_RX_THREAD 359 /* Ethernet Rx Thread */ 360 static void eth_rx_thread_entry(void* parameter) 361 { 362 struct eth_device* device; 363 364 while (1) 365 { 366 if (rt_mb_recv(ð_rx_thread_mb, (rt_uint32_t*)&device, RT_WAITING_FOREVER) == RT_EOK) 367 { 368 struct pbuf *p; 369 370 /* check link status */ 371 if (device->link_changed) 372 { 373 int status; 374 rt_uint32_t level; 375 376 level = rt_hw_interrupt_disable(); 377 status = device->link_status; 378 device->link_changed = 0x00; 379 rt_hw_interrupt_enable(level); 380 381 if (status) 382 netifapi_netif_set_link_up(device->netif); 383 else 384 netifapi_netif_set_link_down(device->netif); 385 } 386 387 /* receive all of buffer */ 388 while (1) 389 { 390 if(device->eth_rx == RT_NULL) break; 391 392 p = device->eth_rx(&(device->parent)); 393 if (p != RT_NULL) 394 { 395 /* notify to upper layer */ 396 if( device->netif->input(p, device->netif) != ERR_OK ) 397 { 398 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); 399 pbuf_free(p); 400 p = NULL; 401 } 402 } 403 else break; 404 } 405 } 406 else 407 { 408 LWIP_ASSERT("Should not happen!\n",0); 409 } 410 } 411 } 412 #endif 413 414 /* this function does not need, 415 * use eth_system_device_init_private() 416 * call by lwip_system_init(). 417 */ 418 int eth_system_device_init(void) 419 { 420 return 0; 421 } 422 423 int eth_system_device_init_private(void) 424 { 425 rt_err_t result = RT_EOK; 426 427 /* initialize Rx thread. */ 428 #ifndef LWIP_NO_RX_THREAD 429 /* initialize mailbox and create Ethernet Rx thread */ 430 result = rt_mb_init(ð_rx_thread_mb, "erxmb", 431 ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4, 432 RT_IPC_FLAG_FIFO); 433 RT_ASSERT(result == RT_EOK); 434 435 result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL, 436 ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack), 437 RT_ETHERNETIF_THREAD_PREORITY, 16); 438 RT_ASSERT(result == RT_EOK); 439 result = rt_thread_startup(ð_rx_thread); 440 RT_ASSERT(result == RT_EOK); 441 #endif 442 443 /* initialize Tx thread */ 444 #ifndef LWIP_NO_TX_THREAD 445 /* initialize mailbox and create Ethernet Tx thread */ 446 result = rt_mb_init(ð_tx_thread_mb, "etxmb", 447 ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4, 448 RT_IPC_FLAG_FIFO); 449 RT_ASSERT(result == RT_EOK); 450 451 result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL, 452 ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack), 453 RT_ETHERNETIF_THREAD_PREORITY, 16); 454 RT_ASSERT(result == RT_EOK); 455 456 result = rt_thread_startup(ð_tx_thread); 457 RT_ASSERT(result == RT_EOK); 458 #endif 459 460 return (int)result; 461 } 462 463 #ifdef RT_USING_FINSH 464 #include <finsh.h> 465 void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) 466 { 467 ip4_addr_t *ip; 468 ip4_addr_t addr; 469 struct netif * netif = netif_list; 470 471 if(strlen(netif_name) > sizeof(netif->name)) 472 { 473 rt_kprintf("network interface name too long!\r\n"); 474 return; 475 } 476 477 while(netif != RT_NULL) 478 { 479 if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) 480 break; 481 482 netif = netif->next; 483 if( netif == RT_NULL ) 484 { 485 rt_kprintf("network interface: %s not found!\r\n", netif_name); 486 return; 487 } 488 } 489 490 ip = (ip4_addr_t *)&addr; 491 492 /* set ip address */ 493 if ((ip_addr != RT_NULL) && ip4addr_aton(ip_addr, &addr)) 494 { 495 netif_set_ipaddr(netif, ip); 496 } 497 498 /* set gateway address */ 499 if ((gw_addr != RT_NULL) && ip4addr_aton(gw_addr, &addr)) 500 { 501 netif_set_gw(netif, ip); 502 } 503 504 /* set netmask address */ 505 if ((nm_addr != RT_NULL) && ip4addr_aton(nm_addr, &addr)) 506 { 507 netif_set_netmask(netif, ip); 508 } 509 } 510 FINSH_FUNCTION_EXPORT(set_if, set network interface address); 511 512 #if LWIP_DNS 513 #include <lwip/dns.h> 514 void set_dns(char* dns_server) 515 { 516 ip_addr_t addr; 517 518 if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr)) 519 { 520 dns_setserver(0, &addr); 521 } 522 } 523 FINSH_FUNCTION_EXPORT(set_dns, set DNS server address); 524 #endif 525 526 void list_if(void) 527 { 528 rt_ubase_t index; 529 struct netif * netif; 530 531 rt_enter_critical(); 532 533 netif = netif_list; 534 535 while( netif != RT_NULL ) 536 { 537 rt_kprintf("network interface: %c%c%s\n", 538 netif->name[0], 539 netif->name[1], 540 (netif == netif_default)?" (Default)":""); 541 rt_kprintf("MTU: %d\n", netif->mtu); 542 rt_kprintf("MAC: "); 543 for (index = 0; index < netif->hwaddr_len; index ++) 544 rt_kprintf("%02x ", netif->hwaddr[index]); 545 rt_kprintf("\nFLAGS:"); 546 if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP"); 547 else rt_kprintf(" DOWN"); 548 if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP"); 549 else rt_kprintf(" LINK_DOWN"); 550 if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP"); 551 if (netif->flags & NETIF_FLAG_BROADCAST) rt_kprintf(" BROADCAST"); 552 if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP"); 553 rt_kprintf("\n"); 554 rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr))); 555 rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw))); 556 rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask))); 557 #if LWIP_IPV6 558 { 559 ip6_addr_t *addr; 560 int addr_state; 561 int i; 562 563 addr = (ip6_addr_t *)&netif->ip6_addr[0]; 564 addr_state = netif->ip6_addr_state[0]; 565 566 rt_kprintf("\nipv6 link-local: %s state:%02X %s\n", ip6addr_ntoa(addr), 567 addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); 568 569 for(i=1; i<LWIP_IPV6_NUM_ADDRESSES; i++) 570 { 571 addr = (ip6_addr_t *)&netif->ip6_addr[i]; 572 addr_state = netif->ip6_addr_state[i]; 573 574 rt_kprintf("ipv6[%d] address: %s state:%02X %s\n", i, ip6addr_ntoa(addr), 575 addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); 576 } 577 578 } 579 rt_kprintf("\r\n"); 580 #endif /* LWIP_IPV6 */ 581 netif = netif->next; 582 } 583 584 #if LWIP_DNS 585 { 586 const ip_addr_t *ip_addr; 587 588 for(index=0; index<DNS_MAX_SERVERS; index++) 589 { 590 ip_addr = dns_getserver(index); 591 rt_kprintf("dns server #%d: %s\n", index, ipaddr_ntoa(ip_addr)); 592 } 593 } 594 #endif /**< #if LWIP_DNS */ 595 596 rt_exit_critical(); 597 } 598 FINSH_FUNCTION_EXPORT(list_if, list network interface information); 599 600 #if LWIP_TCP 601 #include <lwip/tcp.h> 602 #include <lwip/priv/tcp_priv.h> 603 604 void list_tcps(void) 605 { 606 rt_uint32_t num = 0; 607 struct tcp_pcb *pcb; 608 char local_ip_str[16]; 609 char remote_ip_str[16]; 610 611 extern struct tcp_pcb *tcp_active_pcbs; 612 extern union tcp_listen_pcbs_t tcp_listen_pcbs; 613 extern struct tcp_pcb *tcp_tw_pcbs; 614 615 rt_enter_critical(); 616 rt_kprintf("Active PCB states:\n"); 617 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) 618 { 619 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 620 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 621 622 rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", 623 num++, 624 local_ip_str, 625 pcb->local_port, 626 remote_ip_str, 627 pcb->remote_port, 628 pcb->snd_nxt, 629 pcb->rcv_nxt); 630 rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); 631 } 632 633 rt_kprintf("Listen PCB states:\n"); 634 num = 0; 635 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) 636 { 637 rt_kprintf("#%d local port %d ", num++, pcb->local_port); 638 rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); 639 } 640 641 rt_kprintf("TIME-WAIT PCB states:\n"); 642 num = 0; 643 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) 644 { 645 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 646 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 647 648 rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", 649 num++, 650 local_ip_str, 651 pcb->local_port, 652 remote_ip_str, 653 pcb->remote_port, 654 pcb->snd_nxt, 655 pcb->rcv_nxt); 656 rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); 657 } 658 rt_exit_critical(); 659 } 660 FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections); 661 #endif /* LWIP_TCP */ 662 663 #if LWIP_UDP 664 #include "lwip/udp.h" 665 void list_udps(void) 666 { 667 struct udp_pcb *pcb; 668 rt_uint32_t num = 0; 669 char local_ip_str[16]; 670 char remote_ip_str[16]; 671 672 rt_enter_critical(); 673 rt_kprintf("Active UDP PCB states:\n"); 674 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) 675 { 676 strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); 677 strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); 678 679 rt_kprintf("#%d %d %s:%d <==> %s:%d \n", 680 num, (int)pcb->flags, 681 local_ip_str, 682 pcb->local_port, 683 remote_ip_str, 684 pcb->remote_port); 685 686 num++; 687 } 688 rt_exit_critical(); 689 } 690 FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections); 691 #endif /* LWIP_UDP */ 692 693 #endif 694