Compare commits

..

1 Commits

Author SHA1 Message Date
likewise
ccab493c95 Initial import from Adam's 20021017 CVS archive w/ modified license. 2002-10-19 12:59:30 +00:00
377 changed files with 23498 additions and 115777 deletions

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
# These files are text and should be normalized
*.txt text
*.c text
*.h text

13
.gitignore vendored
View File

@@ -1,13 +0,0 @@
/doc/doxygen/output/html
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler/bin/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler/obj/
/src/apps/snmp/LwipMibCompiler/MibViewer/bin/
/src/apps/snmp/LwipMibCompiler/MibViewer/obj/
/src/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/bin/
/src/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/obj/
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/bin/
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
/src/apps/snmp/LwipMibCompiler/*.suo

3910
CHANGELOG

File diff suppressed because it is too large Load Diff

58
COPYING
View File

@@ -1,33 +1,29 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
Copyright (c) 2001, Swedish Institute of Computer Science.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Institute nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

6
FILES
View File

@@ -1,5 +1,5 @@
src/ - The source code for the lwIP TCP/IP stack.
doc/ - The documentation for lwIP.
test/ - Some code to test whether the sources do what they should.
See also the FILES file in each subdirectory.
proj/ - Makefiles and code for compiling lwIP.
See also the FILES file in each subdirectory.

100
README
View File

@@ -1,100 +0,0 @@
INTRODUCTION
lwIP is a small independent implementation of the TCP/IP protocol
suite that has been developed by Adam Dunkels at the Computer and
Networks Architectures (CNA) lab at the Swedish Institute of Computer
Science (SICS).
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
while still having a full scale TCP. This making lwIP suitable for use
in embedded systems with tens of kilobytes of free RAM and room for
around 40 kilobytes of code ROM.
FEATURES
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
multiple network interfaces
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
* IGMP (Internet Group Management Protocol) for multicast traffic management
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
RFC 2710. No support for MLDv2
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
(Address autoconfiguration)
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
and fast recovery/fast retransmit
* raw/native API for enhanced performance
* Optional Berkeley-like socket API
* DNS (Domain names resolver)
APPLICATIONS
* HTTP server with SSI and CGI
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol)
* SNTP (Simple network time protocol)
* NetBIOS name service responder
* MDNS (Multicast DNS) responder
* iPerf server implementation
LICENSE
lwIP is freely available under a BSD license.
DEVELOPMENT
lwIP has grown into an excellent TCP/IP stack for embedded devices,
and developers using the stack often submit bug fixes, improvements,
and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. Everyone can
help improve lwIP by use of Savannah's interface, Git and the
mailing list. A core team of developers will commit changes to the
Git source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' Git module and
contributions (such as platform ports) are in the 'contrib' Git module.
See doc/savannah.txt for details on Git server access for users and
developers.
The current Git trees are web-browsable:
http://git.savannah.gnu.org/cgit/lwip.git
http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git
Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/
Continuous integration builds (GCC, clang):
https://travis-ci.org/yarrick/lwip-merged
DOCUMENTATION
Self documentation of the source code is regularly extracted from the current
Git sources and is available from this web page:
http://www.nongnu.org/lwip/
There is now a constantly growing wiki about lwIP at
http://lwip.wikia.com/wiki/LwIP_Wiki
Also, there are mailing lists you can subscribe at
http://savannah.nongnu.org/mail/?group=lwip
plus searchable archives:
http://lists.nongnu.org/archive/html/lwip-users/
http://lists.nongnu.org/archive/html/lwip-devel/
lwIP was originally written by Adam Dunkels:
http://dunkels.com/adam/
Reading Adam's papers, the files in docs/, browsing the source code
documentation and browsing the mailing list archives is a good way to
become familiar with the design of lwIP.
Adam Dunkels <adam@sics.se>
Leon Woestenberg <leon.woestenberg@gmx.net>

228
UPGRADING
View File

@@ -1,228 +0,0 @@
This file lists major changes between release versions that require
ports or applications to be changed. Use it to update a port or an
application written for an older version of lwIP to correctly work
with newer versions.
(git master)
* [Enter new changes just after this line - do not remove this line]
* TODO
(2.0.0)
++ Application changes:
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
has to be set "up" before starting the DHCP client
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
* Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
supports SNMPv2c (experimental v3 support)
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
+++ Raw API:
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
+++ Socket API:
* Added an implementation for posix sendmsg()
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
++ Port changes
+++ new files:
* MANY new and moved files!
* Added src/Filelists.mk for use in Makefile projects
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
to let abc.h only contain the actual application programmer's API
+++ sys layer:
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
open to priority inversion, so this is not recommended any more)
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
instead of using one per netconn (these semaphores are used even with core locking
enabled as some longer lasting functions like big writes still need to delay)
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
in def.h (to be overridden in cc.h) instead of config
options for netbiosns, httpd, dns, etc. ...
* New abstraction for hton* and ntoh* functions in def.h.
To override them, use the following in cc.h:
#define lwip_htons(x) <your_htons>
#define lwip_htonl(x) <your_htonl>
+++ new options:
* TODO
+++ new pools:
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
that share memp.c code but do not have to be made global via lwippools.h
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
is now available
* Signature of LWIP_HOOK_VLAN_SET macro was changed
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
or to move buffers to dedicated memory using compiler attributes
* Standard C headers are used to define sized types and printf formatters
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
does not support these)
++ Major bugfixes/improvements
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Major rewrite of PPP (incl. keep-up with apache pppd)
see doc/ppp.txt for an upgrading how-to
* Major rewrite of SNMP (incl. MIB parser)
* Fixed timing issues that might have lead to losing a DHCP lease
* Made rx processing path more robust against crafted errors
* TCP window scaling support
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
* made DNS client more robust
* support PBUF_REF for RX packets
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
* Moved and reordered stats (mainly memp/mib2)
(1.4.0)
++ Application changes:
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
compatibility to old applications, but will be removed in the future).
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
+++ Raw API:
* Changed the semantics of tcp_close() (since it was rather a
shutdown before): Now the application does *NOT* get any calls to the recv
callback (aside from NULL/closed) after calling tcp_close()
* When calling tcp_abort() from a raw API TCP callback function,
make sure you return ERR_ABRT to prevent accessing unallocated memory.
(ERR_ABRT now means the applicaiton has called tcp_abort!)
+++ Netconn API:
* Changed netconn_receive() and netconn_accept() to return
err_t, not a pointer to new data/netconn.
+++ Socket API:
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
* Added a minimal version of posix fctl() to have a
standardised way to set O_NONBLOCK for nonblocking sockets.
+++ all APIs:
* correctly implemented SO(F)_REUSEADDR
++ Port changes
+++ new files:
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
the actual application programmer's API
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
still want to use your own timer implementation for NO_SYS==0 (as before).
+++ sys layer:
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
sys_sem_t;
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
binary semaphores instead of mutexes - as before)
+++ new options:
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
prevent creating many small pbufs when calling tcp_write with many small
blocks of data. Instead, pbufs are allocated larger than needed and the
space is used for later calls to tcp_write.
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
in tcp_write/udp_send.
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
(necessary for pure PPPoE)
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
be used to place these pools into user-defined memory by using external
declaration.
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
+++ new pools:
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
so MEMP_NUM_NETDB has to be set accordingly.
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
to be set accordingly.
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
has to be set accordingly
* Integrated loopif into netif.c - loopif does not have to be created by the
port any more, just define LWIP_HAVE_LOOPIF to 1.
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
in cc.h, e.g. used by igmp)
* Added printf-formatter X8_F to printf u8_t as hex
* The heap now may be moved to user-defined memory by defining
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
with user-allocated structs instead of calling mem_malloc
* Added const char* name to mem- and memp-stats for easier debugging.
* Calculate the TCP/UDP checksum while copying to only fetch data once:
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
more than one pcb.
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
off any more, if this is set to 0, only one packet (the most recent one) is
queued (like demanded by RFC 1122).
++ Major bugfixes/improvements
* Implemented tcp_shutdown() to only shut down one end of a connection
* Implemented shutdown() at socket- and netconn-level
* Added errorset support to select() + improved select speed overhead
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
* Use macros defined in ip_addr.h to work with IP addresses
* Implemented many nonblocking socket/netconn functions
* Fixed ARP input processing: only add a new entry if a request was directed as us
* mem_realloc() to mem_trim() to prevent confusion with realloc()
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
existing connections when assigning a routable address)
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
* Added support for static ARP table entries
(STABLE-1.3.2)
* initial version of this file

View File

@@ -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.

View File

@@ -1,117 +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, sizeof(netif->hwaddr));
netif->hwaddr_len = sizeof(netif->hwaddr);
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_init();
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 */
}
}

View File

@@ -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.

View File

@@ -1 +0,0 @@
doxygen lwip.Doxyfile

View File

@@ -1 +0,0 @@
doxygen lwip.Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +0,0 @@
/**
* @defgroup lwip lwIP
*
* @defgroup infrastructure Infrastructure
*
* @defgroup callbackstyle_api Callback-style APIs
* Non thread-safe APIs, callback style for maximum performance and minimum
* memory footprint.
*
* @defgroup sequential_api Sequential-style APIs
* Sequential-style APIs, blocking functions. More overhead, but can be called
* from any thread except TCPIP thread.
*
* @defgroup addons Addons
*
* @defgroup apps Applications
*/
/**
* @mainpage Overview
* @verbinclude "README"
*/
/**
* @page upgrading Upgrading
* @verbinclude "UPGRADING"
*/
/**
* @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).
*
* 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.
*/
/**
* @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
*/
/**
* @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 and @ref sys_prot.\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 raw_api lwIP API
* @verbinclude "rawapi.txt"
*/

View File

@@ -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>

View File

@@ -1,113 +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 needs a strncasecmp() implementation. If you have one, define
LWIP_MDNS_STRNCASECMP 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.
It is recommended to call this function after an IPv4 address has been set,
since there is currently no check if the v4 address is valid.
Call mdns_resp_netif_settings_changed() every time the IP address
on the netif has changed.
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.
Removing services is currently not supported. Services are removed when the
netif is removed.

View File

@@ -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,
&ethif,
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

View File

@@ -1,76 +1,22 @@
Raw TCP/IP interface for lwIP
Raw TCP/IP interface for lwIP 0.5
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
Author: Adam Dunkels
lwIP provides three Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code:
* low-level "core" / "callback" or "raw" API.
* higher-level "sequential" API.
* BSD-style socket API.
$Id: rawapi.txt,v 1.1.1.1 2002/10/19 12:59:32 likewise Exp $
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.
lwIP provides two Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code: the sequential API
(often just called "the API") and the raw TCP/IP interface. This
document is intended as a description of the latter. For lwIP versions
lower than 0.5, this API was not documented.
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
model of execution is based on the 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).
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.
** 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 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 SYS_LIGHTWEIGHT_PROT is set to 1 and
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).
** The remainder of this document discusses the "raw" API. **
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
@@ -86,28 +32,14 @@ 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
Both 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 later 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.
--- Callbacks
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
Program execution is driven by callbacks. 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,
@@ -137,7 +69,7 @@ incoming connections or be explicitly connected to another host.
Creates a new connection identifier (PCB). If memory is not
available for creating the new pcb, NULL is returned.
- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local IP address and port number. The IP address
@@ -165,20 +97,14 @@ incoming connections or be explicitly connected to another host.
listening connection. If so, the memory associated with the pcb
passed as an argument to tcp_listen() will not be deallocated.
- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
Same as tcp_listen, but limits the number of outstanding connections
in the listen queue to the value specified by the backlog argument.
To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
- void tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
err_t err))
Specified the callback function that should be called when a new
connection arrives on a listening connection.
- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port, err_t (* connected)(void *arg,
struct tcp_pcb *tpcb,
err_t err));
@@ -191,15 +117,14 @@ incoming connections or be explicitly connected to another host.
function specified as the fourth argument (the "connected" argument)
when the connection is established. If the connection could not be
properly established, either because the other host refused the
connection or because the other host didn't answer, the "err"
callback function of this pcb (registered with tcp_err, see below)
will be called.
connection or because the other host didn't answer, the "connected"
function will be called with an the "err" argument set accordingly.
The tcp_connect() function can return ERR_MEM if no memory is
available for enqueueing the SYN segment. If the SYN indeed was
enqueued successfully, the tcp_connect() function returns ERR_OK.
--- Sending TCP data
TCP data is sent by enqueueing the data with a call to
@@ -207,19 +132,15 @@ tcp_write(). When the data is successfully transmitted to the remote
host, the application will be notified with a call to a specified
callback function.
- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
u8_t apiflags)
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
u8_t copy)
Enqueues the data pointed to by the argument dataptr. The length of
the data is passed as the len parameter. The apiflags can be one or more of:
- TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
for the data to be copied into. If this flag is not given, no new memory
should be allocated and the data should only be referenced by pointer. This
also means that the memory behind dataptr must not change until the data is
ACKed by the remote host
- TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted,
the PSH flag is set in the last segment created by this call to tcp_write.
If this flag is given, the PSH flag is not set.
the data is passed as the len parameter. The copy argument is either
0 or 1 and indicates whether the new memory should be allocated for
the data to be copied into. If the argument is 0, no new memory
should be allocated and the data should only be referenced by
pointer.
The tcp_write() function will fail and return ERR_MEM if the length
of the data exceeds the current send buffer size or if the length of
@@ -234,7 +155,7 @@ callback function.
- void tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
u16_t len))
u16_t len))
Specifies the callback function that should be called when data has
successfully been received (i.e., acknowledged) by the remote
@@ -256,16 +177,13 @@ window.
Sets the callback function that will be called when new data
arrives. The callback function will be passed a NULL pbuf to
indicate that the remote host has closed the connection. If
there are no errors and the callback function is to return
ERR_OK, then it must free the pbuf. Otherwise, it must not
free the pbuf so that lwIP core code can store it.
indicate that the remote host has closed the connection.
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
Must be called when the application has received the data. The len
argument indicates the length of the received data.
--- Application polling
@@ -278,9 +196,8 @@ if a call to tcp_write() has failed because memory wasn't available,
the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while.
- void tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
u8_t interval)
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
Specifies the polling interval and the callback function that should
be called to poll the application. The interval is specified in
@@ -306,23 +223,29 @@ again when the connection has been idle for a while.
Aborts the connection by sending a RST (reset) segment to the remote
host. The pcb is deallocated. This function never fails.
ATTENTION: When calling this from one of the TCP callbacks, make
sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
or you will risk accessing deallocated memory or memory leaks!
If a connection is aborted because of an error, the application is
alerted of this event by the err callback. Errors that might abort a
connection are when there is a shortage of memory. The callback
function to be called is set using the tcp_err() function.
- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
err_t err))
err_t err))
The error callback function does not get the pcb passed to it as a
parameter since the pcb may already have been deallocated.
--- Lower layer TCP interface
TCP provides a simple interface to the lower layers of the
system. During system initialization, the function tcp_init() has
to be called before any other TCP function is called. When the system
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
must be called with regular intervals. The tcp_fasttmr() should be
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
--- UDP interface
The UDP interface is similar to that of TCP, but due to the lower
@@ -338,24 +261,19 @@ level of complexity of UDP, the interface is significantly simpler.
Removes and deallocates the pcb.
- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Binds the pcb to a local address. The IP-address argument "ipaddr"
can be IP_ADDR_ANY to indicate that it should listen to any local IP
address. The function currently always return ERR_OK.
- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
u16_t port)
Sets the remote end of the pcb. This function does not generate any
network traffic, but only set the remote address of the pcb.
- err_t udp_disconnect(struct udp_pcb *pcb)
Remove the remote end of the pcb. This function does not generate
any network traffic, but only removes the remote address of the pcb.
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
Sends the pbuf p. The pbuf is not deallocated.
@@ -363,137 +281,9 @@ level of complexity of UDP, the interface is significantly simpler.
- void udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb,
struct pbuf *p,
ip_addr_t *addr,
struct ip_addr *addr,
u16_t port),
void *recv_arg)
Specifies a callback function that should be called when a UDP
datagram is received.
--- 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, const ip4_addr_t *ipaddr,
const ip4_addr_t *netmask, const ip4_addr_t *gw,
void *state, netif_init_fn init, netif_input_fn input)
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.
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;
}
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.
--- Optimalization 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 hton*/ntoh* 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.
For more optimization hints take a look at the lwIP wiki.
--- Zero-copy MACs
To achieve zero-copy on transmit, the data passed to the raw API must
remain unchanged until sent. Because the send- (or write-)functions return
when the packets have been enqueued for sending, data must be kept stable
after that, too.
This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
must *not* be reused by the application unless their ref-count is 1.
For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
Also, data passed to tcp_write without the copy-flag must not be changed!
Therefore, be careful which type of PBUF you use and if you copy TCP data
or not!
datagram is received.

View File

@@ -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 -t dsa
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_dsa.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.

View File

