Merge pull request #3709 from xiangxistu/master
Add lwIP 2.1.2 for RT-Thread
This commit is contained in:
commit
3408c57d9e
|
@ -118,16 +118,17 @@ config RT_USING_LWIP
|
|||
config RT_USING_LWIP202
|
||||
bool "lwIP v2.0.2"
|
||||
|
||||
config RT_USING_LWIP210
|
||||
bool "lwIP v2.1.0"
|
||||
config RT_USING_LWIP212
|
||||
bool "lwIP v2.1.2"
|
||||
|
||||
endchoice
|
||||
|
||||
if (RT_USING_LWIP210 || RT_USING_LWIP202)
|
||||
if (RT_USING_LWIP202 || RT_USING_LWIP212)
|
||||
config RT_USING_LWIP_IPV6
|
||||
bool "IPV6 protocol"
|
||||
default n
|
||||
select NETDEV_USING_IPV6
|
||||
select NETDEV_IPV6_SCOPES if RT_USING_LWIP210
|
||||
select NETDEV_IPV6_SCOPES if RT_USING_LWIP212
|
||||
endif
|
||||
|
||||
config RT_LWIP_IGMP
|
||||
|
|
|
@ -8,7 +8,7 @@ cwd = GetCurrentDir()
|
|||
list = os.listdir(cwd)
|
||||
|
||||
# the default version of LWIP is 2.0.2
|
||||
if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP210'):
|
||||
if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP212'):
|
||||
AddDepend('RT_USING_LWIP202')
|
||||
|
||||
for d in list:
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
Porting network interface device for RT-Thread in lwIP.
|
||||
The major jobs following RT-Thread Team. The RT-Thread network interface device need to synchronize some network status and address information in lwIP, so it need to make some changes in the lwIP netwrok status and address operations function.
|
||||
The specific changes are as follows:
|
||||
|
||||
- netif.c: add RT-Thread netdev header file , status synchronize(UP, LINK_UP), address synchronize(IP, netmask, gateway);
|
||||
|
||||
- dns.c: add RT-Thread header file, dns servers synchronize;
|
||||
|
||||
- sockets.c: custom 'select' function implementation in RT-Thread by the wait queue mode.
|
||||
|
||||
by ChenYong 2019/3/26 10:00 AM
|
||||
chenyong@rt-thread.com
|
|
@ -1,9 +0,0 @@
|
|||
doxygen/ - Configuration files and scripts to create the lwIP doxygen source
|
||||
documentation (found at http://www.nongnu.org/lwip/)
|
||||
|
||||
savannah.txt - How to obtain the current development source code.
|
||||
contrib.txt - How to contribute to lwIP as a developer.
|
||||
rawapi.txt - The documentation for the core API of lwIP.
|
||||
Also provides an overview about the other APIs and multithreading.
|
||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||
ppp.txt - Documentation of the PPP interface for lwIP.
|
|
@ -1,122 +0,0 @@
|
|||
void
|
||||
eth_mac_irq()
|
||||
{
|
||||
/* Service MAC IRQ here */
|
||||
|
||||
/* Allocate pbuf from pool (avoid using heap in interrupts) */
|
||||
struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL);
|
||||
|
||||
if(p != NULL) {
|
||||
/* Copy ethernet frame into pbuf */
|
||||
pbuf_take(p, eth_data, eth_data_count);
|
||||
|
||||
/* Put in a queue which is processed in main loop */
|
||||
if(!queue_try_put(&queue, p)) {
|
||||
/* queue is full -> packet loss */
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static err_t
|
||||
netif_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
|
||||
}
|
||||
|
||||
lock_interrupts();
|
||||
pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0);
|
||||
/* Start MAC transmit here */
|
||||
unlock_interrupts();
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
netif_status_callback(struct netif *netif)
|
||||
{
|
||||
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
}
|
||||
|
||||
static err_t
|
||||
netif_init(struct netif *netif)
|
||||
{
|
||||
netif->linkoutput = netif_output;
|
||||
netif->output = etharp_output;
|
||||
netif->output_ip6 = ethip6_output;
|
||||
netif->mtu = ETHERNET_MTU;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
|
||||
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
|
||||
SMEMCPY(netif->hwaddr, your_mac_address_goes_here, ETH_HWADDR_LEN);
|
||||
netif->hwaddr_len = ETH_HWADDR_LEN;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
struct netif netif;
|
||||
|
||||
lwip_init();
|
||||
|
||||
netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input);
|
||||
netif.name[0] = 'e';
|
||||
netif.name[1] = '0';
|
||||
netif_create_ip6_linklocal_address(&netif, 1);
|
||||
netif.ip6_autoconfig_enabled = 1;
|
||||
netif_set_status_callback(&netif, netif_status_callback);
|
||||
netif_set_default(&netif);
|
||||
netif_set_up(&netif);
|
||||
|
||||
/* Start DHCP and HTTPD */
|
||||
dhcp_start(&netif );
|
||||
httpd_init();
|
||||
|
||||
while(1) {
|
||||
/* Check link state, e.g. via MDIO communication with PHY */
|
||||
if(link_state_changed()) {
|
||||
if(link_is_up()) {
|
||||
netif_set_link_up(&netif);
|
||||
} else {
|
||||
netif_set_link_down(&netif);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for received frames, feed them to lwIP */
|
||||
lock_interrupts();
|
||||
struct pbuf* p = queue_try_get(&queue);
|
||||
unlock_interrupts();
|
||||
|
||||
if(p != NULL) {
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
|
||||
}
|
||||
|
||||
if(netif.input(p, &netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cyclic lwIP timers check */
|
||||
sys_check_timeouts();
|
||||
|
||||
/* your application goes here */
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
typedef struct my_custom_pbuf
|
||||
{
|
||||
struct pbuf_custom p;
|
||||
void* dma_descriptor;
|
||||
} my_custom_pbuf_t;
|
||||
|
||||
LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool");
|
||||
|
||||
void my_pbuf_free_custom(void* p)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p;
|
||||
|
||||
// invalidate data cache here - lwIP and/or application may have written into buffer!
|
||||
// (invalidate is faster than flushing, and noone needs the correct data in the buffer)
|
||||
invalidate_cpu_cache(p->payload, p->tot_len);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
free_rx_dma_descriptor(my_pbuf->dma_descriptor);
|
||||
LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf);
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
|
||||
void eth_rx_irq()
|
||||
{
|
||||
dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet();
|
||||
my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL);
|
||||
|
||||
my_pbuf->p.custom_free_function = my_pbuf_free_custom;
|
||||
my_pbuf->dma_descriptor = dma_desc;
|
||||
|
||||
invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length);
|
||||
|
||||
struct pbuf* p = pbuf_alloced_custom(PBUF_RAW,
|
||||
dma_desc->rx_length,
|
||||
PBUF_REF,
|
||||
&my_pbuf->p,
|
||||
dma_desc->rx_data,
|
||||
dma_desc->max_buffer_size);
|
||||
|
||||
if(netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
1 Introduction
|
||||
|
||||
This document describes some guidelines for people participating
|
||||
in lwIP development.
|
||||
|
||||
2 How to contribute to lwIP
|
||||
|
||||
Here is a short list of suggestions to anybody working with lwIP and
|
||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||
First of all as you may already know lwIP is a volunteer project so feedback
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
features of Savannah help us not lose users' input.
|
||||
|
||||
2.1 Source code style:
|
||||
|
||||
1. do not use tabs.
|
||||
2. indentation is two spaces per level (i.e. per tab).
|
||||
3. end debug messages with a trailing newline (\n).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
|
||||
10. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
1. JavaDoc compliant and Doxygen compatible.
|
||||
2. Function documentation above functions in .c files, not .h files.
|
||||
(This forces you to synchronize documentation and implementation.)
|
||||
3. Use current documentation style as further reference.
|
||||
|
||||
2.3 Bug reports and patches:
|
||||
|
||||
1. Make sure you are reporting bugs or send patches against the latest
|
||||
sources. (From the latest release and/or the current Git sources.)
|
||||
2. If you think you found a bug make sure it's not already filed in the
|
||||
bugtracker at Savannah.
|
||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
||||
both core and arch specific stuff please separate them so that the core can
|
||||
be applied separately while leaving the other patch 'open'. The preferred way
|
||||
is to NOT touch archs you can't test and let maintainers take care of them.
|
||||
This is a good way to see if they are used at all - the same goes for unix
|
||||
netifs except tapif.
|
||||
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
||||
or a patch will be enough.
|
||||
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
||||
5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other
|
||||
trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you
|
||||
change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than
|
||||
if it's not to the point and long :) so the chances for it to be applied are greater.
|
||||
|
||||
2.4 Platform porters:
|
||||
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for Git access to submit and maintain your port in the contrib Git module.
|
|
@ -1 +0,0 @@
|
|||
doxygen lwip.Doxyfile
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
doxygen lwip.Doxyfile
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,403 +0,0 @@
|
|||
/**
|
||||
* @defgroup lwip lwIP
|
||||
*
|
||||
* @defgroup infrastructure Infrastructure
|
||||
*
|
||||
* @defgroup api APIs
|
||||
* lwIP provides three Application Program's Interfaces (APIs) for programs
|
||||
* to use for communication with the TCP/IP code:
|
||||
* - low-level "core" / "callback" or @ref callbackstyle_api.
|
||||
* - higher-level @ref sequential_api.
|
||||
* - BSD-style @ref socket.
|
||||
*
|
||||
* The raw TCP/IP interface allows the application program to integrate
|
||||
* better with the TCP/IP code. Program execution is event based by
|
||||
* having callback functions being called from within the TCP/IP
|
||||
* code. The TCP/IP code and the application program both run in the same
|
||||
* thread. The sequential API has a much higher overhead and is not very
|
||||
* well suited for small systems since it forces a multithreaded paradigm
|
||||
* on the application.
|
||||
*
|
||||
* The raw TCP/IP interface is not only faster in terms of code execution
|
||||
* time but is also less memory intensive. The drawback is that program
|
||||
* development is somewhat harder and application programs written for
|
||||
* the raw TCP/IP interface are more difficult to understand. Still, this
|
||||
* is the preferred way of writing applications that should be small in
|
||||
* code size and memory usage.
|
||||
*
|
||||
* All APIs can be used simultaneously by different application
|
||||
* programs. In fact, the sequential API is implemented as an application
|
||||
* program using the raw TCP/IP interface.
|
||||
*
|
||||
* Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
|
||||
* The former is a way of interfacing the lwIP network stack (including
|
||||
* TCP and UDP), the latter refers to processing raw Ethernet or IP data
|
||||
* instead of TCP connections or UDP packets.
|
||||
*
|
||||
* Raw API applications may never block since all packet processing
|
||||
* (input and output) as well as timer processing (TCP mainly) is done
|
||||
* in a single execution context.
|
||||
*
|
||||
* @defgroup callbackstyle_api "raw" APIs
|
||||
* @ingroup api
|
||||
* Non thread-safe APIs, callback style for maximum performance and minimum
|
||||
* memory footprint.
|
||||
* Program execution is driven by callbacks functions, which are then
|
||||
* invoked by the lwIP core when activity related to that application
|
||||
* occurs. A particular application may register to be notified via a
|
||||
* callback function for events such as incoming data available, outgoing
|
||||
* data sent, error notifications, poll timer expiration, connection
|
||||
* closed, etc. An application can provide a callback function to perform
|
||||
* processing for any or all of these events. Each callback is an ordinary
|
||||
* C function that is called from within the TCP/IP code. Every callback
|
||||
* function is passed the current TCP or UDP connection state as an
|
||||
* argument. Also, in order to be able to keep program specific state,
|
||||
* the callback functions are called with a program specified argument
|
||||
* that is independent of the TCP/IP state.
|
||||
* The raw API (sometimes called native API) is an event-driven API designed
|
||||
* to be used without an operating system that implements zero-copy send and
|
||||
* receive. This API is also used by the core stack for interaction between
|
||||
* the various protocols. It is the only API available when running lwIP
|
||||
* without an operating system.
|
||||
*
|
||||
* @defgroup sequential_api Sequential-style APIs
|
||||
* @ingroup api
|
||||
* Sequential-style APIs, blocking functions. More overhead, but can be called
|
||||
* from any thread except TCPIP thread.
|
||||
* The sequential API provides a way for ordinary, sequential, programs
|
||||
* to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||
* model of execution is based on the blocking open-read-write-close
|
||||
* paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||
* code and the application program must reside in different execution
|
||||
* contexts (threads).
|
||||
*
|
||||
* @defgroup socket Socket API
|
||||
* @ingroup api
|
||||
* BSD-style socket API.\n
|
||||
* Thread-safe, to be called from non-TCPIP threads only.\n
|
||||
* Can be activated by defining @ref LWIP_SOCKET to 1.\n
|
||||
* Header is in posix/sys/socket.h\n
|
||||
* The socket API is a compatibility API for existing applications,
|
||||
* currently it is built on top of the sequential API. It is meant to
|
||||
* provide all functions needed to run socket API applications running
|
||||
* on other platforms (e.g. unix / windows etc.). However, due to limitations
|
||||
* in the specification of this API, there might be incompatibilities
|
||||
* that require small modifications of existing programs.
|
||||
*
|
||||
* @defgroup netifs NETIFs
|
||||
*
|
||||
* @defgroup apps Applications
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Overview
|
||||
* @verbinclude "README"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page upgrading Upgrading
|
||||
* @verbinclude "UPGRADING"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page changelog Changelog
|
||||
*
|
||||
* 2.1.0
|
||||
* -----
|
||||
* * Support TLS via new @ref altcp_api connection API (https, smtps, mqtt over TLS)
|
||||
* * Switch to cmake as the main build system (Makefile file lists are still
|
||||
* maintained for now)
|
||||
* * Improve IPv6 support: support address scopes, support stateless DHCPv6, bugfixes
|
||||
* * Add debug helper asserts to ensure threading/locking requirements are met
|
||||
* * Add sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
|
||||
* (for FreeRTOS, mainly)
|
||||
* * socket API: support poll(), sendmsg() and recvmsg(); fix problems on close
|
||||
*
|
||||
* Detailed Changelog
|
||||
* ------------------
|
||||
* @verbinclude "CHANGELOG"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page contrib How to contribute to lwIP
|
||||
* @verbinclude "contrib.txt"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page pitfalls Common pitfalls
|
||||
*
|
||||
* Multiple Execution Contexts in lwIP code
|
||||
* ========================================
|
||||
*
|
||||
* The most common source of lwIP problems is to have multiple execution contexts
|
||||
* inside the lwIP code.
|
||||
*
|
||||
* lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
|
||||
* running on target system) or @ref lwip_os (there is an OS running
|
||||
* on the target system).
|
||||
*
|
||||
* See also: @ref multithreading (especially the part about @ref LWIP_ASSERT_CORE_LOCKED()!)
|
||||
*
|
||||
* Mainloop Mode
|
||||
* -------------
|
||||
* In mainloop mode, only @ref callbackstyle_api can be used.
|
||||
* The user has two possibilities to ensure there is only one
|
||||
* exection context at a time in lwIP:
|
||||
*
|
||||
* 1) Deliver RX ethernet packets directly in interrupt context to lwIP
|
||||
* by calling netif->input directly in interrupt. This implies all lwIP
|
||||
* callback functions are called in IRQ context, which may cause further
|
||||
* problems in application code: IRQ is blocked for a long time, multiple
|
||||
* execution contexts in application code etc. When the application wants
|
||||
* to call lwIP, it only needs to disable interrupts during the call.
|
||||
* If timers are involved, even more locking code is needed to lock out
|
||||
* timer IRQ and ethernet IRQ from each other, assuming these may be nested.
|
||||
*
|
||||
* 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
|
||||
* lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
|
||||
* has to put received telegrams into a queue which is polled in the
|
||||
* mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* OS Mode
|
||||
* -------
|
||||
* In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
|
||||
* @ref sequential_api are designed to be called from threads other than
|
||||
* the TCPIP thread, so there is nothing to consider here.
|
||||
* But @ref callbackstyle_api functions must _ONLY_ be called from
|
||||
* TCPIP thread. It is a common error to call these from other threads
|
||||
* or from IRQ contexts. Ethernet RX needs to deliver incoming packets
|
||||
* in the correct way by sending a message to TCPIP thread, this is
|
||||
* implemented in tcpip_input().
|
||||
* Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* 1) tcpip_callback() can be used get called back from TCPIP thread,
|
||||
* it is safe to call any @ref callbackstyle_api from there.
|
||||
*
|
||||
* 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
|
||||
* functions can be called when lwIP core lock is aquired, see
|
||||
* @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
|
||||
* These macros cannot be used in an interrupt context!
|
||||
* Note the OS must correctly handle priority inversion for this.
|
||||
*
|
||||
* Cache / DMA issues
|
||||
* ==================
|
||||
*
|
||||
* DMA-capable ethernet hardware and zero-copy RX
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* lwIP changes the content of RECEIVED pbufs in the TCP code path.
|
||||
* This implies one or more cacheline(s) of the RX pbuf become dirty
|
||||
* and need to be flushed before the memory is handed over to the
|
||||
* DMA ethernet hardware for the next telegram to be received.
|
||||
* See http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html
|
||||
* for a more detailed explanation.
|
||||
* Also keep in mind the user application may also write into pbufs,
|
||||
* so it is generally a bug not to flush the data cache before handing
|
||||
* a buffer to DMA hardware.
|
||||
*
|
||||
* DMA-capable ethernet hardware and cacheline alignment
|
||||
* -----------------------------------------------------
|
||||
* Nice description about DMA capable hardware and buffer handling:
|
||||
* http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/
|
||||
* Read especially sections "Cache coherency" and "Buffer alignment".
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page bugs Reporting bugs
|
||||
* Please report bugs in the lwIP bug tracker at savannah.\n
|
||||
* BEFORE submitting, please check if the bug has already been reported!\n
|
||||
* https://savannah.nongnu.org/bugs/?group=lwip
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page zerocopyrx Zero-copy RX
|
||||
* The following code is an example for zero-copy RX ethernet driver:
|
||||
* @include ZeroCopyRx.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
|
||||
* @ingroup lwip
|
||||
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
|
||||
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
|
||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
||||
* context and put them into a queue which is processed from mainloop.\n
|
||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
||||
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
|
||||
* @ref compiler_abstraction.\n
|
||||
* You can only use @ref callbackstyle_api in this mode.\n
|
||||
* Sample code:\n
|
||||
* @include NO_SYS_SampleCode.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_os OS mode (TCPIP thread)
|
||||
* @ingroup lwip
|
||||
* Use this mode if you run an OS on your system. It is recommended to
|
||||
* use an RTOS that correctly handles priority inversion and
|
||||
* to use @ref LWIP_TCPIP_CORE_LOCKING.\n
|
||||
* Porting: implement all functions in @ref sys_layer.\n
|
||||
* You can use @ref callbackstyle_api together with @ref tcpip_callback,
|
||||
* and all @ref sequential_api.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page sys_init System initalization
|
||||
A truly complete and generic sequence for initializing the lwIP stack
|
||||
cannot be given because it depends on additional initializations for
|
||||
your runtime environment (e.g. timers).
|
||||
|
||||
We can give you some idea on how to proceed when using the raw API.
|
||||
We assume a configuration using a single Ethernet netif and the
|
||||
UDP and TCP transport layers, IPv4 and the DHCP client.
|
||||
|
||||
Call these functions in the order of appearance:
|
||||
|
||||
- lwip_init(): Initialize the lwIP stack and all of its subsystems.
|
||||
|
||||
- netif_add(struct netif *netif, ...):
|
||||
Adds your network interface to the netif_list. Allocate a struct
|
||||
netif and pass a pointer to this structure as the first argument.
|
||||
Give pointers to cleared ip_addr structures when using DHCP,
|
||||
or fill them with sane numbers otherwise. The state pointer may be NULL.
|
||||
|
||||
The init function pointer must point to a initialization function for
|
||||
your Ethernet netif interface. The following code illustrates its use.
|
||||
|
||||
@code{.c}
|
||||
err_t netif_if_init(struct netif *netif)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
|
||||
netif->hwaddr[i] = some_eth_addr[i];
|
||||
}
|
||||
init_my_eth_device();
|
||||
return ERR_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
For Ethernet drivers, the input function pointer must point to the lwIP
|
||||
function ethernet_input() declared in "netif/etharp.h". Other drivers
|
||||
must use ip_input() declared in "lwip/ip.h".
|
||||
|
||||
- netif_set_default(struct netif *netif)
|
||||
Registers the default network interface.
|
||||
|
||||
- netif_set_link_up(struct netif *netif)
|
||||
This is the hardware link state; e.g. whether cable is plugged for wired
|
||||
Ethernet interface. This function must be called even if you don't know
|
||||
the current state. Having link up and link down events is optional but
|
||||
DHCP and IPv6 discover benefit well from those events.
|
||||
|
||||
- netif_set_up(struct netif *netif)
|
||||
This is the administrative (= software) state of the netif, when the
|
||||
netif is fully configured this function must be called.
|
||||
|
||||
- dhcp_start(struct netif *netif)
|
||||
Creates a new DHCP client for this interface on the first call.
|
||||
You can peek in the netif->dhcp struct for the actual DHCP status.
|
||||
|
||||
- sys_check_timeouts()
|
||||
When the system is running, you have to periodically call
|
||||
sys_check_timeouts() which will handle all timers for all protocols in
|
||||
the stack; add this to your main loop or equivalent.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page multithreading Multithreading
|
||||
* lwIP started targeting single-threaded environments. When adding multi-
|
||||
* threading support, instead of making the core thread-safe, another
|
||||
* approach was chosen: there is one main thread running the lwIP core
|
||||
* (also known as the "tcpip_thread"). When running in a multithreaded
|
||||
* environment, raw API functions MUST only be called from the core thread
|
||||
* since raw API functions are not protected from concurrent access (aside
|
||||
* from pbuf- and memory management functions). Application threads using
|
||||
* the sequential- or socket API communicate with this main thread through
|
||||
* message passing.
|
||||
*
|
||||
* As such, the list of functions that may be called from
|
||||
* other threads or an ISR is very limited! Only functions
|
||||
* from these API header files are thread-safe:
|
||||
* - api.h
|
||||
* - netbuf.h
|
||||
* - netdb.h
|
||||
* - netifapi.h
|
||||
* - pppapi.h
|
||||
* - sockets.h
|
||||
* - sys.h
|
||||
*
|
||||
* Additionaly, memory (de-)allocation functions may be
|
||||
* called from multiple threads (not ISR!) with NO_SYS=0
|
||||
* since they are protected by @ref SYS_LIGHTWEIGHT_PROT and/or
|
||||
* semaphores.
|
||||
*
|
||||
* Netconn or Socket API functions are thread safe against the
|
||||
* core thread but they are not reentrant at the control block
|
||||
* granularity level. That is, a UDP or TCP control block must
|
||||
* not be shared among multiple threads without proper locking.
|
||||
*
|
||||
* If @ref SYS_LIGHTWEIGHT_PROT is set to 1 and
|
||||
* @ref LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
|
||||
* pbuf_free() may also be called from another thread or
|
||||
* an ISR (since only then, mem_free - for PBUF_RAM - may
|
||||
* be called from an ISR: otherwise, the HEAP is only
|
||||
* protected by semaphores).
|
||||
*
|
||||
* How to get threading done right
|
||||
* -------------------------------
|
||||
*
|
||||
* It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED()
|
||||
* macro in an application that uses multithreading. lwIP code has
|
||||
* several places where a check for a correct thread context is
|
||||
* implemented which greatly helps the user to get threading done right.
|
||||
* See the example sys_arch.c files in unix and Win32 port
|
||||
* in the contrib repository.
|
||||
*
|
||||
* In short: Copy the functions sys_mark_tcpip_thread() and
|
||||
* sys_check_core_locking() to your port and modify them to work with your OS.
|
||||
* Then let @ref LWIP_ASSERT_CORE_LOCKED() and @ref LWIP_MARK_TCPIP_THREAD()
|
||||
* point to these functions.
|
||||
*
|
||||
* If you use @ref LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt
|
||||
* the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core().
|
||||
* Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point
|
||||
* to these functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page optimization Optimization hints
|
||||
The first thing you want to optimize is the lwip_standard_checksum()
|
||||
routine from src/core/inet.c. You can override this standard
|
||||
function with the \#define LWIP_CHKSUM your_checksum_routine().
|
||||
|
||||
There are C examples given in inet.c or you might want to
|
||||
craft an assembly function for this. RFC1071 is a good
|
||||
introduction to this subject.
|
||||
|
||||
Other significant improvements can be made by supplying
|
||||
assembly or inline replacements for htons() and htonl()
|
||||
if you're using a little-endian architecture.
|
||||
\#define lwip_htons(x) your_htons()
|
||||
\#define lwip_htonl(x) your_htonl()
|
||||
If you \#define them to htons() and htonl(), you should
|
||||
\#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
|
||||
defining htonx / ntohx compatibility macros.
|
||||
|
||||
Check your network interface driver if it reads at
|
||||
a higher speed than the maximum wire-speed. If the
|
||||
hardware isn't serviced frequently and fast enough
|
||||
buffer overflows are likely to occur.
|
||||
|
||||
E.g. when using the cs8900 driver, call cs8900if_service(ethif)
|
||||
as frequently as possible. When using an RTOS let the cs8900 interrupt
|
||||
wake a high priority task that services your driver using a binary
|
||||
semaphore or event flag. Some drivers might allow additional tuning
|
||||
to match your application and network.
|
||||
|
||||
For a production release it is recommended to set LWIP_STATS to 0.
|
||||
Note that speed performance isn't influenced much by simply setting
|
||||
high values to the memory options.
|
||||
*/
|
|
@ -1,10 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Redirection</title>
|
||||
<meta http-equiv="refresh" content="0; url=html/index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<a href="html/index.html">index.html</a>
|
||||
</body>
|
||||
</html>
|
|
@ -1,112 +0,0 @@
|
|||
Multicast DNS for lwIP
|
||||
|
||||
Author: Erik Ekman
|
||||
|
||||
|
||||
Note! The MDNS responder does not have all features required by the standards.
|
||||
See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal
|
||||
cases - but watch out if many devices on the same network try to use the same
|
||||
host/service instance names.
|
||||
|
||||
|
||||
How to enable:
|
||||
==============
|
||||
|
||||
MDNS support does not depend on DNS.
|
||||
MDNS supports using IPv4 only, v6 only, or v4+v6.
|
||||
|
||||
To enable MDNS responder, set
|
||||
LWIP_MDNS_RESPONDER = 1
|
||||
in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build.
|
||||
|
||||
The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
|
||||
default is 1.
|
||||
|
||||
Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB.
|
||||
Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif).
|
||||
|
||||
MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
|
||||
MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
|
||||
generated.
|
||||
|
||||
The MDNS code puts its structs on the stack where suitable to reduce dynamic
|
||||
memory allocation. It may use up to 1kB of stack.
|
||||
|
||||
MDNS (like other apps) needs a strncasecmp() implementation. If you have one, define
|
||||
'lwip_strnicmp' to it. Otherwise the code will provide an implementation
|
||||
for you.
|
||||
|
||||
|
||||
How to use:
|
||||
===========
|
||||
|
||||
Call mdns_resp_init() during system initialization.
|
||||
This opens UDP sockets on port 5353 for IPv4 and IPv6.
|
||||
|
||||
|
||||
To start responding on a netif, run
|
||||
mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
|
||||
|
||||
The hostname will be copied. If this returns successfully, the netif will join
|
||||
the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
|
||||
to port 5353 will be handled:
|
||||
- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
|
||||
- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
|
||||
returns <hostname>.local
|
||||
Answers will use the supplied TTL (in seconds)
|
||||
MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
|
||||
since the default case-insensitive comparison assumes this.
|
||||
|
||||
Call mdns_resp_announce() every time the IP address on the netif has changed.
|
||||
|
||||
Call mdns_resp_restart() every time the network interface comes up after being
|
||||
down, for example cable connected after being disconnected, administrative
|
||||
interface comes up after being down, or the device wakes up from sleep.
|
||||
|
||||
To stop responding on a netif, run
|
||||
mdns_resp_remove_netif(struct netif *netif)
|
||||
|
||||
|
||||
Adding services:
|
||||
================
|
||||
|
||||
The netif first needs to be registered. Then run
|
||||
mdns_resp_add_service(struct netif *netif, char *name, char *service,
|
||||
u16_t proto, u16_t port, u32_t dns_ttl,
|
||||
service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
|
||||
The name and service pointers will be copied. Name refers to the name of the
|
||||
service instance, and service is the type of service, like _http
|
||||
proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
|
||||
If this call returns successfully, the following queries will be answered:
|
||||
- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
|
||||
- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
|
||||
- <name>.<service>.<proto>.local type SRV returns hostname and port of service
|
||||
- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
|
||||
with the supplied userdata. The callback adds strings to the reply by calling
|
||||
mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
|
||||
int txt_len). Example callback method:
|
||||
|
||||
static void srv_txt(struct mdns_service *service, void *txt_userdata)
|
||||
{
|
||||
res = mdns_resp_add_service_txtitem(service, "path=/", 6);
|
||||
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
|
||||
}
|
||||
|
||||
Since a hostname struct is used for TXT storage each single item can be max
|
||||
63 bytes long, and the total max length (including length bytes for each
|
||||
item) is 255 bytes.
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
mdns_resp_add_service(netif, "myweb", "_http"
|
||||
DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
|
||||
|
||||
which will publish myweb._http._tcp.local for any hosts looking for web servers,
|
||||
and point them to <hostname>.local:80
|
||||
|
||||
Relevant information will be sent as additional records to reduce number of
|
||||
requests required from a client.
|
||||
|
||||
To remove a service from a netif, run
|
||||
mdns_resp_del_service(struct netif *netif, s8_t slot)
|
|
@ -1,162 +0,0 @@
|
|||
MQTT client for lwIP
|
||||
|
||||
Author: Erik Andersson
|
||||
|
||||
Details of the MQTT protocol can be found at:
|
||||
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||
|
||||
-----------------------------------------------------------------
|
||||
1. Initial steps, reserve memory and make connection to server:
|
||||
|
||||
1.1: Provide storage
|
||||
|
||||
Static allocation:
|
||||
mqtt_client_t static_client;
|
||||
example_do_connect(&static_client);
|
||||
|
||||
Dynamic allocation:
|
||||
mqtt_client_t *client = mqtt_client_new();
|
||||
if(client != NULL) {
|
||||
example_do_connect(&client);
|
||||
}
|
||||
|
||||
1.2: Establish Connection with server
|
||||
|
||||
void example_do_connect(mqtt_client_t *client)
|
||||
{
|
||||
struct mqtt_connect_client_info_t ci;
|
||||
err_t err;
|
||||
|
||||
/* Setup an empty client info structure */
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
/* Minimal amount of information required is client identifier, so set it here */
|
||||
ci.client_id = "lwip_test";
|
||||
|
||||
/* Initiate client and connect to server, if this fails immediately an error code is returned
|
||||
otherwise mqtt_connection_cb will be called with connection result after attempting
|
||||
to establish a connection with the server.
|
||||
For now MQTT version 3.1.1 is always used */
|
||||
|
||||
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
|
||||
|
||||
/* For now just print the result code if something goes wrong */
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_connect return %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
Connection to server can also be probed by calling mqtt_client_is_connected(client)
|
||||
|
||||
-----------------------------------------------------------------
|
||||
2. Implementing the connection status callback
|
||||
|
||||
|
||||
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
|
||||
{
|
||||
err_t err;
|
||||
if(status == MQTT_CONNECT_ACCEPTED) {
|
||||
printf("mqtt_connection_cb: Successfully connected\n");
|
||||
|
||||
/* Setup callback for incoming publish requests */
|
||||
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
|
||||
|
||||
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
|
||||
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
|
||||
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_subscribe return: %d\n", err);
|
||||
}
|
||||
} else {
|
||||
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
|
||||
|
||||
/* Its more nice to be connected, so try to reconnect */
|
||||
example_do_connect(client);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_sub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
/* Just print the result code here for simplicity,
|
||||
normal behaviour would be to take some action if subscribe fails like
|
||||
notifying user, retry subscribe or disconnect from server */
|
||||
printf("Subscribe result: %d\n", result);
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
3. Implementing callbacks for incoming publish and data
|
||||
|
||||
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
|
||||
Example here uses a global variable, better would be to use a member in arg
|
||||
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
|
||||
the topic string and use it in mqtt_incoming_data_cb
|
||||
*/
|
||||
static int inpub_id;
|
||||
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
|
||||
{
|
||||
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
|
||||
|
||||
/* Decode topic string into a user defined reference */
|
||||
if(strcmp(topic, "print_payload") == 0) {
|
||||
inpub_id = 0;
|
||||
} else if(topic[0] == 'A') {
|
||||
/* All topics starting with 'A' might be handled at the same way */
|
||||
inpub_id = 1;
|
||||
} else {
|
||||
/* For all other topics */
|
||||
inpub_id = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
|
||||
{
|
||||
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
|
||||
|
||||
if(flags & MQTT_DATA_FLAG_LAST) {
|
||||
/* Last fragment of payload received (or whole part if payload fits receive buffer
|
||||
See MQTT_VAR_HEADER_BUFFER_LEN) */
|
||||
|
||||
/* Call function or do action depending on reference, in this case inpub_id */
|
||||
if(inpub_id == 0) {
|
||||
/* Don't trust the publisher, check zero termination */
|
||||
if(data[len-1] == 0) {
|
||||
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
|
||||
}
|
||||
} else if(inpub_id == 1) {
|
||||
/* Call an 'A' function... */
|
||||
} else {
|
||||
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
|
||||
}
|
||||
} else {
|
||||
/* Handle fragmented payload, store in buffer, write to file or whatever */
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
4. Using outgoing publish
|
||||
|
||||
|
||||
void example_publish(mqtt_client_t *client, void *arg)
|
||||
{
|
||||
const char *pub_payload= "PubSubHubLubJub";
|
||||
err_t err;
|
||||
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
|
||||
u8_t retain = 0; /* No don't retain such crappy payload... */
|
||||
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
|
||||
if(err != ERR_OK) {
|
||||
printf("Publish err: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when publish is complete either with sucess or failure */
|
||||
static void mqtt_pub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
if(result != ERR_OK) {
|
||||
printf("Publish result: %d\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
5. Disconnecting
|
||||
|
||||
Simply call mqtt_disconnect(client)
|
|
@ -1,529 +0,0 @@
|
|||
PPP interface for lwIP
|
||||
|
||||
Author: Sylvain Rochet
|
||||
|
||||
Table of Contents:
|
||||
|
||||
1 - Supported PPP protocols and features
|
||||
2 - Raw API PPP example for all protocols
|
||||
3 - PPPoS input path (raw API, IRQ safe API, TCPIP API)
|
||||
4 - Thread safe PPP API (PPPAPI)
|
||||
5 - Notify phase callback (PPP_NOTIFY_PHASE)
|
||||
6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
|
||||
|
||||
|
||||
|
||||
1 Supported PPP protocols and features
|
||||
======================================
|
||||
|
||||
Supported Low level protocols:
|
||||
* PPP over serial using HDLC-like framing, such as wired dialup modems
|
||||
or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems
|
||||
* PPP over Ethernet, such as xDSL modems
|
||||
* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),
|
||||
IP tunnel over UDP, such as VPN access
|
||||
|
||||
Supported auth protocols:
|
||||
* PAP, Password Authentication Protocol
|
||||
* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5
|
||||
* MSCHAPv1, Microsoft version of CHAP, version 1
|
||||
* MSCHAPv2, Microsoft version of CHAP, version 2
|
||||
* EAP, Extensible Authentication Protocol
|
||||
|
||||
Supported address protocols:
|
||||
* IPCP, IP Control Protocol, IPv4 addresses negotiation
|
||||
* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
|
||||
|
||||
Supported encryption protocols:
|
||||
* MPPE, Microsoft Point-to-Point Encryption
|
||||
|
||||
Supported compression or miscellaneous protocols, for serial links only:
|
||||
* PFC, Protocol Field Compression
|
||||
* ACFC, Address-and-Control-Field-Compression
|
||||
* ACCM, Asynchronous-Control-Character-Map
|
||||
* VJ, Van Jacobson TCP/IP Header Compression
|
||||
|
||||
|
||||
|
||||
2 Raw API PPP example for all protocols
|
||||
=======================================
|
||||
|
||||
As usual, raw API for lwIP means the lightweight API which *MUST* only be used
|
||||
for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.
|
||||
|
||||
/*
|
||||
* Globals
|
||||
* =======
|
||||
*/
|
||||
|
||||
/* The PPP control block */
|
||||
ppp_pcb *ppp;
|
||||
|
||||
/* The PPP IP interface */
|
||||
struct netif ppp_netif;
|
||||
|
||||
|
||||
/*
|
||||
* PPP status callback
|
||||
* ===================
|
||||
*
|
||||
* PPP status callback is called on PPP status change (up, down, …) from lwIP
|
||||
* core thread
|
||||
*/
|
||||
|
||||
/* PPP status callback example */
|
||||
static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
|
||||
struct netif *pppif = ppp_netif(pcb);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
|
||||
switch(err_code) {
|
||||
case PPPERR_NONE: {
|
||||
#if LWIP_DNS
|
||||
const ip_addr_t *ns;
|
||||
#endif /* LWIP_DNS */
|
||||
printf("status_cb: Connected\n");
|
||||
#if PPP_IPV4_SUPPORT
|
||||
printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
|
||||
printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));
|
||||
printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
|
||||
#if LWIP_DNS
|
||||
ns = dns_getserver(0);
|
||||
printf(" dns1 = %s\n", ipaddr_ntoa(ns));
|
||||
ns = dns_getserver(1);
|
||||
printf(" dns2 = %s\n", ipaddr_ntoa(ns));
|
||||
#endif /* LWIP_DNS */
|
||||
#endif /* PPP_IPV4_SUPPORT */
|
||||
#if PPP_IPV6_SUPPORT
|
||||
printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
|
||||
#endif /* PPP_IPV6_SUPPORT */
|
||||
break;
|
||||
}
|
||||
case PPPERR_PARAM: {
|
||||
printf("status_cb: Invalid parameter\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_OPEN: {
|
||||
printf("status_cb: Unable to open PPP session\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_DEVICE: {
|
||||
printf("status_cb: Invalid I/O device for PPP\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_ALLOC: {
|
||||
printf("status_cb: Unable to allocate resources\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_USER: {
|
||||
printf("status_cb: User interrupt\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_CONNECT: {
|
||||
printf("status_cb: Connection lost\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_AUTHFAIL: {
|
||||
printf("status_cb: Failed authentication challenge\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_PROTOCOL: {
|
||||
printf("status_cb: Failed to meet protocol\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_PEERDEAD: {
|
||||
printf("status_cb: Connection timeout\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_IDLETIMEOUT: {
|
||||
printf("status_cb: Idle Timeout\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_CONNECTTIME: {
|
||||
printf("status_cb: Max connect time reached\n");
|
||||
break;
|
||||
}
|
||||
case PPPERR_LOOPBACK: {
|
||||
printf("status_cb: Loopback detected\n");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
printf("status_cb: Unknown error code %d\n", err_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This should be in the switch case, this is put outside of the switch
|
||||
* case for example readability.
|
||||
*/
|
||||
|
||||
if (err_code == PPPERR_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ppp_close() was previously called, don't reconnect */
|
||||
if (err_code == PPPERR_USER) {
|
||||
/* ppp_free(); -- can be called here */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to reconnect in 30 seconds, if you need a modem chatscript you have
|
||||
* to do a much better signaling here ;-)
|
||||
*/
|
||||
ppp_connect(pcb, 30);
|
||||
/* OR ppp_listen(pcb); */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Creating a new PPPoS session
|
||||
* ============================
|
||||
*
|
||||
* In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.
|
||||
*/
|
||||
|
||||
#include "netif/ppp/pppos.h"
|
||||
|
||||
/*
|
||||
* PPPoS serial output callback
|
||||
*
|
||||
* ppp_pcb, PPP control block
|
||||
* data, buffer to write to serial port
|
||||
* len, length of the data buffer
|
||||
* ctx, optional user-provided callback context pointer
|
||||
*
|
||||
* Return value: len if write succeed
|
||||
*/
|
||||
static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
|
||||
return uart_write(UART, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new PPPoS interface
|
||||
*
|
||||
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
|
||||
* output_cb, PPPoS serial output callback
|
||||
* status_cb, PPP status callback, called on PPP status change (up, down, …)
|
||||
* ctx_cb, optional user-provided callback context pointer
|
||||
*/
|
||||
ppp = pppos_create(&ppp_netif,
|
||||
output_cb, status_cb, ctx_cb);
|
||||
|
||||
|
||||
/*
|
||||
* Creating a new PPPoE session
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include "netif/ppp/pppoe.h"
|
||||
|
||||
/*
|
||||
* Create a new PPPoE interface
|
||||
*
|
||||
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
|
||||
* ethif, already existing and setup Ethernet interface to use
|
||||
* service_name, PPPoE service name discriminator (not supported yet)
|
||||
* concentrator_name, PPPoE concentrator name discriminator (not supported yet)
|
||||
* status_cb, PPP status callback, called on PPP status change (up, down, …)
|
||||
* ctx_cb, optional user-provided callback context pointer
|
||||
*/
|
||||
ppp = pppoe_create(&ppp_netif,
|
||||
ðif,
|
||||
service_name, concentrator_name,
|
||||
status_cb, ctx_cb);
|
||||
|
||||
|
||||
/*
|
||||
* Creating a new PPPoL2TP session
|
||||
* ===============================
|
||||
*/
|
||||
|
||||
#include "netif/ppp/pppol2tp.h"
|
||||
|
||||
/*
|
||||
* Create a new PPPoL2TP interface
|
||||
*
|
||||
* ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
|
||||
* netif, optional already existing and setup output netif, necessary if you
|
||||
* want to set this interface as default route to settle the chicken
|
||||
* and egg problem with VPN links
|
||||
* ipaddr, IP to connect to
|
||||
* port, UDP port to connect to (usually 1701)
|
||||
* secret, L2TP secret to use
|
||||
* secret_len, size in bytes of the L2TP secret
|
||||
* status_cb, PPP status callback, called on PPP status change (up, down, …)
|
||||
* ctx_cb, optional user-provided callback context pointer
|
||||
*/
|
||||
ppp = pppol2tp_create(&ppp_netif,
|
||||
struct netif *netif, ip_addr_t *ipaddr, u16_t port,
|
||||
u8_t *secret, u8_t secret_len,
|
||||
ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
|
||||
|
||||
|
||||
/*
|
||||
* Initiate PPP client connection
|
||||
* ==============================
|
||||
*/
|
||||
|
||||
/* Set this interface as default route */
|
||||
ppp_set_default(ppp);
|
||||
|
||||
/*
|
||||
* Basic PPP client configuration. Can only be set if PPP session is in the
|
||||
* dead state (i.e. disconnected). We don't need to provide thread-safe
|
||||
* equivalents through PPPAPI because those helpers are only changing
|
||||
* structure members while session is inactive for lwIP core. Configuration
|
||||
* only need to be done once.
|
||||
*/
|
||||
|
||||
/* Ask the peer for up to 2 DNS server addresses. */
|
||||
ppp_set_usepeerdns(ppp, 1);
|
||||
|
||||
/* Auth configuration, this is pretty self-explanatory */
|
||||
ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
|
||||
|
||||
/*
|
||||
* Initiate PPP negotiation, without waiting (holdoff=0), can only be called
|
||||
* if PPP session is in the dead state (i.e. disconnected).
|
||||
*/
|
||||
u16_t holdoff = 0;
|
||||
ppp_connect(ppp, holdoff);
|
||||
|
||||
|
||||
/*
|
||||
* Initiate PPP server listener
|
||||
* ============================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Basic PPP server configuration. Can only be set if PPP session is in the
|
||||
* dead state (i.e. disconnected). We don't need to provide thread-safe
|
||||
* equivalents through PPPAPI because those helpers are only changing
|
||||
* structure members while session is inactive for lwIP core. Configuration
|
||||
* only need to be done once.
|
||||
*/
|
||||
ip4_addr_t addr;
|
||||
|
||||
/* Set our address */
|
||||
IP4_ADDR(&addr, 192,168,0,1);
|
||||
ppp_set_ipcp_ouraddr(ppp, &addr);
|
||||
|
||||
/* Set peer(his) address */
|
||||
IP4_ADDR(&addr, 192,168,0,2);
|
||||
ppp_set_ipcp_hisaddr(ppp, &addr);
|
||||
|
||||
/* Set primary DNS server */
|
||||
IP4_ADDR(&addr, 192,168,10,20);
|
||||
ppp_set_ipcp_dnsaddr(ppp, 0, &addr);
|
||||
|
||||
/* Set secondary DNS server */
|
||||
IP4_ADDR(&addr, 192,168,10,21);
|
||||
ppp_set_ipcp_dnsaddr(ppp, 1, &addr);
|
||||
|
||||
/* Auth configuration, this is pretty self-explanatory */
|
||||
ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
|
||||
|
||||
/* Require peer to authenticate */
|
||||
ppp_set_auth_required(ppp, 1);
|
||||
|
||||
/*
|
||||
* Only for PPPoS, the PPP session should be up and waiting for input.
|
||||
*
|
||||
* Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.
|
||||
* The listen call is meant for future support of PPPoE and PPPoL2TP server
|
||||
* mode, where we will need to negotiate the incoming PPPoE session or L2TP
|
||||
* session before initiating PPP itself. We need this call because there is
|
||||
* two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.
|
||||
*/
|
||||
ppp_set_silent(pppos, 1);
|
||||
|
||||
/*
|
||||
* Initiate PPP listener (i.e. wait for an incoming connection), can only
|
||||
* be called if PPP session is in the dead state (i.e. disconnected).
|
||||
*/
|
||||
ppp_listen(ppp);
|
||||
|
||||
|
||||
/*
|
||||
* Closing PPP connection
|
||||
* ======================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initiate the end of the PPP session, without carrier lost signal
|
||||
* (nocarrier=0), meaning a clean shutdown of PPP protocols.
|
||||
* You can call this function at anytime.
|
||||
*/
|
||||
u8_t nocarrier = 0;
|
||||
ppp_close(ppp, nocarrier);
|
||||
/*
|
||||
* Then you must wait your status_cb() to be called, it may takes from a few
|
||||
* seconds to several tens of seconds depending on the current PPP state.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Freeing a PPP connection
|
||||
* ========================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Free the PPP control block, can only be called if PPP session is in the
|
||||
* dead state (i.e. disconnected). You need to call ppp_close() before.
|
||||
*/
|
||||
ppp_free(ppp);
|
||||
|
||||
|
||||
|
||||
3 PPPoS input path (raw API, IRQ safe API, TCPIP API)
|
||||
=====================================================
|
||||
|
||||
Received data on serial port should be sent to lwIP using the pppos_input()
|
||||
function or the pppos_input_tcpip() function.
|
||||
|
||||
If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
|
||||
is not IRQ safe and then *MUST* only be called inside your main loop.
|
||||
|
||||
Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
|
||||
safe and can be safely called from an interrupt context, using that is going
|
||||
to reduce your need of buffer if pppos_input() is called byte after byte in
|
||||
your rx serial interrupt.
|
||||
|
||||
if NO_SYS is 0, the thread safe way outside an interrupt context is to use
|
||||
the pppos_input_tcpip() function to pass input data to the lwIP core thread
|
||||
using the TCPIP API. This is thread safe in all cases but you should avoid
|
||||
passing data byte after byte because it uses heavy locking (mailbox) and it
|
||||
allocates pbuf, better fill them !
|
||||
|
||||
if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
|
||||
from an RX thread, however pppos_input() is not thread safe by itself. You can
|
||||
do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
|
||||
ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
|
||||
at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
|
||||
really know what you are doing, your move ;-)
|
||||
|
||||
|
||||
/*
|
||||
* Fonction to call for received data
|
||||
*
|
||||
* ppp, PPP control block
|
||||
* buffer, input buffer
|
||||
* buffer_len, buffer length in bytes
|
||||
*/
|
||||
void pppos_input(ppp, buffer, buffer_len);
|
||||
|
||||
or
|
||||
|
||||
void pppos_input_tcpip(ppp, buffer, buffer_len);
|
||||
|
||||
|
||||
|
||||
4 Thread safe PPP API (PPPAPI)
|
||||
==============================
|
||||
|
||||
There is a thread safe API for all corresponding ppp_* functions, you have to
|
||||
enable LWIP_PPP_API in your lwipopts.h file, then see
|
||||
include/netif/ppp/pppapi.h, this is actually pretty obvious.
|
||||
|
||||
|
||||
|
||||
5 Notify phase callback (PPP_NOTIFY_PHASE)
|
||||
==========================================
|
||||
|
||||
Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
|
||||
you configure a callback that is called on each PPP internal state change.
|
||||
This is different from the status callback which only warns you about
|
||||
up(running) and down(dead) events.
|
||||
|
||||
Notify phase callback can be used, for example, to set a LED pattern depending
|
||||
on the current phase of the PPP session. Here is a callback example which
|
||||
tries to mimic what we usually see on xDSL modems while they are negotiating
|
||||
the link, which should be self-explanatory:
|
||||
|
||||
static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {
|
||||
switch (phase) {
|
||||
|
||||
/* Session is down (either permanently or briefly) */
|
||||
case PPP_PHASE_DEAD:
|
||||
led_set(PPP_LED, LED_OFF);
|
||||
break;
|
||||
|
||||
/* We are between two sessions */
|
||||
case PPP_PHASE_HOLDOFF:
|
||||
led_set(PPP_LED, LED_SLOW_BLINK);
|
||||
break;
|
||||
|
||||
/* Session just started */
|
||||
case PPP_PHASE_INITIALIZE:
|
||||
led_set(PPP_LED, LED_FAST_BLINK);
|
||||
break;
|
||||
|
||||
/* Session is running */
|
||||
case PPP_PHASE_RUNNING:
|
||||
led_set(PPP_LED, LED_ON);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
|
||||
===============================================
|
||||
|
||||
PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting
|
||||
from previous lwIP version is pretty easy:
|
||||
|
||||
* Previous PPP API used an integer to identify PPP sessions, we are now
|
||||
using ppp_pcb* control block, therefore all functions changed from "int ppp"
|
||||
to "ppp_pcb *ppp"
|
||||
|
||||
* struct netif was moved outside the PPP structure, you have to provide a netif
|
||||
for PPP interface in pppoX_create() functions
|
||||
|
||||
* PPP session are not started automatically after you created them anymore,
|
||||
you have to call ppp_connect(), this way you can configure the session before
|
||||
starting it.
|
||||
|
||||
* Previous PPP API used CamelCase, we are now using snake_case.
|
||||
|
||||
* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,
|
||||
PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed
|
||||
pppoe_, common functions are now prefixed ppp_.
|
||||
|
||||
* New PPPERR_ error codes added, check you have all of them in your status
|
||||
callback function
|
||||
|
||||
* Only the following include files should now be used in user application:
|
||||
#include "netif/ppp/pppapi.h"
|
||||
#include "netif/ppp/pppos.h"
|
||||
#include "netif/ppp/pppoe.h"
|
||||
#include "netif/ppp/pppol2tp.h"
|
||||
|
||||
Functions from ppp.h can be used, but you don't need to include this header
|
||||
file as it is already included by above header files.
|
||||
|
||||
* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
|
||||
your own serial rx thread
|
||||
|
||||
* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
|
||||
PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
|
||||
because you might have been fooled by that
|
||||
|
||||
* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
|
||||
the PPPAPI API instead.
|
||||
|
||||
* ppp_sighup and ppp_close functions were merged using an optional argument
|
||||
"nocarrier" on ppp_close.
|
||||
|
||||
* DNS servers are now only remotely asked if LWIP_DNS is set and if
|
||||
ppp_set_usepeerdns() is set to true, they are now automatically registered
|
||||
using the dns_setserver() function so you don't need to do that in the PPP
|
||||
callback anymore.
|
||||
|
||||
* PPPoS does not use the SIO API anymore, as such it now requires a serial
|
||||
output callback in place of sio_write
|
||||
|
||||
* PPP_MAXIDLEFLAG is now in ms instead of jiffies
|
|
@ -1,120 +0,0 @@
|
|||
Daily Use Guide for using Savannah for lwIP
|
||||
|
||||
Table of Contents:
|
||||
|
||||
1 - Obtaining lwIP from the Git repository
|
||||
2 - Committers/developers Git access using SSH
|
||||
3 - Merging a development branch to master branch
|
||||
4 - How to release lwIP
|
||||
|
||||
|
||||
|
||||
1 Obtaining lwIP from the Git repository
|
||||
----------------------------------------
|
||||
|
||||
To perform an anonymous Git clone of the master branch (this is where
|
||||
bug fixes and incremental enhancements occur), do this:
|
||||
git clone git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||
git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
Or, obtain a specific (fixed) release as follows:
|
||||
git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
|
||||
2 Committers/developers Git access using SSH
|
||||
--------------------------------------------
|
||||
|
||||
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||
As such, Git commits to the server occur through a SSH tunnel for project members.
|
||||
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||
ssh-keygen
|
||||
|
||||
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||
documentation and a graphic user interface. Use its key generator.
|
||||
|
||||
Now paste the id_rsa.pub contents into your Savannah account public key list. Wait
|
||||
a while so that Savannah can update its configuration (This can take minutes).
|
||||
|
||||
Try to login using SSH:
|
||||
ssh -v your_login@git.sv.gnu.org
|
||||
|
||||
If it tells you:
|
||||
Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686
|
||||
|
||||
Interactive shell login is not possible for security reasons.
|
||||
VCS commands are allowed.
|
||||
Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
|
||||
You tried to execute:
|
||||
Sorry, you are not allowed to execute that command.
|
||||
Shared connection to git.sv.gnu.org closed.
|
||||
|
||||
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||
are allowed to use SSH for Git only. Now, you should be able to do this:
|
||||
git clone your_login@git.sv.gnu.org:/srv/git/lwip.git
|
||||
|
||||
After which you can edit your local files with bug fixes or new features and
|
||||
commit them. Make sure you know what you are doing when using Git to make
|
||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||
|
||||
(If SSH asks about authenticity of the host, you can check the key
|
||||
fingerprint against https://savannah.nongnu.org/git/?group=lwip
|
||||
|
||||
|
||||
3 - Merging a development branch to master branch
|
||||
-------------------------------------------------
|
||||
|
||||
Merging is a straightforward process in Git. How to merge all changes in a
|
||||
development branch since our last merge from main:
|
||||
|
||||
Checkout the master branch:
|
||||
git checkout master
|
||||
|
||||
Merge the development branch to master:
|
||||
git merge your-development-branch
|
||||
|
||||
Resolve any conflict.
|
||||
|
||||
Commit the merge result.
|
||||
git commit -a
|
||||
|
||||
Push your commits:
|
||||
git push
|
||||
|
||||
|
||||
4 How to release lwIP
|
||||
---------------------
|
||||
|
||||
First, tag the release using Git: (I use release number 1.4.1 throughout
|
||||
this example).
|
||||
git tag -a STABLE-1_4_1
|
||||
|
||||
Share the tag reference by pushing it to remote:
|
||||
git push origin STABLE-1_4_1
|
||||
|
||||
Prepare the release:
|
||||
cp -r lwip lwip-1.4.1
|
||||
rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes
|
||||
|
||||
Archive the current directory using tar, gzip'd, bzip2'd and zip'd.
|
||||
tar czvf lwip-1.4.1.tar.gz lwip-1.4.1
|
||||
tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1
|
||||
zip -r lwip-1.4.1.zip lwip-1.4.1
|
||||
|
||||
Now, sign the archives with a detached GPG binary signature as follows:
|
||||
gpg -b lwip-1.4.1.tar.gz
|
||||
gpg -b lwip-1.4.1.tar.bz2
|
||||
gpg -b lwip-1.4.1.zip
|
||||
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
ncftp> mput *1.4.1.*
|
||||
|
||||
Additionally, you may post a news item on Savannah, like this:
|
||||
|
||||
A new 1.4.1 release is now available here:
|
||||
http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
|
||||
|
||||
You will have to submit this via the user News interface, then approve
|
||||
this via the Administrator News interface.
|
|
@ -1,6 +0,0 @@
|
|||
Some net apps for current version LwIP.
|
||||
|
||||
The RT-Thread develop team ported apps. It's easy to use it on finsh/msh.
|
||||
|
||||
- ping
|
||||
- tftp
|
|
@ -6,6 +6,61 @@ HISTORY
|
|||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
(STABLE-2.1.2):
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2018-11-21: Jens Nielsen
|
||||
* netbiosns.c: fix expecting too large packet (bug #55069)
|
||||
|
||||
2018-11-19: Dirk Ziegelmeier
|
||||
* smtp.c: fix compiling with strict C compatibility because of strnlen (bug #55034)
|
||||
|
||||
2018-11-12: Simon Goldschmidt
|
||||
* tcp.c: fix overflow check in tcp_recved triggering invalid assertion (bug #55015)
|
||||
|
||||
2018-11-12: Simon Goldschmidt
|
||||
* tcp.c: fix a bug in sending RST segments (sent from port 0)
|
||||
|
||||
(STABLE-2.1.1):
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2018-11-01: Joan Lledó
|
||||
* sockets.c: fix bad assertion in lwip_poll_dec_sockets_used() (bug #54933)
|
||||
|
||||
2018-11-01: Dirk Ziegelmeier
|
||||
* ip4.c: don't send 127.* to default netif (bug #54670)
|
||||
|
||||
2018-10-23: David Girault
|
||||
* altcp_tls_mbedtls.c: fix use-after free (bug #54774)
|
||||
|
||||
2018-10-23: Ognjen Bjelica, Dirk Ziegelmeier
|
||||
* snmp_scalar.c: Avoid NULL pointer dereference (bug #54886)
|
||||
|
||||
2018-10-23: Simon Goldschmidt
|
||||
* Fix missing standard includes in multiple files
|
||||
|
||||
2018-10-17: Ivan Warren
|
||||
* def.h: fix casting htonX and ntohX to u16_t (bug #54850)
|
||||
|
||||
2018-10-12: Simon Goldschmidt
|
||||
* Revert "tcp_abandon: no need to buffer pcb->local_port" (fix that source port was 0 for RST
|
||||
called when aborting a connection)
|
||||
|
||||
2018-10-11: Jonas Rabenstein
|
||||
* tcp.c: tcp_recved: check for overflow and warn about too big values (patch #9699)
|
||||
|
||||
2018-10-06: Joan Lledó
|
||||
* sockets.c: alloc_socket(): Check for LWIP_SOCKET_POLL when setting select-
|
||||
related variables (patch #9696)
|
||||
|
||||
2018-10-04: Spencer
|
||||
* tcp.c: Update prev pointer when skipping entries in tcp_slowtmr (patch #9694)
|
||||
|
||||
2018-09-27: Martine Lenders
|
||||
* lowpan6.c: Fix IEEE 802.15.4 address setting (bug #54749)
|
||||
|
||||
(STABLE-2.1.0):
|
||||
|
||||
++ New features:
|
|
@ -0,0 +1,89 @@
|
|||
# lwip 移植说明
|
||||
|
||||
为了适配 RT-Thread 网卡设备,RT-Thread 团队基于原 [lwip](http://savannah.nongnu.org/projects/lwip/) 进行了一些修改,本文档记录了相关修改内容。
|
||||
|
||||
> 本 lwip-2.1.2 版本基于 [lwip STABLE-2_1_2_RELEASE](https://git.savannah.gnu.org/git/lwip.git) 版本移植而来。
|
||||
|
||||
|
||||
| Date | Author | Notes |
|
||||
| :---- | :---- | :---- |
|
||||
| 2019-09-02 | MurphyZhao | 增加 lwip 2.1.2 移植说明 |
|
||||
| 2020-06-18 | xiangxistu | 增加部分 lwIP 2.1.2 移植说明 |
|
||||
|
||||
## 修改内容
|
||||
|
||||
### src/api
|
||||
|
||||
- `src/api/sockets.c` 增加 `lwip_tryget_socket` 函数,作为 `tryget_socket` 函数的全局实现
|
||||
- `src/api/sockets.c` 在 `alloc_socket` 函数中,增加 SAL 移植函数 `rt_wqueue_init`
|
||||
|
||||
```
|
||||
#ifdef SAL_USING_POSIX
|
||||
rt_wqueue_init(&sockets[i].wait_head);
|
||||
#endif
|
||||
```
|
||||
|
||||
### src/app
|
||||
|
||||
- 增加 `ping/ping.c`,便于在 finsh/msh 中使用 ping 功能
|
||||
- 增加 `tftp/tftp_port.c`,便于在 finsh/msh 中使用 tftp_server 功能
|
||||
|
||||
### src/arch
|
||||
|
||||
增加 `src/arch` 目录,存储对接 RT-Thread 设备框架的移植文件,从 lwip-2.0.2 版本中的移植文件修改而来。
|
||||
|
||||
|
||||
|
||||
以及相对于 lwIP2.0.2 的增加修改内容:
|
||||
|
||||
|
||||
* 在 `src/arch/sys_arch.c` 中增加 MTU 与 etharp_output 的初始化
|
||||
|
||||
* 在 `src/arch/sys_arch.c` 中增加新添加的邮箱函数
|
||||
|
||||
对邮箱机制的新增加的 sys_mbox_trypost_fromisr 函数予以实现
|
||||
|
||||
* 在 `src/arch/sys_arch.c` 中增加新添加的内存堆函数
|
||||
|
||||
对内存堆的新增加的 mem_overflow_check_raw 与 mem_overflow_init_raw 函数予以实现
|
||||
|
||||
* 在 `src/arch/cc.h` 中增加对 lwIP 使用的标准错误代码宏的处理,不再使用 lwIP 内置的错误宏
|
||||
|
||||
|
||||
### src/core
|
||||
|
||||
- 在 `src/core/dns.c` 的 `dns_setserver` 函数中增加 RT-Thread netdev 相关的移植
|
||||
- 在 `src/core/netif.c` 中增加 RT-Thread netdev 相关的移植
|
||||
|
||||
### src/include
|
||||
|
||||
- 在 `src/include/lwip/priv/sockets_priv.h` 中增加 SAL 相关的移植
|
||||
|
||||
在 `lwip_sock` 结构体中增加 ` rt_wqueue_t wait_head;` 成员
|
||||
|
||||
- 在 `src/include/lwip/prot/ieee.h` 中增加 EAPOL, EAP over LAN 标识
|
||||
|
||||
- 在 `src/include/lwip/init.h` 中的版本号后增加 `U` 标识
|
||||
|
||||
- 在 `src/include/lwip/sockets.h` 中增加 `LWIP_SOCKET_SELECT`,解决开启 RT_USING_POSIX 时的冲突
|
||||
|
||||
- 在 `src/include/lwip/arch.h` 中修改 `<unistd.h> `为 `"sys/types.h" `,解决编译冲突
|
||||
|
||||
并添加 typedef int ssize_t 定义,补足因 libc 与 dfs 未开启时 ssize_t 的定义不足问题
|
||||
|
||||
- 在 `src/include/netif/` 中增加 `ethernetif.h`,用于对接 RT-Thread 网卡设备
|
||||
|
||||
### src/netif
|
||||
|
||||
- 在 `src/netif/` 中增加 `ethernetif.c`,用于对接 RT-Thread 网卡设备
|
||||
- 在 `src/netif/lowpan6.c` 中增加 `LWIP_6LOWPAN` 宏定义,以防止编译错误
|
||||
|
||||
### src
|
||||
|
||||
- 在 src 目录下,增加 `src/lwipopts.h`,用于 lwip 功能裁剪以及配置设置
|
||||
- 在 src 目录下,增加 `src/lwippools.h`,用于定义 `LWIP_MALLOC_MEMPOOL`
|
||||
|
||||
### 其它
|
||||
|
||||
- 增加 SConscript 文件,用于 scons 构建
|
||||
- 增加 README_RT-THREAD.md 文件,用于记录相对原 lwip 源码的改动
|
|
@ -260,6 +260,6 @@ if GetDepend(['RT_USING_LWIP_IPV6']):
|
|||
if GetDepend(['RT_LWIP_USING_PING']):
|
||||
src += lwipping_SRCS
|
||||
|
||||
group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP210'], CPPPATH = path)
|
||||
group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP212'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
set(LWIP_VERSION_MAJOR "2")
|
||||
set(LWIP_VERSION_MINOR "1")
|
||||
set(LWIP_VERSION_REVISION "0")
|
||||
set(LWIP_VERSION_REVISION "2")
|
||||
# LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases
|
||||
# LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions
|
||||
# Numbers 1..31 are reserved for release candidates
|
|
@ -201,12 +201,12 @@ netconn_prepare_delete(struct netconn *conn)
|
|||
|
||||
API_MSG_VAR_ALLOC(msg);
|
||||
API_MSG_VAR_REF(msg).conn = conn;
|
||||
#if LWIP_TCP
|
||||
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
|
||||
/* get the time we started, which is later compared to
|
||||
sys_now() + conn->send_timeout */
|
||||
API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
|
||||
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
|
||||
#if LWIP_TCP
|
||||
API_MSG_VAR_REF(msg).msg.sd.polls_left =
|
||||
((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
|
||||
#endif /* LWIP_TCP */
|
|
@ -541,17 +541,17 @@ alloc_socket(struct netconn *newconn, int accepted)
|
|||
after having marked it as used. */
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
sockets[i].lastdata.pbuf = NULL;
|
||||
#if LWIP_SOCKET_SELECT
|
||||
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
|
||||
LWIP_ASSERT("sockets[i].select_waiting == 0", sockets[i].select_waiting == 0);
|
||||
sockets[i].rcvevent = 0;
|
||||
/* TCP sendbuf is empty, but the socket is not yet writable until connected
|
||||
* (unless it has been created by accept()). */
|
||||
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
|
||||
sockets[i].errevent = 0;
|
||||
#endif /* LWIP_SOCKET_SELECT */
|
||||
#ifdef SAL_USING_POSIX
|
||||
rt_wqueue_init(&sockets[i].wait_head);
|
||||
#endif
|
||||
#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
|
||||
#ifdef SAL_USING_POSIX
|
||||
rt_wqueue_init(&sockets[i].wait_head);
|
||||
#endif
|
||||
return i + LWIP_SOCKET_OFFSET;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
@ -1327,7 +1327,7 @@ lwip_recvmsg(int s, struct msghdr *message, int flags)
|
|||
if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) ||
|
||||
((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) ||
|
||||
((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) {
|
||||
sock_set_errno(sock, ERR_VAL);
|
||||
sock_set_errno(sock, err_to_errno(ERR_VAL));
|
||||
done_socket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
@ -2326,7 +2326,6 @@ lwip_poll_dec_sockets_used(struct pollfd *fds, nfds_t nfds)
|
|||
/* Go through each struct pollfd in the array. */
|
||||
for (fdi = 0; fdi < nfds; fdi++) {
|
||||
struct lwip_sock *sock = tryget_socket_unconn_nouse(fds[fdi].fd);
|
||||
LWIP_ASSERT("socket gone at the end of select", sock != NULL);
|
||||
if (sock != NULL) {
|
||||
done_socket(sock);
|
||||
}
|
|
@ -40,17 +40,15 @@
|
|||
* track of the ratio of application data and TLS overhead would be too much.
|
||||
*
|
||||
* Mandatory security-related configuration:
|
||||
* - define ALTCP_MBEDTLS_RNG_FN to a custom GOOD rng function returning 0 on success:
|
||||
* int my_rng_fn(void *ctx, unsigned char *buffer , size_t len)
|
||||
* - define ALTCP_MBEDTLS_RNG_FN to mbedtls_entropy_func to use the standard mbedTLS
|
||||
* entropy and ensure to add at least one strong entropy source to your mbedtls port
|
||||
* (implement mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong
|
||||
* entropy)
|
||||
* - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing
|
||||
* GOOD custom entropy
|
||||
*
|
||||
* Missing things / @todo:
|
||||
* - RX data is acknowledged after receiving (tcp_recved is called when enqueueing
|
||||
* the pbuf for mbedTLS receive, not when processed by mbedTLS or the inner
|
||||
* connection; altcp_recved() from inner connection does nothing)
|
||||
* - Client connections starting with 'connect()' are not handled yet...
|
||||
* - some unhandled things are caught by LWIP_ASSERTs...
|
||||
* - some unhandled/untested things migh be caught by LWIP_ASSERTs...
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
@ -309,17 +307,20 @@ altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
|
|||
LWIP_ASSERT("state != NULL", state != NULL);
|
||||
buf = state->rx_app;
|
||||
if (buf) {
|
||||
state->rx_app = NULL;
|
||||
if (conn->recv) {
|
||||
u16_t tot_len = state->rx_app->tot_len;
|
||||
u16_t tot_len = buf->tot_len;
|
||||
/* this needs to be increased first because the 'recved' call may come nested */
|
||||
state->rx_passed_unrecved += tot_len;
|
||||
state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED;
|
||||
err = conn->recv(conn->arg, conn, state->rx_app, ERR_OK);
|
||||
err = conn->recv(conn->arg, conn, buf, ERR_OK);
|
||||
if (err != ERR_OK) {
|
||||
if (err == ERR_ABRT) {
|
||||
return ERR_ABRT;
|
||||
}
|
||||
/* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */
|
||||
LWIP_ASSERT("state == conn->state", state == conn->state);
|
||||
state->rx_app = buf;
|
||||
state->rx_passed_unrecved -= tot_len;
|
||||
LWIP_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0);
|
||||
if (state->rx_passed_unrecved < 0) {
|
||||
|
@ -330,7 +331,6 @@ altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
|
|||
} else {
|
||||
pbuf_free(buf);
|
||||
}
|
||||
state->rx_app = NULL;
|
||||
} else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
|
||||
ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
|
||||
state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
|
||||
|
@ -339,6 +339,11 @@ altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
|
|||
}
|
||||
}
|
||||
|
||||
/* application may have close the connection */
|
||||
if (conn->state != state) {
|
||||
/* return error code to ensure altcp_mbedtls_handle_rx_appldata() exits the loop */
|
||||
return ERR_CLSD;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
@ -635,12 +640,13 @@ altcp_tls_context(struct altcp_pcb *conn)
|
|||
static void
|
||||
altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
|
||||
{
|
||||
LWIP_UNUSED_ARG(str);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
LWIP_UNUSED_ARG(level);
|
||||
LWIP_UNUSED_ARG(file);
|
||||
LWIP_UNUSED_ARG(line);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
/* @todo: output debug string :-) */
|
||||
LWIP_UNUSED_ARG(str);
|
||||
|
||||
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("%s:%04d: %s", file, line, str));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -673,7 +679,7 @@ altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca
|
|||
|
||||
if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) {
|
||||
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS,
|
||||
("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n"));
|
||||
("altcp_tls: TCP_WND is smaller than the RX decryption buffer, connection RX might stall!\n"));
|
||||
}
|
||||
|
||||
altcp_mbedtls_mem_init();
|
|
@ -51,6 +51,8 @@
|
|||
#include "lwip/mem.h"
|
||||
#include "lwip/init.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/** This string is passed in the HTTP header as "User-Agent: " */
|
||||
#ifndef ALTCP_PROXYCONNECT_CLIENT_AGENT
|
||||
#define ALTCP_PROXYCONNECT_CLIENT_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)"
|
Before Width: | Height: | Size: 724 B After Width: | Height: | Size: 724 B |
|
@ -55,6 +55,7 @@
|
|||
#include "lwip/init.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if LWIP_TCP && LWIP_CALLBACK_API
|
|
@ -111,6 +111,22 @@ PACK_STRUCT_END
|
|||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** NetBIOS message question part */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct netbios_question_hdr {
|
||||
PACK_STRUCT_FLD_8(u8_t nametype);
|
||||
PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN * 2) + 1]);
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
PACK_STRUCT_FIELD(u16_t cls);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** NetBIOS message name part */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
|
@ -335,11 +351,11 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
/* if packet is valid */
|
||||
if (p != NULL) {
|
||||
char netbios_name[NETBIOS_NAME_LEN + 1];
|
||||
struct netbios_hdr *netbios_hdr = (struct netbios_hdr *)p->payload;
|
||||
struct netbios_name_hdr *netbios_name_hdr = (struct netbios_name_hdr *)(netbios_hdr + 1);
|
||||
struct netbios_hdr *netbios_hdr = (struct netbios_hdr *)p->payload;
|
||||
struct netbios_question_hdr *netbios_question_hdr = (struct netbios_question_hdr *)(netbios_hdr + 1);
|
||||
|
||||
/* is the packet long enough (we need the header in one piece) */
|
||||
if (p->len < (sizeof(struct netbios_hdr) + sizeof(struct netbios_name_hdr))) {
|
||||
if (p->len < (sizeof(struct netbios_hdr) + sizeof(struct netbios_question_hdr))) {
|
||||
/* packet too short */
|
||||
pbuf_free(p);
|
||||
return;
|
||||
|
@ -352,9 +368,9 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
|
||||
(netbios_hdr->questions == PP_NTOHS(1))) {
|
||||
/* decode the NetBIOS name */
|
||||
netbiosns_name_decode((char *)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
|
||||
netbiosns_name_decode((char *)(netbios_question_hdr->encname), netbios_name, sizeof(netbios_name));
|
||||
/* check the request type */
|
||||
if (netbios_name_hdr->type == PP_HTONS(NETB_QTYPE_NB)) {
|
||||
if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NB)) {
|
||||
/* if the packet is for us */
|
||||
if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
|
||||
struct pbuf *q;
|
||||
|
@ -376,10 +392,10 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
resp->resp_hdr.additionalRRs = 0;
|
||||
|
||||
/* prepare NetBIOS header datas */
|
||||
MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
|
||||
resp->resp_name.nametype = netbios_name_hdr->nametype;
|
||||
resp->resp_name.type = netbios_name_hdr->type;
|
||||
resp->resp_name.cls = netbios_name_hdr->cls;
|
||||
MEMCPY( resp->resp_name.encname, netbios_question_hdr->encname, sizeof(netbios_question_hdr->encname));
|
||||
resp->resp_name.nametype = netbios_question_hdr->nametype;
|
||||
resp->resp_name.type = netbios_question_hdr->type;
|
||||
resp->resp_name.cls = netbios_question_hdr->cls;
|
||||
resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL);
|
||||
resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr));
|
||||
resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
|
||||
|
@ -393,7 +409,7 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
}
|
||||
}
|
||||
#if LWIP_NETBIOS_RESPOND_NAME_QUERY
|
||||
} else if (netbios_name_hdr->type == PP_HTONS(NETB_QTYPE_NBSTAT)) {
|
||||
} else if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NBSTAT)) {
|
||||
/* if the packet is for us or general query */
|
||||
if (!lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) ||
|
||||
!lwip_strnicmp(netbios_name, "*", sizeof(NETBIOS_LOCAL_NAME))) {
|
||||
|
@ -419,9 +435,9 @@ netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t
|
|||
/* resp->answer_hdr.authorityRRs = PP_HTONS(0); done by memset() */
|
||||
/* resp->answer_hdr.additionalRRs = PP_HTONS(0); done by memset() */
|
||||
/* we will copy the length of the station name */
|
||||
resp->name_size = netbios_name_hdr->nametype;
|
||||
resp->name_size = netbios_question_hdr->nametype;
|
||||
/* we will copy the queried name */
|
||||
MEMCPY(resp->query_name, netbios_name_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1);
|
||||
MEMCPY(resp->query_name, netbios_question_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1);
|
||||
/* NBSTAT */
|
||||
resp->packet_type = PP_HTONS(0x21);
|
||||
/* Internet name */
|
|
@ -65,7 +65,7 @@
|
|||
#include "lwip/altcp_tcp.h"
|
||||
#include "lwip/altcp_tls.h"
|
||||
|
||||
#include <string.h> /* strnlen, memcpy */
|
||||
#include <string.h> /* strlen, memcpy */
|
||||
#include <stdlib.h>
|
||||
|
||||
/** TCP poll interval. Unit is 0.5 sec. */
|
||||
|
@ -353,9 +353,8 @@ smtp_set_server_addr(const char* server)
|
|||
LWIP_ASSERT_CORE_LOCKED();
|
||||
|
||||
if (server != NULL) {
|
||||
/* strnlen: returns length WITHOUT terminating 0 byte OR
|
||||
* SMTP_MAX_SERVERNAME_LEN+1 when string is too long */
|
||||
len = strnlen(server, SMTP_MAX_SERVERNAME_LEN+1);
|
||||
/* strlen: returns length WITHOUT terminating 0 byte */
|
||||
len = strlen(server);
|
||||
}
|
||||
if (len > SMTP_MAX_SERVERNAME_LEN) {
|
||||
return ERR_MEM;
|
|
@ -193,28 +193,40 @@ snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, st
|
|||
static s16_t
|
||||
snmp_scalar_array_get_value(struct snmp_node_instance *instance, void *value)
|
||||
{
|
||||
s16_t result = -1;
|
||||
const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node;
|
||||
const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr;
|
||||
|
||||
return array_node->get_value(array_node_def, value);
|
||||
if (array_node->get_value != NULL) {
|
||||
result = array_node->get_value(array_node_def, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
snmp_scalar_array_set_test(struct snmp_node_instance *instance, u16_t value_len, void *value)
|
||||
{
|
||||
snmp_err_t result = SNMP_ERR_NOTWRITABLE;
|
||||
const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node;
|
||||
const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr;
|
||||
|
||||
return array_node->set_test(array_node_def, value_len, value);
|
||||
if (array_node->set_test != NULL) {
|
||||
result = array_node->set_test(array_node_def, value_len, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static snmp_err_t
|
||||
snmp_scalar_array_set_value(struct snmp_node_instance *instance, u16_t value_len, void *value)
|
||||
{
|
||||
snmp_err_t result = SNMP_ERR_NOTWRITABLE;
|
||||
const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node;
|
||||
const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr;
|
||||
|
||||
return array_node->set_value(array_node_def, value_len, value);
|
||||
if (array_node->set_value != NULL) {
|
||||
result = array_node->set_value(array_node_def, value_len, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* LWIP_SNMP */
|
|
@ -55,7 +55,11 @@ threadsync_get_value_synced(void *ctx)
|
|||
{
|
||||
struct threadsync_data *call_data = (struct threadsync_data *)ctx;
|
||||
|
||||
call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value);
|
||||
if (call_data->proxy_instance.get_value != NULL) {
|
||||
call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value);
|
||||
} else {
|
||||
call_data->retval.s16 = -1;
|
||||
}
|
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||
}
|
||||
|
@ -76,7 +80,11 @@ threadsync_set_test_synced(void *ctx)
|
|||
{
|
||||
struct threadsync_data *call_data = (struct threadsync_data *)ctx;
|
||||
|
||||
call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||
if (call_data->proxy_instance.set_test != NULL) {
|
||||
call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||
} else {
|
||||
call_data->retval.err = SNMP_ERR_NOTWRITABLE;
|
||||
}
|
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||
}
|
||||
|
@ -98,7 +106,11 @@ threadsync_set_value_synced(void *ctx)
|
|||
{
|
||||
struct threadsync_data *call_data = (struct threadsync_data *)ctx;
|
||||
|
||||
call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||
if (call_data->proxy_instance.set_value != NULL) {
|
||||
call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
|
||||
} else {
|
||||
call_data->retval.err = SNMP_ERR_NOTWRITABLE;
|
||||
}
|
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem);
|
||||
}
|
|
@ -57,9 +57,7 @@
|
|||
in arch.h has been assigned to another error code. */
|
||||
#define ESHUTDOWN 180
|
||||
#endif /* __CC_ARM/__IAR_SYSTEMS_ICC__ */
|
||||
#else
|
||||
#define LWIP_PROVIDE_ERRNO
|
||||
#endif
|
||||
#endif /* RT_USING_LIBC */
|
||||
|
||||
#if defined(RT_USING_LIBC) || defined(RT_USING_MINILIBC) || defined(RT_LIBC_USING_TIME)
|
||||
#include <sys/time.h>
|
|
@ -59,6 +59,6 @@ typedef rt_mutex_t sys_mutex_t;
|
|||
typedef rt_mailbox_t sys_mbox_t;
|
||||
typedef rt_thread_t sys_thread_t;
|
||||
|
||||
err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg);
|
||||
// err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg);
|
||||
|
||||
#endif /* __ARCH_SYS_ARCH_H__ */
|
0
components/net/lwip-2.1.0/src/arch/sys_arch.c → components/net/lwip-2.1.2/src/arch/sys_arch.c
Executable file → Normal file
0
components/net/lwip-2.1.0/src/arch/sys_arch.c → components/net/lwip-2.1.2/src/arch/sys_arch.c
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue