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