@@ -1,7 +1,8 @@
sys_arch interface for lwIP
sys_arch interface for lwIP 0.5
Author: Adam Dunkels
Simon Goldschmidt
$Id: sys_arch.txt,v 1.1.1.1 2002/10/19 12:59:33 likewise Exp $
The operating system emulation layer provides a common interface
between the lwIP code and the underlying operating system kernel. The
@@ -10,33 +11,25 @@ small changes to a few header files and a new sys_arch
implementation. It is also possible to do a sys_arch implementation
that does not rely on any underlying operating system.
The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full
The sys_arch provides semaphores and mailboxes to lwIP. For the full
lwIP functionality, multiple threads support can be implemented in the
sys_arch, but this is not required for the basic lwIP
functionality. Timer scheduling is implemented in lwIP, but can be implemented
by the sys_arch port (LWIP_TIMERS_CUSTOM==1).
In addition to the source file providing the functionality of sys_arch,
the OS emulation layer must provide several header files defining
macros used throughout lwip. The files required and the macros they
must define are listed below the sys_arch description.
functionality. Previous versions of lwIP required the sys_arch to
implement timer scheduling as well but as of lwIP 0.5 this is
implemented in a higher layer.
Semaphores can be either counting or binary - lwIP works with both
kinds. Mailboxes should be implemented as a queue which allows multiple messages
to be posted (implementing as a rendez-vous point where only one message can be
posted at a time can have a highly negative impact on performance). A message
in a mailbox is just a pointer, nothing more.
kinds. Mailboxes are used for message passing and can be implemented
either as a queue which allows multiple messages to be posted to a
mailbox, or as a rendez-vous point where only one message can be
posted at a time. lwIP works with both kinds, but the former type will
be more efficient. A message in a mailbox is just a pointer, nothing
more.
Semaphores are represented by the type "sys_sem_t" which is typedef'd
in the sys_arch.h file. Mailboxes are equivalently represented by the
type "sys_mbox_t". Mutexes are represented ny the type "sys_mutex_t".
lwIP does not place any restrictions on how these types are represented
internally.
Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that
allows both using pointers or actual OS structures to be used. This way, memory
required for such types can be either allocated in place (globally or on the
stack) or on the heap (allocated internally in the "*_new()" functions).
type "sys_mbox_t". lwIP does not place any restrictions on how
sys_sem_t or sys_mbox_t are represented internally.
The following functions must be implemented by the sys_arch:
@@ -44,260 +37,89 @@ The following functions must be implemented by the sys_arch:
Is called to initialize the sys_arch layer.
- err_t sys_sem_new(sys_sem_t *sem, u8_t count)
- sys_sem_t sys_sem_new(u8_t count)
Creates a new semaphore. The semaphore is allocated to the memory that 'sem'
points to (which can be both a pointer or the actual OS structure).
The "count" argument specifies the initial state of the semaphore (which is
either 0 or 1).
If the semaphore has been created, ERR_OK should be returned. Returning any
other error will provide a hint what went wrong, but except for assertions,
no real error handling is implemented.
Creates and returns a new semaphore. The "count" argument specifies
the initial state of the semaphore.
- void sys_sem_free(sys_sem_t *sem)
- void sys_sem_free(sys_sem_t sem)
Deallocates a semaphore.
Deallocates a semaphore.
- void sys_sem_signal(sys_sem_t *sem)
- void sys_sem_signal(sys_sem_t sem)
Signals a semaphore.
- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
- u16_t sys_arch_sem_wait(sys_sem_t sem, u16_t timeout)
Blocks the thread while waiting for the semaphore to be
signaled. If the "timeout" argument is non-zero, the thread should
only be blocked for the specified time (measured in
milliseconds). If the "timeout" argument is zero, the thread should be
blocked until the semaphore is signalled.
milliseconds).
If the timeout argument is non-zero, the return value is the number of
milliseconds spent waiting for the semaphore to be signaled. If the
semaphore wasn't signaled within the specified time, the return value is
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
(i.e., it was already signaled), the function may return zero.
If the timeout argument is non-zero, the return value is the amount
of time spent waiting for the semaphore to be signaled. If the
semaphore wasn't signaled within the specified time, the return
value is zero. If the thread didn't have to wait for the semaphore
(i.e., it was already signaled), care must be taken to ensure that
the function does not return a zero value since this is used to
indicate that a timeout occured. A suitable way to implement this is
to check if the time spent waiting is zero and if so, the value 1 is
returned.
Notice that lwIP implements a function with a similar name,
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
- int sys_sem_valid(sys_sem_t *sem)
- sys_mbox_t sys_mbox_new(void)
Returns 1 if the semaphore is valid, 0 if it is not valid.
When using pointers, a simple way is to check the pointer for != NULL.
When directly using OS structures, implementing this may be more complex.
This may also be a define, in which case the function is not prototyped.
Creates an empty mailbox.
- void sys_sem_set_invalid(sys_sem_t *sem)
Invalidate a semaphore so that sys_sem_valid() returns 0.
ATTENTION: This does NOT mean that the semaphore shall be deallocated:
sys_sem_free() is always called before calling this function!
This may also be a define, in which case the function is not prototyped.
- void sys_mutex_new(sys_mutex_t *mutex)
Creates a new mutex. The mutex is allocated to the memory that 'mutex'
points to (which can be both a pointer or the actual OS structure).
If the mutex has been created, ERR_OK should be returned. Returning any
other error will provide a hint what went wrong, but except for assertions,
no real error handling is implemented.
- void sys_mutex_free(sys_mutex_t *mutex)
Deallocates a mutex.
- void sys_mutex_lock(sys_mutex_t *mutex)
Blocks the thread until the mutex can be grabbed.
- void sys_mutex_unlock(sys_mutex_t *mutex)
Releases the mutex previously locked through 'sys_mutex_lock()'.
- void sys_mutex_valid(sys_mutex_t *mutex)
Returns 1 if the mutes is valid, 0 if it is not valid.
When using pointers, a simple way is to check the pointer for != NULL.
When directly using OS structures, implementing this may be more complex.
This may also be a define, in which case the function is not prototyped.
- void sys_mutex_set_invalid(sys_mutex_t *mutex)
Invalidate a mutex so that sys_mutex_valid() returns 0.
ATTENTION: This does NOT mean that the mutex shall be deallocated:
sys_mutex_free() is always called before calling this function!
This may also be a define, in which case the function is not prototyped.
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Creates an empty mailbox for maximum "size" elements. Elements stored
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
in your lwipopts.h, or ignore this parameter in your implementation
and use a default size.
If the mailbox has been created, ERR_OK should be returned. Returning any
other error will provide a hint what went wrong, but except for assertions,
no real error handling is implemented.
- void sys_mbox_free(sys_mbox_t *mbox)
- void sys_mbox_free(sys_mbox_t mbox)
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
programming error in lwIP and the developer should be notified.
- void sys_mbox_post(sys_mbox_t *mbox, void *msg)
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
Posts the "msg" to the mailbox. This function have to block until
the "msg" is really posted.
Posts the "msg" to the mailbox.
- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
is full, else, ERR_OK if the "msg" is posted.
- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
- u16_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u16_t timeout)
Blocks the thread until a message arrives in the mailbox, but does
not block the thread longer than "timeout" milliseconds (similar to
the sys_arch_sem_wait() function). If "timeout" is 0, the thread should
be blocked until a message arrives. The "msg" argument is a result
the sys_arch_sem_wait() function). The "msg" argument is a result
parameter that is set by the function (i.e., by doing "*msg =
ptr"). The "msg" parameter maybe NULL to indicate that the message
should be dropped.
The return values are the same as for the sys_arch_sem_wait() function:
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
timeout.
The return values are the same as for the sys_arch_sem_wait()
function and the function must not return zero even if a message was
present in the mailbox and the time spent waiting was zero
milliseconds.
Note that a function with a similar name, sys_mbox_fetch(), is
implemented by lwIP.
- struct sys_timeouts *sys_arch_timeouts(void)
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
This is similar to sys_arch_mbox_fetch, however if a message is not
present in the mailbox, it immediately returns with the code
SYS_MBOX_EMPTY. On success 0 is returned.
To allow for efficient implementations, this can be defined as a
function-like macro in sys_arch.h instead of a normal function. For
example, a naive implementation could be:
#define sys_arch_mbox_tryfetch(mbox,msg) \
sys_arch_mbox_fetch(mbox,msg,1)
although this would introduce unnecessary delays.
- int sys_mbox_valid(sys_mbox_t *mbox)
Returns 1 if the mailbox is valid, 0 if it is not valid.
When using pointers, a simple way is to check the pointer for != NULL.
When directly using OS structures, implementing this may be more complex.
This may also be a define, in which case the function is not prototyped.
- void sys_mbox_set_invalid(sys_mbox_t *mbox)
Invalidate a mailbox so that sys_mbox_valid() returns 0.
ATTENTION: This does NOT mean that the mailbox shall be deallocated:
sys_mbox_free() is always called before calling this function!
This may also be a define, in which case the function is not prototyped.
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
each thread has a list of timeouts which is repressented as a linked
list of sys_timeout structures. The sys_timeouts structure holds a
pointer to a linked list of timeouts. This function is called by
the lwIP timeout scheduler and must not return a NULL value.
In a single threadd sys_arch implementation, this function will
simply return a pointer to a global sys_timeouts variable stored in
the sys_arch module.
If threads are supported by the underlying operating system and if
such functionality is needed in lwIP, the following function will have
to be implemented as well:
- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
- void sys_thread_new(void (* thread)(void *arg), void *arg)
Starts a new thread named "name" with priority "prio" that will begin its
execution in the function "thread()". The "arg" argument will be passed as an
argument to the thread() function. The stack size to used for this thread is
the "stacksize" parameter. The id of the new thread is returned. Both the id
and the priority are system dependent.
Starts a new thread that will begin its execution in the function
"thread()". The "arg" argument will be passed as an argument to the
thread() function.
When lwIP is used from more than one context (e.g. from multiple threads OR from
main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled!
- sys_prot_t sys_arch_protect(void)
This optional function does a "fast" critical region protection and returns
the previous protection level. This function is only called during very short
critical regions. An embedded system which supports ISR-based drivers might
want to implement this function by disabling interrupts. Task-based systems
might want to implement this by using a mutex or disabling tasking. This
function should support recursive calls from the same task or interrupt. In
other words, sys_arch_protect() could be called while already protected. In
that case the return value indicates that it is already protected.
sys_arch_protect() is only required if your port is supporting an operating
system.
- void sys_arch_unprotect(sys_prot_t pval)
This optional function does a "fast" set of critical region protection to the
value specified by pval. See the documentation for sys_arch_protect() for
more information. This function is only required if your port is supporting
an operating system.
For some configurations, you also need:
- u32_t sys_now(void)
This optional function returns the current time in milliseconds (don't care
for wraparound, this is only used for time diffs).
Not implementing this function means you cannot use some modules (e.g. TCP
timestamps, internal timeouts for NO_SYS==1).
Note:
Be careful with using mem_malloc() in sys_arch. When malloc() refers to
mem_malloc() you can run into a circular function call problem. In mem.c
mem_init() tries to allcate a semaphore using mem_malloc, which of course
can't be performed when sys_arch uses mem_malloc.
-------------------------------------------------------------------------------
Additional files required for the "OS support" emulation layer:
-------------------------------------------------------------------------------
cc.h - Architecture environment, some compiler specific, some
environment specific (probably should move env stuff
to sys_arch.h.)
Typedefs for the types used by lwip -
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
Compiler hints for packing lwip's structures -
PACK_STRUCT_FIELD(x)
PACK_STRUCT_STRUCT
PACK_STRUCT_BEGIN
PACK_STRUCT_END
Platform specific diagnostic output -
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
Portability defines for printf formatters:
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
"lightweight" synchronization mechanisms -
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
SYS_ARCH_PROTECT(x) - enter protection mode.
SYS_ARCH_UNPROTECT(x) - leave protection mode.
If the compiler does not provide memset() this file must include a
definition of it, or include a file which defines it.
This file must either include a system-local <errno.h> which defines
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
to make lwip/arch.h define the codes which are used throughout.
perf.h - Architecture specific performance measurement.
Measurement calls made throughout lwip, these can be defined to nothing.
PERF_START - start measuring something.
PERF_STOP(x) - stop measuring something, and record the result.
sys_arch.h - Tied to sys_arch.c
Arch dependent types for the following objects:
sys_sem_t, sys_mbox_t, sys_thread_t,
And, optionally:
sys_prot_t
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
SYS_MBOX_NULL NULL
SYS_SEM_NULL NULL

94
proj/minimal/Makefile Normal file
View File

@@ -0,0 +1,94 @@
# Copyright (c) 2001, Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# $Id: Makefile,v 1.1.1.1 2002/10/19 12:59:33 likewise Exp $
CCDEP=gcc
CC=gcc
CFLAGS=-g -Wall -DIPv4 -Os -fpack-struct
LWIPARCH=unix
ARFLAGS=rs
LWIPDIR=../../src
CFLAGS:=$(CFLAGS) \
-I$(LWIPDIR)/include -I$(LWIPDIR)/arch/$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-Iapps -I.
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/stats.c $(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_input.c \
$(LWIPDIR)/core/tcp_output.c $(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c $(LWIPDIR)/core/ipv4/ip.c \
$(LWIPDIR)/core/inet.c $(LWIPDIR)/core/ipv4/ip_addr.c
# NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/etharp.c mintapif.c
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(NETIFFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
# APPFILES
APPFILES=echo.c
LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)
all ipv4 compile: minimal
.PHONY: all
clean:
rm -f *.o $(LWIPLIB) $(APPLIB) minimal .depend* *.core core
depend dep: .depend
include .depend
$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?
$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?
.depend: main.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
minimal: .depend $(LWIPLIB) $(APPLIB) main.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -o minimal main.o $(APPLIB) $(LWIPLIB)

3
proj/minimal/README Normal file
View File

@@ -0,0 +1,3 @@
This is an example of a very minimal lwIP project. It runs in a single
thread and runs a single example application - an echo server. The
echo application is implemented using the raw API.

220
proj/minimal/echo.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
struct echo_state {
struct pbuf *p;
u8_t failed;
#define FAILED_MAX 8
};
/*-----------------------------------------------------------------------------------*/
static void
echo_err(void *arg, err_t err)
{
struct echo_state *es = arg;
if(arg != NULL) {
pbuf_free(es->p);
mem_free(arg);
}
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct echo_state *es)
{
tcp_arg(pcb, NULL);
#if 0
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
#endif /* 0 */
if(es != NULL) {
pbuf_free(es->p);
mem_free(es);
}
tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_buf(struct tcp_pcb *pcb, struct echo_state *es)
{
struct pbuf *q;
do {
q = es->p;
es->p = pbuf_dechain(q);
if(tcp_write(pcb, q->payload, q->len, 1) == ERR_MEM) {
pbuf_chain(q, es->p);
es->p = q;
return;
}
tcp_recved(pcb, q->len);
pbuf_free(q);
} while(es->p != NULL);
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_poll(void *arg, struct tcp_pcb *pcb)
{
struct echo_state *es;
if(arg == NULL) {
return tcp_close(pcb);
}
es = arg;
if(es->failed >= FAILED_MAX) {
close_conn(pcb, es);
tcp_abort(pcb);
return ERR_ABRT;
}
if(es->p != NULL) {
++es->failed;
send_buf(pcb, es);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct echo_state *es;
es = arg;
if(es != NULL && es->p != NULL) {
send_buf(pcb, es);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct echo_state *es;
es = arg;
if(p == NULL) {
close_conn(pcb, es);
return ERR_OK;
}
if(es->p != NULL) {
pbuf_chain(es->p, p);
} else {
es->p = p;
}
send_buf(pcb, es);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
echo_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct echo_state *es;
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
es = mem_malloc(sizeof(struct echo_state));
if(es == NULL) {
return ERR_MEM;
}
/* Initialize the structure. */
es->p = NULL;
es->failed = 0;
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, es);
/* Tell TCP that we wish to be informed of incoming data by a call
to the http_recv() function. */
#if 0
tcp_recv(pcb, echo_recv);
tcp_err(pcb, echo_err);
#endif /* 0 */
tcp_poll(pcb, echo_poll, 2);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
echo_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 7);
pcb = tcp_listen(pcb);
#if 0
tcp_accept(pcb, echo_accept);
#endif /* 0 */
}
/*-----------------------------------------------------------------------------------*/
err_t
lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
enum lwip_event ev, struct pbuf *p,
u16_t size, err_t err)
{
switch(ev) {
case LWIP_EVENT_ACCEPT:
return echo_accept(arg, pcb, err);
case LWIP_EVENT_SENT:
return echo_sent(arg, pcb, size);
case LWIP_EVENT_RECV:
return echo_recv(arg, pcb, p, err);
case LWIP_EVENT_ERR:
echo_err(arg, err);
break;
case LWIP_EVENT_POLL:
return echo_poll(arg, pcb);
default:
break;
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/

168
proj/minimal/lwipopts.h Normal file
View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
#define NO_SYS 1
#define LWIP_EVENT_API 1
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 2
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 1000
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 8
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 2
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 8
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 0
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 0
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs. */
#define MEMP_NUM_API_MSG 0
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG 0
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 0
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 8
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
#define PBUF_LINK_HLEN 16
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0
/* TCP Maximum segment size. */
#define TCP_MSS 128
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 256
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS
/* TCP receive window. */
#define TCP_WND 512
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 0
/* If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 0
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK 1
/* ---------- UDP options ---------- */
#define LWIP_UDP 0
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
/*#define STATS*/
#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */
#endif /* __LWIPOPTS_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -26,37 +26,76 @@
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_LWIPOPTS_H
#define LWIP_HDR_LWIPOPTS_H
/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
#define NO_SYS 1
#define SYS_LIGHTWEIGHT_PROT 0
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
#include "lwip/debug.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "mintapif.h"
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
struct ip_addr ipaddr, netmask, gw;
struct netif *netif;
#ifdef PERF
perf_init("/tmp/minimal.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
mem_init();
memp_init();
pbuf_init();
netif_init();
ip_init();
udp_init();
tcp_init();
printf("TCP/IP initialized.\n");
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif = netif_add(&ipaddr, &netmask, &gw, mintapif_init, ip_input);
netif_set_default(netif);
echo_init();
printf("Applications started.\n");
while(1) {
if(mintapif_wait(netif, 100) == MINTAPIF_TIMEOUT) {
tcp_tmr();
}
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
/* Enable DHCP to test it, disable UDP checksum to easier inject packets */
#define LWIP_DHCP 1
/* Minimal changes to opt.h required for tcp unit tests: */
#define MEM_SIZE 16000
#define TCP_SND_QUEUELEN 40
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
#define TCP_SND_BUF (12 * TCP_MSS)
#define TCP_WND (10 * TCP_MSS)
#define LWIP_WND_SCALE 1
#define TCP_RCV_SCALE 0
#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */
/* Enable IGMP and MDNS for MDNS tests */
#define LWIP_IGMP 1
#define LWIP_MDNS_RESPONDER 1
#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER)
/* Minimal changes to opt.h required for etharp unit tests: */
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
#endif /* LWIP_HDR_LWIPOPTS_H */

354
proj/minimal/mintapif.c Normal file
View File

@@ -0,0 +1,354 @@
/*-----------------------------------------------------------------------------------*/
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
#ifdef linux
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#define DEVTAP "/dev/net/tun"
#else /* linux */
#define DEVTAP "/dev/tap0"
#endif /* linux */
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "netif/etharp.h"
#include "mintapif.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 't'
struct mintapif {
struct eth_addr *ethaddr;
/* Add whatever per-interface state that is needed here. */
u32_t lasttime;
int fd;
};
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
/* Forward declarations. */
static void mintapif_input(struct netif *netif);
static err_t mintapif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
/*-----------------------------------------------------------------------------------*/
static void
low_level_init(struct netif *netif)
{
struct mintapif *mintapif;
char buf[1024];
mintapif = netif->state;
/* Obtain MAC address from network interface. */
mintapif->ethaddr->addr[0] = 1;
mintapif->ethaddr->addr[1] = 2;
mintapif->ethaddr->addr[2] = 3;
mintapif->ethaddr->addr[3] = 4;
mintapif->ethaddr->addr[4] = 5;
mintapif->ethaddr->addr[5] = 6;
/* Do whatever else is needed to initialize interface. */
mintapif->fd = open(DEVTAP, O_RDWR);
if(mintapif->fd == -1) {
perror("tapif: tapif_init: open");
exit(1);
}
#ifdef linux
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
if (ioctl(mintapif->fd, TUNSETIFF, (void *) &ifr) < 0) {
perror(buf);
exit(1);
}
}
#endif /* Linux */
snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d",
ip4_addr1(&(netif->gw)),
ip4_addr2(&(netif->gw)),
ip4_addr3(&(netif->gw)),
ip4_addr4(&(netif->gw)));
system(buf);
mintapif->lasttime = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_output():
*
* Should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct mintapif *mintapif;
struct pbuf *q;
char buf[1500];
char *bufptr;
mintapif = netif->state;
/* initiate transfer(); */
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
variable. */
/* send data from(q->payload, q->len); */
bcopy(q->payload, bufptr, q->len);
bufptr += q->len;
}
/* signal that packet should be sent(); */
if(write(mintapif->fd, buf, p->tot_len) == -1) {
perror("tapif: write");
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_input():
*
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
*/
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct mintapif *mintapif)
{
struct pbuf *p, *q;
u16_t len;
char buf[1500];
char *bufptr;
/* Obtain the size of the packet and put it into the "len"
variable. */
len = read(mintapif->fd, buf, sizeof(buf));
/* if(((double)rand()/(double)RAND_MAX) < 0.1) {
printf("drop\n");
return NULL;
}*/
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
if(p != NULL) {
/* We iterate over the pbuf chain until we have read the entire
packet into the pbuf. */
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
variable. */
/* read data into(q->payload, q->len); */
bcopy(bufptr, q->payload, q->len);
bufptr += q->len;
}
/* acknowledge that packet has been read(); */
} else {
/* drop packet(); */
printf("Could not allocate pbufs\n");
}
return p;
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actuall transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
mintapif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
p = etharp_output(netif, ipaddr, p);
if(p != NULL) {
return low_level_output(netif, p);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
mintapif_input(struct netif *netif)
{
struct mintapif *mintapif;
struct eth_hdr *ethhdr;
struct pbuf *p, *q;
mintapif = netif->state;
p = low_level_input(mintapif);
if(p != NULL) {
#ifdef LINK_STATS
stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
q = NULL;
switch(htons(ethhdr->type)) {
case ETHTYPE_IP:
q = etharp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
q = etharp_arp_input(netif, mintapif->ethaddr, p);
break;
default:
pbuf_free(p);
break;
}
if(q != NULL) {
low_level_output(netif, q);
pbuf_free(q);
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* mintapif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
void
mintapif_init(struct netif *netif)
{
struct mintapif *mintapif;
mintapif = mem_malloc(sizeof(struct mintapif));
netif->state = mintapif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = mintapif_output;
netif->linkoutput = low_level_output;
mintapif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
}
/*-----------------------------------------------------------------------------------*/
enum mintapif_signal
mintapif_wait(struct netif *netif, u16_t time)
{
fd_set fdset;
struct timeval tv, now;
struct timezone tz;
int ret;
struct mintapif *mintapif;
mintapif = netif->state;
while(1) {
if(mintapif->lasttime >= (u32_t)time * 1000) {
mintapif->lasttime = 0;
return MINTAPIF_TIMEOUT;
}
tv.tv_sec = 0;
tv.tv_usec = (u32_t)time * 1000 - mintapif->lasttime;
FD_ZERO(&fdset);
FD_SET(mintapif->fd, &fdset);
gettimeofday(&now, &tz);
ret = select(mintapif->fd + 1, &fdset, NULL, NULL, &tv);
if(ret == 0) {
mintapif->lasttime = 0;
return MINTAPIF_TIMEOUT;
}
gettimeofday(&tv, &tz);
mintapif->lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec);
mintapif_input(netif);
}
return MINTAPIF_PACKET;
}

45
proj/minimal/mintapif.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __MINTAPIF_H__
#define __MINTAPIF_H__
#include "lwip/netif.h"
enum mintapif_signal {
MINTAPIF_TIMEOUT,
MINTAPIF_PACKET
};
void mintapif_init(struct netif *netif);
enum mintapif_signal mintapif_wait(struct netif *netif, u16_t time);
#endif /* __MINTAPIF_H__ */

111
proj/unixsim/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# Copyright (c) 2001, Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# $Id: Makefile,v 1.1.1.1 2002/10/19 12:59:37 likewise Exp $
CCDEP=gcc
CC=gcc
CFLAGS=-g -Wall -DIPv4 -DLWIP_DEBUG -pedantic
LDFLAGS=-lpcap
LWIPARCH=unix
ARFLAGS=rs
LWIPDIR=../../src
CFLAGS:=$(CFLAGS) \
-I$(LWIPDIR)/include -I$(LWIPDIR)/arch/$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-Iapps -I.
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/stats.c $(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_input.c \
$(LWIPDIR)/core/tcp_output.c $(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c $(LWIPDIR)/core/ipv4/ip.c \
$(LWIPDIR)/core/inet.c $(LWIPDIR)/core/ipv4/ip_addr.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \
$(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c
# NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/loopif.c \
$(LWIPDIR)/netif/tcpdump.c $(LWIPDIR)/netif/etharp.c
# ARCHFILES: Archiecture specific files.
ARCHFILES=$(wildcard $(LWIPDIR)/arch/$(LWIPARCH)/*.c $(LWIPDIR)/arch/$(LWIPARCH)/netif/*.c)
# APPFILES: Applications.
APPFILES=apps/fs.c apps/httpd.c \
apps/udpecho.c apps/tcpecho.c \
apps/shell.c
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)
all ipv4 compile: simhost simnode simrouter
.PHONY: all
clean:
rm -f *.o $(LWIPLIB) $(APPLIB) simhost simnode simrouter *.s .depend* *.core core
depend dep: .depend
include .depend
$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?
$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?
.depend: simhost.c simnode.c simrouter.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
simhost: .depend $(LWIPLIB) $(APPLIB) simhost.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simhost simhost.o $(APPLIB) $(LWIPLIB)
simrouter: .depend $(LWIPLIB) $(APPLIB) simrouter.o
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simrouter simrouter.o $(APPLIB) $(LWIPLIB)
simnode: .depend $(LWIPLIB) $(APPLIB) simnode.o
$(CC) $(CFLAGS) $(LDFLAGS) -pthread -o simnode simnode.o $(APPLIB) $(LWIPLIB)

47
proj/unixsim/README Normal file
View File

@@ -0,0 +1,47 @@
This directory contains an example of how a project using lwIP might
look. It is also the development platform of lwIP, since it can be run
as a user process under FreeBSD or Linux. There are also a number of
example applications (including a simple web server) in the apps/
directory.
Some short instructions on how to build and run lwIP on a FreeBSD or
Linux host. For FreeBSD, the tap interface must be enabled in the
kernel configuration and the kernel must be recompiled. The tap
interface is enabled by adding the line "pseudo-device tap" in the
kernel configuration. See Chapter 9 in the FreeBSD handbook for
instructions on how to build a custom FreeBSD kernel.
* Compile the code. This must be done by using GNU Make. Under
FreeBSD, GNU Make can be found in the ports collection under
/usr/ports/devel/gmake (type "make install distclean" to
install). Under Linux, GNU Make is the default "make".
> gmake (FreeBSD)
> make (Linux)
* The compilation process produces the executable file "simhost". To
run this, you have to be root.
> su (Type password for the root account)
# ./simhost
* The lwIP TCP/IP stack is now running with IP address
192.168.0.2. Some things that you can try:
To see the packets that are going to and from the lwIP stack, run
tcpdump:
# tcpdump -l -n -i tap0
You can ping lwIP:
> ping 192.168.0.2
For a telnet shell, run:
> telnet 192.168.0.2
Finally, "simhost" also includes a simple web server; the URL is
of course http://192.168.0.2/.

55
proj/unixsim/apps/fs.c Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/def.h"
#include "fs.h"
#include "fsdata.h"
#include "fsdata.c"
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
int
fs_open(char *name, struct fs_file *file)
{
struct fsdata_file_noconst *f;
for(f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next) {
if(!strcmp(name, f->name)) {
file->data = f->data;
file->len = f->len;
return 1;
}
}
return 0;
}
/*-----------------------------------------------------------------------------------*/

44
proj/unixsim/apps/fs.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __FS_H__
#define __FS_H__
struct fs_file {
char *data;
int len;
};
/* file must be allocated by caller and will be filled in
by the function. */
int fs_open(char *name, struct fs_file *file);
#endif /* __FS_H__ */

View File

@@ -0,0 +1,191 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Documentation</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
[Documentation]
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Documentation</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<ul>
<li><a href="os.html">Using lwIP with and without an operating
system</a>.
<br><br>
<li>The lwIP source archive contains documentation on how to port lwIP
and how to write applications using the native API. They can also be
found here: <a href="doc/sys_arch.txt">sys_arch.txt</a>, <a
href="doc/rawapi.txt">rawapi.txt</a>.
<br><br>
<li>Selected messages from the mailinglist: <a
href="maillist/msg00231.html">lwIP memory buffers and allocators</a>,
<a href="maillist/msg00227.html">Threads, semaphores and raw interface
question</a>, <a href="maillist/msg00242.html">Threads, semaphores and
raw interface question [2]</a>. <a href="maillist/msg00460.html">Some notes on using lwIP with the development enviroment ADS
1.1 from ARM.</a>
<br><br>
<li>A report describing the design and implementation of an old
version of lwIP. The algorithms and data structures used both in the
protocol implementations and in the sub systems such as the memory and
buffer management systems are described. Also included in this report
is a reference manual for the lwIP sequential API and some code
examples of using lwIP. <a href="doc/lwip.pdf">PDF</a>, <a
href="doc/lwip.ps.gz">.ps.gz</a>.
<br><br>
<li>Slides from a presentation that talks a bit about lwIP: <a
href="doc/pres.pdf">PDF</a> (86k), <a href="doc/pres.ps.gz">.ps.gz</a>
(36k).
</ul>
<p align="justify">
For more documentation regarding lwIP and a proxy architecture to
support TCP/IP communication for small clients, look in <a
href="/~adam/publications.html">Adam Dunkels' masters thesis</a>.
</p>
<p align="justify">
The <a href="mailinglist.html">lwIP mailing list</a> can be used to
discuss lwIP.
</p>
<p align="justify">
For questions or suggestions, please contact the author at <a
href="mailto:Adam Dunkels <adam@sics.se>">Adam Dunkels
&lt;adam@sics.se&gt;</a>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:01 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
[Documentation]
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,232 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Download</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
[Download]
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Download</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<p align="justify">
lwIP is avaliable for download provided that you read and accept <a
href="licence.html">this</a> BSD-style license.
</p>
<h3>Release versions</h3>
<p align="justify">
The latest version is 0.5.3. (Older versions are also provided for an
unknown reason.)
</p>
<ul>
<li>Version 0.5.3 (latest): <a
href="download/?f=lwip-0.5.3.tar.gz">lwip-0.5.3.tar.gz</a>
<br><br>
<li>
<font size="-2">
Obsolete versions: <a
href="download/?f=lwip-0.5.2.tar.gz">lwip-0.5.2.tar.gz</a>
<a
href="download/?f=lwip-0.5.1.tar.gz">lwip-0.5.1.tar.gz</a>
<a
href="download/?f=lwip-0.5.0.tar.gz">lwip-0.5.0.tar.gz</a>
<a
href="download/?f=lwip-0.4.2.tar.gz">lwip-0.4.2.tar.gz</a>
<a
href="download/?f=lwip-0.4.1.tar.gz">lwip-0.4.1.tar.gz</a>
<a
href="download/?f=lwip-0.4.tar.gz">lwip-0.4.tar.gz</a>
<a
href="download/?f=lwip-0.3.1.tar.gz">lwip-0.3.1.tar.gz</a>
<a
href="download/?f=lwip-0.3.tar.gz">lwip-0.3.tar.gz</a>
<a
href="download/?f=lwip-0.2.tar.gz">lwip-0.2.tar.gz</a>
</font>
<br>
</ul>
<h3>Development version</h3>
<p align="justify">
The latest development code from the CVS is also avaliable <a
href="download/?f=lwip-cvs.tar.gz">here</a>. Note that this code may
very well be unstable and might not even compile.
</p>
<h3>Source code online</h3>
<p align="justify">
Joe MacDonald has put an HTML version of the latest lwIP source code
online at <a
href="http://www.deserted.net/lwIP/">http://www.deserted.net/lwIP/</a>.
</p>
<h3>Ports</h3>
<p align="justify">
Florian Shulze has ported lwIP to DJGPP/MS-DOS and to Visual C++
6.0/Win32. They can be downloaded <a
href="http://homepages.fh-giessen.de/~hg10836/dev/djgpp/lwipdjgpptest-0.1.zip">here</a>
(DJGPP/MS-DOS) and <a
href="http://homepages.fh-giessen.de/~hg10836/crowproductions/dev/lwip-win32-msvc-0.1.zip">here</a>
(Visual C++ 6.0/Win32).
</p>
<h3>Add-ons/drivers/applications</h3>
<h4>DHCP client</h4>
<p align="justify">
Leon Woestenberg from Axon Digital Design B.V. has written a CS8900a
network interface driver and is currently developing a DHCP client for
lwIP. They can both be found <a
href="http://www.esrac.ele.tue.nl/~leon/lwip/">here</a>. The plan is
to eventually integrate Leon's DHCP client in the main lwIP
distribution.
</p>
<h4>IGMPv2 implementation</h4>
<p align="justify">
Steve Reynolds of Citel Technologies Ltd. has donated his IGMPv2
implementation for lwIP to the community. It is avaliable for download
<a href="download/igmpfiles.zip">here</a> (note that the copyright and
license differs slightly from lwIP - read the license in the igmp.c
file). The plan is to integrate his code into the main lwIP
distribution.
</p>
<h4>Alternative BSD socket layer</h4>
<p align="justify">
Paul Sheer has incorporated lwIP into his PaulOS system and has
written an alternative BSD socket layer. It is avaliable for download
<a href="download/bsdsocket.c">here</a>. It is copyright Paul Sheer
and licensed under the <a
href="http://www.gnu.org/licenses/gpl.html">GNU GPL</a>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:06 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
[Download]
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 724 B

View File

@@ -0,0 +1,169 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - lwIP source code licence</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>lwIP source code licence</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
Copyright (c) 2001, Swedish Institute of Computer Science.
All rights reserved.<br>
<br>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:<br>
<ol>
<li> Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.<br>
<br>
<li> Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.<br>
<br>
<li> Neither the name of the Institute nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission. <br>
</ol>
<br>
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS `AS IS' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. <br>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:01 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,266 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Links</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
[Links]
<hr>
</td></tr>
<tr>
<td><center><h2>Links</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
lwIP pages:
<ul>
<li><a href="http://www.esrac.ele.tue.nl/~leon/lwip/">Leon Woestenberg's lwIP page</a>
</ul>
Companies using lwIP in their products:
<ul>
<li>UK based <a href="http://www.tangentdevices.co.uk/">Tangent Devices Ltd</a> are incorporating lwIP in their film
and video post-production equipment.
<li><a href="http://www.axon.tv">Axon Digital Design BV</a> in The
Netherlands is merging lwIP with their current IP stack for use in the
Synapse modular broadcasting system.
</ul>
Projects using lwIP:
<ul>
<li><a href="http://www.cdt.luth.se/projects/arena/">The ARENA Project</a> - Hockey players equipped with pulse and breathing sensors running lwIP.<br>
<li><a href="http://bart.sm.luth.se/eis2001/">The Embedded Internet Systems 2001 Student Project</a> - Flow meter and belt tension sensors
running lwIP.<br>
<li><a href="http://dcdev.allusion.net/">KOS</a> - The KOS operating system for
Sega Dreamcast uses lwIP.<br>
</ul>
Other small TCP/IP implementations:
<ul>
<li><a href="http://dunkels.com/adam/uip/">uIP</a> - A very small TCP/IP
implementation, suitable for systems with hundreds of bytes free RAM
and a few kilobytes of free code space.<br>
<li><a href="http://ucip.sourceforge.net/">uC/IP</a> - uC/IP is a BSD-based
TCP/IP protocol stack for microcontrollers.<br>
<li><a href="http://liquorice.sourceforge.net">Liquorice</a> - Liquorice
includes a TCP/IP stack.<br>
<li><a href="http://www.nenie.org/cpcip/">CPC/IP</a> - A TCP/IP stack for
Amstrad CPCs.<br>
<li><a href="http://lng.sourceforge.net/">LUnix</a> - LUnix contains a small
TCP/IP stack.<br>
<li><a href="http://www.sweetcherrie.com/jolz64/jos/">JOS</a> - JOS includes a
TCP/IP implementation.<br>
<li><a href="http://www.csonline.net/bpaddock/tinytcp/default.htm">TinyTCP</a> - A very slim
TCP, IP, and FTP implementation.<br>
<li><a href="http://kyllikki.fluff.org/hardware/wwwpic2/">WWWpic2</a> - Small
HTTP/TCP/IP implementation for a PIC.<br>
<li><a href="http://www.rmbeales.fsnet.co.uk/files/html/picserver/picservd.htm">PIC Web Server</a> - Small HTTP/TCP/IP/SLIP PIC implementation.<br>
</ul>
Very small web servers:
<ul>
<li><a href="http://world.std.com/~fwhite/ace/">webACE</a> - World's Smallest
Web Server.<br>
<li><a href="http://www-ccs.cs.umass.edu/~shri/iPic.html">iPIC</a> - A Match
Head Sized Web Server.<br>
</ul>
Related RFCs:
<ul>
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc791.txt">Internet Protocol</a>, RFC791, September 1981.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc792.txt">Internet Control Message Protocol</a>, RFC792, September 1981.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc768.txt">User Datagram Protocol</a>, RFC768, August 1980.
<li>J. Postel, <a
href="ftp://ftp.ietf.org/rfc/rfc793.txt">Transmission Control Protocol</a>, RFC793, September 1981.
<li>D. D. Clark, <a
href="ftp://ftp.ietf.org/rfc/rfc813.txt">Window and Acknowledgement Strategy in TCP</a>, RFC813, July 1982.
<li>D. D. Clark, <a
href="ftp://ftp.ietf.org/rfc/rfc817.txt">Modularity and Efficiency in Protocol Implementation</a>, RFC817, July 1982.
<li>R. Braden, <a
href="ftp://ftp.ietf.org/rfc/rfc1122.txt">Requirements for Internet Hosts -- Communication Layers</a>, RFC1122, October 1989.
<li>T. Mallory and A. Kullberg, <a
href="ftp://ftp.ietf.org/rfc/rfc1141.txt">Incremental Updating of the Internet Checksum</a>, RFC1141, January 1990.
<li>A. Rijsinghani, <a
href="ftp://ftp.ietf.org/rfc/rfc1624.txt">Computation of the Internet Checksum via Incremental Update</a>, RFC1624, May 1994.
<li>R. Braden, <a
href="ftp://ftp.ietf.org/rfc/rfc1337.txt">TIME-WAIT Assasination Hazards in TCP</a>, RFC1337, May 1992.
<li>B. Carpenter, <a
href="ftp://ftp.ietf.org/rfc/rfc1958.txt">Architectural Principles of the Internet</a>, RFC1958, June 1996.
<li>M. Allman, V. Paxson and W. Stevens, <a
href="ftp://ftp.ietf.org/rfc/rfc2581.txt">TCP Congestion Control</a>, RFC2581, April 1999.
<li>S. Parker and C. Schmechel, <a
href="ftp://ftp.ietf.org/rfc/rfc2398.txt">Some Testing Tools for TCP Implementors</a>, RFC2398, August 1998.
</ul>
Related publications:
<ul>
<li>V. Jacobson. Congestion avoidance and control. In <i>Proceedings of
the SIGCOMM '88 Conference</i>, Stanford, California, August 1988.
<li>V. Jacobson. 4.3BSD TCP header prediction. <i>ACM Computer
Communications Review</i>, 20(2), April 1990.
<li>P. Karn and C. Partridge. Improving round-trip time estimates
in reliablie transport protocols. In <i>Proceedings of the SIGCOMM '87
Conference</i>, Stowe, Vermont, August 1987.
<li>J. Kay and J. Pasquale. Profiling and Reducing Processing
Overheads in TCP/IP. <i>IEEE/ACM Transactions of Networking</i>, 4(6), December 1996.
<li>L. Larzon, M. Degermark, and S. Pink. UDP Lite for
real-time multimedia applications. In <i>Proceedings of the IEEE
International Conference of Communications</i>, Vancouver, British
Columbia, Canada, June 1999.
<li>P. E. McKenney and K. F. Dove. Efcient demultiplexing of
incoming TCP packets. In <i>Proceedings of the SIGCOMM '92 Conference</i>, Baltimore, Maryland, August 1992.
<li>C. Partridge and S. Pink. A faster UDP. <i>IEEE/ACM Transactions
in Networking</i>, 1(4), August 1993.
</ul>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:02 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
[Links]
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,187 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - Mailing list</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
[Mailing list]
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>Mailing list</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<p align="justify">
The lwIP mailing list is the place to discuss lwIP. All topics related
to lwIP, such as porting or using lwIP, writing device drivers or
application programs for lwIP can be discussed here.
</p>
<h3>Archives</h3>
<p align="justify">
Archives can be found <a href="maillist/">here</a>.
</p>
<h3>Subscribe</h3>
<p align="justify">
To subscribe, send a mail to <a
href="mailto:majordomo@sics.se">majordomo@sics.se</a> with the message
<pre>
subscribe lwip
</pre>
in the message body. The subject should be kept blank.
</p>
<p align="justify">
In a few minutes, you should receive a welcome message and some
information regarding the subscription, including instructions for
unsubscribing. Save those messages for future reference.
</p>
<p align="justify">
You are now an lwIP mailing list subscriber!
</p>
<h3>Post</h3>
<p align="justify">
Posting to the lwIP mailing list is a simple as sending a mail to the
address <a href="mailto:lwip@sics.se">lwip@sics.se</a>.
</p>
<h3>Unsubscribe</h3>
<p align="justify">
To subscribe, send a mail to <a
href="mailto:majordomo@sics.se">majordomo@sics.se</a> with the message
<pre>
unsubscribe lwip
</pre>
in the message body. The subject should be kept blank.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:02 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
[Mailing list]
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,225 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack - OS vs non-OS</title></head>
<body bgcolor="white">
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td>
<center><h1>lwIP - A Lightweight TCP/IP Stack</h1></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr>
<tr>
<td><center><h2>OS vs non-OS</h2></center>
</td></tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0"><tr>
<td width="50">
&nbsp;
</td>
<td bgcolor="white" width="540">
<h2>Using lwIP with or without an operating system</h2>
<p align="justify">
There has been a few questions about how lwIP can be used in a
standalone environment (i.e., an environment without a multi-threaded
operating system) lately. The purpose of this document is to describe
how lwIP is designed to be used with and without a multi-threaded
operating system.
</p>
<center><img src="os.png"></center>
<h3>The lwIP single-threaded core</h3>
<p align="justify">
The core of lwIP consists of the actual implementations of the IP,
ICMP, UDP, and TCP protocols, as well as the support functions such as
buffer and memory management. The core components are the only ones
that are needed when lwIP is to be run in a single-threaded (non-OS)
environment.
</p>
<p align="justify">
The core components can be viewed as a software library which has the
following interface:
</p>
<ul>
<li><tt>ip_input(pbuf, netif)</tt>: Takes an IP packet and the incoming network
interface as arguments and does the TCP/IP processing for the packet.
<li><tt>tcp_tmr()</tt>: Should be called every 100 ms. Does all TCP
timer processing such as doing retransmissions.
</ul>
<p align="justify">
Because none of the core functions ever needs to block when run in a
single-threaded environment, the <tt>sys_arch</tt> (the operating
system abstraction layer) does not need to implement locking
semaphores or mailboxes. In future versions of lwIP, the dependancy of
the <tt>sys_arch</tt> will be removed in the single-threaded case.
</p>
<p align="justify">
A simple main loop for a single-threaded system might look
like this:
</p>
<pre>
while(1) {
if(poll_driver(netif) == PACKET_READY) {
pbuf = get_packet(netif);
ip_input(pbuf, netif);
}
if(clock() - last_time == 100 * CLOCK_MS) {
tcp_tmr();
last_time = clock();
}
}
</pre>
<h3>lwIP in a multi-threaded system</h3>
<p align="justify">
lwIP is designed to be able to be run in a multi-threaded system with
applications running in concurrent threads. The model used in this
case is that all TCP/IP processing is done in a single thread. The
application thread communicate with the TCP/IP thread using the
sequential API.
</p>
<center><img src="threads.png"></center>
<p align="justify">
The inter-thread communication is implemented in the two files
<tt>api_lib.c</tt> and <tt>api_msg.c</tt>. The former contains the
functions used by the application programs and the latter implements
the TCP/IP stack interface. A third file, <tt>tcpip.c</tt>, handles
incoming packets and timer events as described in the previous
section.
</p>
<p align="justify">
When run in a multi-threaded environment, incoming packets are handled
by the function <tt>tcpip_input()</tt>, which takes the same arguments
as the <tt>ip_input()</tt> function. The difference between the two
functions is that the <tt>tcpip_input()</tt> function does not process
the incoming packet immediately. It merely puts the packet on a queue
which later is drained by the TCP/IP thread.
</p>
<p align="justify">
When being run in a multi-threaded system, timer events are taken care
of internally in <tt>tcpip.c</tt>.
</p>
<p align="right">
<font size="-1"><i>
$Date: 2002/10/19 13:00:03 $
</i></font>
</p>
</td>
<td width="50">
&nbsp;
</td>
</tr></table>
<table width="640" border="0" cellpadding="0"
cellspacing="0">
<tr><td align="center">
<hr>
<a href="index.html">Introduction</a>
|
<a href="news.html">News</a>
|
<a href="documentation.html">Documentation</a>
|
<a href="mailinglist.html">Mailing list</a>
|
<a href="changelog.html">Changelog</a>
|
<a href="download.html">Download</a>
|
<a href="links.html">Links</a>
<hr>
</td></tr><tr>
<td>
<div align="right">
<a href="http://www.sics.se/~adam/">Adam Dunkels</a></div>
</td>
</tr>
</table>
</body>
</html>

BIN
proj/unixsim/apps/fs/os.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

4188
proj/unixsim/apps/fsdata.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -29,22 +29,21 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_FSDATA_H
#define LWIP_FSDATA_H
#include "lwip/apps/httpd_opts.h"
#include "lwip/apps/fs.h"
#ifndef __FSDATA_H__
#define __FSDATA_H__
struct fsdata_file {
const struct fsdata_file *next;
const unsigned char *name;
const unsigned char *data;
int len;
u8_t flags;
#if HTTPD_PRECALCULATED_CHECKSUM
u16_t chksum_count;
const struct fsdata_chksum *chksum;
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
const char *name;
const char *data;
const int len;
};
#endif /* LWIP_FSDATA_H */
struct fsdata_file_noconst {
struct fsdata_file *next;
char *name;
char *data;
int len;
};
#endif /* __FSDATA_H__ */

244
proj/unixsim/apps/httpd.c Normal file
View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "httpd.h"
#include "lwip/tcp.h"
#include "fs.h"
struct http_state {
char *file;
u32_t left;
u8_t retries;
};
/*-----------------------------------------------------------------------------------*/
static void
conn_err(void *arg, err_t err)
{
struct http_state *hs;
hs = arg;
mem_free(hs);
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
mem_free(hs);
tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
err_t err;
u16_t len;
/* We cannot send more data than space avaliable in the send
buffer. */
if(tcp_sndbuf(pcb) < hs->left) {
len = tcp_sndbuf(pcb);
} else {
len = hs->left;
}
do {
err = tcp_write(pcb, hs->file, len, 0);
if(err == ERR_MEM) {
len /= 2;
}
} while(err == ERR_MEM && len > 1);
if(err == ERR_OK) {
hs->file += len;
hs->left -= len;
/* } else {
printf("send_data: error %s len %d %d\n", lwip_strerr(err), len, tcp_sndbuf(pcb));*/
}
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
struct http_state *hs;
hs = arg;
/* printf("Polll\n");*/
if(hs == NULL) {
/* printf("Null, close\n");*/
tcp_abort(pcb);
return ERR_ABRT;
} else {
++hs->retries;
if(hs->retries == 4) {
tcp_abort(pcb);
return ERR_ABRT;
}
send_data(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct http_state *hs;
hs = arg;
hs->retries = 0;
if(hs->left > 0) {
send_data(pcb, hs);
} else {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
int i;
char *data;
struct fs_file file;
struct http_state *hs;
hs = arg;
if(err == ERR_OK && p != NULL) {
/* Inform TCP that we have taken the data. */
tcp_recved(pcb, p->tot_len);
if(hs->file == NULL) {
data = p->payload;
if(strncmp(data, "GET ", 4) == 0) {
for(i = 0; i < 40; i++) {
if(((char *)data + 4)[i] == ' ' ||
((char *)data + 4)[i] == '\r' ||
((char *)data + 4)[i] == '\n') {
((char *)data + 4)[i] = 0;
}
}
if(*(char *)(data + 4) == '/' &&
*(char *)(data + 5) == 0) {
fs_open("/index.html", &file);
} else if(!fs_open((char *)data + 4, &file)) {
fs_open("/404.html", &file);
}
hs->file = file.data;
hs->left = file.len;
/* printf("data %p len %ld\n", hs->file, hs->left);*/
pbuf_free(p);
send_data(pcb, hs);
/* Tell TCP that we wish be to informed of data that has been
successfully sent by a call to the http_sent() function. */
tcp_sent(pcb, http_sent);
} else {
pbuf_free(p);
close_conn(pcb, hs);
}
} else {
pbuf_free(p);
}
}
if(err == ERR_OK && p == NULL) {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct http_state *hs;
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
hs = mem_malloc(sizeof(struct http_state));
if(hs == NULL) {
printf("http_accept: Out of memory\n");
return ERR_MEM;
}
/* Initialize the structure. */
hs->file = NULL;
hs->left = 0;
hs->retries = 0;
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, hs);
/* Tell TCP that we wish to be informed of incoming data by a call
to the http_recv() function. */
tcp_recv(pcb, http_recv);
tcp_err(pcb, conn_err);
tcp_poll(pcb, http_poll, 4);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 80);
pcb = tcp_listen(pcb);
tcp_accept(pcb, http_accept);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,10 +1,8 @@
/**
* @file
* This file is a posix wrapper for lwip/errno.h.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +11,27 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __HTTPD_H__
#define __HTTPD_H__
#include "lwip/errno.h"
void httpd_init(void);
#endif /* __HTTPD_H__ */

View File

@@ -53,7 +53,7 @@ while($file = <FILES>) {
$fvar = $file;
$fvar =~ s-/-_-g;
$fvar =~ s-\.-_-g;
print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
print(OUTPUT "static const char data".$fvar."[] = {\n");
print(OUTPUT "\t/* $file */\n\t");
for($j = 0; $j < length($file); $j++) {
printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
@@ -61,7 +61,7 @@ while($file = <FILES>) {
printf(OUTPUT "0,\n");
$i = 0;
$i = 0;
while(read(FILE, $data, 1)) {
if($i == 0) {
print(OUTPUT "\t");
@@ -94,4 +94,4 @@ for($i = 0; $i < @fvars; $i++) {
}
print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
print(OUTPUT "#define FS_NUMFILES $i\n");
print(OUTPUT "#define FS_NUMFILES $i");

1056
proj/unixsim/apps/shell.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,8 @@
/**
* @file
* This file is a posix wrapper for lwip/netdb.h.
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +11,27 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __SHELL_H__
#define __SHELL_H__
#include "lwip/netdb.h"
void shell_init(void);
#endif /* __SHELL_H__ */

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/sys.h"
#include "lwip/api.h"
/*-----------------------------------------------------------------------------------*/
static void
tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
/* Bind connection to well known port number 7. */
netconn_bind(conn, NULL, 7);
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while(1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/*printf("accepted new connection %p\n", newconn);*/
/* Process the new connection. */
if(newconn != NULL) {
struct netbuf *buf;
void *data;
u16_t len;
while((buf = netconn_recv(newconn)) != NULL) {
/*printf("Recved\n");*/
do {
netbuf_data(buf, &data, &len);
err = netconn_write(newconn, data, len, NETCONN_COPY);
if(err != ERR_OK) {
/* printf("tcpecho: netconn_write: error \"%s\"\n", lwip_strerr(err));*/
}
} while(netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/*printf("Got EOF, looping\n");*/
/* Close connection and discard connection identifier. */
netconn_delete(newconn);
}
}
}
/*-----------------------------------------------------------------------------------*/
void
tcpecho_init(void)
{
sys_thread_new(tcpecho_thread, NULL);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __TCPECHO_H__
#define __TCPECHO_H__
void tcpecho_init(void);
#endif /* __TCPECHO_H__ */

View File

@@ -1,14 +1,8 @@
/**
* @file
*
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
*/
/*
* Copyright (c) 2010 Inico Technologies Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -17,52 +11,55 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
* Author: Ivan Delamer <delamer@inicotech.com>
*
*
* Please coordinate changes and requests with Ivan Delamer
* <delamer@inicotech.com>
*/
#ifndef LWIP_HDR_ETHIP6_H
#define LWIP_HDR_ETHIP6_H
#include "lwip/api.h"
#include "lwip/sys.h"
#include "lwip/opt.h"
/*-----------------------------------------------------------------------------------*/
void
udpecho_thread(void *arg)
{
static struct netconn *conn;
static struct netbuf *buf;
static struct ip_addr *addr;
static unsigned short port;
char buffer[4096];
conn = netconn_new(NETCONN_UDP);
netconn_bind(conn, NULL, 7);
#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
#include "lwip/pbuf.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr);
#ifdef __cplusplus
while(1) {
buf = netconn_recv(conn);
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
netconn_connect(conn, addr, port);
netconn_send(conn, buf);
netbuf_copy(buf, buffer, sizeof(buffer));
printf("got %s\n", buffer);
netbuf_delete(buf);
}
}
/*-----------------------------------------------------------------------------------*/
void
udpecho_init(void)
{
sys_thread_new(udpecho_thread, NULL);
}
#endif
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
#endif /* LWIP_HDR_ETHIP6_H */

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __UDPECHO_H__
#define __UDPECHO_H__
void udpecho_init(void);
#endif /* __UDPECHO_H__ */

171
proj/unixsim/lwipopts.h Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 1
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 1600
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 16
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 5
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 16
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 3
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 4
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs. */
#define MEMP_NUM_API_MSG 8
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG 8
/* These two control is reclaimer functions should be compiled
in. Should always be turned on (1). */
#define MEM_RECLAIM 1
#define MEMP_RECLAIM 1
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 6
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
#define PBUF_LINK_HLEN 16
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 1
/* TCP Maximum segment size. */
#define TCP_MSS 128
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 256
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS
/* TCP receive window. */
#define TCP_WND 1024
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 1
/* If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 0
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK 1
/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
#define STATS
#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */
#endif /* __LWIPOPTS_H__ */

189
proj/unixsim/simhost.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/tapif.h"
#include "netif/tunif.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/pcapif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
netif_init();
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
#if LWIP_DHCP
{
struct netif *netif;
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
netif = netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input);
netif_set_default(netif);
dhcp_init();
dhcp_start(netif);
}
#else
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
/* netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));*/
netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));
#endif
/* Only used for testing purposes: */
/* IP4_ADDR(&gw, 193,10,66,1);
IP4_ADDR(&ipaddr, 193,10,66,107);
IP4_ADDR(&netmask, 255,255,252,0);
netif_add(&ipaddr, &netmask, &gw, pcapif_init,
tcpip_input);*/
IP4_ADDR(&gw, 127,0,0,1);
IP4_ADDR(&ipaddr, 127,0,0,1);
IP4_ADDR(&netmask, 255,0,0,0);
netif_add(&ipaddr, &netmask, &gw, loopif_init,
tcpip_input);
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
/* sys_timeout(5000, tcp_timeout, NULL);*/
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
/* Block for ever. */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/simhost.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

157
proj/unixsim/simnode.c Normal file
View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "netif/sioslipif.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
IP4_ADDR(&gw, 192,168,1,1);
IP4_ADDR(&ipaddr, 192,168,1,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, unixif_init_client,
tcpip_input));
/* netif_set_default(netif_add(&ipaddr, &netmask, &gw, sioslipif_init1,
tcpip_input)); */
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
sys_timeout(5000, tcp_timeout, NULL);
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/client.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

167
proj/unixsim/simrouter.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include <unistd.h>
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "netif/tapif.h"
#include "netif/unixif.h"
#include "netif/dropif.h"
#include "netif/loopif.h"
#include "netif/tcpdump.h"
#include "netif/sioslipif.h"
#include "lwip/ip_addr.h"
#include "arch/perf.h"
#include "httpd.h"
#include "udpecho.h"
#include "tcpecho.h"
#include "shell.h"
/*-----------------------------------------------------------------------------------*/
static void
tcp_timeout(void *data)
{
#if TCP_DEBUG
tcp_debug_print_pcbs();
#endif /* TCP_DEBUG */
sys_timeout(5000, tcp_timeout, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_init_done(void *arg)
{
sys_sem_t *sem;
sem = arg;
sys_sem_signal(*sem);
}
/*-----------------------------------------------------------------------------------*/
static void
main_thread(void *arg)
{
struct ip_addr ipaddr, netmask, gw;
sys_sem_t sem;
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,2);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, tapif_init,
tcpip_input));
IP4_ADDR(&gw, 192,168,1,1);
IP4_ADDR(&ipaddr, 192,168,1,1);
IP4_ADDR(&netmask, 255,255,255,0);
netif_set_default(netif_add(&ipaddr, &netmask, &gw, unixif_init_server,
tcpip_input));
system("route add 192.168.1.1 192.168.0.2");
system("route add 192.168.1.2 192.168.0.2");
/*netif_set_default(netif_add(&ipaddr, &netmask, &gw, sioslipif_init1,
tcpip_input)); */
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
tcpecho_init();
shell_init();
httpd_init();
udpecho_init();
printf("Applications started.\n");
sys_timeout(5000, tcp_timeout, NULL);
#ifdef MEM_PERF
mem_perf_init("/tmp/memstats.client");
#endif /* MEM_PERF */
sem = sys_sem_new(0);
sys_sem_wait(sem);
}
/*-----------------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
#ifdef PERF
perf_init("/tmp/client.perf");
#endif /* PERF */
#ifdef STATS
stats_init();
#endif /* STATS */
sys_init();
mem_init();
memp_init();
pbuf_init();
tcpdump_init();
printf("System initialized.\n");
sys_thread_new((void *)(main_thread), NULL);
pause();
return 0;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,12 +1,10 @@
api/ - The code for the high-level wrapper API. Not needed if
you use the lowel-level call-back/raw API.
api/ - The code for the API.
apps/ - Higher layer applications that are specifically programmed
with the lwIP low-level raw API.
core/ - The core of the TPC/IP stack; protocol implementations,
memory and buffer management, and the low-level raw API.
arch/ - Architectural specific files are kept here.
core/ - The core files including protocol implementations, memory
and buffer management etc.
include/ - lwIP include files.
netif/ - Generic network interface device drivers are kept here.

View File

@@ -1,177 +0,0 @@
#
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/init.c \
$(LWIPDIR)/core/def.c \
$(LWIPDIR)/core/dns.c \
$(LWIPDIR)/core/inet_chksum.c \
$(LWIPDIR)/core/ip.c \
$(LWIPDIR)/core/mem.c \
$(LWIPDIR)/core/memp.c \
$(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c \
$(LWIPDIR)/core/raw.c \
$(LWIPDIR)/core/stats.c \
$(LWIPDIR)/core/sys.c \
$(LWIPDIR)/core/tcp.c \
$(LWIPDIR)/core/tcp_in.c \
$(LWIPDIR)/core/tcp_out.c \
$(LWIPDIR)/core/timeouts.c \
$(LWIPDIR)/core/udp.c
CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \
$(LWIPDIR)/core/ipv4/dhcp.c \
$(LWIPDIR)/core/ipv4/etharp.c \
$(LWIPDIR)/core/ipv4/icmp.c \
$(LWIPDIR)/core/ipv4/igmp.c \
$(LWIPDIR)/core/ipv4/ip4_frag.c \
$(LWIPDIR)/core/ipv4/ip4.c \
$(LWIPDIR)/core/ipv4/ip4_addr.c
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
$(LWIPDIR)/core/ipv6/ethip6.c \
$(LWIPDIR)/core/ipv6/icmp6.c \
$(LWIPDIR)/core/ipv6/inet6.c \
$(LWIPDIR)/core/ipv6/ip6.c \
$(LWIPDIR)/core/ipv6/ip6_addr.c \
$(LWIPDIR)/core/ipv6/ip6_frag.c \
$(LWIPDIR)/core/ipv6/mld6.c \
$(LWIPDIR)/core/ipv6/nd6.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c \
$(LWIPDIR)/api/api_msg.c \
$(LWIPDIR)/api/err.c \
$(LWIPDIR)/api/netbuf.c \
$(LWIPDIR)/api/netdb.c \
$(LWIPDIR)/api/netifapi.c \
$(LWIPDIR)/api/sockets.c \
$(LWIPDIR)/api/tcpip.c
# NETIFFILES: Files implementing various generic network interface functions
NETIFFILES=$(LWIPDIR)/netif/ethernet.c \
$(LWIPDIR)/netif/slipif.c
# SIXLOWPAN: 6LoWPAN
SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \
# PPPFILES: PPP
PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \
$(LWIPDIR)/netif/ppp/ccp.c \
$(LWIPDIR)/netif/ppp/chap-md5.c \
$(LWIPDIR)/netif/ppp/chap_ms.c \
$(LWIPDIR)/netif/ppp/chap-new.c \
$(LWIPDIR)/netif/ppp/demand.c \
$(LWIPDIR)/netif/ppp/eap.c \
$(LWIPDIR)/netif/ppp/ecp.c \
$(LWIPDIR)/netif/ppp/eui64.c \
$(LWIPDIR)/netif/ppp/fsm.c \
$(LWIPDIR)/netif/ppp/ipcp.c \
$(LWIPDIR)/netif/ppp/ipv6cp.c \
$(LWIPDIR)/netif/ppp/lcp.c \
$(LWIPDIR)/netif/ppp/magic.c \
$(LWIPDIR)/netif/ppp/mppe.c \
$(LWIPDIR)/netif/ppp/multilink.c \
$(LWIPDIR)/netif/ppp/ppp.c \
$(LWIPDIR)/netif/ppp/pppapi.c \
$(LWIPDIR)/netif/ppp/pppcrypt.c \
$(LWIPDIR)/netif/ppp/pppoe.c \
$(LWIPDIR)/netif/ppp/pppol2tp.c \
$(LWIPDIR)/netif/ppp/pppos.c \
$(LWIPDIR)/netif/ppp/upap.c \
$(LWIPDIR)/netif/ppp/utils.c \
$(LWIPDIR)/netif/ppp/vj.c \
$(LWIPDIR)/netif/ppp/polarssl/arc4.c \
$(LWIPDIR)/netif/ppp/polarssl/des.c \
$(LWIPDIR)/netif/ppp/polarssl/md4.c \
$(LWIPDIR)/netif/ppp/polarssl/md5.c \
$(LWIPDIR)/netif/ppp/polarssl/sha1.c
# LWIPNOAPPSFILES: All LWIP files without apps
LWIPNOAPPSFILES=$(COREFILES) \
$(CORE4FILES) \
$(CORE6FILES) \
$(APIFILES) \
$(NETIFFILES) \
$(PPPFILES) \
$(SIXLOWPAN)
# SNMPFILES: SNMPv2c agent
SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \
$(LWIPDIR)/apps/snmp/snmp_core.c \
$(LWIPDIR)/apps/snmp/snmp_mib2.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_system.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \
$(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \
$(LWIPDIR)/apps/snmp/snmp_msg.c \
$(LWIPDIR)/apps/snmp/snmpv3.c \
$(LWIPDIR)/apps/snmp/snmp_netconn.c \
$(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \
$(LWIPDIR)/apps/snmp/snmp_raw.c \
$(LWIPDIR)/apps/snmp/snmp_scalar.c \
$(LWIPDIR)/apps/snmp/snmp_table.c \
$(LWIPDIR)/apps/snmp/snmp_threadsync.c \
$(LWIPDIR)/apps/snmp/snmp_traps.c \
$(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \
$(LWIPDIR)/apps/snmp/snmpv3_dummy.c
# HTTPDFILES: HTTP server
HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \
$(LWIPDIR)/apps/httpd/httpd.c
# LWIPERFFILES: IPERF server
LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c
# SNTPFILES: SNTP client
SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c
# MDNSFILES: MDNS responder
MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c
# NETBIOSNSFILES: NetBIOS name server
NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
# TFTPFILES: TFTP server files
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
# LWIPAPPFILES: All LWIP APPs
LWIPAPPFILES=$(SNMPFILES) \
$(HTTPDFILES) \
$(LWIPERFFILES) \
$(SNTPFILES) \
$(MDNSFILES) \
$(NETBIOSNSFILES) \
$(TFTPFILES)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,8 @@
/**
* @file
* Error Management module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -17,101 +11,49 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/err.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/errno.h"
#if !NO_SYS
/** Table to quickly map an lwIP error (err_t) to a socket error
* by using -err as an index */
static const int err_to_errno_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
EINVAL, /* ERR_VAL -6 Illegal value. */
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
EADDRINUSE, /* ERR_USE -8 Address in use. */
EALREADY, /* ERR_ALREADY -9 Already connecting. */
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
ENOTCONN, /* ERR_CONN -11 Not connected. */
-1, /* ERR_IF -12 Low-level netif error */
ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
ECONNRESET, /* ERR_RST -14 Connection reset. */
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
EIO /* ERR_ARG -16 Illegal argument. */
};
#endif /* !NO_SYS */
#ifdef LWIP_DEBUG
static const char *err_strerr[] = {
"Ok.", /* ERR_OK 0 */
"Out of memory error.", /* ERR_MEM -1 */
"Buffer error.", /* ERR_BUF -2 */
"Timeout.", /* ERR_TIMEOUT -3 */
"Routing problem.", /* ERR_RTE -4 */
"Operation in progress.", /* ERR_INPROGRESS -5 */
"Illegal value.", /* ERR_VAL -6 */
"Operation would block.", /* ERR_WOULDBLOCK -7 */
"Address in use.", /* ERR_USE -8 */
"Already connecting.", /* ERR_ALREADY -9 */
"Already connected.", /* ERR_ISCONN -10 */
"Not connected.", /* ERR_CONN -11 */
"Low-level netif error.", /* ERR_IF -12 */
"Connection aborted.", /* ERR_ABRT -13 */
"Connection reset.", /* ERR_RST -14 */
"Connection closed.", /* ERR_CLSD -15 */
"Illegal argument." /* ERR_ARG -16 */
static char *err_strerr[] = {"Ok.",
"Out of memory error.",
"Buffer error.",
"Connection aborted.",
"Connection reset.",
"Connection closed.",
"Not connected.",
"Illegal value.",
"Illegal argument.",
"Routing problem.",
"Address in use."
};
/**
* Convert an lwip internal error to a string representation.
*
* @param err an lwip internal err_t
* @return a string representation for err
*/
const char *
/*-----------------------------------------------------------------------------------*/
char *
lwip_strerr(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) {
return "Unknown error.";
}
return err_strerr[-err];
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */
#if !NO_SYS
int
err_to_errno(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
return EIO;
}
return err_to_errno_table[-err];
}
#endif /* !NO_SYS */

View File

@@ -1,246 +0,0 @@
/**
* @file
* Network buffer management
*
* @defgroup netbuf Network buffers
* @ingroup netconn
* Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
* to avoid copying data around.\n
* Buffers must not be shared accross multiple threads, all functions except
* netbuf_new() and netbuf_delete() are not thread-safe.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
#include "lwip/netbuf.h"
#include "lwip/memp.h"
#include <string.h>
/**
* @ingroup netbuf
* Create (allocate) and initialize a new netbuf.
* The netbuf doesn't yet contain a packet buffer!
*
* @return a pointer to a new netbuf
* NULL on lack of memory
*/
struct
netbuf *netbuf_new(void)
{
struct netbuf *buf;
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf != NULL) {
memset(buf, 0, sizeof(struct netbuf));
}
return buf;
}
/**
* @ingroup netbuf
* Deallocate a netbuf allocated by netbuf_new().
*
* @param buf pointer to a netbuf allocated by netbuf_new()
*/
void
netbuf_delete(struct netbuf *buf)
{
if (buf != NULL) {
if (buf->p != NULL) {
pbuf_free(buf->p);
buf->p = buf->ptr = NULL;
}
memp_free(MEMP_NETBUF, buf);
}
}
/**
* @ingroup netbuf
* Allocate memory for a packet buffer for a given netbuf.
*
* @param buf the netbuf for which to allocate a packet buffer
* @param size the size of the packet buffer to allocate
* @return pointer to the allocated memory
* NULL if no memory could be allocated
*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
/* Deallocate any previously allocated memory. */
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
if (buf->p == NULL) {
return NULL;
}
LWIP_ASSERT("check that first pbuf can hold size",
(buf->p->len >= size));
buf->ptr = buf->p;
return buf->p->payload;
}
/**
* @ingroup netbuf
* Free the packet buffer included in a netbuf
*
* @param buf pointer to the netbuf which contains the packet buffer to free
*/
void
netbuf_free(struct netbuf *buf)
{
LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = buf->ptr = NULL;
}
/**
* @ingroup netbuf
* Let a netbuf reference existing (non-volatile) data.
*
* @param buf netbuf which should reference the data
* @param dataptr pointer to the data to reference
* @param size size of the data
* @return ERR_OK if data is referenced
* ERR_MEM if data couldn't be referenced due to lack of memory
*/
err_t
netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
{
LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
if (buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
if (buf->p == NULL) {
buf->ptr = NULL;
return ERR_MEM;
}
((struct pbuf_rom*)buf->p)->payload = dataptr;
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
return ERR_OK;
}
/**
* @ingroup netbuf
* Chain one netbuf to another (@see pbuf_chain)
*
* @param head the first netbuf
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
pbuf_cat(head->p, tail->p);
head->ptr = head->p;
memp_free(MEMP_NETBUF, tail);
}
/**
* @ingroup netbuf
* Get the data pointer and length of the data inside a netbuf.
*
* @param buf netbuf to get the data from
* @param dataptr pointer to a void pointer where to store the data pointer
* @param len pointer to an u16_t where the length of the data is stored
* @return ERR_OK if the information was retrieved,
* ERR_BUF on error.
*/
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
if (buf->ptr == NULL) {
return ERR_BUF;
}
*dataptr = buf->ptr->payload;
*len = buf->ptr->len;
return ERR_OK;
}
/**
* @ingroup netbuf
* Move the current data pointer of a packet buffer contained in a netbuf
* to the next part.
* The packet buffer itself is not modified.
*
* @param buf the netbuf to modify
* @return -1 if there is no next part
* 1 if moved to the next part but now there is no next part
* 0 if moved to the next part and there are still more parts
*/
s8_t
netbuf_next(struct netbuf *buf)
{
LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
if (buf->ptr->next == NULL) {
return -1;
}
buf->ptr = buf->ptr->next;
if (buf->ptr->next == NULL) {
return 1;
}
return 0;
}
/**
* @ingroup netbuf
* Move the current data pointer of a packet buffer contained in a netbuf
* to the beginning of the packet.
* The packet buffer itself is not modified.
*
* @param buf the netbuf to modify
*/
void
netbuf_first(struct netbuf *buf)
{
LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
buf->ptr = buf->p;
}
#endif /* LWIP_NETCONN */

View File

@@ -1,413 +0,0 @@
/**
* @file
* API functions for name resolving
*
* @defgroup netdbapi NETDB API
* @ingroup socket
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#include "lwip/netdb.h"
#if LWIP_DNS && LWIP_SOCKET
#include "lwip/err.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/ip_addr.h"
#include "lwip/api.h"
#include "lwip/dns.h"
#include <string.h>
#include <stdlib.h>
/** helper struct for gethostbyname_r to access the char* buffer */
struct gethostbyname_r_helper {
ip_addr_t *addr_list[2];
ip_addr_t addr;
char *aliases;
};
/** h_errno is exported in netdb.h for access by applications. */
#if LWIP_DNS_API_DECLARE_H_ERRNO
int h_errno;
#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
/** define "hostent" variables storage: 0 if we use a static (but unprotected)
* set of variables for lwip_gethostbyname, 1 if we use a local storage */
#ifndef LWIP_DNS_API_HOSTENT_STORAGE
#define LWIP_DNS_API_HOSTENT_STORAGE 0
#endif
/** define "hostent" variables storage */
#if LWIP_DNS_API_HOSTENT_STORAGE
#define HOSTENT_STORAGE
#else
#define HOSTENT_STORAGE static
#endif /* LWIP_DNS_API_STATIC_HOSTENT */
/**
* Returns an entry containing addresses of address family AF_INET
* for the host with name name.
* Due to dns_gethostbyname limitations, only one address is returned.
*
* @param name the hostname to resolve
* @return an entry containing addresses of address family AF_INET
* for the host with name name
*/
struct hostent*
lwip_gethostbyname(const char *name)
{
err_t err;
ip_addr_t addr;
/* buffer variables for lwip_gethostbyname() */
HOSTENT_STORAGE struct hostent s_hostent;
HOSTENT_STORAGE char *s_aliases;
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1];
/* query host IP address */
err = netconn_gethostbyname(name, &addr);
if (err != ERR_OK) {
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
h_errno = HOST_NOT_FOUND;
return NULL;
}
/* fill hostent */
s_hostent_addr = addr;
s_phostent_addr[0] = &s_hostent_addr;
s_phostent_addr[1] = NULL;
strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
s_hostname[DNS_MAX_NAME_LENGTH] = 0;
s_hostent.h_name = s_hostname;
s_aliases = NULL;
s_hostent.h_aliases = &s_aliases;
s_hostent.h_addrtype = AF_INET;
s_hostent.h_length = sizeof(ip_addr_t);
s_hostent.h_addr_list = (char**)&s_phostent_addr;
#if DNS_DEBUG
/* dump hostent */
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases));
/* h_aliases are always empty */
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list));
if (s_hostent.h_addr_list != NULL) {
u8_t idx;
for (idx=0; s_hostent.h_addr_list[idx]; idx++) {
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
}
}
#endif /* DNS_DEBUG */
#if LWIP_DNS_API_HOSTENT_STORAGE
/* this function should return the "per-thread" hostent after copy from s_hostent */
return sys_thread_hostent(&s_hostent);
#else
return &s_hostent;
#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
}
/**
* Thread-safe variant of lwip_gethostbyname: instead of using a static
* buffer, this function takes buffer and errno pointers as arguments
* and uses these for the result.
*
* @param name the hostname to resolve
* @param ret pre-allocated struct where to store the result
* @param buf pre-allocated buffer where to store additional data
* @param buflen the size of buf
* @param result pointer to a hostent pointer that is set to ret on success
* and set to zero on error
* @param h_errnop pointer to an int where to store errors (instead of modifying
* the global h_errno)
* @return 0 on success, non-zero on error, additional error information
* is stored in *h_errnop instead of h_errno to be thread-safe
*/
int
lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
size_t buflen, struct hostent **result, int *h_errnop)
{
err_t err;
struct gethostbyname_r_helper *h;
char *hostname;
size_t namelen;
int lh_errno;
if (h_errnop == NULL) {
/* ensure h_errnop is never NULL */
h_errnop = &lh_errno;
}
if (result == NULL) {
/* not all arguments given */
*h_errnop = EINVAL;
return -1;
}
/* first thing to do: set *result to nothing */
*result = NULL;
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
/* not all arguments given */
*h_errnop = EINVAL;
return -1;
}
namelen = strlen(name);
if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
/* buf can't hold the data needed + a copy of name */
*h_errnop = ERANGE;
return -1;
}
h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
/* query host IP address */
err = netconn_gethostbyname(name, &h->addr);
if (err != ERR_OK) {
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
*h_errnop = HOST_NOT_FOUND;
return -1;
}
/* copy the hostname into buf */
MEMCPY(hostname, name, namelen);
hostname[namelen] = 0;
/* fill hostent */
h->addr_list[0] = &h->addr;
h->addr_list[1] = NULL;
h->aliases = NULL;
ret->h_name = hostname;
ret->h_aliases = &h->aliases;
ret->h_addrtype = AF_INET;
ret->h_length = sizeof(ip_addr_t);
ret->h_addr_list = (char**)&h->addr_list;
/* set result != NULL */
*result = ret;
/* return success */
return 0;
}
/**
* Frees one or more addrinfo structures returned by getaddrinfo(), along with
* any additional storage associated with those structures. If the ai_next field
* of the structure is not null, the entire list of structures is freed.
*
* @param ai struct addrinfo to free
*/
void
lwip_freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next;
while (ai != NULL) {
next = ai->ai_next;
memp_free(MEMP_NETDB, ai);
ai = next;
}
}
/**
* Translates the name of a service location (for example, a host name) and/or
* a service name and returns a set of socket addresses and associated
* information to be used in creating a socket with which to address the
* specified service.
* Memory for the result is allocated internally and must be freed by calling
* lwip_freeaddrinfo()!
*
* Due to a limitation in dns_gethostbyname, only the first address of a
* host is returned.
* Also, service names are not supported (only port numbers)!
*
* @param nodename descriptive name or address string of the host
* (may be NULL -> local address)
* @param servname port number as string of NULL
* @param hints structure containing input values that set socktype and protocol
* @param res pointer to a pointer where to store the result (set to NULL on failure)
* @return 0 on success, non-zero on failure
*
* @todo: implement AI_V4MAPPED, AI_ADDRCONFIG
*/
int
lwip_getaddrinfo(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
err_t err;
ip_addr_t addr;
struct addrinfo *ai;
struct sockaddr_storage *sa = NULL;
int port_nr = 0;
size_t total_size;
size_t namelen = 0;
int ai_family;
if (res == NULL) {
return EAI_FAIL;
}
*res = NULL;
if ((nodename == NULL) && (servname == NULL)) {
return EAI_NONAME;
}
if (hints != NULL) {
ai_family = hints->ai_family;
if ((ai_family != AF_UNSPEC)
#if LWIP_IPV4
&& (ai_family != AF_INET)
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
&& (ai_family != AF_INET6)
#endif /* LWIP_IPV6 */
) {
return EAI_FAMILY;
}
} else {
ai_family = AF_UNSPEC;
}
if (servname != NULL) {
/* service name specified: convert to port number
* @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */
port_nr = atoi(servname);
if ((port_nr <= 0) || (port_nr > 0xffff)) {
return EAI_SERVICE;
}
}
if (nodename != NULL) {
/* service location specified, try to resolve */
if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) {
/* no DNS lookup, just parse for an address string */
if (!ipaddr_aton(nodename, &addr)) {
return EAI_NONAME;
}
#if LWIP_IPV4 && LWIP_IPV6
if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) ||
(IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) {
return EAI_NONAME;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
} else {
#if LWIP_IPV4 && LWIP_IPV6
/* AF_UNSPEC: prefer IPv4 */
u8_t type = NETCONN_DNS_IPV4_IPV6;
if (ai_family == AF_INET) {
type = NETCONN_DNS_IPV4;
} else if (ai_family == AF_INET6) {
type = NETCONN_DNS_IPV6;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
if (err != ERR_OK) {
return EAI_FAIL;
}
}
} else {
/* service location specified, use loopback address */
if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) {
ip_addr_set_any(ai_family == AF_INET6, &addr);
} else {
ip_addr_set_loopback(ai_family == AF_INET6, &addr);
}
}
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
if (nodename != NULL) {
namelen = strlen(nodename);
if (namelen > DNS_MAX_NAME_LENGTH) {
/* invalid name length */
return EAI_FAIL;
}
LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size);
total_size += namelen + 1;
}
/* If this fails, please report to lwip-devel! :-) */
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
total_size <= NETDB_ELEM_SIZE);
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
if (ai == NULL) {
return EAI_MEMORY;
}
memset(ai, 0, total_size);
/* cast through void* to get rid of alignment warnings */
sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo));
if (IP_IS_V6_VAL(addr)) {
#if LWIP_IPV6
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
/* set up sockaddr */
inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr));
sa6->sin6_family = AF_INET6;
sa6->sin6_len = sizeof(struct sockaddr_in6);
sa6->sin6_port = lwip_htons((u16_t)port_nr);
ai->ai_family = AF_INET6;
#endif /* LWIP_IPV6 */
} else {
#if LWIP_IPV4
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
/* set up sockaddr */
inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
sa4->sin_family = AF_INET;
sa4->sin_len = sizeof(struct sockaddr_in);
sa4->sin_port = lwip_htons((u16_t)port_nr);
ai->ai_family = AF_INET;
#endif /* LWIP_IPV4 */
}
/* set up addrinfo */
if (hints != NULL) {
/* copy socktype & protocol from hints if specified */
ai->ai_socktype = hints->ai_socktype;
ai->ai_protocol = hints->ai_protocol;
}
if (nodename != NULL) {
/* copy nodename to canonname if specified */
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
MEMCPY(ai->ai_canonname, nodename, namelen);
ai->ai_canonname[namelen] = 0;
}
ai->ai_addrlen = sizeof(struct sockaddr_storage);
ai->ai_addr = (struct sockaddr*)sa;
*res = ai;
return 0;
}
#endif /* LWIP_DNS && LWIP_SOCKET */

View File

@@ -1,221 +0,0 @@
/**
* @file
* Network Interface Sequential API module
*
* @defgroup netifapi NETIF API
* @ingroup sequential_api
* Thread-safe functions to be called from non-TCPIP threads
*
* @defgroup netifapi_netif NETIF related
* @ingroup netifapi
* To be called from non-TCPIP threads
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#include "lwip/opt.h"
#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
#include "lwip/netifapi.h"
#include "lwip/memp.h"
#include "lwip/priv/tcpip_priv.h"
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name)
#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
/**
* Call netif_add() inside the tcpip_thread context.
*/
static err_t
netifapi_do_netif_add(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
if (!netif_add( msg->netif,
#if LWIP_IPV4
API_EXPR_REF(msg->msg.add.ipaddr),
API_EXPR_REF(msg->msg.add.netmask),
API_EXPR_REF(msg->msg.add.gw),
#endif /* LWIP_IPV4 */
msg->msg.add.state,
msg->msg.add.init,
msg->msg.add.input)) {
return ERR_IF;
} else {
return ERR_OK;
}
}
#if LWIP_IPV4
/**
* Call netif_set_addr() inside the tcpip_thread context.
*/
static err_t
netifapi_do_netif_set_addr(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
netif_set_addr( msg->netif,
API_EXPR_REF(msg->msg.add.ipaddr),
API_EXPR_REF(msg->msg.add.netmask),
API_EXPR_REF(msg->msg.add.gw));
return ERR_OK;
}
#endif /* LWIP_IPV4 */
/**
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
* tcpip_thread context.
*/
static err_t
netifapi_do_netif_common(struct tcpip_api_call_data *m)
{
/* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */
struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
if (msg->msg.common.errtfunc != NULL) {
return msg->msg.common.errtfunc(msg->netif);
} else {
msg->msg.common.voidfunc(msg->netif);
return ERR_OK;
}
}
/**
* @ingroup netifapi_netif
* Call netif_add() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @note for params @see netif_add()
*/
err_t
netifapi_netif_add(struct netif *netif,
#if LWIP_IPV4
const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
#endif /* LWIP_IPV4 */
void *state, netif_init_fn init, netif_input_fn input)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
#if LWIP_IPV4
if (ipaddr == NULL) {
ipaddr = IP4_ADDR_ANY4;
}
if (netmask == NULL) {
netmask = IP4_ADDR_ANY4;
}
if (gw == NULL) {
gw = IP4_ADDR_ANY4;
}
#endif /* LWIP_IPV4 */
NETIFAPI_VAR_REF(msg).netif = netif;
#if LWIP_IPV4
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
#endif /* LWIP_IPV4 */
NETIFAPI_VAR_REF(msg).msg.add.state = state;
NETIFAPI_VAR_REF(msg).msg.add.init = init;
NETIFAPI_VAR_REF(msg).msg.add.input = input;
err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
#if LWIP_IPV4
/**
* @ingroup netifapi_netif
* Call netif_set_addr() in a thread-safe way by running that function inside the
* tcpip_thread context.
*
* @note for params @see netif_set_addr()
*/
err_t
netifapi_netif_set_addr(struct netif *netif,
const ip4_addr_t *ipaddr,
const ip4_addr_t *netmask,
const ip4_addr_t *gw)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
if (ipaddr == NULL) {
ipaddr = IP4_ADDR_ANY4;
}
if (netmask == NULL) {
netmask = IP4_ADDR_ANY4;
}
if (gw == NULL) {
gw = IP4_ADDR_ANY4;
}
NETIFAPI_VAR_REF(msg).netif = netif;
NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr);
NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw);
err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
#endif /* LWIP_IPV4 */
/**
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
* way by running that function inside the tcpip_thread context.
*
* @note use only for functions where there is only "netif" parameter.
*/
err_t
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
netifapi_errt_fn errtfunc)
{
err_t err;
NETIFAPI_VAR_DECLARE(msg);
NETIFAPI_VAR_ALLOC(msg);
NETIFAPI_VAR_REF(msg).netif = netif;
NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
NETIFAPI_VAR_FREE(msg);
return err;
}
#endif /* LWIP_NETIF_API */

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,8 @@
/**
* @file
* Sequential API Main thread module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@@ -17,502 +11,127 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/debug.h"
#include "lwip/opt.h"
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
#include "lwip/priv/tcpip_priv.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
#include "lwip/init.h"
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
/* global variables */
static tcpip_init_done_fn tcpip_init_done;
#include "lwip/tcpip.h"
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */
/*-----------------------------------------------------------------------------------*/
static void
tcpip_tcp_timer(void *arg)
{
tcp_tmr();
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_TIMERS
/* wait for a message, timeouts are processed while waiting */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
#else /* LWIP_TIMERS */
/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
#endif /* LWIP_TIMERS */
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
* (unless access to them is not locked). Other threads communicate with this
* thread using message boxes.
*
* It also starts all the timers to make sure they are running in the right
* thread context.
*
* @param arg unused argument
*/
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
LWIP_UNUSED_ARG(arg);
if (tcpip_init_done != NULL) {
ip_init();
udp_init();
tcp_init();
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
if(tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
LOCK_TCPIP_CORE();
while (1) { /* MAIN Loop */
UNLOCK_TCPIP_CORE();
LWIP_TCPIP_THREAD_ALIVE();
/* wait for a message, timeouts are processed while waiting */
TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
LOCK_TCPIP_CORE();
if (msg == NULL) {
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
continue;
}
switch (msg->type) {
#if !LWIP_TCPIP_CORE_LOCKING
while(1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg);
switch(msg->type) {
case TCPIP_MSG_API:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
msg->msg.api_msg.function(msg->msg.api_msg.msg);
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", msg));
api_msg_input(msg->msg.apimsg);
break;
case TCPIP_MSG_API_CALL:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
sys_sem_signal(msg->msg.api_call.sem);
case TCPIP_MSG_INPUT:
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", msg));
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING */
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
case TCPIP_MSG_INPKT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
case TCPIP_MSG_TIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_UNTIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_CALLBACK_STATIC:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
break;
default:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
break;
}
memp_freep(MEMP_TCPIP_MSG, msg);
}
}
/**
* Pass a received packet to tcpip_thread for input processing
*
* @param p the received packet
* @param inp the network interface on which the packet was received
* @param input_fn input function to call
*/
err_t
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
{
#if LWIP_TCPIP_CORE_LOCKING_INPUT
err_t ret;
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
LOCK_TCPIP_CORE();
ret = input_fn(p, inp);
UNLOCK_TCPIP_CORE();
return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPKT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
msg->msg.inp.input_fn = input_fn;
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
/**
* @ingroup lwip_os
* Pass a received packet to tcpip_thread for input processing with
* ethernet_input or ip_input. Don't call directly, pass to netif_add()
* and call netif->input().
*
* @param p the received packet, p->payload pointing to the Ethernet header or
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
* NETIF_FLAG_ETHERNET flags)
* @param inp the network interface on which the packet was received
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_ETHERNET
if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
return tcpip_inpkt(p, inp, ethernet_input);
} else
#endif /* LWIP_ETHERNET */
return tcpip_inpkt(p, inp, ip_input);
}
/**
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
*
* @param function the function to call
* @param ctx parameter passed to f
* @param block 1 to block until the request is posted, 0 to non-blocking mode
* @return ERR_OK if the function was called, another err_t if not
*/
err_t
tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
if (block) {
sys_mbox_post(&mbox, msg);
} else {
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
pbuf_free(p);
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPUT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
/**
* call sys_timeout in tcpip_thread
*
* @param msecs time in milliseconds for timeout
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_TIMEOUT;
msg->msg.tmo.msecs = msecs;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&mbox, msg);
return ERR_OK;
}
/**
* call sys_untimeout in tcpip_thread
*
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_untimeout(sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_UNTIMEOUT;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&mbox, msg);
return ERR_OK;
}
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
/**
* Sends a message to TCPIP thread to call a function. Caller thread blocks on
* on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
* this has to be done by the user.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
* with least runtime overhead.
*
* @param fn function to be called from TCPIP thread
* @param apimsg argument to API function
* @param sem semaphore to wait on
* @return ERR_OK if the function was called, another err_t if not
*/
err_t
tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem)
{
#if LWIP_TCPIP_CORE_LOCKING
LWIP_UNUSED_ARG(sem);
LOCK_TCPIP_CORE();
fn(apimsg);
UNLOCK_TCPIP_CORE();
return ERR_OK;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(sem, 0);
TCPIP_MSG_VAR_FREE(msg);
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* Synchronously calls function in TCPIP thread and waits for its completion.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
* LWIP_NETCONN_SEM_PER_THREAD.
* If not, a semaphore is created and destroyed on every call which is usually
* an expensive/slow operation.
* @param fn Function to call
* @param call Call parameters
* @return Return value from tcpip_api_call_fn
*/
err_t
tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
{
#if LWIP_TCPIP_CORE_LOCKING
err_t err;
LOCK_TCPIP_CORE();
err = fn(call);
UNLOCK_TCPIP_CORE();
return err;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
err_t err = sys_sem_new(&call->sem, 0);
if (err != ERR_OK) {
return err;
}
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
#if LWIP_NETCONN_SEM_PER_THREAD
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
#else /* LWIP_NETCONN_SEM_PER_THREAD */
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
TCPIP_MSG_VAR_FREE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(&call->sem);
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
return call->err;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* Allocate a structure for a static callback message and initialize it.
* This is intended to be used to send "static" messages from interrupt context.
*
* @param function the function to call
* @param ctx parameter passed to function
* @return a struct pointer to pass to tcpip_trycallback().
*/
struct tcpip_callback_msg*
tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return NULL;
}
msg->type = TCPIP_MSG_CALLBACK_STATIC;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
return (struct tcpip_callback_msg*)msg;
}
/**
* Free a callback message allocated by tcpip_callbackmsg_new().
*
* @param msg the message to free
*/
/*-----------------------------------------------------------------------------------*/
void
tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
tcpip_apimsg(struct api_msg *apimsg)
{
memp_free(MEMP_TCPIP_MSG_API, msg);
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
}
msg->type = TCPIP_MSG_API;
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/**
* Try to post a callback-message to the tcpip_thread mbox
* This is intended to be used to send "static" messages from interrupt context.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost() return code
*/
err_t
tcpip_trycallback(struct tcpip_callback_msg* msg)
{
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
return sys_mbox_trypost(&mbox, msg);
}
/**
* @ingroup lwip_os
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
tcpip_init(void (* initfunc)(void *), void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
mbox = sys_mbox_new();
sys_thread_new((void *)tcpip_thread, NULL);
}
/*-----------------------------------------------------------------------------------*/
/**
* Simple callback function used with tcpip_callback to free a pbuf
* (pbuf_free has a wrong signature for tcpip_callback)
*
* @param p The pbuf (chain) to be dereferenced.
*/
static void
pbuf_free_int(void *p)
{
struct pbuf *q = (struct pbuf *)p;
pbuf_free(q);
}
/**
* A simple wrapper function that allows you to free a pbuf from interrupt context.
*
* @param p The pbuf (chain) to be dereferenced.
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
pbuf_free_callback(struct pbuf *p)
{
return tcpip_callback_with_block(pbuf_free_int, p, 0);
}
/**
* A simple wrapper function that allows you to free heap memory from
* interrupt context.
*
* @param m the heap memory to free
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
mem_free_callback(void *m)
{
return tcpip_callback_with_block(mem_free, m, 0);
}
#endif /* !NO_SYS */

View File

@@ -1,179 +0,0 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/apps/httpd_opts.h"
#include "lwip/def.h"
#include "lwip/apps/fs.h"
#include "fsdata.h"
#include <string.h>
#if HTTPD_USE_CUSTOM_FSDATA
#include "fsdata_custom.c"
#else /* HTTPD_USE_CUSTOM_FSDATA */
#include "fsdata.c"
#endif /* HTTPD_USE_CUSTOM_FSDATA */
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_CUSTOM_FILES
int fs_open_custom(struct fs_file *file, const char *name);
void fs_close_custom(struct fs_file *file);
#if LWIP_HTTPD_FS_ASYNC_READ
u8_t fs_canread_custom(struct fs_file *file);
u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_read_custom(struct fs_file *file, char *buffer, int count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#endif /* LWIP_HTTPD_CUSTOM_FILES */
/*-----------------------------------------------------------------------------------*/
err_t
fs_open(struct fs_file *file, const char *name)
{
const struct fsdata_file *f;
if ((file == NULL) || (name == NULL)) {
return ERR_ARG;
}
#if LWIP_HTTPD_CUSTOM_FILES
if (fs_open_custom(file, name)) {
file->is_custom_file = 1;
return ERR_OK;
}
file->is_custom_file = 0;
#endif /* LWIP_HTTPD_CUSTOM_FILES */
for (f = FS_ROOT; f != NULL; f = f->next) {
if (!strcmp(name, (const char *)f->name)) {
file->data = (const char *)f->data;
file->len = f->len;
file->index = f->len;
file->pextension = NULL;
file->flags = f->flags;
#if HTTPD_PRECALCULATED_CHECKSUM
file->chksum_count = f->chksum_count;
file->chksum = f->chksum;
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
#if LWIP_HTTPD_FILE_STATE
file->state = fs_state_init(file, name);
#endif /* #if LWIP_HTTPD_FILE_STATE */
return ERR_OK;
}
}
/* file not found */
return ERR_VAL;
}
/*-----------------------------------------------------------------------------------*/
void
fs_close(struct fs_file *file)
{
#if LWIP_HTTPD_CUSTOM_FILES
if (file->is_custom_file) {
fs_close_custom(file);
}
#endif /* LWIP_HTTPD_CUSTOM_FILES */
#if LWIP_HTTPD_FILE_STATE
fs_state_free(file, file->state);
#endif /* #if LWIP_HTTPD_FILE_STATE */
LWIP_UNUSED_ARG(file);
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_DYNAMIC_FILE_READ
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int
fs_read(struct fs_file *file, char *buffer, int count)
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
{
int read;
if(file->index == file->len) {
return FS_READ_EOF;
}
#if LWIP_HTTPD_FS_ASYNC_READ
LWIP_UNUSED_ARG(callback_fn);
LWIP_UNUSED_ARG(callback_arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#if LWIP_HTTPD_CUSTOM_FILES
if (file->is_custom_file) {
#if LWIP_HTTPD_FS_ASYNC_READ
return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
return fs_read_custom(file, buffer, count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
}
#endif /* LWIP_HTTPD_CUSTOM_FILES */
read = file->len - file->index;
if(read > count) {
read = count;
}
MEMCPY(buffer, (file->data + file->index), read);
file->index += read;
return(read);
}
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
{
if (file != NULL) {
#if LWIP_HTTPD_FS_ASYNC_READ
#if LWIP_HTTPD_CUSTOM_FILES
if (!fs_canread_custom(file)) {
if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
return 0;
}
}
#else /* LWIP_HTTPD_CUSTOM_FILES */
LWIP_UNUSED_ARG(callback_fn);
LWIP_UNUSED_ARG(callback_arg);
#endif /* LWIP_HTTPD_CUSTOM_FILES */
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
}
return 1;
}
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
/*-----------------------------------------------------------------------------------*/
int
fs_bytes_left(struct fs_file *file)
{
return file->len - file->index;
}

View File

@@ -1,21 +0,0 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
<body bgcolor="white" text="black">
<table width="100%">
<tr valign="top"><td width="80">
<a href="http://www.sics.se/"><img src="/img/sics.gif"
border="0" alt="SICS logo" title="SICS logo"></a>
</td><td width="500">
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
<h2>404 - Page not found</h2>
<p>
Sorry, the page you are requesting was not found on this
server.
</p>
</td><td>
&nbsp;
</td></tr>
</table>
</body>
</html>

View File

@@ -1,47 +0,0 @@
<html>
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head>
<body bgcolor="white" text="black">
<table width="100%">
<tr valign="top"><td width="80">
<a href="http://www.sics.se/"><img src="/img/sics.gif"
border="0" alt="SICS logo" title="SICS logo"></a>
</td><td width="500">
<h1>lwIP - A Lightweight TCP/IP Stack</h1>
<p>
The web page you are watching was served by a simple web
server running on top of the lightweight TCP/IP stack <a
href="http://www.sics.se/~adam/lwip/">lwIP</a>.
</p>
<p>
lwIP is an open source implementation of the TCP/IP
protocol suite that was originally written by <a
href="http://www.sics.se/~adam/lwip/">Adam Dunkels
of the Swedish Institute of Computer Science</a> but now is
being actively developed by a team of developers
distributed world-wide. Since it's release, lwIP has
spurred a lot of interest and has been ported to several
platforms and operating systems. lwIP can be used either
with or without an underlying OS.
</p>
<p>
The focus of the lwIP TCP/IP implementation is to reduce
the RAM usage while still having a full scale TCP. This
makes lwIP suitable for use in embedded systems with tens
of kilobytes of free RAM and room for around 40 kilobytes
of code ROM.
</p>
<p>
More information about lwIP can be found at the lwIP
homepage at <a
href="http://savannah.nongnu.org/projects/lwip/">http://savannah.nongnu.org/projects/lwip/</a>
or at the lwIP wiki at <a
href="http://lwip.wikia.com/">http://lwip.wikia.com/</a>.
</p>
</td><td>
&nbsp;
</td></tr>
</table>
</body>
</html>

View File

@@ -1,298 +0,0 @@
#include "lwip/apps/fs.h"
#include "lwip/def.h"
#include "fsdata.h"
#define file_NULL (struct fsdata_file *) NULL
static const unsigned int dummy_align__img_sics_gif = 0;
static const unsigned char data__img_sics_gif[] = {
/* /img/sics.gif (14 chars) */
0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00,
/* HTTP header */
/* "HTTP/1.0 200 OK
" (17 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
0x0a,
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
" (63 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-type: image/gif
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d,
0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a,
/* raw file data (724 bytes) */
0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39,
0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6,
0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e,
0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99,
0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5,
0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b,
0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00,
0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f,
0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac,
0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31,
0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9,
0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51,
0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78,
0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0,
0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07,
0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42,
0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c,
0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01,
0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10,
0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8,
0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4,
0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86,
0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06,
0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07,
0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29,
0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a,
0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97,
0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9,
0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70,
0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c,
0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01,
0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24,
0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29,
0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73,
0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab,
0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45,
0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8,
0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5,
0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10,
0x41,0x00,0x00,0x3b,};
static const unsigned int dummy_align__404_html = 1;
static const unsigned char data__404_html[] = {
/* /404.html (10 chars) */
0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00,
/* HTTP header */
/* "HTTP/1.0 404 File not found
" (29 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c,
0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a,
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
" (63 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-type: text/html
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
/* raw file data (565 bytes) */
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20,
0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a,
0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72,
0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,
0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20,
0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e,
0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,
0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
0x6d,0x6c,0x3e,0x0d,0x0a,};
static const unsigned int dummy_align__index_html = 2;
static const unsigned char data__index_html[] = {
/* /index.html (12 chars) */
0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00,
/* HTTP header */
/* "HTTP/1.0 200 OK
" (17 bytes) */
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,
0x0a,
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
" (63 bytes) */
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33,
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a,
/* "Content-type: text/html
" (27 bytes) */
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a,
/* raw file data (1751 bytes) */
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74,
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69,
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f,
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63,
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78,
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c,
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20,
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69,
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20,
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d,
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c,
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f,
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69,
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20,
0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77,
0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20,
0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72,
0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20,
0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72,
0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20,
0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,
0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,
0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,
0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c,
0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,
0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,
0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20,
0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,
0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50,
0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63,
0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61,
0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69,
0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,
0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,
0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b,
0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,
0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75,
0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53,
0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e,
0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e,
0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c,
0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f,
0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20,
0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77,
0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65,
0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c,
0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70,
0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69,
0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20,
0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73,
0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61,
0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61,
0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77,
0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65,
0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,
0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75,
0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09,
0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,
0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49,
0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09,
0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67,
0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61,
0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c,
0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69,
0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e,
0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,
0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f,
0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72,
0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34,
0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20,
0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a,
0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,
0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,
0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49,
0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61,
0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,
0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d,
0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,
0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,
0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,
0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,
0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f,
0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74,
0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61,
0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,
0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,
0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c,
0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e,
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72,
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,
0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,};
const struct fsdata_file file__img_sics_gif[] = { {
file_NULL,
data__img_sics_gif,
data__img_sics_gif + 16,
sizeof(data__img_sics_gif) - 16,
1,
}};
const struct fsdata_file file__404_html[] = { {
file__img_sics_gif,
data__404_html,
data__404_html + 12,
sizeof(data__404_html) - 12,
1,
}};
const struct fsdata_file file__index_html[] = { {
file__404_html,
data__index_html,
data__index_html + 12,
sizeof(data__index_html) - 12,
1,
}};
#define FS_ROOT file__index_html
#define FS_NUMFILES 3

File diff suppressed because it is too large Load Diff

View File

@@ -1,114 +0,0 @@
#ifndef LWIP_HTTPD_STRUCTS_H
#define LWIP_HTTPD_STRUCTS_H
#include "lwip/apps/httpd.h"
#if LWIP_HTTPD_DYNAMIC_HEADERS
/** This struct is used for a list of HTTP header strings for various
* filename extensions. */
typedef struct
{
const char *extension;
const char *content_type;
} tHTTPHeader;
/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and
* RFC 2616 HTTP/1.1 for header field definitions) */
static const char * const g_psHTTPHeaderStrings[] =
{
"HTTP/1.0 200 OK\r\n",
"HTTP/1.0 404 File not found\r\n",
"HTTP/1.0 400 Bad Request\r\n",
"HTTP/1.0 501 Not Implemented\r\n",
"HTTP/1.1 200 OK\r\n",
"HTTP/1.1 404 File not found\r\n",
"HTTP/1.1 400 Bad Request\r\n",
"HTTP/1.1 501 Not Implemented\r\n",
"Content-Length: ",
"Connection: Close\r\n",
"Connection: keep-alive\r\n",
"Connection: keep-alive\r\nContent-Length: ",
"Server: "HTTPD_SERVER_AGENT"\r\n",
"\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
#endif
};
/* Indexes into the g_psHTTPHeaderStrings array */
#define HTTP_HDR_OK 0 /* 200 OK */
#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */
#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */
#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */
#define HTTP_HDR_OK_11 4 /* 200 OK */
#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */
#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */
#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */
#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/
#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */
#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */
#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/
#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */
#define DEFAULT_404_HTML 13 /* default 404 body */
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */
#endif
#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n"
#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n"
#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n"
#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n"
#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n"
#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n"
#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n"
#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n"
#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n"
#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n"
#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n"
#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n"
#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n"
#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n"
#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n"
#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n"
/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES
* and http://www.iana.org/assignments/media-types for registered content types
* and subtypes) */
static const tHTTPHeader g_psHTTPHeaders[] =
{
{ "html", HTTP_HDR_HTML},
{ "htm", HTTP_HDR_HTML},
{ "shtml",HTTP_HDR_SSI},
{ "shtm", HTTP_HDR_SSI},
{ "ssi", HTTP_HDR_SSI},
{ "gif", HTTP_HDR_GIF},
{ "png", HTTP_HDR_PNG},
{ "jpg", HTTP_HDR_JPG},
{ "bmp", HTTP_HDR_BMP},
{ "ico", HTTP_HDR_ICO},
{ "class",HTTP_HDR_APP},
{ "cls", HTTP_HDR_APP},
{ "js", HTTP_HDR_JS},
{ "ram", HTTP_HDR_RA},
{ "css", HTTP_HDR_CSS},
{ "swf", HTTP_HDR_SWF},
{ "xml", HTTP_HDR_XML},
{ "xsl", HTTP_HDR_XML},
{ "pdf", HTTP_HDR_PDF},
{ "json", HTTP_HDR_JSON}
};
#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader))
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
#if LWIP_HTTPD_SSI
static const char * const g_pcSSIExtensions[] = {
".shtml", ".shtm", ".ssi", ".xml"
};
#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *))
#endif /* LWIP_HTTPD_SSI */
#endif /* LWIP_HTTPD_STRUCTS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
This directory contains a script ('makefsdata') to create C code suitable for
httpd for given html pages (or other files) in a directory.
There is also a plain C console application doing the same and extended a bit.
Usage: htmlgen [targetdir] [-s] [-i]s
targetdir: relative or absolute path to files to convert
switch -s: toggle processing of subdirectories (default is on)
switch -e: exclude HTTP header from file (header is created at runtime, default is on)
switch -11: include HTTP 1.1 header (1.0 is default)
if targetdir not specified, makefsdata will attempt to
process files in subdirectory 'fs'.

View File

@@ -1,663 +0,0 @@
/**
* @file
* lwIP iPerf server implementation
*/
/**
* @defgroup iperf Iperf server
* @ingroup apps
*
* This is a simple performance measuring server to check your bandwith using
* iPerf2 on a PC as client.
* It is currently a minimal implementation providing an IPv4 TCP server only.
*
* @todo: implement UDP mode and IPv6
*/
/*
* Copyright (c) 2014 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*/
#include "lwip/apps/lwiperf.h"
#include "lwip/tcp.h"
#include "lwip/sys.h"
#include <string.h>
/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
#if LWIP_IPV4 && LWIP_TCP
/** Specify the idle timeout (in seconds) after that the test fails */
#ifndef LWIPERF_TCP_MAX_IDLE_SEC
#define LWIPERF_TCP_MAX_IDLE_SEC 10U
#endif
#if LWIPERF_TCP_MAX_IDLE_SEC > 255
#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t
#endif
/* File internal memory allocation (struct lwiperf_*): this defaults to
the heap */
#ifndef LWIPERF_ALLOC
#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type))
#define LWIPERF_FREE(type, item) mem_free(item)
#endif
/** If this is 1, check that received data has the correct format */
#ifndef LWIPERF_CHECK_RX_DATA
#define LWIPERF_CHECK_RX_DATA 0
#endif
/** This is the Iperf settings struct sent from the client */
typedef struct _lwiperf_settings {
#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000
#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001
u32_t flags;
u32_t num_threads; /* unused for now */
u32_t remote_port;
u32_t buffer_len; /* unused for now */
u32_t win_band; /* TCP window / UDP rate: unused for now */
u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */
} lwiperf_settings_t;
/** Basic connection handle */
struct _lwiperf_state_base;
typedef struct _lwiperf_state_base lwiperf_state_base_t;
struct _lwiperf_state_base {
/* 1=tcp, 0=udp */
u8_t tcp;
/* 1=server, 0=client */
u8_t server;
lwiperf_state_base_t* next;
lwiperf_state_base_t* related_server_state;
};
/** Connection handle for a TCP iperf session */
typedef struct _lwiperf_state_tcp {
lwiperf_state_base_t base;
struct tcp_pcb* server_pcb;
struct tcp_pcb* conn_pcb;
u32_t time_started;
lwiperf_report_fn report_fn;
void* report_arg;
u8_t poll_count;
u8_t next_num;
u32_t bytes_transferred;
lwiperf_settings_t settings;
u8_t have_settings_buf;
} lwiperf_state_tcp_t;
/** List of active iperf sessions */
static lwiperf_state_base_t* lwiperf_all_connections;
/** A const buffer to send from: we want to measure sending, not copying! */
static const u8_t lwiperf_txbuf_const[1600] = {
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9',
};
static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb);
static void lwiperf_tcp_err(void *arg, err_t err);
/** Add an iperf session to the 'active' list */
static void
lwiperf_list_add(lwiperf_state_base_t* item)
{
if (lwiperf_all_connections == NULL) {
lwiperf_all_connections = item;
} else {
item = lwiperf_all_connections;
}
}
/** Remove an iperf session from the 'active' list */
static void
lwiperf_list_remove(lwiperf_state_base_t* item)
{
lwiperf_state_base_t* prev = NULL;
lwiperf_state_base_t* iter;
for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) {
if (iter == item) {
if (prev == NULL) {
lwiperf_all_connections = iter->next;
} else {
prev->next = item;
}
/* @debug: ensure this item is listed only once */
for (iter = iter->next; iter != NULL; iter = iter->next) {
LWIP_ASSERT("duplicate entry", iter != item);
}
break;
}
}
}
/** Call the report function of an iperf tcp session */
static void
lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
{
if ((conn != NULL) && (conn->report_fn != NULL)) {
u32_t now, duration_ms, bandwidth_kbitpsec;
now = sys_now();
duration_ms = now - conn->time_started;
if (duration_ms == 0) {
bandwidth_kbitpsec = 0;
} else {
bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U;
}
conn->report_fn(conn->report_arg, report_type,
&conn->conn_pcb->local_ip, conn->conn_pcb->local_port,
&conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port,
conn->bytes_transferred, duration_ms, bandwidth_kbitpsec);
}
}
/** Close an iperf tcp session */
static void
lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type)
{
err_t err;
lwip_tcp_conn_report(conn, report_type);
lwiperf_list_remove(&conn->base);
if (conn->conn_pcb != NULL) {
tcp_arg(conn->conn_pcb, NULL);
tcp_poll(conn->conn_pcb, NULL, 0);
tcp_sent(conn->conn_pcb, NULL);
tcp_recv(conn->conn_pcb, NULL);
tcp_err(conn->conn_pcb, NULL);
err = tcp_close(conn->conn_pcb);
if (err != ERR_OK) {
/* don't want to wait for free memory here... */
tcp_abort(conn->conn_pcb);
}
} else {
/* no conn pcb, this is the server pcb */
err = tcp_close(conn->server_pcb);
LWIP_ASSERT("error", err != ERR_OK);
}
LWIPERF_FREE(lwiperf_state_tcp_t, conn);
}
/** Try to send more data on an iperf tcp session */
static err_t
lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
{
int send_more;
err_t err;
u16_t txlen;
u16_t txlen_max;
void* txptr;
u8_t apiflags;
LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));
do {
send_more = 0;
if (conn->settings.amount & PP_HTONL(0x80000000)) {
/* this session is time-limited */
u32_t now = sys_now();
u32_t diff_ms = now - conn->time_started;
u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount);
u32_t time_ms = time * 10;
if (diff_ms >= time_ms) {
/* time specified by the client is over -> close the connection */
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
return ERR_OK;
}
} else {
/* this session is byte-limited */
u32_t amount_bytes = lwip_htonl(conn->settings.amount);
/* @todo: this can send up to 1*MSS more than requested... */
if (amount_bytes >= conn->bytes_transferred) {
/* all requested bytes transferred -> close the connection */
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
return ERR_OK;
}
}
if (conn->bytes_transferred < 24) {
/* transmit the settings a first time */
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred];
txlen_max = (u16_t)(24 - conn->bytes_transferred);
apiflags = TCP_WRITE_FLAG_COPY;
} else if (conn->bytes_transferred < 48) {
/* transmit the settings a second time */
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24];
txlen_max = (u16_t)(48 - conn->bytes_transferred);
apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
send_more = 1;
} else {
/* transmit data */
/* @todo: every x bytes, transmit the settings again */
txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
txlen_max = TCP_MSS;
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
txlen_max = TCP_MSS - 24;
}
apiflags = 0; /* no copying needed */
send_more = 1;
}
txlen = txlen_max;
do {
err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
if (err == ERR_MEM) {
txlen /= 2;
}
} while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2)));
if (err == ERR_OK) {
conn->bytes_transferred += txlen;
} else {
send_more = 0;
}
} while(send_more);
tcp_output(conn->conn_pcb);
return ERR_OK;
}
/** TCP sent callback, try to send more data */
static err_t
lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
/* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
LWIP_UNUSED_ARG(len);
conn->poll_count = 0;
return lwiperf_tcp_client_send_more(conn);
}
/** TCP connected callback (active connection), send data now */
static err_t
lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (err != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
return ERR_OK;
}
conn->poll_count = 0;
conn->time_started = sys_now();
return lwiperf_tcp_client_send_more(conn);
}
/** Start TCP connection back to the client (either parallel or after the
* receive test has finished.
*/
static err_t
lwiperf_tx_start(lwiperf_state_tcp_t* conn)
{
err_t err;
lwiperf_state_tcp_t* client_conn;
struct tcp_pcb* newpcb;
ip_addr_t remote_addr;
u16_t remote_port;
client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (client_conn == NULL) {
return ERR_MEM;
}
newpcb = tcp_new();
if (newpcb == NULL) {
LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
return ERR_MEM;
}
MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t));
client_conn->base.server = 0;
client_conn->server_pcb = NULL;
client_conn->conn_pcb = newpcb;
client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */
client_conn->poll_count = 0;
client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
client_conn->bytes_transferred = 0;
client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */
tcp_arg(newpcb, client_conn);
tcp_sent(newpcb, lwiperf_tcp_client_sent);
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
tcp_err(newpcb, lwiperf_tcp_err);
ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port);
err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
if (err != ERR_OK) {
lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
return err;
}
lwiperf_list_add(&client_conn->base);
return ERR_OK;
}
/** Receive data on an iperf tcp session */
static err_t
lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
u8_t tmp;
u16_t tot_len;
u32_t packet_idx;
struct pbuf* q;
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (err != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
return ERR_OK;
}
if (p == NULL) {
/* connection closed -> test done */
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
/* client requested transmission after end of test */
lwiperf_tx_start(conn);
}
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER);
return ERR_OK;
}
tot_len = p->tot_len;
conn->poll_count = 0;
if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) {
/* wait for 24-byte header */
if (p->tot_len < sizeof(lwiperf_settings_t)) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_VAL;
}
if (!conn->have_settings_buf) {
if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
pbuf_free(p);
return ERR_VAL;
}
conn->have_settings_buf = 1;
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) ==
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) {
/* client requested parallel transmission test */
err_t err2 = lwiperf_tx_start(conn);
if (err2 != ERR_OK) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR);
pbuf_free(p);
return err2;
}
}
} else {
if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_VAL;
}
}
conn->bytes_transferred += sizeof(lwiperf_settings_t);
if (conn->bytes_transferred <= 24) {
conn->time_started = sys_now();
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
conn->next_num = 4; /* 24 bytes received... */
tmp = pbuf_header(p, -24);
LWIP_ASSERT("pbuf_header failed", tmp == 0);
}
packet_idx = 0;
for (q = p; q != NULL; q = q->next) {
#if LWIPERF_CHECK_RX_DATA
const u8_t* payload = (const u8_t*)q->payload;
u16_t i;
for (i = 0; i < q->len; i++) {
u8_t val = payload[i];
u8_t num = val - '0';
if (num == conn->next_num) {
conn->next_num++;
if (conn->next_num == 10) {
conn->next_num = 0;
}
} else {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
pbuf_free(p);
return ERR_VAL;
}
}
packet_idx += i;
#else
packet_idx += q->len;
#endif
}
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
conn->bytes_transferred += packet_idx;
tcp_recved(tpcb, tot_len);
pbuf_free(p);
return ERR_OK;
}
/** Error callback, iperf tcp session aborted */
static void
lwiperf_tcp_err(void *arg, err_t err)
{
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
LWIP_UNUSED_ARG(err);
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
}
/** TCP poll callback, try to send more data */
static err_t
lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb)
{
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg;
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
LWIP_UNUSED_ARG(tpcb);
if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) {
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
return ERR_OK; /* lwiperf_tcp_close frees conn */
}
if (!conn->base.server) {
lwiperf_tcp_client_send_more(conn);
}
return ERR_OK;
}
/** This is called when a new client connects for an iperf tcp session */
static err_t
lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
lwiperf_state_tcp_t *s, *conn;
if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) {
return ERR_VAL;
}
s = (lwiperf_state_tcp_t*)arg;
conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (conn == NULL) {
return ERR_MEM;
}
memset(conn, 0, sizeof(lwiperf_state_tcp_t));
conn->base.tcp = 1;
conn->base.server = 1;
conn->base.related_server_state = &s->base;
conn->server_pcb = s->server_pcb;
conn->conn_pcb = newpcb;
conn->time_started = sys_now();
conn->report_fn = s->report_fn;
conn->report_arg = s->report_arg;
/* setup the tcp rx connection */
tcp_arg(newpcb, conn);
tcp_recv(newpcb, lwiperf_tcp_recv);
tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
tcp_err(conn->conn_pcb, lwiperf_tcp_err);
lwiperf_list_add(&conn->base);
return ERR_OK;
}
/**
* @ingroup iperf
* Start a TCP iperf server on the default TCP port (5001) and listen for
* incoming connections from iperf clients.
*
* @returns a connection handle that can be used to abort the server
* by calling @ref lwiperf_abort()
*/
void*
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
{
return lwiperf_start_tcp_server(IP4_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
report_fn, report_arg);
}
/**
* @ingroup iperf
* Start a TCP iperf server on a specific IP address and port and listen for
* incoming connections from iperf clients.
*
* @returns a connection handle that can be used to abort the server
* by calling @ref lwiperf_abort()
*/
void*
lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port,
lwiperf_report_fn report_fn, void* report_arg)
{
err_t err;
struct tcp_pcb* pcb;
lwiperf_state_tcp_t* s;
if (local_addr == NULL) {
return NULL;
}
s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
if (s == NULL) {
return NULL;
}
memset(s, 0, sizeof(lwiperf_state_tcp_t));
s->base.tcp = 1;
s->base.server = 1;
s->report_fn = report_fn;
s->report_arg = report_arg;
pcb = tcp_new();
if (pcb != NULL) {
err = tcp_bind(pcb, local_addr, local_port);
if (err == ERR_OK) {
s->server_pcb = tcp_listen_with_backlog(pcb, 1);
}
}
if (s->server_pcb == NULL) {
if (pcb != NULL) {
tcp_close(pcb);
}
LWIPERF_FREE(lwiperf_state_tcp_t, s);
return NULL;
}
pcb = NULL;
tcp_arg(s->server_pcb, s);
tcp_accept(s->server_pcb, lwiperf_tcp_accept);
lwiperf_list_add(&s->base);
return s;
}
/**
* @ingroup iperf
* Abort an iperf session (handle returned by lwiperf_start_tcp_server*())
*/
void
lwiperf_abort(void* lwiperf_session)
{
lwiperf_state_base_t* i, *dealloc, *last = NULL;
for (i = lwiperf_all_connections; i != NULL; ) {
if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) {
dealloc = i;
i = i->next;
if (last != NULL) {
last->next = i;
}
LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */
} else {
last = i;
i = i->next;
}
}
}
#endif /* LWIP_IPV4 && LWIP_TCP */

File diff suppressed because it is too large Load Diff

View File

@@ -1,367 +0,0 @@
/**
* @file
* NetBIOS name service responder
*/
/**
* @defgroup netbiosns NETBIOS responder
* @ingroup apps
*
* This is an example implementation of a NetBIOS name server.
* It responds to name queries for a configurable name.
* Name resolving is not supported.
*
* Note that the device doesn't broadcast it's own name so can't
* detect duplicate names!
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#include "lwip/apps/netbiosns.h"
#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */
#include "lwip/def.h"
#include "lwip/udp.h"
#include "lwip/netif.h"
#include <string.h>
/** default port number for "NetBIOS Name service */
#define NETBIOS_PORT 137
/** size of a NetBIOS name */
#define NETBIOS_NAME_LEN 16
/** The Time-To-Live for NetBIOS name responds (in seconds)
* Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
#define NETBIOS_NAME_TTL 300000u
/** NetBIOS header flags */
#define NETB_HFLAG_RESPONSE 0x8000U
#define NETB_HFLAG_OPCODE 0x7800U
#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U
#define NETB_HFLAG_AUTHORATIVE 0x0400U
#define NETB_HFLAG_TRUNCATED 0x0200U
#define NETB_HFLAG_RECURS_DESIRED 0x0100U
#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U
#define NETB_HFLAG_BROADCAST 0x0010U
#define NETB_HFLAG_REPLYCODE 0x0008U
#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U
/** NetBIOS name flags */
#define NETB_NFLAG_UNIQUE 0x8000U
#define NETB_NFLAG_NODETYPE 0x6000U
#define NETB_NFLAG_NODETYPE_HNODE 0x6000U
#define NETB_NFLAG_NODETYPE_MNODE 0x4000U
#define NETB_NFLAG_NODETYPE_PNODE 0x2000U
#define NETB_NFLAG_NODETYPE_BNODE 0x0000U
/** NetBIOS message header */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_hdr {
PACK_STRUCT_FIELD(u16_t trans_id);
PACK_STRUCT_FIELD(u16_t flags);
PACK_STRUCT_FIELD(u16_t questions);
PACK_STRUCT_FIELD(u16_t answerRRs);
PACK_STRUCT_FIELD(u16_t authorityRRs);
PACK_STRUCT_FIELD(u16_t additionalRRs);
} 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"
#endif
PACK_STRUCT_BEGIN
struct netbios_name_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_FIELD(u32_t ttl);
PACK_STRUCT_FIELD(u16_t datalen);
PACK_STRUCT_FIELD(u16_t flags);
PACK_STRUCT_FLD_S(ip4_addr_p_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** NetBIOS message */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_resp
{
struct netbios_hdr resp_hdr;
struct netbios_name_hdr resp_name;
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef NETBIOS_LWIP_NAME
#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME
#else
static char netbiosns_local_name[NETBIOS_NAME_LEN];
#define NETBIOS_LOCAL_NAME netbiosns_local_name
#endif
struct udp_pcb *netbiosns_pcb;
/** Decode a NetBIOS name (from packet to string) */
static int
netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len)
{
char *pname;
char cname;
char cnbname;
int idx = 0;
LWIP_UNUSED_ARG(name_dec_len);
/* Start decoding netbios name. */
pname = name_enc;
for (;;) {
/* Every two characters of the first level-encoded name
* turn into one character in the decoded name. */
cname = *pname;
if (cname == '\0')
break; /* no more characters */
if (cname == '.')
break; /* scope ID follows */
if (cname < 'A' || cname > 'Z') {
/* Not legal. */
return -1;
}
cname -= 'A';
cnbname = cname << 4;
pname++;
cname = *pname;
if (cname == '\0' || cname == '.') {
/* No more characters in the name - but we're in
* the middle of a pair. Not legal. */
return -1;
}
if (cname < 'A' || cname > 'Z') {
/* Not legal. */
return -1;
}
cname -= 'A';
cnbname |= cname;
pname++;
/* Do we have room to store the character? */
if (idx < NETBIOS_NAME_LEN) {
/* Yes - store the character. */
name_dec[idx++] = (cnbname!=' '?cnbname:'\0');
}
}
return 0;
}
#if 0 /* function currently unused */
/** Encode a NetBIOS name (from string to packet) - currently unused because
we don't ask for names. */
static int
netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len)
{
char *pname;
char cname;
unsigned char ucname;
int idx = 0;
/* Start encoding netbios name. */
pname = name_enc;
for (;;) {
/* Every two characters of the first level-encoded name
* turn into one character in the decoded name. */
cname = *pname;
if (cname == '\0')
break; /* no more characters */
if (cname == '.')
break; /* scope ID follows */
if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
/* Not legal. */
return -1;
}
/* Do we have room to store the character? */
if (idx >= name_dec_len) {
return -1;
}
/* Yes - store the character. */
ucname = cname;
name_dec[idx++] = ('A'+((ucname>>4) & 0x0F));
name_dec[idx++] = ('A'+( ucname & 0x0F));
pname++;
}
/* Fill with "space" coding */
for (;idx < name_dec_len - 1;) {
name_dec[idx++] = 'C';
name_dec[idx++] = 'A';
}
/* Terminate string */
name_dec[idx] = '\0';
return 0;
}
#endif /* 0 */
/** NetBIOS Name service recv callback */
static void
netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
LWIP_UNUSED_ARG(arg);
/* 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);
/* we only answer if we got a default interface */
if (netif_default != NULL) {
/* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
/* if the packet is a NetBIOS name query question */
if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
((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));
/* if the packet is for us */
if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) {
struct pbuf *q;
struct netbios_resp *resp;
q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
if (q != NULL) {
resp = (struct netbios_resp*)q->payload;
/* prepare NetBIOS header response */
resp->resp_hdr.trans_id = netbios_hdr->trans_id;
resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE |
NETB_HFLAG_OPCODE_NAME_QUERY |
NETB_HFLAG_AUTHORATIVE |
NETB_HFLAG_RECURS_DESIRED);
resp->resp_hdr.questions = 0;
resp->resp_hdr.answerRRs = PP_HTONS(1);
resp->resp_hdr.authorityRRs = 0;
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;
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);
ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default));
/* send the NetBIOS response */
udp_sendto(upcb, q, addr, port);
/* free the "reference" pbuf */
pbuf_free(q);
}
}
}
}
/* free the pbuf */
pbuf_free(p);
}
}
/**
* @ingroup netbiosns
* Init netbios responder
*/
void
netbiosns_init(void)
{
#ifdef NETBIOS_LWIP_NAME
LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
#endif
netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
if (netbiosns_pcb != NULL) {
/* we have to be allowed to send broadcast packets! */
ip_set_option(netbiosns_pcb, SOF_BROADCAST);
udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT);
udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb);
}
}
#ifndef NETBIOS_LWIP_NAME
/**
* @ingroup netbiosns
* Set netbios name. ATTENTION: the hostname must be less than 15 characters!
*/
void
netbiosns_set_name(const char* hostname)
{
size_t copy_len = strlen(hostname);
LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN);
if (copy_len >= NETBIOS_NAME_LEN) {
copy_len = NETBIOS_NAME_LEN - 1;
}
MEMCPY(netbiosns_local_name, hostname, copy_len + 1);
}
#endif
/**
* @ingroup netbiosns
* Stop netbios responder
*/
void
netbiosns_stop(void)
{
if (netbiosns_pcb != NULL) {
udp_remove(netbiosns_pcb);
netbiosns_pcb = NULL;
}
}
#endif /* LWIP_IPV4 && LWIP_UDP */

View File

@@ -1,749 +0,0 @@
/**
* @file
* Abstract Syntax Notation One (ISO 8824, 8825) encoding
*
* @todo not optimised (yet), favor correctness over speed, favor speed over size
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Christiaan Simons <christiaan.simons@axon.tv>
* Martin Hentschel <info@cl-soft.de>
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "snmp_asn1.h"
#define PBUF_OP_EXEC(code) \
if ((code) != ERR_OK) { \
return ERR_BUF; \
}
/**
* Encodes a TLV into a pbuf stream.
*
* @param pbuf_stream points to a pbuf stream
* @param tlv TLV to encode
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*/
err_t
snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv)
{
u8_t data;
u8_t length_bytes_required;
/* write type */
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) {
/* extended format is not used by SNMP so we do not accept those values */
return ERR_ARG;
}
if (tlv->type_len != 0) {
/* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */
return ERR_ARG;
}
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type));
tlv->type_len = 1;
/* write length */
if (tlv->value_len <= 127) {
length_bytes_required = 1;
} else if (tlv->value_len <= 255) {
length_bytes_required = 2;
} else {
length_bytes_required = 3;
}
/* check for forced min length */
if (tlv->length_len > 0) {
if (tlv->length_len < length_bytes_required) {
/* unable to code requested length in requested number of bytes */
return ERR_ARG;
}
length_bytes_required = tlv->length_len;
} else {
tlv->length_len = length_bytes_required;
}
if (length_bytes_required > 1) {
/* multi byte representation required */
length_bytes_required--;
data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
while (length_bytes_required > 1) {
if (length_bytes_required == 2) {
/* append high byte */
data = (u8_t)(tlv->value_len >> 8);
} else {
/* append leading 0x00 */
data = 0x00;
}
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
length_bytes_required--;
}
}
/* append low byte */
data = (u8_t)(tlv->value_len & 0xFF);
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data));
return ERR_OK;
}
/**
* Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg.
*
* @param pbuf_stream points to a pbuf stream
* @param raw_len raw data length
* @param raw points raw data
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*/
err_t
snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len)
{
PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len));
return ERR_OK;
}
/**
* Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg.
*
* @param pbuf_stream points to a pbuf stream
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt())
* @param value is the host order u32_t value to be encoded
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*
* @see snmp_asn1_enc_u32t_cnt()
*/
err_t
snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value)
{
if (octets_needed > 5) {
return ERR_ARG;
}
if (octets_needed == 5) {
/* not enough bits in 'value' add leading 0x00 */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00));
octets_needed--;
}
while (octets_needed > 1) {
octets_needed--;
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3))));
}
/* (only) one least significant octet */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value));
return ERR_OK;
}
/**
* Encodes u64_t (counter64) into a pbuf chained ASN1 msg.
*
* @param pbuf_stream points to a pbuf stream
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt())
* @param value is the host order u32_t value to be encoded
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*
* @see snmp_asn1_enc_u64t_cnt()
*/
err_t
snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value)
{
if (octets_needed > 9) {
return ERR_ARG;
}
if (octets_needed == 9) {
/* not enough bits in 'value' add leading 0x00 */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00));
octets_needed--;
}
while (octets_needed > 4) {
octets_needed--;
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3))));
}
/* skip to low u32 */
value++;
while (octets_needed > 1) {
octets_needed--;
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3))));
}
/* always write at least one octet (also in case of value == 0) */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value)));
return ERR_OK;
}
/**
* Encodes s32_t integer into a pbuf chained ASN1 msg.
*
* @param pbuf_stream points to a pbuf stream
* @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt())
* @param value is the host order s32_t value to be encoded
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*
* @see snmp_asn1_enc_s32t_cnt()
*/
err_t
snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value)
{
while (octets_needed > 1) {
octets_needed--;
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3))));
}
/* (only) one least significant octet */
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value));
return ERR_OK;
}
/**
* Encodes object identifier into a pbuf chained ASN1 msg.
*
* @param pbuf_stream points to a pbuf stream
* @param oid points to object identifier array
* @param oid_len object identifier array length
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode
*/
err_t
snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len)
{
if (oid_len > 1) {
/* write compressed first two sub id's */
u32_t compressed_byte = ((oid[0] * 40) + oid[1]);
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte));
oid_len -= 2;
oid += 2;
} else {
/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */
/* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */
return ERR_ARG;
}
while (oid_len > 0) {
u32_t sub_id;
u8_t shift, tail;
oid_len--;
sub_id = *oid;
tail = 0;
shift = 28;
while (shift > 0) {
u8_t code;
code = (u8_t)(sub_id >> shift);
if ((code != 0) || (tail != 0)) {
tail = 1;
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80));
}
shift -= 7;
}
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F));
/* proceed to next sub-identifier */
oid++;
}
return ERR_OK;
}
/**
* Returns octet count for length.
*
* @param length parameter length
* @param octets_needed points to the return value
*/
void
snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
{
if (length < 0x80U) {
*octets_needed = 1;
} else if (length < 0x100U) {
*octets_needed = 2;
} else {
*octets_needed = 3;
}
}
/**
* Returns octet count for an u32_t.
*
* @param value value to be encoded
* @param octets_needed points to the return value
*
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
*/
void
snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
{
if (value < 0x80UL) {
*octets_needed = 1;
} else if (value < 0x8000UL) {
*octets_needed = 2;
} else if (value < 0x800000UL) {
*octets_needed = 3;
} else if (value < 0x80000000UL) {
*octets_needed = 4;
} else {
*octets_needed = 5;
}
}
/**
* Returns octet count for an u64_t.
*
* @param value value to be encoded
* @param octets_needed points to the return value
*
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
*/
void
snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed)
{
/* check if high u32 is 0 */
if (*value == 0x00) {
/* only low u32 is important */
value++;
snmp_asn1_enc_u32t_cnt(*value, octets_needed);
} else {
/* low u32 does not matter for length determination */
snmp_asn1_enc_u32t_cnt(*value, octets_needed);
*octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */
}
}
/**
* Returns octet count for an s32_t.
*
* @param value value to be encoded
* @param octets_needed points to the return value
*
* @note ASN coded integers are _always_ signed.
*/
void
snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed)
{
if (value < 0) {
value = ~value;
}
if (value < 0x80L) {
*octets_needed = 1;
} else if (value < 0x8000L) {
*octets_needed = 2;
} else if (value < 0x800000L) {
*octets_needed = 3;
} else {
*octets_needed = 4;
}
}
/**
* Returns octet count for an object identifier.
*
* @param oid points to object identifier array
* @param oid_len object identifier array length
* @param octets_needed points to the return value
*/
void
snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed)
{
u32_t sub_id;
*octets_needed = 0;
if (oid_len > 1) {
/* compressed prefix in one octet */
(*octets_needed)++;
oid_len -= 2;
oid += 2;
}
while (oid_len > 0) {
oid_len--;
sub_id = *oid;
sub_id >>= 7;
(*octets_needed)++;
while (sub_id > 0) {
sub_id >>= 7;
(*octets_needed)++;
}
oid++;
}
}
/**
* Decodes a TLV from a pbuf stream.
*
* @param pbuf_stream points to a pbuf stream
* @param tlv returns decoded TLV
* @return ERR_OK if successful, ERR_VAL if we can't decode
*/
err_t
snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv)
{
u8_t data;
/* decode type first */
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
tlv->type = data;
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) {
/* extended format is not used by SNMP so we do not accept those values */
return ERR_VAL;
}
tlv->type_len = 1;
/* now, decode length */
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
if (data < 0x80) { /* short form */
tlv->length_len = 1;
tlv->value_len = data;
} else if (data > 0x80) { /* long form */
u8_t length_bytes = data - 0x80;
tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */
tlv->value_len = 0;
while (length_bytes > 0) {
/* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */
if (tlv->value_len > 0xFF) {
return ERR_VAL;
}
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
tlv->value_len <<= 8;
tlv->value_len |= data;
/* take care for special value used for indefinite length */
if (tlv->value_len == 0xFFFF) {
return ERR_VAL;
}
length_bytes--;
}
} else { /* data == 0x80 indefinite length form */
/* (not allowed for SNMP; RFC 1157, 3.2.2) */
return ERR_VAL;
}
return ERR_OK;
}
/**
* Decodes positive integer (counter, gauge, timeticks) into u32_t.
*
* @param pbuf_stream points to a pbuf stream
* @param len length of the coded integer field
* @param value return host order integer
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
*
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
*/
err_t
snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value)
{
u8_t data;
if ((len > 0) && (len <= 5)) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
/* expecting sign bit to be zero, only unsigned please! */
if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) {
*value = data;
len--;
while (len > 0) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
*value <<= 8;
*value |= data;
}
return ERR_OK;
}
}
return ERR_VAL;
}
/**
* Decodes large positive integer (counter64) into 2x u32_t.
*
* @param pbuf_stream points to a pbuf stream
* @param len length of the coded integer field
* @param value return host order integer
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
*
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
*/
err_t
snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value)
{
u8_t data;
if (len <= 4) {
/* high u32 is 0 */
*value = 0;
/* directly skip to low u32 */
value++;
}
if ((len > 0) && (len <= 9)) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
/* expecting sign bit to be zero, only unsigned please! */
if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) {
*value = data;
len--;
while (len > 0) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
if (len == 4) {
/* skip to low u32 */
value++;
*value = 0;
} else {
*value <<= 8;
}
*value |= data;
len--;
}
return ERR_OK;
}
}
return ERR_VAL;
}
/**
* Decodes integer into s32_t.
*
* @param pbuf_stream points to a pbuf stream
* @param len length of the coded integer field
* @param value return host order integer
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
*
* @note ASN coded integers are _always_ signed!
*/
err_t
snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value)
{
#if BYTE_ORDER == LITTLE_ENDIAN
u8_t *lsb_ptr = (u8_t*)value;
#endif
#if BYTE_ORDER == BIG_ENDIAN
u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1;
#endif
u8_t sign;
u8_t data;
if ((len > 0) && (len < 5)) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
if (data & 0x80) {
/* negative, start from -1 */
*value = -1;
sign = 1;
*lsb_ptr &= data;
} else {
/* positive, start from 0 */
*value = 0;
sign = 0;
*lsb_ptr |= data;
}
/* OR/AND octets with value */
while (len > 0) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
#if BYTE_ORDER == LITTLE_ENDIAN
*value <<= 8;
#endif
#if BYTE_ORDER == BIG_ENDIAN
*value >>= 8;
#endif
if (sign) {
*lsb_ptr |= 255;
*lsb_ptr &= data;
} else {
*lsb_ptr |= data;
}
}
return ERR_OK;
}
return ERR_VAL;
}
/**
* Decodes object identifier from incoming message into array of u32_t.
*
* @param pbuf_stream points to a pbuf stream
* @param len length of the coded object identifier
* @param oid return decoded object identifier
* @param oid_len return decoded object identifier length
* @param oid_max_len size of oid buffer
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
*/
err_t
snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len)
{
u32_t *oid_ptr;
u8_t data;
*oid_len = 0;
oid_ptr = oid;
if (len > 0) {
if (oid_max_len < 2) {
return ERR_MEM;
}
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
/* first compressed octet */
if (data == 0x2B) {
/* (most) common case 1.3 (iso.org) */
*oid_ptr = 1;
oid_ptr++;
*oid_ptr = 3;
oid_ptr++;
} else if (data < 40) {
*oid_ptr = 0;
oid_ptr++;
*oid_ptr = data;
oid_ptr++;
} else if (data < 80) {
*oid_ptr = 1;
oid_ptr++;
*oid_ptr = data - 40;
oid_ptr++;
} else {
*oid_ptr = 2;
oid_ptr++;
*oid_ptr = data - 80;
oid_ptr++;
}
*oid_len = 2;
} else {
/* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */
return ERR_OK;
}
while ((len > 0) && (*oid_len < oid_max_len)) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
if ((data & 0x80) == 0x00) {
/* sub-identifier uses single octet */
*oid_ptr = data;
} else {
/* sub-identifier uses multiple octets */
u32_t sub_id = (data & ~0x80);
while ((len > 0) && ((data & 0x80) != 0)) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
len--;
sub_id = (sub_id << 7) + (data & ~0x80);
}
if ((data & 0x80) != 0) {
/* "more bytes following" bit still set at end of len */
return ERR_VAL;
}
*oid_ptr = sub_id;
}
oid_ptr++;
(*oid_len)++;
}
if (len > 0) {
/* OID to long to fit in our buffer */
return ERR_MEM;
}
return ERR_OK;
}
/**
* Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding)
* from incoming message into array.
*
* @param pbuf_stream points to a pbuf stream
* @param len length of the coded raw data (zero is valid, e.g. empty string!)
* @param buf return raw bytes
* @param buf_len returns length of the raw return value
* @param buf_max_len buffer size
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode
*/
err_t
snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len)
{
if (len > buf_max_len) {
/* not enough dst space */
return ERR_MEM;
}
*buf_len = len;
while (len > 0) {
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf));
buf++;
len--;
}
return ERR_OK;
}
#endif /* LWIP_SNMP */

View File

@@ -1,108 +0,0 @@
/**
* @file
* Abstract Syntax Notation One (ISO 8824, 8825) codec.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2016 Elias Oenal.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Christiaan Simons <christiaan.simons@axon.tv>
* Martin Hentschel <info@cl-soft.de>
* Elias Oenal <lwip@eliasoenal.com>
*/
#ifndef LWIP_HDR_APPS_SNMP_ASN1_H
#define LWIP_HDR_APPS_SNMP_ASN1_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP
#include "lwip/err.h"
#include "lwip/apps/snmp_core.h"
#include "snmp_pbuf_stream.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80
#define SNMP_ASN1_CLASS_MASK 0xC0
#define SNMP_ASN1_CONTENTTYPE_MASK 0x20
#define SNMP_ASN1_DATATYPE_MASK 0x1F
#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */
/* context specific (SNMP) tags (from SNMP spec. RFC1157) */
#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0
#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1
#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2
#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3
#define SNMP_ASN1_CONTEXT_PDU_TRAP 4
#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5
#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0
#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2
struct snmp_asn1_tlv
{
u8_t type; /* only U8 because extended types are not specified by SNMP */
u8_t type_len; /* encoded length of 'type' field (normally 1) */
u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */
u16_t value_len; /* encoded length of the value */
};
#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len)
#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len)
#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0);
err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv);
err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value);
err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value);
err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value);
err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len);
err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len);
err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv);
void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed);
void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed);
void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed);
void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed);
void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed);
err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len);
err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value);
err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value);
err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value);
err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H
#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/snmp_core.h"
#include "snmp_asn1.h"
#ifdef __cplusplus
extern "C" {
#endif
/* (outdated) SNMPv1 error codes
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request
*/
#define SNMP_ERR_NOSUCHNAME 2
#define SNMP_ERR_BADVALUE 3
#define SNMP_ERR_READONLY 4
/* error codes which are internal and shall not be used by MIBS
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request
*/
#define SNMP_ERR_TOOBIG 1
#define SNMP_ERR_AUTHORIZATIONERROR 16
#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT
#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW
const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len);
const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret);
typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*);
u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance);
u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */

View File

@@ -1,116 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
/**
* @defgroup snmp_mib2 MIB2
* @ingroup snmp
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */
#if !LWIP_STATS
#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2)
#endif
#if !MIB2_STATS
#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2)
#endif
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_scalar.h"
#if SNMP_USE_NETCONN
#include "lwip/tcpip.h"
#include "lwip/priv/tcpip_priv.h"
void
snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg)
{
#if LWIP_TCPIP_CORE_LOCKING
LOCK_TCPIP_CORE();
fn(arg);
UNLOCK_TCPIP_CORE();
#else
tcpip_callback(fn, arg);
#endif
}
struct snmp_threadsync_instance snmp_mib2_lwip_locks;
#endif
/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */
/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */
/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */
/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */
extern const struct snmp_scalar_array_node snmp_mib2_snmp_root;
extern const struct snmp_tree_node snmp_mib2_udp_root;
extern const struct snmp_tree_node snmp_mib2_tcp_root;
extern const struct snmp_scalar_array_node snmp_mib2_icmp_root;
extern const struct snmp_tree_node snmp_mib2_interface_root;
extern const struct snmp_scalar_array_node snmp_mib2_system_node;
extern const struct snmp_tree_node snmp_mib2_at_root;
extern const struct snmp_tree_node snmp_mib2_ip_root;
static const struct snmp_node* const mib2_nodes[] = {
&snmp_mib2_system_node.node.node,
&snmp_mib2_interface_root.node,
#if LWIP_ARP && LWIP_IPV4
&snmp_mib2_at_root.node,
#endif /* LWIP_ARP && LWIP_IPV4 */
#if LWIP_IPV4
&snmp_mib2_ip_root.node,
#endif /* LWIP_IPV4 */
#if LWIP_ICMP
&snmp_mib2_icmp_root.node.node,
#endif /* LWIP_ICMP */
#if LWIP_TCP
&snmp_mib2_tcp_root.node,
#endif /* LWIP_TCP */
#if LWIP_UDP
&snmp_mib2_udp_root.node,
#endif /* LWIP_UDP */
&snmp_mib2_snmp_root.node.node
};
static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes);
static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 };
const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */

View File

@@ -1,182 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) ICMP objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/icmp.h"
#include "lwip/stats.h"
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */
static s16_t
icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
{
u32_t *uint_ptr = (u32_t*)value;
switch (node->oid) {
case 1: /* icmpInMsgs */
*uint_ptr = STATS_GET(mib2.icmpinmsgs);
return sizeof(*uint_ptr);
case 2: /* icmpInErrors */
*uint_ptr = STATS_GET(mib2.icmpinerrors);
return sizeof(*uint_ptr);
case 3: /* icmpInDestUnreachs */
*uint_ptr = STATS_GET(mib2.icmpindestunreachs);
return sizeof(*uint_ptr);
case 4: /* icmpInTimeExcds */
*uint_ptr = STATS_GET(mib2.icmpintimeexcds);
return sizeof(*uint_ptr);
case 5: /* icmpInParmProbs */
*uint_ptr = STATS_GET(mib2.icmpinparmprobs);
return sizeof(*uint_ptr);
case 6: /* icmpInSrcQuenchs */
*uint_ptr = STATS_GET(mib2.icmpinsrcquenchs);
return sizeof(*uint_ptr);
case 7: /* icmpInRedirects */
*uint_ptr = STATS_GET(mib2.icmpinredirects);
return sizeof(*uint_ptr);
case 8: /* icmpInEchos */
*uint_ptr = STATS_GET(mib2.icmpinechos);
return sizeof(*uint_ptr);
case 9: /* icmpInEchoReps */
*uint_ptr = STATS_GET(mib2.icmpinechoreps);
return sizeof(*uint_ptr);
case 10: /* icmpInTimestamps */
*uint_ptr = STATS_GET(mib2.icmpintimestamps);
return sizeof(*uint_ptr);
case 11: /* icmpInTimestampReps */
*uint_ptr = STATS_GET(mib2.icmpintimestampreps);
return sizeof(*uint_ptr);
case 12: /* icmpInAddrMasks */
*uint_ptr = STATS_GET(mib2.icmpinaddrmasks);
return sizeof(*uint_ptr);
case 13: /* icmpInAddrMaskReps */
*uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps);
return sizeof(*uint_ptr);
case 14: /* icmpOutMsgs */
*uint_ptr = STATS_GET(mib2.icmpoutmsgs);
return sizeof(*uint_ptr);
case 15: /* icmpOutErrors */
*uint_ptr = STATS_GET(mib2.icmpouterrors);
return sizeof(*uint_ptr);
case 16: /* icmpOutDestUnreachs */
*uint_ptr = STATS_GET(mib2.icmpoutdestunreachs);
return sizeof(*uint_ptr);
case 17: /* icmpOutTimeExcds */
*uint_ptr = STATS_GET(mib2.icmpouttimeexcds);
return sizeof(*uint_ptr);
case 18: /* icmpOutParmProbs: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 20: /* icmpOutRedirects: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 21: /* icmpOutEchos */
*uint_ptr = STATS_GET(mib2.icmpoutechos);
return sizeof(*uint_ptr);
case 22: /* icmpOutEchoReps */
*uint_ptr = STATS_GET(mib2.icmpoutechoreps);
return sizeof(*uint_ptr);
case 23: /* icmpOutTimestamps: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 24: /* icmpOutTimestampReps: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 25: /* icmpOutAddrMasks: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid));
break;
}
return 0;
}
static const struct snmp_scalar_array_node_def icmp_nodes[] = {
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}
};
const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */

View File

@@ -1,375 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) INTERFACES objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include <string.h>
#if LWIP_SNMP && SNMP_LWIP_MIB2
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
static s16_t
interfaces_get_value(struct snmp_node_instance* instance, void* value)
{
if (instance->node->oid == 1) {
s32_t *sint_ptr = (s32_t*)value;
s32_t num_netifs = 0;
struct netif *netif = netif_list;
while (netif != NULL) {
num_netifs++;
netif = netif->next;
}
*sint_ptr = num_netifs;
return sizeof(*sint_ptr);
}
return 0;
}
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range interfaces_Table_oid_ranges[] = {
{ 1, 0xff } /* netif->num is u8_t */
};
static const u8_t iftable_ifOutQLen = 0;
static const u8_t iftable_ifOperStatus_up = 1;
static const u8_t iftable_ifOperStatus_down = 2;
static const u8_t iftable_ifAdminStatus_up = 1;
static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7;
static const u8_t iftable_ifAdminStatus_down = 2;
static snmp_err_t
interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance)
{
u32_t ifIndex;
struct netif *netif;
LWIP_UNUSED_ARG(column);
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get netif index from incoming OID */
ifIndex = row_oid[0];
/* find netif with index */
netif = netif_list;
while (netif != NULL) {
if (netif_to_num(netif) == ifIndex) {
/* store netif pointer for subsequent operations (get/test/set) */
cell_instance->reference.ptr = netif;
return SNMP_ERR_NOERROR;
}
netif = netif->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance)
{
struct netif *netif;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
LWIP_UNUSED_ARG(column);
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges));
/* iterate over all possible OIDs to find the next one */
netif = netif_list;
while (netif != NULL) {
u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
test_oid[0] = netif_to_num(netif);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif);
netif = netif->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* store netif pointer for subsequent operations (get/test/set) */
cell_instance->reference.ptr = /* (struct netif*) */state.reference;
return SNMP_ERR_NOERROR;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static s16_t
interfaces_Table_get_value(struct snmp_node_instance* instance, void* value)
{
struct netif *netif = (struct netif*)instance->reference.ptr;
u32_t* value_u32 = (u32_t*)value;
s32_t* value_s32 = (s32_t*)value;
u16_t value_len;
switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
{
case 1: /* ifIndex */
*value_s32 = netif_to_num(netif);
value_len = sizeof(*value_s32);
break;
case 2: /* ifDescr */
value_len = sizeof(netif->name);
MEMCPY(value, netif->name, value_len);
break;
case 3: /* ifType */
*value_s32 = netif->link_type;
value_len = sizeof(*value_s32);
break;
case 4: /* ifMtu */
*value_s32 = netif->mtu;
value_len = sizeof(*value_s32);
break;
case 5: /* ifSpeed */
*value_u32 = netif->link_speed;
value_len = sizeof(*value_u32);
break;
case 6: /* ifPhysAddress */
value_len = sizeof(netif->hwaddr);
MEMCPY(value, &netif->hwaddr, value_len);
break;
case 7: /* ifAdminStatus */
if (netif_is_up(netif)) {
*value_s32 = iftable_ifOperStatus_up;
} else {
*value_s32 = iftable_ifOperStatus_down;
}
value_len = sizeof(*value_s32);
break;
case 8: /* ifOperStatus */
if (netif_is_up(netif)) {
if (netif_is_link_up(netif)) {
*value_s32 = iftable_ifAdminStatus_up;
} else {
*value_s32 = iftable_ifAdminStatus_lowerLayerDown;
}
} else {
*value_s32 = iftable_ifAdminStatus_down;
}
value_len = sizeof(*value_s32);
break;
case 9: /* ifLastChange */
*value_u32 = netif->ts;
value_len = sizeof(*value_u32);
break;
case 10: /* ifInOctets */
*value_u32 = netif->mib2_counters.ifinoctets;
value_len = sizeof(*value_u32);
break;
case 11: /* ifInUcastPkts */
*value_u32 = netif->mib2_counters.ifinucastpkts;
value_len = sizeof(*value_u32);
break;
case 12: /* ifInNUcastPkts */
*value_u32 = netif->mib2_counters.ifinnucastpkts;
value_len = sizeof(*value_u32);
break;
case 13: /* ifInDiscards */
*value_u32 = netif->mib2_counters.ifindiscards;
value_len = sizeof(*value_u32);
break;
case 14: /* ifInErrors */
*value_u32 = netif->mib2_counters.ifinerrors;
value_len = sizeof(*value_u32);
break;
case 15: /* ifInUnkownProtos */
*value_u32 = netif->mib2_counters.ifinunknownprotos;
value_len = sizeof(*value_u32);
break;
case 16: /* ifOutOctets */
*value_u32 = netif->mib2_counters.ifoutoctets;
value_len = sizeof(*value_u32);
break;
case 17: /* ifOutUcastPkts */
*value_u32 = netif->mib2_counters.ifoutucastpkts;
value_len = sizeof(*value_u32);
break;
case 18: /* ifOutNUcastPkts */
*value_u32 = netif->mib2_counters.ifoutnucastpkts;
value_len = sizeof(*value_u32);
break;
case 19: /* ifOutDiscarts */
*value_u32 = netif->mib2_counters.ifoutdiscards;
value_len = sizeof(*value_u32);
break;
case 20: /* ifOutErrors */
*value_u32 = netif->mib2_counters.ifouterrors;
value_len = sizeof(*value_u32);
break;
case 21: /* ifOutQLen */
*value_u32 = iftable_ifOutQLen;
value_len = sizeof(*value_u32);
break;
/** @note returning zeroDotZero (0.0) no media specific MIB support */
case 22: /* ifSpecific */
value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
MEMCPY(value, snmp_zero_dot_zero.id, value_len);
break;
default:
return 0;
}
return value_len;
}
#if !SNMP_SAFE_REQUESTS
static snmp_err_t
interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
{
s32_t *sint_ptr = (s32_t*)value;
/* stack should never call this method for another column,
because all other columns are set to readonly */
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
LWIP_UNUSED_ARG(len);
if (*sint_ptr == 1 || *sint_ptr == 2) {
return SNMP_ERR_NOERROR;
}
return SNMP_ERR_WRONGVALUE;
}
static snmp_err_t
interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
{
struct netif *netif = (struct netif*)instance->reference.ptr;
s32_t *sint_ptr = (s32_t*)value;
/* stack should never call this method for another column,
because all other columns are set to readonly */
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
LWIP_UNUSED_ARG(len);
if (*sint_ptr == 1) {
netif_set_up(netif);
} else if (*sint_ptr == 2) {
netif_set_down(netif);
}
return SNMP_ERR_NOERROR;
}
#endif /* SNMP_SAFE_REQUESTS */
static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value);
static const struct snmp_table_col_def interfaces_Table_columns[] = {
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */
{ 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */
{ 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */
#if !SNMP_SAFE_REQUESTS
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */
#else
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */
#endif
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */
{ 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */
{ 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */
{ 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */
{ 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */
{ 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */
{ 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */
{ 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */
{ 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */
{ 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */
{ 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */
{ 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */
{ 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */
{ 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */
{ 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */
};
#if !SNMP_SAFE_REQUESTS
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
2, interfaces_Table_columns,
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value);
#else
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
2, interfaces_Table_columns,
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
interfaces_Table_get_value, NULL, NULL);
#endif
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
static const struct snmp_node* const interface_nodes[] = {
&SYNC_NODE_NAME(interfaces_Number).node.node,
&SYNC_NODE_NAME(interfaces_Table).node.node
};
const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */

View File

@@ -1,743 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) IP objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/stats.h"
#include "lwip/netif.h"
#include "lwip/ip.h"
#include "lwip/etharp.h"
#if LWIP_SNMP && SNMP_LWIP_MIB2
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
#if LWIP_IPV4
/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */
static s16_t
ip_get_value(struct snmp_node_instance* instance, void* value)
{
s32_t* sint_ptr = (s32_t*)value;
u32_t* uint_ptr = (u32_t*)value;
switch (instance->node->oid) {
case 1: /* ipForwarding */
#if IP_FORWARD
/* forwarding */
*sint_ptr = 1;
#else
/* not-forwarding */
*sint_ptr = 2;
#endif
return sizeof(*sint_ptr);
case 2: /* ipDefaultTTL */
*sint_ptr = IP_DEFAULT_TTL;
return sizeof(*sint_ptr);
case 3: /* ipInReceives */
*uint_ptr = STATS_GET(mib2.ipinreceives);
return sizeof(*uint_ptr);
case 4: /* ipInHdrErrors */
*uint_ptr = STATS_GET(mib2.ipinhdrerrors);
return sizeof(*uint_ptr);
case 5: /* ipInAddrErrors */
*uint_ptr = STATS_GET(mib2.ipinaddrerrors);
return sizeof(*uint_ptr);
case 6: /* ipForwDatagrams */
*uint_ptr = STATS_GET(mib2.ipforwdatagrams);
return sizeof(*uint_ptr);
case 7: /* ipInUnknownProtos */
*uint_ptr = STATS_GET(mib2.ipinunknownprotos);
return sizeof(*uint_ptr);
case 8: /* ipInDiscards */
*uint_ptr = STATS_GET(mib2.ipindiscards);
return sizeof(*uint_ptr);
case 9: /* ipInDelivers */
*uint_ptr = STATS_GET(mib2.ipindelivers);
return sizeof(*uint_ptr);
case 10: /* ipOutRequests */
*uint_ptr = STATS_GET(mib2.ipoutrequests);
return sizeof(*uint_ptr);
case 11: /* ipOutDiscards */
*uint_ptr = STATS_GET(mib2.ipoutdiscards);
return sizeof(*uint_ptr);
case 12: /* ipOutNoRoutes */
*uint_ptr = STATS_GET(mib2.ipoutnoroutes);
return sizeof(*uint_ptr);
case 13: /* ipReasmTimeout */
#if IP_REASSEMBLY
*sint_ptr = IP_REASS_MAXAGE;
#else
*sint_ptr = 0;
#endif
return sizeof(*sint_ptr);
case 14: /* ipReasmReqds */
*uint_ptr = STATS_GET(mib2.ipreasmreqds);
return sizeof(*uint_ptr);
case 15: /* ipReasmOKs */
*uint_ptr = STATS_GET(mib2.ipreasmoks);
return sizeof(*uint_ptr);
case 16: /* ipReasmFails */
*uint_ptr = STATS_GET(mib2.ipreasmfails);
return sizeof(*uint_ptr);
case 17: /* ipFragOKs */
*uint_ptr = STATS_GET(mib2.ipfragoks);
return sizeof(*uint_ptr);
case 18: /* ipFragFails */
*uint_ptr = STATS_GET(mib2.ipfragfails);
return sizeof(*uint_ptr);
case 19: /* ipFragCreates */
*uint_ptr = STATS_GET(mib2.ipfragcreates);
return sizeof(*uint_ptr);
case 23: /* ipRoutingDiscards: not supported -> always 0 */
*uint_ptr = 0;
return sizeof(*uint_ptr);
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
break;
}
return 0;
}
/**
* Test ip object value before setting.
*
* @param instance node instance
* @param len return value space (in bytes)
* @param value points to (varbind) space to copy value from.
*
* @note we allow set if the value matches the hardwired value,
* otherwise return badvalue.
*/
static snmp_err_t
ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
{
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
s32_t *sint_ptr = (s32_t*)value;
LWIP_UNUSED_ARG(len);
switch (instance->node->oid) {
case 1: /* ipForwarding */
#if IP_FORWARD
/* forwarding */
if (*sint_ptr == 1)
#else
/* not-forwarding */
if (*sint_ptr == 2)
#endif
{
ret = SNMP_ERR_NOERROR;
}
break;
case 2: /* ipDefaultTTL */
if (*sint_ptr == IP_DEFAULT_TTL) {
ret = SNMP_ERR_NOERROR;
}
break;
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid));
break;
}
return ret;
}
static snmp_err_t
ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
{
LWIP_UNUSED_ARG(instance);
LWIP_UNUSED_ARG(len);
LWIP_UNUSED_ARG(value);
/* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */
return SNMP_ERR_NOERROR;
}
/* --- ipAddrTable --- */
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = {
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff } /* IP D */
};
static snmp_err_t
ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
{
LWIP_UNUSED_ARG(value_len);
switch (*column) {
case 1: /* ipAdEntAddr */
value->u32 = netif_ip4_addr(netif)->addr;
break;
case 2: /* ipAdEntIfIndex */
value->u32 = netif_to_num(netif);
break;
case 3: /* ipAdEntNetMask */
value->u32 = netif_ip4_netmask(netif)->addr;
break;
case 4: /* ipAdEntBcastAddr */
/* lwIP oddity, there's no broadcast
address in the netif we can rely on */
value->u32 = IPADDR_BROADCAST & 1;
break;
case 5: /* ipAdEntReasmMaxSize */
#if IP_REASSEMBLY
/* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
* but only if receiving one fragmented packet at a time.
* The current solution is to calculate for 2 simultaneous packets...
*/
value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) *
(PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN)));
#else
/** @todo returning MTU would be a bad thing and
returning a wild guess like '576' isn't good either */
value->u32 = 0;
#endif
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip4_addr_t ip;
struct netif *netif;
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get IP from incoming OID */
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
/* find netif with requested ip */
netif = netif_list;
while (netif != NULL) {
if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) {
/* fill in object properties */
return ip_AddrTable_get_cell_value_core(netif, column, value, value_len);
}
netif = netif->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct netif *netif;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges));
/* iterate over all possible OIDs to find the next one */
netif = netif_list;
while (netif != NULL) {
u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif);
netif = netif->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len);
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
/* --- ipRouteTable --- */
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = {
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff }, /* IP D */
};
static snmp_err_t
ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
{
switch (*column) {
case 1: /* ipRouteDest */
if (default_route) {
/* default rte has 0.0.0.0 dest */
value->u32 = IP4_ADDR_ANY4->addr;
} else {
/* netifs have netaddress dest */
ip4_addr_t tmp;
ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif));
value->u32 = tmp.addr;
}
break;
case 2: /* ipRouteIfIndex */
value->u32 = netif_to_num(netif);
break;
case 3: /* ipRouteMetric1 */
if (default_route) {
value->s32 = 1; /* default */
} else {
value->s32 = 0; /* normal */
}
break;
case 4: /* ipRouteMetric2 */
case 5: /* ipRouteMetric3 */
case 6: /* ipRouteMetric4 */
value->s32 = -1; /* none */
break;
case 7: /* ipRouteNextHop */
if (default_route) {
/* default rte: gateway */
value->u32 = netif_ip4_gw(netif)->addr;
} else {
/* other rtes: netif ip_addr */
value->u32 = netif_ip4_addr(netif)->addr;
}
break;
case 8: /* ipRouteType */
if (default_route) {
/* default rte is indirect */
value->u32 = 4; /* indirect */
} else {
/* other rtes are direct */
value->u32 = 3; /* direct */
}
break;
case 9: /* ipRouteProto */
/* locally defined routes */
value->u32 = 2; /* local */
break;
case 10: /* ipRouteAge */
/* @todo (sysuptime - timestamp last change) / 100 */
value->u32 = 0;
break;
case 11: /* ipRouteMask */
if (default_route) {
/* default rte use 0.0.0.0 mask */
value->u32 = IP4_ADDR_ANY4->addr;
} else {
/* other rtes use netmask */
value->u32 = netif_ip4_netmask(netif)->addr;
}
break;
case 12: /* ipRouteMetric5 */
value->s32 = -1; /* none */
break;
case 13: /* ipRouteInfo */
value->const_ptr = snmp_zero_dot_zero.id;
*value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip4_addr_t test_ip;
struct netif *netif;
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get IP and port from incoming OID */
snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */
/* default route is on default netif */
if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) {
/* fill in object properties */
return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len);
}
/* find netif with requested route */
netif = netif_list;
while (netif != NULL) {
ip4_addr_t dst;
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
if (ip4_addr_cmp(&dst, &test_ip)) {
/* fill in object properties */
return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len);
}
netif = netif->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct netif *netif;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges));
/* check default route */
if (netif_default != NULL) {
snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]);
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default);
}
/* iterate over all possible OIDs to find the next one */
netif = netif_list;
while (netif != NULL) {
ip4_addr_t dst;
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
/* check generated OID: is it a candidate for the next one? */
if (!ip4_addr_isany_val(dst)) {
snmp_ip4_to_oid(&dst, &test_oid[0]);
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif);
}
netif = netif->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
ip4_addr_t dst;
snmp_oid_to_ip4(&result_temp[0], &dst);
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len);
} else {
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
}
#if LWIP_ARP && LWIP_IPV4
/* --- ipNetToMediaTable --- */
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = {
{ 1, 0xff }, /* IfIndex */
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff } /* IP D */
};
static snmp_err_t
ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
{
ip4_addr_t *ip;
struct netif *netif;
struct eth_addr *ethaddr;
etharp_get_entry(arp_table_index, &ip, &netif, &ethaddr);
/* value */
switch (*column) {
case 1: /* atIfIndex / ipNetToMediaIfIndex */
value->u32 = netif_to_num(netif);
break;
case 2: /* atPhysAddress / ipNetToMediaPhysAddress */
value->ptr = ethaddr;
*value_len = sizeof(*ethaddr);
break;
case 3: /* atNetAddress / ipNetToMediaNetAddress */
value->u32 = ip->addr;
break;
case 4: /* ipNetToMediaType */
value->u32 = 3; /* dynamic*/
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip4_addr_t ip_in;
u8_t netif_index;
u8_t i;
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get IP from incoming OID */
netif_index = (u8_t)row_oid[0];
snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */
/* find requested entry */
for (i=0; i<ARP_TABLE_SIZE; i++) {
ip4_addr_t *ip;
struct netif *netif;
struct eth_addr *ethaddr;
if (etharp_get_entry(i, &ip, &netif, &ethaddr)) {
if ((netif_index == netif_to_num(netif)) && ip4_addr_cmp(&ip_in, ip)) {
/* fill in object properties */
return ip_NetToMediaTable_get_cell_value_core(i, column, value, value_len);
}
}
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
u8_t i;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges));
/* iterate over all possible OIDs to find the next one */
for (i=0; i<ARP_TABLE_SIZE; i++) {
ip4_addr_t *ip;
struct netif *netif;
struct eth_addr *ethaddr;
if (etharp_get_entry(i, &ip, &netif, &ethaddr)) {
u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
test_oid[0] = netif_to_num(netif);
snmp_ip4_to_oid(ip, &test_oid[1]);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i);
}
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len);
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
#endif /* LWIP_ARP && LWIP_IPV4 */
static const struct snmp_scalar_node ip_Forwarding = SNMP_SCALAR_CREATE_NODE(1, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
static const struct snmp_scalar_node ip_DefaultTTL = SNMP_SCALAR_CREATE_NODE(2, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
static const struct snmp_scalar_node ip_InReceives = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_InHdrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_InAddrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_ForwDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_InUnknownProtos = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_InDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_InDelivers = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_OutRequests = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_OutDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_OutNoRoutes = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_ReasmTimeout = SNMP_SCALAR_CREATE_NODE_READONLY(13, SNMP_ASN1_TYPE_INTEGER, ip_get_value);
static const struct snmp_scalar_node ip_ReasmReqds = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_ReasmOKs = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_ReasmFails = SNMP_SCALAR_CREATE_NODE_READONLY(16, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_FragOKs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_FragFails = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_FragCreates = SNMP_SCALAR_CREATE_NODE_READONLY(19, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_scalar_node ip_RoutingDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(23, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
static const struct snmp_table_simple_col_def ip_AddrTable_columns[] = {
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntAddr */
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntIfIndex */
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntNetMask */
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntBcastAddr */
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipAdEntReasmMaxSize */
};
static const struct snmp_table_simple_node ip_AddrTable = SNMP_TABLE_CREATE_SIMPLE(20, ip_AddrTable_columns, ip_AddrTable_get_cell_value, ip_AddrTable_get_next_cell_instance_and_value);
static const struct snmp_table_simple_col_def ip_RouteTable_columns[] = {
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteDest */
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteIfIndex */
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric1 */
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric2 */
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric3 */
{ 6, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric4 */
{ 7, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteNextHop */
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteType */
{ 9, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteProto */
{ 10, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteAge */
{ 11, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteMask */
{ 12, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric5 */
{ 13, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_VARIANT_VALUE_TYPE_PTR } /* ipRouteInfo */
};
static const struct snmp_table_simple_node ip_RouteTable = SNMP_TABLE_CREATE_SIMPLE(21, ip_RouteTable_columns, ip_RouteTable_get_cell_value, ip_RouteTable_get_next_cell_instance_and_value);
#endif /* LWIP_IPV4 */
#if LWIP_ARP && LWIP_IPV4
static const struct snmp_table_simple_col_def ip_NetToMediaTable_columns[] = {
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaIfIndex */
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* ipNetToMediaPhysAddress */
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaNetAddress */
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipNetToMediaType */
};
static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREATE_SIMPLE(22, ip_NetToMediaTable_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
#endif /* LWIP_ARP && LWIP_IPV4 */
#if LWIP_IPV4
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding)
CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL)
CREATE_LWIP_SYNC_NODE( 3, ip_InReceives)
CREATE_LWIP_SYNC_NODE( 4, ip_InHdrErrors)
CREATE_LWIP_SYNC_NODE( 5, ip_InAddrErrors)
CREATE_LWIP_SYNC_NODE( 6, ip_ForwDatagrams)
CREATE_LWIP_SYNC_NODE( 7, ip_InUnknownProtos)
CREATE_LWIP_SYNC_NODE( 8, ip_InDiscards)
CREATE_LWIP_SYNC_NODE( 9, ip_InDelivers)
CREATE_LWIP_SYNC_NODE(10, ip_OutRequests)
CREATE_LWIP_SYNC_NODE(11, ip_OutDiscards)
CREATE_LWIP_SYNC_NODE(12, ip_OutNoRoutes)
CREATE_LWIP_SYNC_NODE(13, ip_ReasmTimeout)
CREATE_LWIP_SYNC_NODE(14, ip_ReasmReqds)
CREATE_LWIP_SYNC_NODE(15, ip_ReasmOKs)
CREATE_LWIP_SYNC_NODE(15, ip_ReasmFails)
CREATE_LWIP_SYNC_NODE(17, ip_FragOKs)
CREATE_LWIP_SYNC_NODE(18, ip_FragFails)
CREATE_LWIP_SYNC_NODE(19, ip_FragCreates)
CREATE_LWIP_SYNC_NODE(20, ip_AddrTable)
CREATE_LWIP_SYNC_NODE(21, ip_RouteTable)
#if LWIP_ARP
CREATE_LWIP_SYNC_NODE(22, ip_NetToMediaTable)
#endif /* LWIP_ARP */
CREATE_LWIP_SYNC_NODE(23, ip_RoutingDiscards)
static const struct snmp_node* const ip_nodes[] = {
&SYNC_NODE_NAME(ip_Forwarding).node.node,
&SYNC_NODE_NAME(ip_DefaultTTL).node.node,
&SYNC_NODE_NAME(ip_InReceives).node.node,
&SYNC_NODE_NAME(ip_InHdrErrors).node.node,
&SYNC_NODE_NAME(ip_InAddrErrors).node.node,
&SYNC_NODE_NAME(ip_ForwDatagrams).node.node,
&SYNC_NODE_NAME(ip_InUnknownProtos).node.node,
&SYNC_NODE_NAME(ip_InDiscards).node.node,
&SYNC_NODE_NAME(ip_InDelivers).node.node,
&SYNC_NODE_NAME(ip_OutRequests).node.node,
&SYNC_NODE_NAME(ip_OutDiscards).node.node,
&SYNC_NODE_NAME(ip_OutNoRoutes).node.node,
&SYNC_NODE_NAME(ip_ReasmTimeout).node.node,
&SYNC_NODE_NAME(ip_ReasmReqds).node.node,
&SYNC_NODE_NAME(ip_ReasmOKs).node.node,
&SYNC_NODE_NAME(ip_ReasmFails).node.node,
&SYNC_NODE_NAME(ip_FragOKs).node.node,
&SYNC_NODE_NAME(ip_FragFails).node.node,
&SYNC_NODE_NAME(ip_FragCreates).node.node,
&SYNC_NODE_NAME(ip_AddrTable).node.node,
&SYNC_NODE_NAME(ip_RouteTable).node.node,
#if LWIP_ARP
&SYNC_NODE_NAME(ip_NetToMediaTable).node.node,
#endif /* LWIP_ARP */
&SYNC_NODE_NAME(ip_RoutingDiscards).node.node
};
const struct snmp_tree_node snmp_mib2_ip_root = SNMP_CREATE_TREE_NODE(4, ip_nodes);
#endif /* LWIP_IPV4 */
/* --- at .1.3.6.1.2.1.3 ----------------------------------------------------- */
#if LWIP_ARP && LWIP_IPV4
/* at node table is a subset of ip_nettomedia table (same rows but less columns) */
static const struct snmp_table_simple_col_def at_Table_columns[] = {
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* atIfIndex */
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* atPhysAddress */
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 } /* atNetAddress */
};
static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
CREATE_LWIP_SYNC_NODE(1, at_Table)
static const struct snmp_node* const at_nodes[] = {
&SYNC_NODE_NAME(at_Table).node.node
};
const struct snmp_tree_node snmp_mib2_at_root = SNMP_CREATE_TREE_NODE(3, at_nodes);
#endif /* LWIP_ARP && LWIP_IPV4 */
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */

View File

@@ -1,227 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) SNMP objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_scalar.h"
#if LWIP_SNMP && SNMP_LWIP_MIB2
#define MIB2_AUTH_TRAPS_ENABLED 1
#define MIB2_AUTH_TRAPS_DISABLED 2
/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */
static s16_t
snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
{
u32_t *uint_ptr = (u32_t*)value;
switch (node->oid) {
case 1: /* snmpInPkts */
*uint_ptr = snmp_stats.inpkts;
break;
case 2: /* snmpOutPkts */
*uint_ptr = snmp_stats.outpkts;
break;
case 3: /* snmpInBadVersions */
*uint_ptr = snmp_stats.inbadversions;
break;
case 4: /* snmpInBadCommunityNames */
*uint_ptr = snmp_stats.inbadcommunitynames;
break;
case 5: /* snmpInBadCommunityUses */
*uint_ptr = snmp_stats.inbadcommunityuses;
break;
case 6: /* snmpInASNParseErrs */
*uint_ptr = snmp_stats.inasnparseerrs;
break;
case 8: /* snmpInTooBigs */
*uint_ptr = snmp_stats.intoobigs;
break;
case 9: /* snmpInNoSuchNames */
*uint_ptr = snmp_stats.innosuchnames;
break;
case 10: /* snmpInBadValues */
*uint_ptr = snmp_stats.inbadvalues;
break;
case 11: /* snmpInReadOnlys */
*uint_ptr = snmp_stats.inreadonlys;
break;
case 12: /* snmpInGenErrs */
*uint_ptr = snmp_stats.ingenerrs;
break;
case 13: /* snmpInTotalReqVars */
*uint_ptr = snmp_stats.intotalreqvars;
break;
case 14: /* snmpInTotalSetVars */
*uint_ptr = snmp_stats.intotalsetvars;
break;
case 15: /* snmpInGetRequests */
*uint_ptr = snmp_stats.ingetrequests;
break;
case 16: /* snmpInGetNexts */
*uint_ptr = snmp_stats.ingetnexts;
break;
case 17: /* snmpInSetRequests */
*uint_ptr = snmp_stats.insetrequests;
break;
case 18: /* snmpInGetResponses */
*uint_ptr = snmp_stats.ingetresponses;
break;
case 19: /* snmpInTraps */
*uint_ptr = snmp_stats.intraps;
break;
case 20: /* snmpOutTooBigs */
*uint_ptr = snmp_stats.outtoobigs;
break;
case 21: /* snmpOutNoSuchNames */
*uint_ptr = snmp_stats.outnosuchnames;
break;
case 22: /* snmpOutBadValues */
*uint_ptr = snmp_stats.outbadvalues;
break;
case 24: /* snmpOutGenErrs */
*uint_ptr = snmp_stats.outgenerrs;
break;
case 25: /* snmpOutGetRequests */
*uint_ptr = snmp_stats.outgetrequests;
break;
case 26: /* snmpOutGetNexts */
*uint_ptr = snmp_stats.outgetnexts;
break;
case 27: /* snmpOutSetRequests */
*uint_ptr = snmp_stats.outsetrequests;
break;
case 28: /* snmpOutGetResponses */
*uint_ptr = snmp_stats.outgetresponses;
break;
case 29: /* snmpOutTraps */
*uint_ptr = snmp_stats.outtraps;
break;
case 30: /* snmpEnableAuthenTraps */
if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) {
*uint_ptr = MIB2_AUTH_TRAPS_DISABLED;
} else {
*uint_ptr = MIB2_AUTH_TRAPS_ENABLED;
}
break;
case 31: /* snmpSilentDrops */
*uint_ptr = 0; /* not supported */
break;
case 32: /* snmpProxyDrops */
*uint_ptr = 0; /* not supported */
break;
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid));
return 0;
}
return sizeof(*uint_ptr);
}
static snmp_err_t
snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
{
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
LWIP_UNUSED_ARG(len);
if (node->oid == 30) {
/* snmpEnableAuthenTraps */
s32_t *sint_ptr = (s32_t*)value;
/* we should have writable non-volatile mem here */
if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) {
ret = SNMP_ERR_NOERROR;
}
}
return ret;
}
static snmp_err_t
snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
{
LWIP_UNUSED_ARG(len);
if (node->oid == 30) {
/* snmpEnableAuthenTraps */
s32_t *sint_ptr = (s32_t*)value;
if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) {
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED);
} else {
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED);
}
}
return SNMP_ERR_NOERROR;
}
/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */
static const struct snmp_scalar_array_node_def snmp_nodes[] = {
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */
{27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */
{28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */
{29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */
{30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */
{31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */
{32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */
};
const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */

View File

@@ -1,377 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) SYSTEM objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/sys.h"
#include <string.h>
#if LWIP_SNMP && SNMP_LWIP_MIB2
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */
/** mib-2.system.sysDescr */
static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC;
static const u8_t* sysdescr = sysdescr_default;
static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */
/** mib-2.system.sysContact */
static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT;
static const u8_t* syscontact = syscontact_default;
static const u16_t* syscontact_len = NULL; /* use strlen for determining len */
static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */
static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */
static u16_t syscontact_bufsize = 0; /* 0=not writable */
/** mib-2.system.sysName */
static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME;
static const u8_t* sysname = sysname_default;
static const u16_t* sysname_len = NULL; /* use strlen for determining len */
static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */
static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */
static u16_t sysname_bufsize = 0; /* 0=not writable */
/** mib-2.system.sysLocation */
static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION;
static const u8_t* syslocation = syslocation_default;
static const u16_t* syslocation_len = NULL; /* use strlen for determining len */
static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */
static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */
static u16_t syslocation_bufsize = 0; /* 0=not writable */
/**
* @ingroup snmp_mib2
* Initializes sysDescr pointers.
*
* @param str if non-NULL then copy str pointer
* @param len points to string length, excluding zero terminator
*/
void
snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len)
{
if (str != NULL) {
sysdescr = str;
sysdescr_len = len;
}
}
/**
* @ingroup snmp_mib2
* Initializes sysContact pointers
*
* @param ocstr if non-NULL then copy str pointer
* @param ocstrlen points to string length, excluding zero terminator.
* if set to NULL it is assumed that ocstr is NULL-terminated.
* @param bufsize size of the buffer in bytes.
* (this is required because the buffer can be overwritten by snmp-set)
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
* otherwise complete buffer is used for string.
* if bufsize is set to 0, the value is regarded as read-only.
*/
void
snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
{
if (ocstr != NULL) {
syscontact = ocstr;
syscontact_wr = ocstr;
syscontact_len = ocstrlen;
syscontact_wr_len = ocstrlen;
syscontact_bufsize = bufsize;
}
}
/**
* @ingroup snmp_mib2
* see \ref snmp_mib2_set_syscontact but set pointer to readonly memory
*/
void
snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
{
if (ocstr != NULL) {
syscontact = ocstr;
syscontact_len = ocstrlen;
syscontact_wr = NULL;
syscontact_wr_len = NULL;
syscontact_bufsize = 0;
}
}
/**
* @ingroup snmp_mib2
* Initializes sysName pointers
*
* @param ocstr if non-NULL then copy str pointer
* @param ocstrlen points to string length, excluding zero terminator.
* if set to NULL it is assumed that ocstr is NULL-terminated.
* @param bufsize size of the buffer in bytes.
* (this is required because the buffer can be overwritten by snmp-set)
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
* otherwise complete buffer is used for string.
* if bufsize is set to 0, the value is regarded as read-only.
*/
void
snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
{
if (ocstr != NULL) {
sysname = ocstr;
sysname_wr = ocstr;
sysname_len = ocstrlen;
sysname_wr_len = ocstrlen;
sysname_bufsize = bufsize;
}
}
/**
* @ingroup snmp_mib2
* see \ref snmp_mib2_set_sysname but set pointer to readonly memory
*/
void
snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
{
if (ocstr != NULL) {
sysname = ocstr;
sysname_len = ocstrlen;
sysname_wr = NULL;
sysname_wr_len = NULL;
sysname_bufsize = 0;
}
}
/**
* @ingroup snmp_mib2
* Initializes sysLocation pointers
*
* @param ocstr if non-NULL then copy str pointer
* @param ocstrlen points to string length, excluding zero terminator.
* if set to NULL it is assumed that ocstr is NULL-terminated.
* @param bufsize size of the buffer in bytes.
* (this is required because the buffer can be overwritten by snmp-set)
* if ocstrlen is NULL buffer needs space for terminating 0 byte.
* otherwise complete buffer is used for string.
* if bufsize is set to 0, the value is regarded as read-only.
*/
void
snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
{
if (ocstr != NULL) {
syslocation = ocstr;
syslocation_wr = ocstr;
syslocation_len = ocstrlen;
syslocation_wr_len = ocstrlen;
syslocation_bufsize = bufsize;
}
}
/**
* @ingroup snmp_mib2
* see \ref snmp_mib2_set_syslocation but set pointer to readonly memory
*/
void
snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
{
if (ocstr != NULL) {
syslocation = ocstr;
syslocation_len = ocstrlen;
syslocation_wr = NULL;
syslocation_wr_len = NULL;
syslocation_bufsize = 0;
}
}
static s16_t
system_get_value(const struct snmp_scalar_array_node_def *node, void *value)
{
const u8_t* var = NULL;
const s16_t* var_len;
u16_t result;
switch (node->oid) {
case 1: /* sysDescr */
var = sysdescr;
var_len = (const s16_t*)sysdescr_len;
break;
case 2: /* sysObjectID */
{
const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid();
MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t));
return dev_enterprise_oid->len * sizeof(u32_t);
}
case 3: /* sysUpTime */
MIB2_COPY_SYSUPTIME_TO((u32_t*)value);
return sizeof(u32_t);
case 4: /* sysContact */
var = syscontact;
var_len = (const s16_t*)syscontact_len;
break;
case 5: /* sysName */
var = sysname;
var_len = (const s16_t*)sysname_len;
break;
case 6: /* sysLocation */
var = syslocation;
var_len = (const s16_t*)syslocation_len;
break;
case 7: /* sysServices */
*(s32_t*)value = SNMP_SYSSERVICES;
return sizeof(s32_t);
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid));
return 0;
}
/* handle string values (OID 1,4,5 and 6) */
LWIP_ASSERT("", (value != NULL));
if (var_len == NULL) {
result = (s16_t)strlen((const char*)var);
} else {
result = *var_len;
}
MEMCPY(value, var, result);
return result;
}
static snmp_err_t
system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
{
snmp_err_t ret = SNMP_ERR_WRONGVALUE;
const u16_t* var_bufsize = NULL;
const u16_t* var_wr_len;
LWIP_UNUSED_ARG(value);
switch (node->oid) {
case 4: /* sysContact */
var_bufsize = &syscontact_bufsize;
var_wr_len = syscontact_wr_len;
break;
case 5: /* sysName */
var_bufsize = &sysname_bufsize;
var_wr_len = sysname_wr_len;
break;
case 6: /* sysLocation */
var_bufsize = &syslocation_bufsize;
var_wr_len = syslocation_wr_len;
break;
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid));
return ret;
}
/* check if value is writable at all */
if (*var_bufsize > 0) {
if (var_wr_len == NULL) {
/* we have to take the terminating 0 into account */
if (len < *var_bufsize) {
ret = SNMP_ERR_NOERROR;
}
} else {
if (len <= *var_bufsize) {
ret = SNMP_ERR_NOERROR;
}
}
} else {
ret = SNMP_ERR_NOTWRITABLE;
}
return ret;
}
static snmp_err_t
system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
{
u8_t* var_wr = NULL;
u16_t* var_wr_len;
switch (node->oid) {
case 4: /* sysContact */
var_wr = syscontact_wr;
var_wr_len = syscontact_wr_len;
break;
case 5: /* sysName */
var_wr = sysname_wr;
var_wr_len = sysname_wr_len;
break;
case 6: /* sysLocation */
var_wr = syslocation_wr;
var_wr_len = syslocation_wr_len;
break;
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid));
return SNMP_ERR_GENERROR;
}
/* no need to check size of target buffer, this was already done in set_test method */
LWIP_ASSERT("", var_wr != NULL);
MEMCPY(var_wr, value, len);
if (var_wr_len == NULL) {
/* add terminating 0 */
var_wr[len] = 0;
} else {
*var_wr_len = len;
}
return SNMP_ERR_NOERROR;
}
static const struct snmp_scalar_array_node_def system_nodes[] = {
{1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */
{2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */
{3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */
{4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */
{5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */
{6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */
{7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */
};
const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */

View File

@@ -1,594 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) TCP objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/tcp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include <string.h>
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */
static s16_t
tcp_get_value(struct snmp_node_instance* instance, void* value)
{
u32_t *uint_ptr = (u32_t*)value;
s32_t *sint_ptr = (s32_t*)value;
switch (instance->node->oid) {
case 1: /* tcpRtoAlgorithm, vanj(4) */
*sint_ptr = 4;
return sizeof(*sint_ptr);
case 2: /* tcpRtoMin */
/* @todo not the actual value, a guess,
needs to be calculated */
*sint_ptr = 1000;
return sizeof(*sint_ptr);
case 3: /* tcpRtoMax */
/* @todo not the actual value, a guess,
needs to be calculated */
*sint_ptr = 60000;
return sizeof(*sint_ptr);
case 4: /* tcpMaxConn */
*sint_ptr = MEMP_NUM_TCP_PCB;
return sizeof(*sint_ptr);
case 5: /* tcpActiveOpens */
*uint_ptr = STATS_GET(mib2.tcpactiveopens);
return sizeof(*uint_ptr);
case 6: /* tcpPassiveOpens */
*uint_ptr = STATS_GET(mib2.tcppassiveopens);
return sizeof(*uint_ptr);
case 7: /* tcpAttemptFails */
*uint_ptr = STATS_GET(mib2.tcpattemptfails);
return sizeof(*uint_ptr);
case 8: /* tcpEstabResets */
*uint_ptr = STATS_GET(mib2.tcpestabresets);
return sizeof(*uint_ptr);
case 9: /* tcpCurrEstab */
{
u16_t tcpcurrestab = 0;
struct tcp_pcb *pcb = tcp_active_pcbs;
while (pcb != NULL) {
if ((pcb->state == ESTABLISHED) ||
(pcb->state == CLOSE_WAIT)) {
tcpcurrestab++;
}
pcb = pcb->next;
}
*uint_ptr = tcpcurrestab;
}
return sizeof(*uint_ptr);
case 10: /* tcpInSegs */
*uint_ptr = STATS_GET(mib2.tcpinsegs);
return sizeof(*uint_ptr);
case 11: /* tcpOutSegs */
*uint_ptr = STATS_GET(mib2.tcpoutsegs);
return sizeof(*uint_ptr);
case 12: /* tcpRetransSegs */
*uint_ptr = STATS_GET(mib2.tcpretranssegs);
return sizeof(*uint_ptr);
case 14: /* tcpInErrs */
*uint_ptr = STATS_GET(mib2.tcpinerrs);
return sizeof(*uint_ptr);
case 15: /* tcpOutRsts */
*uint_ptr = STATS_GET(mib2.tcpoutrsts);
return sizeof(*uint_ptr);
case 17: /* tcpHCInSegs */
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
return 2*sizeof(u32_t);
case 18: /* tcpHCOutSegs */
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
return 2*sizeof(u32_t);
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
break;
}
return 0;
}
/* --- tcpConnTable --- */
#if LWIP_IPV4
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = {
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff }, /* IP D */
{ 0, 0xffff }, /* Port */
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff }, /* IP D */
{ 0, 0xffff } /* Port */
};
static snmp_err_t
tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
{
LWIP_UNUSED_ARG(value_len);
/* value */
switch (*column) {
case 1: /* tcpConnState */
value->u32 = pcb->state + 1;
break;
case 2: /* tcpConnLocalAddress */
value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
break;
case 3: /* tcpConnLocalPort */
value->u32 = pcb->local_port;
break;
case 4: /* tcpConnRemAddress */
if (pcb->state == LISTEN) {
value->u32 = IP4_ADDR_ANY4->addr;
} else {
value->u32 = ip_2_ip4(&pcb->remote_ip)->addr;
}
break;
case 5: /* tcpConnRemPort */
if (pcb->state == LISTEN) {
value->u32 = 0;
} else {
value->u32 = pcb->remote_port;
}
break;
default:
LWIP_ASSERT("invalid id", 0);
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
u8_t i;
ip4_addr_t local_ip;
ip4_addr_t remote_ip;
u16_t local_port;
u16_t remote_port;
struct tcp_pcb *pcb;
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get IPs and ports from incoming OID */
snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */
local_port = (u16_t)row_oid[4];
snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */
remote_port = (u16_t)row_oid[9];
/* find tcp_pcb with requested ips and ports */
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
pcb = *tcp_pcb_lists[i];
while (pcb != NULL) {
/* do local IP and local port match? */
if (IP_IS_V4_VAL(pcb->local_ip) &&
ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) {
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
if (pcb->state == LISTEN) {
if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) {
/* fill in object properties */
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
}
} else {
if (IP_IS_V4_VAL(pcb->remote_ip) &&
ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) {
/* fill in object properties */
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
}
}
}
pcb = pcb->next;
}
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
u8_t i;
struct tcp_pcb *pcb;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges));
/* iterate over all possible OIDs to find the next one */
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
pcb = *tcp_pcb_lists[i];
while (pcb != NULL) {
u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
if (IP_IS_V4_VAL(pcb->local_ip)) {
snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
test_oid[4] = pcb->local_port;
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
if (pcb->state == LISTEN) {
snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]);
test_oid[9] = 0;
} else {
if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */
continue;
}
snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]);
test_oid[9] = pcb->remote_port;
}
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb);
}
pcb = pcb->next;
}
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len);
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
#endif /* LWIP_IPV4 */
/* --- tcpConnectionTable --- */
static snmp_err_t
tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value)
{
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
switch (*column) {
case 7: /* tcpConnectionState */
value->u32 = pcb->state + 1;
break;
case 8: /* tcpConnectionProcess */
value->u32 = 0; /* not supported */
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip_addr_t local_ip, remote_ip;
u16_t local_port, remote_port;
struct tcp_pcb *pcb;
u8_t idx = 0;
u8_t i;
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
LWIP_UNUSED_ARG(value_len);
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
if (idx == 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
if (idx == 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* find tcp_pcb with requested ip and port*/
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
pcb = *tcp_pcb_nonlisten_lists[i];
while (pcb != NULL) {
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
(local_port == pcb->local_port) &&
ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
(remote_port == pcb->remote_port)) {
/* fill in object properties */
return tcp_ConnectionTable_get_cell_value_core(column, pcb, value);
}
pcb = pcb->next;
}
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct tcp_pcb *pcb;
struct snmp_next_oid_state state;
/* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort
* 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */
u32_t result_temp[38];
u8_t i;
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
LWIP_UNUSED_ARG(value_len);
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
/* iterate over all possible OIDs to find the next one */
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
pcb = *tcp_pcb_nonlisten_lists[i];
while (pcb != NULL) {
u8_t idx = 0;
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, idx, pcb);
pcb = pcb->next;
}
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value);
} else {
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
}
/* --- tcpListenerTable --- */
static snmp_err_t
tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
{
/* all items except tcpListenerProcess are declared as not-accessible */
switch (*column) {
case 4: /* tcpListenerProcess */
value->u32 = 0; /* not supported */
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip_addr_t local_ip;
u16_t local_port;
struct tcp_pcb_listen *pcb;
u8_t idx = 0;
LWIP_UNUSED_ARG(value_len);
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
if (idx == 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* find tcp_pcb with requested ip and port*/
pcb = tcp_listen_pcbs.listen_pcbs;
while (pcb != NULL) {
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
(local_port == pcb->local_port)) {
/* fill in object properties */
return tcp_ListenerTable_get_cell_value_core(column, value);
}
pcb = pcb->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct tcp_pcb_listen *pcb;
struct snmp_next_oid_state state;
/* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */
u32_t result_temp[19];
LWIP_UNUSED_ARG(value_len);
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
/* iterate over all possible OIDs to find the next one */
pcb = tcp_listen_pcbs.listen_pcbs;
while (pcb != NULL) {
u8_t idx = 0;
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, idx, NULL);
pcb = pcb->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return tcp_ListenerTable_get_cell_value_core(column, value);
} else {
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
}
static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value);
static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
#if LWIP_IPV4
static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = {
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */
{ 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */
{ 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */
};
static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value);
#endif /* LWIP_IPV4 */
static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = {
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */
};
static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value);
static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = {
/* all items except tcpListenerProcess are declared as not-accessible */
{ 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */
};
static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value);
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm)
CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin)
CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax)
CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn)
CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens)
CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens)
CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails)
CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets)
CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab)
CREATE_LWIP_SYNC_NODE(10, tcp_InSegs)
CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs)
CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs)
#if LWIP_IPV4
CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable)
#endif /* LWIP_IPV4 */
CREATE_LWIP_SYNC_NODE(14, tcp_InErrs)
CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts)
CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs)
CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs)
CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable)
CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable)
static const struct snmp_node* const tcp_nodes[] = {
&SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node,
&SYNC_NODE_NAME(tcp_RtoMin).node.node,
&SYNC_NODE_NAME(tcp_RtoMax).node.node,
&SYNC_NODE_NAME(tcp_MaxConn).node.node,
&SYNC_NODE_NAME(tcp_ActiveOpens).node.node,
&SYNC_NODE_NAME(tcp_PassiveOpens).node.node,
&SYNC_NODE_NAME(tcp_AttemptFails).node.node,
&SYNC_NODE_NAME(tcp_EstabResets).node.node,
&SYNC_NODE_NAME(tcp_CurrEstab).node.node,
&SYNC_NODE_NAME(tcp_InSegs).node.node,
&SYNC_NODE_NAME(tcp_OutSegs).node.node,
&SYNC_NODE_NAME(tcp_RetransSegs).node.node,
#if LWIP_IPV4
&SYNC_NODE_NAME(tcp_ConnTable).node.node,
#endif /* LWIP_IPV4 */
&SYNC_NODE_NAME(tcp_InErrs).node.node,
&SYNC_NODE_NAME(tcp_OutRsts).node.node,
&SYNC_NODE_NAME(tcp_HCInSegs).node.node,
&SYNC_NODE_NAME(tcp_HCOutSegs).node.node,
&SYNC_NODE_NAME(tcp_ConnectionTable).node.node,
&SYNC_NODE_NAME(tcp_ListenerTable).node.node
};
const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */

View File

@@ -1,357 +0,0 @@
/**
* @file
* Management Information Base II (RFC1213) UDP objects and functions.
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
* Christiaan Simons <christiaan.simons@axon.tv>
*/
#include "lwip/snmp.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_mib2.h"
#include "lwip/apps/snmp_table.h"
#include "lwip/apps/snmp_scalar.h"
#include "lwip/udp.h"
#include "lwip/stats.h"
#include <string.h>
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP
#if SNMP_USE_NETCONN
#define SYNC_NODE_NAME(node_name) node_name ## _synced
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
#else
#define SYNC_NODE_NAME(node_name) node_name
#define CREATE_LWIP_SYNC_NODE(oid, node_name)
#endif
/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */
static s16_t
udp_get_value(struct snmp_node_instance* instance, void* value)
{
u32_t *uint_ptr = (u32_t*)value;
switch (instance->node->oid) {
case 1: /* udpInDatagrams */
*uint_ptr = STATS_GET(mib2.udpindatagrams);
return sizeof(*uint_ptr);
case 2: /* udpNoPorts */
*uint_ptr = STATS_GET(mib2.udpnoports);
return sizeof(*uint_ptr);
case 3: /* udpInErrors */
*uint_ptr = STATS_GET(mib2.udpinerrors);
return sizeof(*uint_ptr);
case 4: /* udpOutDatagrams */
*uint_ptr = STATS_GET(mib2.udpoutdatagrams);
return sizeof(*uint_ptr);
case 8: /* udpHCInDatagrams */
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
return 2*sizeof(u32_t);
case 9: /* udpHCOutDatagrams */
memset(value, 0, 2*sizeof(u32_t)); /* not supported */
return 2*sizeof(u32_t);
default:
LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
break;
}
return 0;
}
/* --- udpEndpointTable --- */
static snmp_err_t
udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
{
/* all items except udpEndpointProcess are declared as not-accessible */
switch (*column) {
case 8: /* udpEndpointProcess */
value->u32 = 0; /* not supported */
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip_addr_t local_ip, remote_ip;
u16_t local_port, remote_port;
struct udp_pcb *pcb;
u8_t idx = 0;
LWIP_UNUSED_ARG(value_len);
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
if (idx == 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
if (idx == 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* udpEndpointInstance */
if (row_oid_len < (idx+1)) {
return SNMP_ERR_NOSUCHINSTANCE;
}
if (row_oid[idx] != 0) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* find udp_pcb with requested ip and port*/
pcb = udp_pcbs;
while (pcb != NULL) {
if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
(local_port == pcb->local_port) &&
ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
(remote_port == pcb->remote_port)) {
/* fill in object properties */
return udp_endpointTable_get_cell_value_core(column, value);
}
pcb = pcb->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct udp_pcb *pcb;
struct snmp_next_oid_state state;
/* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort +
* 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort +
* 1x udpEndpointInstance = 39
*/
u32_t result_temp[39];
LWIP_UNUSED_ARG(value_len);
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
/* iterate over all possible OIDs to find the next one */
pcb = udp_pcbs;
while (pcb != NULL) {
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
u8_t idx = 0;
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
test_oid[idx] = 0; /* udpEndpointInstance */
idx++;
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, idx, NULL);
pcb = pcb->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return udp_endpointTable_get_cell_value_core(column, value);
} else {
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
}
/* --- udpTable --- */
#if LWIP_IPV4
/* list of allowed value ranges for incoming OID */
static const struct snmp_oid_range udp_Table_oid_ranges[] = {
{ 0, 0xff }, /* IP A */
{ 0, 0xff }, /* IP B */
{ 0, 0xff }, /* IP C */
{ 0, 0xff }, /* IP D */
{ 1, 0xffff } /* Port */
};
static snmp_err_t
udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
{
LWIP_UNUSED_ARG(value_len);
switch (*column) {
case 1: /* udpLocalAddress */
/* set reference to PCB local IP and return a generic node that copies IP4 addresses */
value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
break;
case 2: /* udpLocalPort */
/* set reference to PCB local port and return a generic node that copies u16_t values */
value->u32 = pcb->local_port;
break;
default:
return SNMP_ERR_NOSUCHINSTANCE;
}
return SNMP_ERR_NOERROR;
}
static snmp_err_t
udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len)
{
ip4_addr_t ip;
u16_t port;
struct udp_pcb *pcb;
/* check if incoming OID length and if values are in plausible range */
if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) {
return SNMP_ERR_NOSUCHINSTANCE;
}
/* get IP and port from incoming OID */
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
port = (u16_t)row_oid[4];
/* find udp_pcb with requested ip and port*/
pcb = udp_pcbs;
while (pcb != NULL) {
if (IP_IS_V4_VAL(pcb->local_ip)) {
if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) {
/* fill in object properties */
return udp_Table_get_cell_value_core(pcb, column, value, value_len);
}
}
pcb = pcb->next;
}
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
static snmp_err_t
udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len)
{
struct udp_pcb *pcb;
struct snmp_next_oid_state state;
u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
/* init struct to search next oid */
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges));
/* iterate over all possible OIDs to find the next one */
pcb = udp_pcbs;
while (pcb != NULL) {
u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
if (IP_IS_V4_VAL(pcb->local_ip)) {
snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
test_oid[4] = pcb->local_port;
/* check generated OID: is it a candidate for the next one? */
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb);
}
pcb = pcb->next;
}
/* did we find a next one? */
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
/* fill in object properties */
return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len);
} else {
/* not found */
return SNMP_ERR_NOSUCHINSTANCE;
}
}
#endif /* LWIP_IPV4 */
static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
#if LWIP_IPV4
static const struct snmp_table_simple_col_def udp_Table_columns[] = {
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */
};
static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value);
#endif /* LWIP_IPV4 */
static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = {
/* all items except udpEndpointProcess are declared as not-accessible */
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */
};
static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value);
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams)
CREATE_LWIP_SYNC_NODE(2, udp_noPorts)
CREATE_LWIP_SYNC_NODE(3, udp_inErrors)
CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams)
#if LWIP_IPV4
CREATE_LWIP_SYNC_NODE(5, udp_Table)
#endif /* LWIP_IPV4 */
CREATE_LWIP_SYNC_NODE(7, udp_endpointTable)
CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams)
CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams)
static const struct snmp_node* const udp_nodes[] = {
&SYNC_NODE_NAME(udp_inDatagrams).node.node,
&SYNC_NODE_NAME(udp_noPorts).node.node,
&SYNC_NODE_NAME(udp_inErrors).node.node,
&SYNC_NODE_NAME(udp_outDatagrams).node.node,
#if LWIP_IPV4
&SYNC_NODE_NAME(udp_Table).node.node,
#endif /* LWIP_IPV4 */
&SYNC_NODE_NAME(udp_endpointTable).node.node,
&SYNC_NODE_NAME(udp_HCInDatagrams).node.node,
&SYNC_NODE_NAME(udp_HCOutDatagrams).node.node
};
const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes);
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */

File diff suppressed because it is too large Load Diff

View File

@@ -1,194 +0,0 @@
/**
* @file
* SNMP Agent message handling structures (internal API, do not use in client code).
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2016 Elias Oenal.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Christiaan Simons <christiaan.simons@axon.tv>
* Martin Hentschel <info@cl-soft.de>
* Elias Oenal <lwip@eliasoenal.com>
*/
#ifndef LWIP_HDR_APPS_SNMP_MSG_H
#define LWIP_HDR_APPS_SNMP_MSG_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "snmp_pbuf_stream.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#if LWIP_SNMP_V3
#include "snmpv3_priv.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* The listen port of the SNMP agent. Clients have to make their requests to
this port. Most standard clients won't work if you change this! */
#ifndef SNMP_IN_PORT
#define SNMP_IN_PORT 161
#endif
/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't
work if you change this! */
#ifndef SNMP_TRAP_PORT
#define SNMP_TRAP_PORT 162
#endif
/* version defines used in PDU */
#define SNMP_VERSION_1 0
#define SNMP_VERSION_2c 1
#define SNMP_VERSION_3 3
struct snmp_varbind_enumerator
{
struct snmp_pbuf_stream pbuf_stream;
u16_t varbind_count;
};
typedef enum {
SNMP_VB_ENUMERATOR_ERR_OK = 0,
SNMP_VB_ENUMERATOR_ERR_EOVB = 1,
SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2,
SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3
} snmp_vb_enumerator_err_t;
void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length);
snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind);
struct snmp_request
{
/* Communication handle */
void *handle;
/* source IP address */
const ip_addr_t *source_ip;
/* source UDP port */
u16_t source_port;
/* incoming snmp version */
u8_t version;
/* community name (zero terminated) */
u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1];
/* community string length (exclusive zero term) */
u16_t community_strlen;
/* request type */
u8_t request_type;
/* request ID */
s32_t request_id;
/* error status */
s32_t error_status;
/* error index */
s32_t error_index;
/* non-repeaters (getBulkRequest (SNMPv2c)) */
s32_t non_repeaters;
/* max-repetitions (getBulkRequest (SNMPv2c)) */
s32_t max_repetitions;
#if LWIP_SNMP_V3
s32_t msg_id;
s32_t msg_max_size;
u8_t msg_flags;
s32_t msg_security_model;
u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH];
u8_t msg_authoritative_engine_id_len;
s32_t msg_authoritative_engine_boots;
s32_t msg_authoritative_engine_time;
u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH];
u8_t msg_user_name_len;
u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH];
u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH];
u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH];
u8_t context_engine_id_len;
u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH];
u8_t context_name_len;
#endif
struct pbuf *inbound_pbuf;
struct snmp_varbind_enumerator inbound_varbind_enumerator;
u16_t inbound_varbind_offset;
u16_t inbound_varbind_len;
u16_t inbound_padding_len;
struct pbuf *outbound_pbuf;
struct snmp_pbuf_stream outbound_pbuf_stream;
u16_t outbound_pdu_offset;
u16_t outbound_error_status_offset;
u16_t outbound_error_index_offset;
u16_t outbound_varbind_offset;
#if LWIP_SNMP_V3
u16_t outbound_msg_global_data_offset;
u16_t outbound_msg_global_data_end;
u16_t outbound_msg_security_parameters_str_offset;
u16_t outbound_msg_security_parameters_seq_offset;
u16_t outbound_msg_security_parameters_end;
u16_t outbound_msg_authentication_parameters_offset;
u16_t outbound_scoped_pdu_seq_offset;
u16_t outbound_scoped_pdu_string_offset;
#endif
u8_t value_buffer[SNMP_MAX_VALUE_SIZE];
};
/** A helper struct keeping length information about varbinds */
struct snmp_varbind_len
{
u8_t vb_len_len;
u16_t vb_value_len;
u8_t oid_len_len;
u16_t oid_value_len;
u8_t value_len_len;
u16_t value_value_len;
};
/** Agent community string */
extern const char *snmp_community;
/** Agent community string for write access */
extern const char *snmp_community_write;
/** handle for sending traps */
extern void* snmp_traps_handle;
void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port);
err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port);
u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result);
err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len);
err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_MSG_H */

View File

@@ -1,120 +0,0 @@
/**
* @file
* SNMP netconn frontend.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP && SNMP_USE_NETCONN
#include "lwip/api.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "snmp_msg.h"
#include "lwip/sys.h"
/** SNMP netconn API worker thread */
static void
snmp_netconn_thread(void *arg)
{
struct netconn *conn;
struct netbuf *buf;
err_t err;
LWIP_UNUSED_ARG(arg);
/* Bind to SNMP port with default IP address */
#if LWIP_IPV6
conn = netconn_new(NETCONN_UDP_IPV6);
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT);
#else /* LWIP_IPV6 */
conn = netconn_new(NETCONN_UDP);
netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT);
#endif /* LWIP_IPV6 */
LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;);
snmp_traps_handle = conn;
do {
err = netconn_recv(conn, &buf);
if (err == ERR_OK) {
snmp_receive(conn, buf->p, &buf->addr, buf->port);
}
if (buf != NULL) {
netbuf_delete(buf);
}
} while(1);
}
err_t
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port)
{
err_t result;
struct netbuf buf;
memset(&buf, 0, sizeof(buf));
buf.p = p;
result = netconn_sendto((struct netconn*)handle, &buf, dst, port);
return result;
}
u8_t
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result)
{
struct netconn* conn = (struct netconn*)handle;
struct netif *dst_if;
const ip_addr_t* dst_ip;
LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */
ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip);
if ((dst_if != NULL) && (dst_ip != NULL)) {
ip_addr_copy(*result, *dst_ip);
return 1;
} else {
return 0;
}
}
/**
* Starts SNMP Agent.
*/
void
snmp_init(void)
{
sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO);
}
#endif /* LWIP_SNMP && SNMP_USE_NETCONN */

View File

@@ -1,156 +0,0 @@
/**
* @file
* SNMP pbuf stream wrapper implementation (internal API, do not use in client code).
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "snmp_pbuf_stream.h"
#include "lwip/def.h"
#include <string.h>
err_t
snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length)
{
pbuf_stream->offset = offset;
pbuf_stream->length = length;
pbuf_stream->pbuf = p;
return ERR_OK;
}
err_t
snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data)
{
if (pbuf_stream->length == 0) {
return ERR_BUF;
}
if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) {
return ERR_BUF;
}
pbuf_stream->offset++;
pbuf_stream->length--;
return ERR_OK;
}
err_t
snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data)
{
return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1);
}
err_t
snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len)
{
if (pbuf_stream->length < buf_len) {
return ERR_BUF;
}
if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) {
return ERR_BUF;
}
pbuf_stream->offset += buf_len;
pbuf_stream->length -= buf_len;
return ERR_OK;
}
err_t
snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len)
{
if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) {
return ERR_ARG;
}
if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) {
return ERR_ARG;
}
if (len == 0) {
len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length);
}
while (len > 0) {
u16_t chunk_len;
err_t err;
u16_t target_offset;
struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset);
if ((pbuf == NULL) || (pbuf->len == 0)) {
return ERR_BUF;
}
chunk_len = LWIP_MIN(len, pbuf->len);
err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len);
if (err != ERR_OK) {
return err;
}
pbuf_stream->offset += chunk_len;
pbuf_stream->length -= chunk_len;
len -= chunk_len;
}
return ERR_OK;
}
err_t
snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset)
{
if ((offset < 0) || (offset > pbuf_stream->length)) {
/* we cannot seek backwards or forward behind stream end */
return ERR_ARG;
}
pbuf_stream->offset += (u16_t)offset;
pbuf_stream->length -= (u16_t)offset;
return ERR_OK;
}
err_t
snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset)
{
s32_t rel_offset = offset - pbuf_stream->offset;
return snmp_pbuf_stream_seek(pbuf_stream, rel_offset);
}
#endif /* LWIP_SNMP */

View File

@@ -1,73 +0,0 @@
/**
* @file
* SNMP pbuf stream wrapper (internal API, do not use in client code).
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H
#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP
#include "lwip/err.h"
#include "lwip/pbuf.h"
#ifdef __cplusplus
extern "C" {
#endif
struct snmp_pbuf_stream
{
struct pbuf* pbuf;
u16_t offset;
u16_t length;
};
err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length);
err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data);
err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data);
err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len);
err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len);
err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset);
err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */

View File

@@ -1,100 +0,0 @@
/**
* @file
* SNMP RAW API frontend.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
*/
#include "lwip/apps/snmp_opts.h"
#include "lwip/ip_addr.h"
#if LWIP_SNMP && SNMP_USE_RAW
#include "lwip/udp.h"
#include "lwip/ip.h"
#include "snmp_msg.h"
/* lwIP UDP receive callback function */
static void
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
LWIP_UNUSED_ARG(arg);
snmp_receive(pcb, p, addr, port);
pbuf_free(p);
}
err_t
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port)
{
return udp_sendto((struct udp_pcb*)handle, p, dst, port);
}
u8_t
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result)
{
struct udp_pcb* udp_pcb = (struct udp_pcb*)handle;
struct netif *dst_if;
const ip_addr_t* dst_ip;
LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */
ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip);
if ((dst_if != NULL) && (dst_ip != NULL)) {
ip_addr_copy(*result, *dst_ip);
return 1;
} else {
return 0;
}
}
/**
* @ingroup snmp_core
* Starts SNMP Agent.
* Allocates UDP pcb and binds it to IP_ANY_TYPE port 161.
*/
void
snmp_init(void)
{
err_t err;
struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;);
snmp_traps_handle = snmp_pcb;
udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT);
err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT);
LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;);
}
#endif /* LWIP_SNMP && SNMP_USE_RAW */

View File

@@ -1,220 +0,0 @@
/**
* @file
* SNMP scalar node support implementation.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/snmp_scalar.h"
#include "lwip/apps/snmp_core.h"
static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value);
static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value);
static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value);
snmp_err_t
snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
/* scalar only has one dedicated instance: .0 */
if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) {
return SNMP_ERR_NOSUCHINSTANCE;
}
instance->access = scalar_node->access;
instance->asn1_type = scalar_node->asn1_type;
instance->get_value = scalar_node->get_value;
instance->set_test = scalar_node->set_test;
instance->set_value = scalar_node->set_value;
return SNMP_ERR_NOERROR;
}
snmp_err_t
snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
/* because our only instance is .0 we can only return a next instance if no instance oid is passed */
if (instance->instance_oid.len == 0) {
instance->instance_oid.len = 1;
instance->instance_oid.id[0] = 0;
return snmp_scalar_get_instance(root_oid, root_oid_len, instance);
}
return SNMP_ERR_NOSUCHINSTANCE;
}
snmp_err_t
snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) {
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 = array_node->array_nodes;
u32_t i = 0;
while (i < array_node->array_node_count) {
if (array_node_def->oid == instance->instance_oid.id[0]) {
break;
}
array_node_def++;
i++;
}
if (i < array_node->array_node_count) {
instance->access = array_node_def->access;
instance->asn1_type = array_node_def->asn1_type;
instance->get_value = snmp_scalar_array_get_value;
instance->set_test = snmp_scalar_array_set_test;
instance->set_value = snmp_scalar_array_set_value;
instance->reference.const_ptr = array_node_def;
return SNMP_ERR_NOERROR;
}
}
return SNMP_ERR_NOSUCHINSTANCE;
}
snmp_err_t
snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
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 = array_node->array_nodes;
const struct snmp_scalar_array_node_def* result = NULL;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) {
/* return node with lowest OID */
u16_t i = 0;
result = array_node_def;
array_node_def++;
for (i = 1; i < array_node->array_node_count; i++) {
if (array_node_def->oid < result->oid) {
result = array_node_def;
}
array_node_def++;
}
} else if (instance->instance_oid.len >= 1) {
if (instance->instance_oid.len == 1) {
/* if we have the requested OID we return its instance, otherwise we search for the next available */
u16_t i = 0;
while (i < array_node->array_node_count) {
if (array_node_def->oid == instance->instance_oid.id[0]) {
result = array_node_def;
break;
}
array_node_def++;
i++;
}
}
if (result == NULL) {
u32_t oid_dist = 0xFFFFFFFFUL;
u16_t i = 0;
array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */
while (i < array_node->array_node_count) {
if ((array_node_def->oid > instance->instance_oid.id[0]) &&
((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) {
result = array_node_def;
oid_dist = array_node_def->oid - instance->instance_oid.id[0];
}
array_node_def++;
i++;
}
}
}
if (result == NULL) {
/* nothing to return */
return SNMP_ERR_NOSUCHINSTANCE;
}
instance->instance_oid.len = 2;
instance->instance_oid.id[0] = result->oid;
instance->instance_oid.id[1] = 0;
instance->access = result->access;
instance->asn1_type = result->asn1_type;
instance->get_value = snmp_scalar_array_get_value;
instance->set_test = snmp_scalar_array_set_test;
instance->set_value = snmp_scalar_array_set_value;
instance->reference.const_ptr = result;
return SNMP_ERR_NOERROR;
}
static s16_t
snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value)
{
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);
}
static snmp_err_t
snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value)
{
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);
}
static snmp_err_t
snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value)
{
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);
}
#endif /* LWIP_SNMP */

View File

@@ -1,343 +0,0 @@
/**
* @file
* SNMP table support implementation.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/snmp_core.h"
#include "lwip/apps/snmp_table.h"
#include <string.h>
snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
/* fixed row entry always has oid 1 */
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
/* search column */
const struct snmp_table_col_def* col_def = table_node->columns;
u16_t i = table_node->column_count;
while (i > 0) {
if (col_def->index == instance->instance_oid.id[1]) {
break;
}
col_def++;
i--;
}
if (i > 0) {
/* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */
instance->asn1_type = col_def->asn1_type;
instance->access = col_def->access;
instance->get_value = table_node->get_value;
instance->set_test = table_node->set_test;
instance->set_value = table_node->set_value;
ret = table_node->get_cell_instance(
&(instance->instance_oid.id[1]),
&(instance->instance_oid.id[2]),
instance->instance_oid.len-2,
instance);
}
}
return ret;
}
snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node;
const struct snmp_table_col_def* col_def;
struct snmp_obj_id row_oid;
u32_t column = 0;
snmp_err_t result;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
/* check that first part of id is 0 or 1, referencing fixed row entry */
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
return SNMP_ERR_NOSUCHINSTANCE;
}
if (instance->instance_oid.len > 1) {
column = instance->instance_oid.id[1];
}
if (instance->instance_oid.len > 2) {
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
} else {
row_oid.len = 0;
}
instance->get_value = table_node->get_value;
instance->set_test = table_node->set_test;
instance->set_value = table_node->set_value;
/* resolve column and value */
do {
u16_t i;
const struct snmp_table_col_def* next_col_def = NULL;
col_def = table_node->columns;
for (i = 0; i < table_node->column_count; i++) {
if (col_def->index == column) {
next_col_def = col_def;
break;
} else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) {
next_col_def = col_def;
}
col_def++;
}
if (next_col_def == NULL) {
/* no further column found */
return SNMP_ERR_NOSUCHINSTANCE;
}
instance->asn1_type = next_col_def->asn1_type;
instance->access = next_col_def->access;
result = table_node->get_next_cell_instance(
&next_col_def->index,
&row_oid,
instance);
if (result == SNMP_ERR_NOERROR) {
col_def = next_col_def;
break;
}
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
column = next_col_def->index + 1;
} while (1);
/* build resulting oid */
instance->instance_oid.len = 2;
instance->instance_oid.id[0] = 1;
instance->instance_oid.id[1] = col_def->index;
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
return SNMP_ERR_NOERROR;
}
snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
/* fixed row entry always has oid 1 */
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
ret = table_node->get_cell_value(
&(instance->instance_oid.id[1]),
&(instance->instance_oid.id[2]),
instance->instance_oid.len-2,
&instance->reference,
&instance->reference_len);
if (ret == SNMP_ERR_NOERROR) {
/* search column */
const struct snmp_table_simple_col_def* col_def = table_node->columns;
u32_t i = table_node->column_count;
while (i > 0) {
if (col_def->index == instance->instance_oid.id[1]) {
break;
}
col_def++;
i--;
}
if (i > 0) {
instance->asn1_type = col_def->asn1_type;
instance->access = SNMP_NODE_INSTANCE_READ_ONLY;
instance->set_test = NULL;
instance->set_value = NULL;
switch (col_def->data_type) {
case SNMP_VARIANT_VALUE_TYPE_U32:
instance->get_value = snmp_table_extract_value_from_u32ref;
break;
case SNMP_VARIANT_VALUE_TYPE_S32:
instance->get_value = snmp_table_extract_value_from_s32ref;
break;
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
instance->get_value = snmp_table_extract_value_from_refconstptr;
break;
default:
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
return SNMP_ERR_GENERROR;
}
ret = SNMP_ERR_NOERROR;
} else {
ret = SNMP_ERR_NOSUCHINSTANCE;
}
}
}
return ret;
}
snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node;
const struct snmp_table_simple_col_def* col_def;
struct snmp_obj_id row_oid;
u32_t column = 0;
snmp_err_t result;
LWIP_UNUSED_ARG(root_oid);
LWIP_UNUSED_ARG(root_oid_len);
/* check that first part of id is 0 or 1, referencing fixed row entry */
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
return SNMP_ERR_NOSUCHINSTANCE;
}
if (instance->instance_oid.len > 1) {
column = instance->instance_oid.id[1];
}
if (instance->instance_oid.len > 2) {
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
} else {
row_oid.len = 0;
}
/* resolve column and value */
do {
u32_t i;
const struct snmp_table_simple_col_def* next_col_def = NULL;
col_def = table_node->columns;
for (i = 0; i < table_node->column_count; i++) {
if (col_def->index == column) {
next_col_def = col_def;
break;
} else if ((col_def->index > column) && ((next_col_def == NULL) ||
(col_def->index < next_col_def->index))) {
next_col_def = col_def;
}
col_def++;
}
if (next_col_def == NULL) {
/* no further column found */
return SNMP_ERR_NOSUCHINSTANCE;
}
result = table_node->get_next_cell_instance_and_value(
&next_col_def->index,
&row_oid,
&instance->reference,
&instance->reference_len);
if (result == SNMP_ERR_NOERROR) {
col_def = next_col_def;
break;
}
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
column = next_col_def->index + 1;
}
while (1);
instance->asn1_type = col_def->asn1_type;
instance->access = SNMP_NODE_INSTANCE_READ_ONLY;
instance->set_test = NULL;
instance->set_value = NULL;
switch (col_def->data_type) {
case SNMP_VARIANT_VALUE_TYPE_U32:
instance->get_value = snmp_table_extract_value_from_u32ref;
break;
case SNMP_VARIANT_VALUE_TYPE_S32:
instance->get_value = snmp_table_extract_value_from_s32ref;
break;
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
instance->get_value = snmp_table_extract_value_from_refconstptr;
break;
default:
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
return SNMP_ERR_GENERROR;
}
/* build resulting oid */
instance->instance_oid.len = 2;
instance->instance_oid.id[0] = 1;
instance->instance_oid.id[1] = col_def->index;
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
return SNMP_ERR_NOERROR;
}
s16_t
snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value)
{
s32_t *dst = (s32_t*)value;
*dst = instance->reference.s32;
return sizeof(*dst);
}
s16_t
snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value)
{
u32_t *dst = (u32_t*)value;
*dst = instance->reference.u32;
return sizeof(*dst);
}
s16_t
snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value)
{
MEMCPY(value, instance->reference.const_ptr, instance->reference_len);
return (u16_t)instance->reference_len;
}
#endif /* LWIP_SNMP */

View File

@@ -1,218 +0,0 @@
/**
* @file
* SNMP thread synchronization implementation.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/snmp_threadsync.h"
#include "lwip/apps/snmp_core.h"
#include "lwip/sys.h"
#include <string.h>
static void
call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn)
{
sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex);
call_data->threadsync_node->instance->sync_fn(fn, call_data);
sys_sem_wait(&call_data->threadsync_node->instance->sem);
sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex);
}
static void
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);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static s16_t
threadsync_get_value(struct snmp_node_instance* instance, void* value)
{
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
call_data->arg1.value = value;
call_synced_function(call_data, threadsync_get_value_synced);
return call_data->retval.s16;
}
static void
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);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static snmp_err_t
threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
{
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
call_data->arg1.value = value;
call_data->arg2.len = len;
call_synced_function(call_data, threadsync_set_test_synced);
return call_data->retval.err;
}
static void
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);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static snmp_err_t
threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
{
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
call_data->arg1.value = value;
call_data->arg2.len = len;
call_synced_function(call_data, threadsync_set_value_synced);
return call_data->retval.err;
}
static void
threadsync_release_instance_synced(void* ctx)
{
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
call_data->proxy_instance.release_instance(&call_data->proxy_instance);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static void
threadsync_release_instance(struct snmp_node_instance *instance)
{
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
if (call_data->proxy_instance.release_instance != NULL) {
call_synced_function(call_data, threadsync_release_instance_synced);
}
}
static void
get_instance_synced(void* ctx)
{
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static void
get_next_instance_synced(void* ctx)
{
struct threadsync_data *call_data = (struct threadsync_data*)ctx;
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
sys_sem_signal(&call_data->threadsync_node->instance->sem);
}
static snmp_err_t
do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn)
{
const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node;
struct threadsync_data *call_data = &threadsync_node->instance->data;
if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) {
LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID"));
return SNMP_ERR_NOSUCHINSTANCE;
}
memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance));
instance->reference.ptr = call_data;
snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len);
call_data->proxy_instance.node = &threadsync_node->target->node;
call_data->threadsync_node = threadsync_node;
call_data->arg1.root_oid = root_oid;
call_data->arg2.root_oid_len = root_oid_len;
call_synced_function(call_data, fn);
if (call_data->retval.err == SNMP_ERR_NOERROR) {
instance->access = call_data->proxy_instance.access;
instance->asn1_type = call_data->proxy_instance.asn1_type;
instance->release_instance = threadsync_release_instance;
instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL;
instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL;
instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL;
snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len);
}
return call_data->retval.err;
}
snmp_err_t
snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
return do_sync(root_oid, root_oid_len, instance, get_instance_synced);
}
snmp_err_t
snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
{
return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced);
}
/** Initializes thread synchronization instance */
void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn)
{
err_t err = sys_mutex_new(&instance->sem_usage_mutex);
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
err = sys_sem_new(&instance->sem, 0);
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
instance->sync_fn = sync_fn;
}
#endif /* LWIP_SNMP */

View File

@@ -1,445 +0,0 @@
/**
* @file
* SNMPv1 traps implementation.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel
* Christiaan Simons <christiaan.simons@axon.tv>
*
*/
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include <string.h>
#include "lwip/snmp.h"
#include "lwip/sys.h"
#include "lwip/apps/snmp.h"
#include "lwip/apps/snmp_core.h"
#include "snmp_msg.h"
#include "snmp_asn1.h"
#include "snmp_core_priv.h"
struct snmp_msg_trap
{
/* source enterprise ID (sysObjectID) */
const struct snmp_obj_id *enterprise;
/* source IP address, raw network order format */
ip_addr_t sip;
/* generic trap code */
u32_t gen_trap;
/* specific trap code */
u32_t spc_trap;
/* timestamp */
u32_t ts;
/* snmp_version */
u32_t snmp_version;
/* output trap lengths used in ASN encoding */
/* encoding pdu length */
u16_t pdulen;
/* encoding community length */
u16_t comlen;
/* encoding sequence length */
u16_t seqlen;
/* encoding varbinds sequence length */
u16_t vbseqlen;
};
static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds);
static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len);
static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream);
static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds);
/** Agent community string for sending traps */
extern const char *snmp_community_trap;
void* snmp_traps_handle;
struct snmp_trap_dst
{
/* destination IP address in network order */
ip_addr_t dip;
/* set to 0 when disabled, >0 when enabled */
u8_t enable;
};
static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];
static u8_t snmp_auth_traps_enabled = 0;
/**
* @ingroup snmp_traps
* Sets enable switch for this trap destination.
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
* @param enable switch if 0 destination is disabled >0 enabled.
*/
void
snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
{
if (dst_idx < SNMP_TRAP_DESTINATIONS) {
trap_dst[dst_idx].enable = enable;
}
}
/**
* @ingroup snmp_traps
* Sets IPv4 address for this trap destination.
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
* @param dst IPv4 address in host order.
*/
void
snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst)
{
if (dst_idx < SNMP_TRAP_DESTINATIONS) {
ip_addr_set(&trap_dst[dst_idx].dip, dst);
}
}
/**
* @ingroup snmp_traps
* Enable/disable authentication traps
*/
void
snmp_set_auth_traps_enabled(u8_t enable)
{
snmp_auth_traps_enabled = enable;
}
/**
* @ingroup snmp_traps
* Get authentication traps enabled state
*/
u8_t
snmp_get_auth_traps_enabled(void)
{
return snmp_auth_traps_enabled;
}
/**
* @ingroup snmp_traps
* Sends a generic or enterprise specific trap message.
*
* @param eoid points to enterprise object identifier
* @param generic_trap is the trap code
* @param specific_trap used for enterprise traps when generic_trap == 6
* @param varbinds linked list of varbinds to be sent
* @return ERR_OK when success, ERR_MEM if we're out of memory
*
* @note the use of the enterprise identifier field
* is per RFC1215.
* Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps
* and .iso.org.dod.internet.private.enterprises.yourenterprise
* (sysObjectID) for specific traps.
*/
err_t
snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds)
{
struct snmp_msg_trap trap_msg;
struct snmp_trap_dst *td;
struct pbuf *p;
u16_t i, tot_len;
err_t err = ERR_OK;
trap_msg.snmp_version = 0;
for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) {
if ((td->enable != 0) && !ip_addr_isany(&td->dip)) {
/* lookup current source address for this dst */
if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) {
if (eoid == NULL) {
trap_msg.enterprise = snmp_get_device_enterprise_oid();
} else {
trap_msg.enterprise = eoid;
}
trap_msg.gen_trap = generic_trap;
if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) {
trap_msg.spc_trap = specific_trap;
} else {
trap_msg.spc_trap = 0;
}
MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts);
/* pass 0, calculate length fields */
tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds);
tot_len = snmp_trap_header_sum(&trap_msg, tot_len);
/* allocate pbuf(s) */
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM);
if (p != NULL) {
struct snmp_pbuf_stream pbuf_stream;
snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len);
/* pass 1, encode packet ino the pbuf(s) */
snmp_trap_header_enc(&trap_msg, &pbuf_stream);
snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds);
snmp_stats.outtraps++;
snmp_stats.outpkts++;
/** send to the TRAP destination */
snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT);
pbuf_free(p);
} else {
err = ERR_MEM;
}
} else {
/* routing error */
err = ERR_RTE;
}
}
}
return err;
}
/**
* @ingroup snmp_traps
* Send generic SNMP trap
*/
err_t
snmp_send_trap_generic(s32_t generic_trap)
{
static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } };
return snmp_send_trap(&oid, generic_trap, 0, NULL);
}
/**
* @ingroup snmp_traps
* Send specific SNMP trap with variable bindings
*/
err_t
snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds)
{
return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds);
}
/**
* @ingroup snmp_traps
* Send coldstart trap
*/
void
snmp_coldstart_trap(void)
{
snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART);
}
/**
* @ingroup snmp_traps
* Send authentication failure trap (used internally by agent)
*/
void
snmp_authfail_trap(void)
{
if (snmp_auth_traps_enabled != 0) {
snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE);
}
}
static u16_t
snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds)
{
struct snmp_varbind *varbind;
u16_t tot_len;
u8_t tot_len_len;
tot_len = 0;
varbind = varbinds;
while (varbind != NULL) {
struct snmp_varbind_len len;
if (snmp_varbind_length(varbind, &len) == ERR_OK) {
tot_len += 1 + len.vb_len_len + len.vb_value_len;
}
varbind = varbind->next;
}
trap->vbseqlen = tot_len;
snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len);
tot_len += 1 + tot_len_len;
return tot_len;
}
/**
* Sums trap header field lengths from tail to head and
* returns trap_header_lengths for second encoding pass.
*
* @param trap Trap message
* @param vb_len varbind-list length
* @return the required length for encoding the trap header
*/
static u16_t
snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len)
{
u16_t tot_len;
u16_t len;
u8_t lenlen;
tot_len = vb_len;
snmp_asn1_enc_u32t_cnt(trap->ts, &len);
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len);
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len);
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
if (IP_IS_V6_VAL(trap->sip)) {
#if LWIP_IPV6
len = sizeof(ip_2_ip6(&trap->sip)->addr);
#endif
} else {
#if LWIP_IPV4
len = sizeof(ip_2_ip4(&trap->sip)->addr);
#endif
}
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len);
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
trap->pdulen = tot_len;
snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen);
tot_len += 1 + lenlen;
trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF);
snmp_asn1_enc_length_cnt(trap->comlen, &lenlen);
tot_len += 1 + lenlen + trap->comlen;
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len);
snmp_asn1_enc_length_cnt(len, &lenlen);
tot_len += 1 + len + lenlen;
trap->seqlen = tot_len;
snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen);
tot_len += 1 + lenlen;
return tot_len;
}
static void
snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds)
{
struct snmp_asn1_tlv tlv;
struct snmp_varbind *varbind;
varbind = varbinds;
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
while (varbind != NULL) {
snmp_append_outbound_varbind(pbuf_stream, varbind);
varbind = varbind->next;
}
}
/**
* Encodes trap header from head to tail.
*/
static void
snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream)
{
struct snmp_asn1_tlv tlv;
/* 'Message' sequence */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
/* version */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version);
/* community */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen);
/* 'PDU' sequence */
SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
/* object ID */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0);
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len);
/* IP addr */
if (IP_IS_V6_VAL(trap->sip)) {
#if LWIP_IPV6
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr));
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr));
#endif
} else {
#if LWIP_IPV4
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr));
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr));
#endif
}
/* trap length */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap);
/* specific trap */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap);
/* timestamp */
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0);
snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len);
snmp_ans1_enc_tlv(pbuf_stream, &tlv);
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts);
}
#endif /* LWIP_SNMP */

View File

@@ -1,136 +0,0 @@
/**
* @file
* Additional SNMPv3 functionality RFC3414 and RFC3826.
*/
/*
* Copyright (c) 2016 Elias Oenal.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Elias Oenal <lwip@eliasoenal.com>
*/
#include "snmpv3_priv.h"
#include "lwip/apps/snmpv3.h"
#include "lwip/sys.h"
#include <string.h>
#if LWIP_SNMP && LWIP_SNMP_V3
#ifdef LWIP_SNMPV3_INCLUDE_ENGINE
#include LWIP_SNMPV3_INCLUDE_ENGINE
#endif
#define SNMP_MAX_TIME_BOOT 2147483647UL
/** Call this if engine has been changed. Has to reset boots, see below */
void
snmpv3_engine_id_changed(void)
{
snmpv3_set_engine_boots(0);
}
/** According to RFC3414 2.2.2.
*
* The number of times that the SNMP engine has
* (re-)initialized itself since snmpEngineID
* was last configured.
*/
u32_t
snmpv3_get_engine_boots_internal(void)
{
if (snmpv3_get_engine_boots() == 0 ||
snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) {
return snmpv3_get_engine_boots();
}
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
return snmpv3_get_engine_boots();
}
/** RFC3414 2.2.2.
*
* Once the timer reaches 2147483647 it gets reset to zero and the
* engine boot ups get incremented.
*/
u32_t
snmpv3_get_engine_time_internal(void)
{
if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) {
snmpv3_reset_engine_time();
if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) {
snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1);
} else {
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT);
}
}
return snmpv3_get_engine_time();
}
#if LWIP_SNMP_V3_CRYPTO
/* This function ignores the byte order suggestion in RFC3414
* since it simply doesn't influence the effectiveness of an IV.
*
* Implementing RFC3826 priv param algorithm if LWIP_RAND is available.
*
* @todo: This is a potential thread safety issue.
*/
err_t
snmpv3_build_priv_param(u8_t* priv_param)
{
#ifdef LWIP_RAND /* Based on RFC3826 */
static u8_t init;
static u32_t priv1, priv2;
/* Lazy initialisation */
if (init == 0) {
init = 1;
priv1 = LWIP_RAND();
priv2 = LWIP_RAND();
}
SMEMCPY(&priv_param[0], &priv1, sizeof(priv1));
SMEMCPY(&priv_param[4], &priv2, sizeof(priv2));
/* Emulate 64bit increment */
priv1++;
if (!priv1) { /* Overflow */
priv2++;
}
#else /* Based on RFC3414 */
static u32_t ctr;
u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS();
SMEMCPY(&priv_param[0], &boots, 4);
SMEMCPY(&priv_param[4], &ctr, 4);
ctr++;
#endif
return ERR_OK;
}
#endif /* LWIP_SNMP_V3_CRYPTO */
#endif

View File

@@ -1,145 +0,0 @@
/**
* @file
* Dummy SNMPv3 functions.
*/
/*
* Copyright (c) 2016 Elias Oenal.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Elias Oenal <lwip@eliasoenal.com>
* Dirk Ziegelmeier <dirk@ziegelmeier.net>
*/
#include "lwip/apps/snmpv3.h"
#include "snmpv3_priv.h"
#include <string.h>
#include "lwip/err.h"
#if LWIP_SNMP && LWIP_SNMP_V3
/**
* @param username is a pointer to a string.
* @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found.
* @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
* @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found.
* @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
*/
err_t
snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key)
{
const char* engine_id;
u8_t engine_id_len;
if(strlen(username) == 0) {
return ERR_OK;
}
if(memcmp(username, "lwip", 4) != 0) {
return ERR_VAL;
}
snmpv3_get_engine_id(&engine_id, &engine_id_len);
if(auth_key != NULL) {
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10,
(const u8_t*)engine_id, engine_id_len,
auth_key);
*auth_algo = SNMP_V3_AUTH_ALGO_SHA;
}
if(priv_key != NULL) {
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10,
(const u8_t*)engine_id, engine_id_len,
priv_key);
*priv_algo = SNMP_V3_PRIV_ALGO_DES;
}
return ERR_OK;
}
/**
* Get engine ID from persistence
* @param id
* @param len
*/
void
snmpv3_get_engine_id(const char **id, u8_t *len)
{
*id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02";
*len = 12;
}
/**
* Store engine ID in persistence
* @param id
* @param len
*/
err_t
snmpv3_set_engine_id(const char *id, u8_t len)
{
LWIP_UNUSED_ARG(id);
LWIP_UNUSED_ARG(len);
return ERR_OK;
}
/**
* Get engine boots from persistence. Must be increased on each boot.
* @return
*/
u32_t
snmpv3_get_engine_boots(void)
{
return 0;
}
/**
* Store engine boots in persistence
* @param boots
*/
void
snmpv3_set_engine_boots(u32_t boots)
{
LWIP_UNUSED_ARG(boots);
}
/**
* RFC3414 2.2.2.
* Once the timer reaches 2147483647 it gets reset to zero and the
* engine boot ups get incremented.
*/
u32_t
snmpv3_get_engine_time(void)
{
return 0;
}
/**
* Reset current engine time to 0
*/
void
snmpv3_reset_engine_time(void)
{
}
#endif /* LWIP_SNMP && LWIP_SNMP_V3 */

Some files were not shown because too many files have changed in this diff Show More