Compare commits
103 Commits
STABLE-1_4
...
cvs-reposi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7385449f33 | ||
|
|
1f4b814d0b | ||
|
|
a93d9c4310 | ||
|
|
1813d11b9d | ||
|
|
09ac68c196 | ||
|
|
c2fd905e32 | ||
|
|
cc84f28d1b | ||
|
|
2bd498524d | ||
|
|
4b934945f3 | ||
|
|
b666ab0673 | ||
|
|
6a4c30fe5d | ||
|
|
4002aef594 | ||
|
|
ba28d36e67 | ||
|
|
4444db2990 | ||
|
|
d0026793bf | ||
|
|
93b5cd5ddd | ||
|
|
12c2d7e4cf | ||
|
|
4eb5acd9e2 | ||
|
|
0f56d838ec | ||
|
|
12a948dacb | ||
|
|
137953605e | ||
|
|
629fad6f5f | ||
|
|
2911c84a69 | ||
|
|
89a1420609 | ||
|
|
e584557afe | ||
|
|
2ed5413e24 | ||
|
|
91532b2d5c | ||
|
|
732cac1c0e | ||
|
|
5b04860b8b | ||
|
|
5a674f419d | ||
|
|
d30246dc05 | ||
|
|
af5a913019 | ||
|
|
604e69c7ae | ||
|
|
d765c9de37 | ||
|
|
98b6e2bcce | ||
|
|
d80be7961c | ||
|
|
2aec3a9789 | ||
|
|
ccd7dbe0e4 | ||
|
|
92fcfd7a6f | ||
|
|
1b2b054139 | ||
|
|
853d1eac96 | ||
|
|
2ef29d6839 | ||
|
|
6865806b55 | ||
|
|
9546e65617 | ||
|
|
5852993243 | ||
|
|
90a03a77ad | ||
|
|
4bfbe7ebeb | ||
|
|
f3c1686a40 | ||
|
|
33a587d97e | ||
|
|
a444ec5111 | ||
|
|
5ead1bf5c8 | ||
|
|
3a267586f4 | ||
|
|
52271e0366 | ||
|
|
e4739da961 | ||
|
|
80b344e9fc | ||
|
|
036cb26fa3 | ||
|
|
33d6dcec5b | ||
|
|
791505ab6e | ||
|
|
88e1719d8e | ||
|
|
0885555521 | ||
|
|
36c1750b8f | ||
|
|
11b1c9f19f | ||
|
|
b5dd87b184 | ||
|
|
b54c7bedfd | ||
|
|
783404d8d4 | ||
|
|
3bad9f013e | ||
|
|
4495516497 | ||
|
|
3f849848a4 | ||
|
|
7203680146 | ||
|
|
d793ed3b9b | ||
|
|
c6de17d1e5 | ||
|
|
5b084f4b95 | ||
|
|
4e3b2b9f6b | ||
|
|
856ccb5bb7 | ||
|
|
dbf5659cd9 | ||
|
|
fee0c6afe9 | ||
|
|
fb7d3a159a | ||
|
|
dc6b4e65e0 | ||
|
|
17d4ef4053 | ||
|
|
03be8f88fe | ||
|
|
effcb90fdf | ||
|
|
1bd06bee82 | ||
|
|
92cdc1e33f | ||
|
|
377628216e | ||
|
|
f7627929d5 | ||
|
|
b49cf5e7a2 | ||
|
|
231a6cecb4 | ||
|
|
32f02325f9 | ||
|
|
f418782c2c | ||
|
|
e52730d1fb | ||
|
|
d2679e58a6 | ||
|
|
e3817cd549 | ||
|
|
4ace50a7d7 | ||
|
|
fa092c47c8 | ||
|
|
704d90f693 | ||
|
|
93dc36e091 | ||
|
|
4cc36b2284 | ||
|
|
aaa8d2795e | ||
|
|
229137cad1 | ||
|
|
d73262a0e5 | ||
|
|
cd22a8d851 | ||
|
|
7f7df4ae19 | ||
|
|
3c5723e49d |
187
CHANGELOG
187
CHANGELOG
@@ -1,18 +1,60 @@
|
|||||||
FUTURE
|
|
||||||
|
|
||||||
* TODO: The lwIP source code makes some invalid assumptions on processor
|
|
||||||
word-length, storage sizes and alignment. See the mailing lists for
|
|
||||||
problems with exoteric (/DSP) architectures showing these problems.
|
|
||||||
We still have to fix some of these issues neatly.
|
|
||||||
|
|
||||||
HISTORY
|
HISTORY
|
||||||
|
|
||||||
(CVS HEAD)
|
(CVS HEAD)
|
||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
|
++ New features:
|
||||||
|
|
||||||
|
2011-06-26: Simon Goldschmidt (patch by Cameron Gutman)
|
||||||
|
* tcp.c, tcp_out.c: bug #33604: added some more asserts to check that
|
||||||
|
pcb->state != LISTEN
|
||||||
|
|
||||||
|
2011-05-25: Simon Goldschmidt
|
||||||
|
* again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c,
|
||||||
|
combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4
|
||||||
|
and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP
|
||||||
|
code so that the code is more readable.
|
||||||
|
|
||||||
|
2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt)
|
||||||
|
* nearly the whole stack: Finally, we got decent IPv6 support, big thanks to
|
||||||
|
Ivan! (this is work in progress: we're just post release anyway :-)
|
||||||
|
|
||||||
|
2011-05-14: Simon Goldschmidt (patch by St<53>phane Lesage)
|
||||||
|
* tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static
|
||||||
|
memory message
|
||||||
|
|
||||||
|
|
||||||
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2011-07-04: Simon Goldschmidt
|
||||||
|
* sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0.
|
||||||
|
|
||||||
|
2011-06-26: Simon Goldschmidt
|
||||||
|
* tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by
|
||||||
|
updating its documentation only.
|
||||||
|
|
||||||
|
2011-06-26: Simon Goldschmidt
|
||||||
|
* mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an
|
||||||
|
unaligned pointer.
|
||||||
|
|
||||||
|
2011-06-26: Simon Goldschmidt
|
||||||
|
* mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(STABLE-1.4.0)
|
||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
|
||||||
|
2011-03-27: Simon Goldschmidt
|
||||||
|
* tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and
|
||||||
|
calculate it in tcp_zero_window_probe (the only place where it was used).
|
||||||
|
|
||||||
|
2010-11-21: Simon Goldschmidt
|
||||||
|
* dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
|
||||||
|
(fixes bug #31525).
|
||||||
|
|
||||||
2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
|
2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
|
||||||
* ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
|
* ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
|
||||||
IP_MULTICAST_LOOP at socket- and raw-API level.
|
IP_MULTICAST_LOOP at socket- and raw-API level.
|
||||||
@@ -229,6 +271,137 @@ HISTORY
|
|||||||
|
|
||||||
++ Bugfixes:
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2011-04-20: Simon Goldschmidt
|
||||||
|
* sys_arch.txt: sys_arch_timeouts() is not needed any more.
|
||||||
|
|
||||||
|
2011-04-13: Simon Goldschmidt
|
||||||
|
* tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by
|
||||||
|
using ports in the IANA private/dynamic range (49152 through 65535).
|
||||||
|
|
||||||
|
2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl:
|
||||||
|
* etharp.h/.c: Fixed broken VLAN support.
|
||||||
|
|
||||||
|
2011-03-27: Simon Goldschmidt
|
||||||
|
* tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp
|
||||||
|
pcbs) by checking if the pcb was bound (local_port != 0).
|
||||||
|
|
||||||
|
2011-03-27: Simon Goldschmidt
|
||||||
|
* ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice)
|
||||||
|
|
||||||
|
2011-03-27: Simon Goldschmidt
|
||||||
|
* sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and
|
||||||
|
raw pcbs with LWIP_TCPIP_CORE_LOCKING==1.
|
||||||
|
|
||||||
|
2011-03-27: Simon Goldschmidt
|
||||||
|
* tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route
|
||||||
|
is present never times out) by starting retransmission timer before checking
|
||||||
|
route.
|
||||||
|
|
||||||
|
2011-03-22: Simon Goldschmidt
|
||||||
|
* ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only
|
||||||
|
calling sio_read_abort() if the file descriptor is valid.
|
||||||
|
|
||||||
|
2011-03-14: Simon Goldschmidt
|
||||||
|
* err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect
|
||||||
|
more than once can render a socket useless) since it mainly involves changing
|
||||||
|
"FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal.
|
||||||
|
|
||||||
|
2011-03-13: Simon Goldschmidt
|
||||||
|
* sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing
|
||||||
|
err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN:
|
||||||
|
use EALRADY instead of -1
|
||||||
|
|
||||||
|
2011-03-13: Simon Goldschmidt
|
||||||
|
* api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the
|
||||||
|
connection has been aborted by err_tcp (since this is not a normal closing
|
||||||
|
procedure).
|
||||||
|
|
||||||
|
2011-03-13: Simon Goldschmidt
|
||||||
|
* tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind
|
||||||
|
with pcb->state != CLOSED
|
||||||
|
|
||||||
|
2011-02-17: Simon Goldschmidt
|
||||||
|
* rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in
|
||||||
|
documentation
|
||||||
|
|
||||||
|
2011-02-17: Simon Goldschmidt
|
||||||
|
* many files: Added missing U/UL modifiers to fix 16-bit-arch portability.
|
||||||
|
|
||||||
|
2011-01-24: Simon Goldschmidt
|
||||||
|
* sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
|
||||||
|
|
||||||
|
2010-12-02: Simon Goldschmidt
|
||||||
|
* err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
|
||||||
|
|
||||||
|
2010-11-23: Simon Goldschmidt
|
||||||
|
* api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
|
||||||
|
LWIP_SO_RCVBUF and ioctl/FIONREAD.
|
||||||
|
|
||||||
|
2010-11-23: Simon Goldschmidt
|
||||||
|
* etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
|
||||||
|
least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
|
||||||
|
|
||||||
|
2010-11-23: Simon Goldschmidt
|
||||||
|
* tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
|
||||||
|
refusing 'refused_data' again.
|
||||||
|
|
||||||
|
2010-11-22: Simon Goldschmidt
|
||||||
|
* sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
|
||||||
|
after a successful nonblocking connection.
|
||||||
|
|
||||||
|
2010-11-22: Simon Goldschmidt
|
||||||
|
* etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
|
||||||
|
must be sent link-local
|
||||||
|
|
||||||
|
2010-11-22: Simon Goldschmidt
|
||||||
|
* timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
|
||||||
|
LWIP_TIMERS==0
|
||||||
|
|
||||||
|
2010-11-20: Simon Goldschmidt
|
||||||
|
* sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
|
||||||
|
|
||||||
|
2010-11-20: Simon Goldschmidt
|
||||||
|
* sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
|
||||||
|
resemble other stacks.
|
||||||
|
|
||||||
|
2010-11-20: Simon Goldschmidt
|
||||||
|
* dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
|
||||||
|
no-copy TCP writes will never succeed.
|
||||||
|
|
||||||
|
2010-11-20: Simon Goldschmidt
|
||||||
|
* dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
|
||||||
|
not match documentation: return ERR_ARG instead of ERR_VAL if not
|
||||||
|
initialized or wrong argument.
|
||||||
|
|
||||||
|
2010-10-20: Simon Goldschmidt
|
||||||
|
* sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
|
||||||
|
|
||||||
|
2010-10-05: Simon Goldschmidt
|
||||||
|
* dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
|
||||||
|
replugging the network cable after an AutoIP address was assigned.
|
||||||
|
|
||||||
|
2010-08-10: Simon Goldschmidt
|
||||||
|
* tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
|
||||||
|
|
||||||
|
2010-08-03: Simon Goldschmidt
|
||||||
|
* udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
|
||||||
|
|
||||||
|
2010-08-01: Simon Goldschmidt (patch by Greg Renda)
|
||||||
|
* ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
|
||||||
|
endian architectures)
|
||||||
|
|
||||||
|
2010-07-28: Simon Goldschmidt
|
||||||
|
* api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
|
||||||
|
disabled.
|
||||||
|
|
||||||
|
2010-07-27: Simon Goldschmidt
|
||||||
|
* tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
|
||||||
|
harm but never did anything
|
||||||
|
|
||||||
|
2010-07-21: Simon Goldschmidt
|
||||||
|
* ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
|
||||||
|
add IP options)
|
||||||
|
|
||||||
2010-07-16: Kieran Mansley
|
2010-07-16: Kieran Mansley
|
||||||
* msg_in.c: Fixed SNMP ASN constant defines to not use ! operator
|
* msg_in.c: Fixed SNMP ASN constant defines to not use ! operator
|
||||||
|
|
||||||
|
|||||||
@@ -111,11 +111,16 @@ with newer versions.
|
|||||||
* Added const char* name to mem- and memp-stats for easier debugging.
|
* Added const char* name to mem- and memp-stats for easier debugging.
|
||||||
|
|
||||||
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
* 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
|
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
|
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
||||||
more than one pcb.
|
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
|
++ Major bugfixes/improvements
|
||||||
|
|
||||||
* Implemented tcp_shutdown() to only shut down one end of a connection
|
* Implemented tcp_shutdown() to only shut down one end of a connection
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ incoming connections or be explicitly connected to another host.
|
|||||||
Creates a new connection identifier (PCB). If memory is not
|
Creates a new connection identifier (PCB). If memory is not
|
||||||
available for creating the new pcb, NULL is returned.
|
available for creating the new pcb, NULL is returned.
|
||||||
|
|
||||||
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||||
u16_t port)
|
u16_t port)
|
||||||
|
|
||||||
Binds the pcb to a local IP address and port number. The IP address
|
Binds the pcb to a local IP address and port number. The IP address
|
||||||
@@ -147,6 +147,8 @@ incoming connections or be explicitly connected to another host.
|
|||||||
usually be called from the accept callback. This allows lwIP to perform
|
usually be called from the accept callback. This allows lwIP to perform
|
||||||
housekeeping tasks, such as allowing further incoming connections to be
|
housekeeping tasks, such as allowing further incoming connections to be
|
||||||
queued in the listen backlog.
|
queued in the listen backlog.
|
||||||
|
ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed
|
||||||
|
into the accept callback!
|
||||||
|
|
||||||
- void tcp_accept(struct tcp_pcb *pcb,
|
- void tcp_accept(struct tcp_pcb *pcb,
|
||||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||||
@@ -154,8 +156,8 @@ incoming connections or be explicitly connected to another host.
|
|||||||
|
|
||||||
Specified the callback function that should be called when a new
|
Specified the callback function that should be called when a new
|
||||||
connection arrives on a listening connection.
|
connection arrives on a listening connection.
|
||||||
|
|
||||||
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||||
u16_t port, err_t (* connected)(void *arg,
|
u16_t port, err_t (* connected)(void *arg,
|
||||||
struct tcp_pcb *tpcb,
|
struct tcp_pcb *tpcb,
|
||||||
err_t err));
|
err_t err));
|
||||||
@@ -176,7 +178,7 @@ incoming connections or be explicitly connected to another host.
|
|||||||
available for enqueueing the SYN segment. If the SYN indeed was
|
available for enqueueing the SYN segment. If the SYN indeed was
|
||||||
enqueued successfully, the tcp_connect() function returns ERR_OK.
|
enqueued successfully, the tcp_connect() function returns ERR_OK.
|
||||||
|
|
||||||
|
|
||||||
--- Sending TCP data
|
--- Sending TCP data
|
||||||
|
|
||||||
TCP data is sent by enqueueing the data with a call to
|
TCP data is sent by enqueueing the data with a call to
|
||||||
@@ -184,15 +186,19 @@ tcp_write(). When the data is successfully transmitted to the remote
|
|||||||
host, the application will be notified with a call to a specified
|
host, the application will be notified with a call to a specified
|
||||||
callback function.
|
callback function.
|
||||||
|
|
||||||
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||||
u8_t copy)
|
u8_t apiflags)
|
||||||
|
|
||||||
Enqueues the data pointed to by the argument dataptr. The length of
|
Enqueues the data pointed to by the argument dataptr. The length of
|
||||||
the data is passed as the len parameter. The copy argument is either
|
the data is passed as the len parameter. The apiflags can be one or more of:
|
||||||
0 or 1 and indicates whether the new memory should be allocated for
|
- TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
|
||||||
the data to be copied into. If the argument is 0, no new memory
|
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
|
should be allocated and the data should only be referenced by pointer. This
|
||||||
pointer.
|
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 given,
|
||||||
|
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 tcp_write() function will fail and return ERR_MEM if the length
|
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
|
of the data exceeds the current send buffer size or if the length of
|
||||||
@@ -238,7 +244,7 @@ window.
|
|||||||
|
|
||||||
Must be called when the application has received the data. The len
|
Must be called when the application has received the data. The len
|
||||||
argument indicates the length of the received data.
|
argument indicates the length of the received data.
|
||||||
|
|
||||||
|
|
||||||
--- Application polling
|
--- Application polling
|
||||||
|
|
||||||
@@ -251,8 +257,9 @@ if a call to tcp_write() has failed because memory wasn't available,
|
|||||||
the application may use the polling functionality to call tcp_write()
|
the application may use the polling functionality to call tcp_write()
|
||||||
again when the connection has been idle for a while.
|
again when the connection has been idle for a while.
|
||||||
|
|
||||||
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
|
- void tcp_poll(struct tcp_pcb *pcb,
|
||||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
|
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
|
||||||
|
u8_t interval)
|
||||||
|
|
||||||
Specifies the polling interval and the callback function that should
|
Specifies the polling interval and the callback function that should
|
||||||
be called to poll the application. The interval is specified in
|
be called to poll the application. The interval is specified in
|
||||||
@@ -321,14 +328,14 @@ level of complexity of UDP, the interface is significantly simpler.
|
|||||||
|
|
||||||
Removes and deallocates the pcb.
|
Removes and deallocates the pcb.
|
||||||
|
|
||||||
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||||
u16_t port)
|
u16_t port)
|
||||||
|
|
||||||
Binds the pcb to a local address. The IP-address argument "ipaddr"
|
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
|
can be IP_ADDR_ANY to indicate that it should listen to any local IP
|
||||||
address. The function currently always return ERR_OK.
|
address. The function currently always return ERR_OK.
|
||||||
|
|
||||||
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||||
u16_t port)
|
u16_t port)
|
||||||
|
|
||||||
Sets the remote end of the pcb. This function does not generate any
|
Sets the remote end of the pcb. This function does not generate any
|
||||||
@@ -346,7 +353,7 @@ level of complexity of UDP, the interface is significantly simpler.
|
|||||||
- void udp_recv(struct udp_pcb *pcb,
|
- void udp_recv(struct udp_pcb *pcb,
|
||||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||||
struct pbuf *p,
|
struct pbuf *p,
|
||||||
struct ip_addr *addr,
|
ip_addr_t *addr,
|
||||||
u16_t port),
|
u16_t port),
|
||||||
void *recv_arg)
|
void *recv_arg)
|
||||||
|
|
||||||
@@ -407,8 +414,8 @@ Call these functions in the order of appearance:
|
|||||||
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
||||||
predefined regular intervals after this initialization.
|
predefined regular intervals after this initialization.
|
||||||
|
|
||||||
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
|
- netif_add(struct netif *netif, ip_addr_t *ipaddr,
|
||||||
struct ip_addr *netmask, struct ip_addr *gw,
|
ip_addr_t *netmask, ip_addr_t *gw,
|
||||||
void *state, err_t (* init)(struct netif *netif),
|
void *state, err_t (* init)(struct netif *netif),
|
||||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||||
|
|
||||||
|
|||||||
@@ -34,26 +34,36 @@ in the sys_arch.h file. Mailboxes are equivalently represented by the
|
|||||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
type "sys_mbox_t". lwIP does not place any restrictions on how
|
||||||
sys_sem_t or sys_mbox_t are represented internally.
|
sys_sem_t or sys_mbox_t are represented internally.
|
||||||
|
|
||||||
|
Since lwIP 1.4.0, semaphore 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).
|
||||||
|
|
||||||
The following functions must be implemented by the sys_arch:
|
The following functions must be implemented by the sys_arch:
|
||||||
|
|
||||||
- void sys_init(void)
|
- void sys_init(void)
|
||||||
|
|
||||||
Is called to initialize the sys_arch layer.
|
Is called to initialize the sys_arch layer.
|
||||||
|
|
||||||
- sys_sem_t sys_sem_new(u8_t count)
|
- err_t sys_sem_new(sys_sem_t *sem, u8_t count)
|
||||||
|
|
||||||
Creates and returns a new semaphore. The "count" argument specifies
|
Creates a new semaphore. The semaphore is allocated to the memory that 'sem'
|
||||||
the initial state of the semaphore.
|
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.
|
||||||
|
|
||||||
- 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.
|
Signals a semaphore.
|
||||||
|
|
||||||
- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||||
|
|
||||||
Blocks the thread while waiting for the semaphore to be
|
Blocks the thread while waiting for the semaphore to be
|
||||||
signaled. If the "timeout" argument is non-zero, the thread should
|
signaled. If the "timeout" argument is non-zero, the thread should
|
||||||
@@ -70,30 +80,47 @@ The following functions must be implemented by the sys_arch:
|
|||||||
Notice that lwIP implements a function with a similar name,
|
Notice that lwIP implements a function with a similar name,
|
||||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||||
|
|
||||||
- sys_mbox_t sys_mbox_new(int size)
|
- int sys_sem_valid(sys_sem_t *sem)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||||
|
|
||||||
Creates an empty mailbox for maximum "size" elements. Elements stored
|
Creates an empty mailbox for maximum "size" elements. Elements stored
|
||||||
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
||||||
in your lwipopts.h, or ignore this parameter in your implementation
|
in your lwipopts.h, or ignore this parameter in your implementation
|
||||||
and use a default size.
|
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
|
Deallocates a mailbox. If there are messages still present in the
|
||||||
mailbox when the mailbox is deallocated, it is an indication of a
|
mailbox when the mailbox is deallocated, it is an indication of a
|
||||||
programming error in lwIP and the developer should be notified.
|
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
|
Posts the "msg" to the mailbox. This function have to block until
|
||||||
the "msg" is really posted.
|
the "msg" is really posted.
|
||||||
|
|
||||||
- err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
|
- 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
|
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
|
||||||
is full, else, ERR_OK if the "msg" is posted.
|
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)
|
- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
|
||||||
|
|
||||||
Blocks the thread until a message arrives in the mailbox, but does
|
Blocks the thread until a message arrives in the mailbox, but does
|
||||||
not block the thread longer than "timeout" milliseconds (similar to
|
not block the thread longer than "timeout" milliseconds (similar to
|
||||||
@@ -110,7 +137,7 @@ The following functions must be implemented by the sys_arch:
|
|||||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||||
implemented by lwIP.
|
implemented by lwIP.
|
||||||
|
|
||||||
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
|
- 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
|
This is similar to sys_arch_mbox_fetch, however if a message is not
|
||||||
present in the mailbox, it immediately returns with the code
|
present in the mailbox, it immediately returns with the code
|
||||||
@@ -122,19 +149,21 @@ The following functions must be implemented by the sys_arch:
|
|||||||
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
||||||
sys_arch_mbox_fetch(mbox,msg,1)
|
sys_arch_mbox_fetch(mbox,msg,1)
|
||||||
although this would introduce unnecessary delays.
|
although this would introduce unnecessary delays.
|
||||||
|
|
||||||
- struct sys_timeouts *sys_arch_timeouts(void)
|
|
||||||
|
|
||||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
- int sys_mbox_valid(sys_mbox_t *mbox)
|
||||||
each thread has a list of timeouts which is repressented as a linked
|
|
||||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
Returns 1 if the mailbox is valid, 0 if it is not valid.
|
||||||
pointer to a linked list of timeouts. This function is called by
|
When using pointers, a simple way is to check the pointer for != NULL.
|
||||||
the lwIP timeout scheduler and must not return a NULL value.
|
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.
|
||||||
|
|
||||||
In a single thread 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
|
If threads are supported by the underlying operating system and if
|
||||||
such functionality is needed in lwIP, the following function will have
|
such functionality is needed in lwIP, the following function will have
|
||||||
to be implemented as well:
|
to be implemented as well:
|
||||||
@@ -168,6 +197,16 @@ to be implemented as well:
|
|||||||
more information. This function is only required if your port is supporting
|
more information. This function is only required if your port is supporting
|
||||||
an operating system.
|
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:
|
Note:
|
||||||
|
|
||||||
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
|
|||||||
|
|
||||||
msg.function = do_getaddr;
|
msg.function = do_getaddr;
|
||||||
msg.msg.conn = conn;
|
msg.msg.conn = conn;
|
||||||
msg.msg.msg.ad.ipaddr = addr;
|
msg.msg.msg.ad.ipaddr = ip_2_ipX(addr);
|
||||||
msg.msg.msg.ad.port = port;
|
msg.msg.msg.ad.port = port;
|
||||||
msg.msg.msg.ad.local = local;
|
msg.msg.msg.ad.local = local;
|
||||||
err = TCPIP_APIMSG(&msg);
|
err = TCPIP_APIMSG(&msg);
|
||||||
@@ -240,6 +240,7 @@ netconn_disconnect(struct netconn *conn)
|
|||||||
err_t
|
err_t
|
||||||
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
||||||
{
|
{
|
||||||
|
#if LWIP_TCP
|
||||||
struct api_msg msg;
|
struct api_msg msg;
|
||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
@@ -257,6 +258,11 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
|||||||
|
|
||||||
NETCONN_SET_SAFE_ERR(conn, err);
|
NETCONN_SET_SAFE_ERR(conn, err);
|
||||||
return err;
|
return err;
|
||||||
|
#else /* LWIP_TCP */
|
||||||
|
LWIP_UNUSED_ARG(conn);
|
||||||
|
LWIP_UNUSED_ARG(backlog);
|
||||||
|
return ERR_ARG;
|
||||||
|
#endif /* LWIP_TCP */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,9 +307,9 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||||
|
|
||||||
if (newconn == NULL) {
|
if (newconn == NULL) {
|
||||||
/* connection has been closed */
|
/* connection has been aborted */
|
||||||
NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
|
NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
|
||||||
return ERR_CLSD;
|
return ERR_ABRT;
|
||||||
}
|
}
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
/* Let the stack know that we have accepted the connection. */
|
/* Let the stack know that we have accepted the connection. */
|
||||||
@@ -366,7 +372,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||||||
#endif /* LWIP_SO_RCVTIMEO*/
|
#endif /* LWIP_SO_RCVTIMEO*/
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
if (conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||||
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
|
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
|
||||||
/* Let the stack know that we have taken the data. */
|
/* Let the stack know that we have taken the data. */
|
||||||
/* TODO: Speedup: Don't block and wait for the answer here
|
/* TODO: Speedup: Don't block and wait for the answer here
|
||||||
@@ -402,7 +408,9 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||||||
}
|
}
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||||
|
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
SYS_ARCH_DEC(conn->recv_avail, len);
|
SYS_ARCH_DEC(conn->recv_avail, len);
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
/* Register event with callback */
|
/* Register event with callback */
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
||||||
|
|
||||||
@@ -426,7 +434,7 @@ err_t
|
|||||||
netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
|
netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
|
||||||
{
|
{
|
||||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
|
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
|
||||||
netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
|
NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
|
||||||
|
|
||||||
return netconn_recv_data(conn, (void **)new_buf);
|
return netconn_recv_data(conn, (void **)new_buf);
|
||||||
}
|
}
|
||||||
@@ -453,7 +461,7 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
|||||||
LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
if (conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||||
struct pbuf *p = NULL;
|
struct pbuf *p = NULL;
|
||||||
/* This is not a listening netconn, since recvmbox is set */
|
/* This is not a listening netconn, since recvmbox is set */
|
||||||
|
|
||||||
@@ -473,7 +481,7 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
|||||||
buf->p = p;
|
buf->p = p;
|
||||||
buf->ptr = p;
|
buf->ptr = p;
|
||||||
buf->port = 0;
|
buf->port = 0;
|
||||||
ip_addr_set_any(&buf->addr);
|
ipX_addr_set_any(LWIP_IPV6, &buf->addr);
|
||||||
*new_buf = buf;
|
*new_buf = buf;
|
||||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@@ -499,7 +507,8 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
|||||||
void
|
void
|
||||||
netconn_recved(struct netconn *conn, u32_t length)
|
netconn_recved(struct netconn *conn, u32_t length)
|
||||||
{
|
{
|
||||||
if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
|
#if LWIP_TCP
|
||||||
|
if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) &&
|
||||||
(netconn_get_noautorecved(conn))) {
|
(netconn_get_noautorecved(conn))) {
|
||||||
struct api_msg msg;
|
struct api_msg msg;
|
||||||
/* Let the stack know that we have taken the data. */
|
/* Let the stack know that we have taken the data. */
|
||||||
@@ -511,6 +520,10 @@ netconn_recved(struct netconn *conn, u32_t length)
|
|||||||
/* don't care for the return value of do_recv */
|
/* don't care for the return value of do_recv */
|
||||||
TCPIP_APIMSG(&msg);
|
TCPIP_APIMSG(&msg);
|
||||||
}
|
}
|
||||||
|
#else /* LWIP_TCP */
|
||||||
|
LWIP_UNUSED_ARG(conn);
|
||||||
|
LWIP_UNUSED_ARG(length);
|
||||||
|
#endif /* LWIP_TCP */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -527,7 +540,7 @@ err_t
|
|||||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
|
netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
|
||||||
{
|
{
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
ip_addr_set(&buf->addr, addr);
|
ipX_addr_set_ipaddr(PCB_ISIPV6(conn->pcb.ip), &buf->addr, addr);
|
||||||
buf->port = port;
|
buf->port = port;
|
||||||
return netconn_send(conn, buf);
|
return netconn_send(conn, buf);
|
||||||
}
|
}
|
||||||
@@ -578,7 +591,7 @@ netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apifl
|
|||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||||
LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
|
LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -651,7 +664,7 @@ netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
|
|||||||
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
|
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
/**
|
/**
|
||||||
* Join multicast groups for UDP netconns.
|
* Join multicast groups for UDP netconns.
|
||||||
*
|
*
|
||||||
@@ -675,15 +688,15 @@ netconn_join_leave_group(struct netconn *conn,
|
|||||||
|
|
||||||
msg.function = do_join_leave_group;
|
msg.function = do_join_leave_group;
|
||||||
msg.msg.conn = conn;
|
msg.msg.conn = conn;
|
||||||
msg.msg.msg.jl.multiaddr = multiaddr;
|
msg.msg.msg.jl.multiaddr = ip_2_ipX(multiaddr);
|
||||||
msg.msg.msg.jl.netif_addr = netif_addr;
|
msg.msg.msg.jl.netif_addr = ip_2_ipX(netif_addr);
|
||||||
msg.msg.msg.jl.join_or_leave = join_or_leave;
|
msg.msg.msg.jl.join_or_leave = join_or_leave;
|
||||||
err = TCPIP_APIMSG(&msg);
|
err = TCPIP_APIMSG(&msg);
|
||||||
|
|
||||||
NETCONN_SET_SAFE_ERR(conn, err);
|
NETCONN_SET_SAFE_ERR(conn, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
|
|
||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
#include "lwip/tcpip.h"
|
#include "lwip/tcpip.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
|||||||
|
|
||||||
buf->p = q;
|
buf->p = q;
|
||||||
buf->ptr = q;
|
buf->ptr = q;
|
||||||
ip_addr_copy(buf->addr, *ip_current_src_addr());
|
ipX_addr_copy(PCB_ISIPV6(pcb), buf->addr, *ipX_current_src_addr());
|
||||||
buf->port = pcb->protocol;
|
buf->port = pcb->protocol;
|
||||||
|
|
||||||
len = q->tot_len;
|
len = q->tot_len;
|
||||||
@@ -120,7 +121,9 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
|||||||
netbuf_delete(buf);
|
netbuf_delete(buf);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
SYS_ARCH_INC(conn->recv_avail, len);
|
SYS_ARCH_INC(conn->recv_avail, len);
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
/* Register event with callback */
|
/* Register event with callback */
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||||
}
|
}
|
||||||
@@ -173,17 +176,16 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
} else {
|
} else {
|
||||||
buf->p = p;
|
buf->p = p;
|
||||||
buf->ptr = p;
|
buf->ptr = p;
|
||||||
ip_addr_set(&buf->addr, addr);
|
ipX_addr_set_ipaddr(ip_current_is_v6(), &buf->addr, addr);
|
||||||
buf->port = port;
|
buf->port = port;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
{
|
{
|
||||||
const struct ip_hdr* iphdr = ip_current_header();
|
|
||||||
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
||||||
const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
|
const struct udp_hdr* udphdr = ipX_next_header_ptr();
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
buf->flags = NETBUF_FLAG_DESTADDR;
|
buf->flags = NETBUF_FLAG_DESTADDR;
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
ip_addr_set(&buf->toaddr, ip_current_dest_addr());
|
ipX_addr_set(ip_current_is_v6(), &buf->toaddr, ipX_current_dest_addr());
|
||||||
buf->toport_chksum = udphdr->dest;
|
buf->toport_chksum = udphdr->dest;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
@@ -194,7 +196,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
netbuf_delete(buf);
|
netbuf_delete(buf);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
SYS_ARCH_INC(conn->recv_avail, len);
|
SYS_ARCH_INC(conn->recv_avail, len);
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
/* Register event with callback */
|
/* Register event with callback */
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||||
}
|
}
|
||||||
@@ -248,7 +252,9 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
|||||||
/* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
|
/* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
} else {
|
} else {
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
SYS_ARCH_INC(conn->recv_avail, len);
|
SYS_ARCH_INC(conn->recv_avail, len);
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
/* Register event with callback */
|
/* Register event with callback */
|
||||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||||
}
|
}
|
||||||
@@ -482,46 +488,50 @@ pcb_new(struct api_msg_msg *msg)
|
|||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
case NETCONN_RAW:
|
case NETCONN_RAW:
|
||||||
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
|
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
|
||||||
if(msg->conn->pcb.raw == NULL) {
|
if(msg->conn->pcb.raw != NULL) {
|
||||||
msg->err = ERR_MEM;
|
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
case NETCONN_UDP:
|
case NETCONN_UDP:
|
||||||
msg->conn->pcb.udp = udp_new();
|
msg->conn->pcb.udp = udp_new();
|
||||||
if(msg->conn->pcb.udp == NULL) {
|
if(msg->conn->pcb.udp != NULL) {
|
||||||
msg->err = ERR_MEM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#if LWIP_UDPLITE
|
#if LWIP_UDPLITE
|
||||||
if (msg->conn->type==NETCONN_UDPLITE) {
|
if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
|
||||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_UDPLITE */
|
#endif /* LWIP_UDPLITE */
|
||||||
if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
|
if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) {
|
||||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||||
|
}
|
||||||
|
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||||
}
|
}
|
||||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
case NETCONN_TCP:
|
case NETCONN_TCP:
|
||||||
msg->conn->pcb.tcp = tcp_new();
|
msg->conn->pcb.tcp = tcp_new();
|
||||||
if(msg->conn->pcb.tcp == NULL) {
|
if(msg->conn->pcb.tcp != NULL) {
|
||||||
msg->err = ERR_MEM;
|
setup_tcp(msg->conn);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
setup_tcp(msg->conn);
|
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
default:
|
default:
|
||||||
/* Unsupported netconn type, e.g. protocol disabled */
|
/* Unsupported netconn type, e.g. protocol disabled */
|
||||||
msg->err = ERR_VAL;
|
msg->err = ERR_VAL;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
if (msg->conn->pcb.ip == NULL) {
|
||||||
|
msg->err = ERR_MEM;
|
||||||
|
}
|
||||||
|
#if LWIP_IPV6
|
||||||
|
else {
|
||||||
|
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||||
|
ip_set_v6(msg->conn->pcb.ip, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -614,7 +624,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
|
|||||||
conn->socket = -1;
|
conn->socket = -1;
|
||||||
#endif /* LWIP_SOCKET */
|
#endif /* LWIP_SOCKET */
|
||||||
conn->callback = callback;
|
conn->callback = callback;
|
||||||
conn->recv_avail = 0;
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
conn->current_msg = NULL;
|
conn->current_msg = NULL;
|
||||||
conn->write_offset = 0;
|
conn->write_offset = 0;
|
||||||
@@ -624,6 +633,7 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
|
|||||||
#endif /* LWIP_SO_RCVTIMEO */
|
#endif /* LWIP_SO_RCVTIMEO */
|
||||||
#if LWIP_SO_RCVBUF
|
#if LWIP_SO_RCVBUF
|
||||||
conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
|
conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
|
||||||
|
conn->recv_avail = 0;
|
||||||
#endif /* LWIP_SO_RCVBUF */
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
conn->flags = 0;
|
conn->flags = 0;
|
||||||
return conn;
|
return conn;
|
||||||
@@ -674,7 +684,7 @@ netconn_drain(struct netconn *conn)
|
|||||||
if (sys_mbox_valid(&conn->recvmbox)) {
|
if (sys_mbox_valid(&conn->recvmbox)) {
|
||||||
while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
|
while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
if (conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||||
if(mem != NULL) {
|
if(mem != NULL) {
|
||||||
p = (struct pbuf*)mem;
|
p = (struct pbuf*)mem;
|
||||||
/* pcb might be set to NULL already by err_tcp() */
|
/* pcb might be set to NULL already by err_tcp() */
|
||||||
@@ -732,7 +742,7 @@ do_close_internal(struct netconn *conn)
|
|||||||
u8_t shut, shut_rx, shut_tx, close;
|
u8_t shut, shut_rx, shut_tx, close;
|
||||||
|
|
||||||
LWIP_ASSERT("invalid conn", (conn != NULL));
|
LWIP_ASSERT("invalid conn", (conn != NULL));
|
||||||
LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
|
LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP));
|
||||||
LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
|
LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
|
||||||
LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
|
LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
|
||||||
LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
|
LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
|
||||||
@@ -818,7 +828,8 @@ do_delconn(struct api_msg_msg *msg)
|
|||||||
(msg->conn->state != NETCONN_LISTEN) &&
|
(msg->conn->state != NETCONN_LISTEN) &&
|
||||||
(msg->conn->state != NETCONN_CONNECT)) {
|
(msg->conn->state != NETCONN_CONNECT)) {
|
||||||
/* this only happens for TCP netconns */
|
/* this only happens for TCP netconns */
|
||||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
|
LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP",
|
||||||
|
NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP);
|
||||||
msg->err = ERR_INPROGRESS;
|
msg->err = ERR_INPROGRESS;
|
||||||
} else {
|
} else {
|
||||||
LWIP_ASSERT("blocking connect in progress",
|
LWIP_ASSERT("blocking connect in progress",
|
||||||
@@ -936,7 +947,7 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||||||
if (conn->current_msg != NULL) {
|
if (conn->current_msg != NULL) {
|
||||||
conn->current_msg->err = err;
|
conn->current_msg->err = err;
|
||||||
}
|
}
|
||||||
if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
|
if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) {
|
||||||
setup_tcp(conn);
|
setup_tcp(conn);
|
||||||
}
|
}
|
||||||
was_blocking = !IN_NONBLOCKING_CONNECT(conn);
|
was_blocking = !IN_NONBLOCKING_CONNECT(conn);
|
||||||
@@ -944,12 +955,7 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||||||
conn->current_msg = NULL;
|
conn->current_msg = NULL;
|
||||||
conn->state = NETCONN_NONE;
|
conn->state = NETCONN_NONE;
|
||||||
if (!was_blocking) {
|
if (!was_blocking) {
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
NETCONN_SET_SAFE_ERR(conn, ERR_OK);
|
||||||
SYS_ARCH_PROTECT(lev);
|
|
||||||
if (conn->last_err == ERR_INPROGRESS) {
|
|
||||||
conn->last_err = ERR_OK;
|
|
||||||
}
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
}
|
}
|
||||||
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
|
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
|
||||||
|
|
||||||
@@ -1040,6 +1046,7 @@ do_disconnect(struct api_msg_msg *msg)
|
|||||||
TCPIP_APIMSG_ACK(msg);
|
TCPIP_APIMSG_ACK(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_TCP
|
||||||
/**
|
/**
|
||||||
* Set a TCP pcb contained in a netconn into listen mode
|
* Set a TCP pcb contained in a netconn into listen mode
|
||||||
* Called from netconn_listen.
|
* Called from netconn_listen.
|
||||||
@@ -1049,13 +1056,12 @@ do_disconnect(struct api_msg_msg *msg)
|
|||||||
void
|
void
|
||||||
do_listen(struct api_msg_msg *msg)
|
do_listen(struct api_msg_msg *msg)
|
||||||
{
|
{
|
||||||
#if LWIP_TCP
|
|
||||||
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
||||||
msg->err = msg->conn->last_err;
|
msg->err = msg->conn->last_err;
|
||||||
} else {
|
} else {
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
if (msg->conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||||
if (msg->conn->state == NETCONN_NONE) {
|
if (msg->conn->state == NETCONN_NONE) {
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
|
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
|
||||||
@@ -1091,9 +1097,9 @@ do_listen(struct api_msg_msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
TCPIP_APIMSG_ACK(msg);
|
TCPIP_APIMSG_ACK(msg);
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_TCP */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send some data on a RAW or UDP pcb contained in a netconn
|
* Send some data on a RAW or UDP pcb contained in a netconn
|
||||||
@@ -1112,29 +1118,29 @@ do_send(struct api_msg_msg *msg)
|
|||||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
case NETCONN_RAW:
|
case NETCONN_RAW:
|
||||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) {
|
||||||
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
||||||
} else {
|
} else {
|
||||||
msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
|
msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
case NETCONN_UDP:
|
case NETCONN_UDP:
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) {
|
||||||
msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
||||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||||
} else {
|
} else {
|
||||||
msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
||||||
&msg->msg.b->addr, msg->msg.b->port,
|
ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port,
|
||||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||||
}
|
}
|
||||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
#else /* LWIP_CHECKSUM_ON_COPY */
|
||||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) {
|
||||||
msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
|
msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
|
||||||
} else {
|
} else {
|
||||||
msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
|
msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
break;
|
break;
|
||||||
@@ -1147,6 +1153,7 @@ do_send(struct api_msg_msg *msg)
|
|||||||
TCPIP_APIMSG_ACK(msg);
|
TCPIP_APIMSG_ACK(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_TCP
|
||||||
/**
|
/**
|
||||||
* Indicate data has been received from a TCP pcb contained in a netconn
|
* Indicate data has been received from a TCP pcb contained in a netconn
|
||||||
* Called from netconn_recv
|
* Called from netconn_recv
|
||||||
@@ -1156,10 +1163,9 @@ do_send(struct api_msg_msg *msg)
|
|||||||
void
|
void
|
||||||
do_recv(struct api_msg_msg *msg)
|
do_recv(struct api_msg_msg *msg)
|
||||||
{
|
{
|
||||||
#if LWIP_TCP
|
|
||||||
msg->err = ERR_OK;
|
msg->err = ERR_OK;
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
if (msg->conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||||
tcp_accepted(msg->conn->pcb.tcp);
|
tcp_accepted(msg->conn->pcb.tcp);
|
||||||
@@ -1175,11 +1181,9 @@ do_recv(struct api_msg_msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
TCPIP_APIMSG_ACK(msg);
|
TCPIP_APIMSG_ACK(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_TCP
|
|
||||||
/**
|
/**
|
||||||
* See if more data needs to be written from a previous call to netconn_write.
|
* See if more data needs to be written from a previous call to netconn_write.
|
||||||
* Called initially from do_write. If the first call can't send all data
|
* Called initially from do_write. If the first call can't send all data
|
||||||
@@ -1316,7 +1320,7 @@ do_write(struct api_msg_msg *msg)
|
|||||||
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
||||||
msg->err = msg->conn->last_err;
|
msg->err = msg->conn->last_err;
|
||||||
} else {
|
} else {
|
||||||
if (msg->conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
if (msg->conn->state != NETCONN_NONE) {
|
if (msg->conn->state != NETCONN_NONE) {
|
||||||
/* netconn is connecting, closing or in blocking write */
|
/* netconn is connecting, closing or in blocking write */
|
||||||
@@ -1369,9 +1373,13 @@ void
|
|||||||
do_getaddr(struct api_msg_msg *msg)
|
do_getaddr(struct api_msg_msg *msg)
|
||||||
{
|
{
|
||||||
if (msg->conn->pcb.ip != NULL) {
|
if (msg->conn->pcb.ip != NULL) {
|
||||||
*(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip :
|
if (msg->msg.ad.local) {
|
||||||
msg->conn->pcb.ip->remote_ip);
|
ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr),
|
||||||
|
msg->conn->pcb.ip->local_ip);
|
||||||
|
} else {
|
||||||
|
ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr),
|
||||||
|
msg->conn->pcb.ip->remote_ip);
|
||||||
|
}
|
||||||
msg->err = ERR_OK;
|
msg->err = ERR_OK;
|
||||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
@@ -1425,9 +1433,10 @@ do_close(struct api_msg_msg *msg)
|
|||||||
/* @todo: abort running write/connect? */
|
/* @todo: abort running write/connect? */
|
||||||
if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
|
if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
|
||||||
/* this only happens for TCP netconns */
|
/* this only happens for TCP netconns */
|
||||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
|
LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP",
|
||||||
|
NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP);
|
||||||
msg->err = ERR_INPROGRESS;
|
msg->err = ERR_INPROGRESS;
|
||||||
} else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
|
} else if ((msg->conn->pcb.tcp != NULL) && (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)) {
|
||||||
if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
|
if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
|
||||||
/* LISTEN doesn't support half shutdown */
|
/* LISTEN doesn't support half shutdown */
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
@@ -1452,7 +1461,7 @@ do_close(struct api_msg_msg *msg)
|
|||||||
sys_sem_signal(&msg->conn->op_completed);
|
sys_sem_signal(&msg->conn->op_completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
/**
|
/**
|
||||||
* Join multicast groups for UDP netconns.
|
* Join multicast groups for UDP netconns.
|
||||||
* Called from netconn_join_leave_group
|
* Called from netconn_join_leave_group
|
||||||
@@ -1468,10 +1477,28 @@ do_join_leave_group(struct api_msg_msg *msg)
|
|||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
if (PCB_ISIPV6(msg->conn->pcb.udp)) {
|
||||||
} else {
|
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
||||||
msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
msg->err = mld6_joingroup(ipX_2_ip6(msg->msg.jl.netif_addr),
|
||||||
|
ipX_2_ip6(msg->msg.jl.multiaddr));
|
||||||
|
} else {
|
||||||
|
msg->err = mld6_leavegroup(ipX_2_ip6(msg->msg.jl.netif_addr),
|
||||||
|
ipX_2_ip6(msg->msg.jl.multiaddr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
|
{
|
||||||
|
#if LWIP_IGMP
|
||||||
|
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
||||||
|
msg->err = igmp_joingroup(ipX_2_ip(msg->msg.jl.netif_addr),
|
||||||
|
ipX_2_ip(msg->msg.jl.multiaddr));
|
||||||
|
} else {
|
||||||
|
msg->err = igmp_leavegroup(ipX_2_ip(msg->msg.jl.netif_addr),
|
||||||
|
ipX_2_ip(msg->msg.jl.multiaddr));
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IGMP */
|
||||||
}
|
}
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if (LWIP_TCP || LWIP_RAW)
|
#if (LWIP_TCP || LWIP_RAW)
|
||||||
@@ -1485,7 +1512,7 @@ do_join_leave_group(struct api_msg_msg *msg)
|
|||||||
}
|
}
|
||||||
TCPIP_APIMSG_ACK(msg);
|
TCPIP_APIMSG_ACK(msg);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
|
|
||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ static const char *err_strerr[] = {
|
|||||||
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
||||||
"Illegal value.", /* ERR_VAL -6 */
|
"Illegal value.", /* ERR_VAL -6 */
|
||||||
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
||||||
"Connection aborted.", /* ERR_ABRT -8 */
|
"Address in use.", /* ERR_USE -8 */
|
||||||
"Connection reset.", /* ERR_RST -9 */
|
"Already connected.", /* ERR_ISCONN -9 */
|
||||||
"Connection closed.", /* ERR_CLSD -10 */
|
"Connection aborted.", /* ERR_ABRT -10 */
|
||||||
"Not connected.", /* ERR_CONN -11 */
|
"Connection reset.", /* ERR_RST -11 */
|
||||||
"Illegal argument.", /* ERR_ARG -12 */
|
"Connection closed.", /* ERR_CLSD -12 */
|
||||||
"Address in use.", /* ERR_USE -13 */
|
"Not connected.", /* ERR_CONN -13 */
|
||||||
"Low-level netif error.", /* ERR_IF -14 */
|
"Illegal argument.", /* ERR_ARG -14 */
|
||||||
"Already connected.", /* ERR_ISCONN -15 */
|
"Low-level netif error.", /* ERR_IF -15 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ netbuf *netbuf_new(void)
|
|||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
buf->p = NULL;
|
buf->p = NULL;
|
||||||
buf->ptr = NULL;
|
buf->ptr = NULL;
|
||||||
ip_addr_set_any(&buf->addr);
|
ipX_addr_set_any(LWIP_IPV6, &buf->addr);
|
||||||
buf->port = 0;
|
buf->port = 0;
|
||||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
@@ -69,7 +69,7 @@ netbuf *netbuf_new(void)
|
|||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
buf->toport_chksum = 0;
|
buf->toport_chksum = 0;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
ip_addr_set_any(&buf->toaddr);
|
ipX_addr_set_any(LWIP_IPV6, &buf->toaddr);
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||||
return buf;
|
return buf;
|
||||||
|
|||||||
@@ -58,6 +58,66 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipXaddr, port) do { \
|
||||||
|
(sin)->sin_len = sizeof(struct sockaddr_in); \
|
||||||
|
(sin)->sin_family = AF_INET; \
|
||||||
|
(sin)->sin_port = htons((port)); \
|
||||||
|
inet_addr_from_ipaddr(&(sin)->sin_addr, ipX_2_ip(ipXaddr)); \
|
||||||
|
memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
|
||||||
|
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipXaddr, port) do { \
|
||||||
|
inet_addr_to_ipaddr(ipX_2_ip(ipXaddr), &((sin)->sin_addr)); \
|
||||||
|
(port) = ntohs((sin)->sin_port); }while(0)
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \
|
||||||
|
((namelen) == sizeof(struct sockaddr_in6)))
|
||||||
|
#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \
|
||||||
|
((name)->sa_family == AF_INET6))
|
||||||
|
#define SOCK_ADDR_TYPE_MATCH(name, sock) \
|
||||||
|
((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
|
||||||
|
(((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
|
||||||
|
#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipXaddr, port) do { \
|
||||||
|
(sin6)->sin6_len = sizeof(struct sockaddr_in6); \
|
||||||
|
(sin6)->sin6_family = AF_INET6; \
|
||||||
|
(sin6)->sin6_port = htons((port)); \
|
||||||
|
(sin6)->sin6_flowinfo = 0; \
|
||||||
|
inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipX_2_ip6(ipXaddr)); }while(0)
|
||||||
|
#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) do { \
|
||||||
|
if (isipv6) { \
|
||||||
|
IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \
|
||||||
|
} else { \
|
||||||
|
IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \
|
||||||
|
} } while(0)
|
||||||
|
#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipXaddr, port) do { \
|
||||||
|
inet6_addr_to_ip6addr(ipX_2_ip6(ipXaddr), &((sin6)->sin6_addr)); \
|
||||||
|
(port) = ntohs((sin6)->sin6_port); }while(0)
|
||||||
|
#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) do { \
|
||||||
|
if (isipv6) { \
|
||||||
|
SOCKADDR6_TO_IP6ADDR_PORT((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \
|
||||||
|
} else { \
|
||||||
|
SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \
|
||||||
|
} } while(0)
|
||||||
|
#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
|
||||||
|
(type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in))
|
||||||
|
#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)
|
||||||
|
#define SOCK_ADDR_TYPE_MATCH(name, sock) 1
|
||||||
|
#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) \
|
||||||
|
IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port)
|
||||||
|
#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) \
|
||||||
|
SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port)
|
||||||
|
#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \
|
||||||
|
IS_SOCK_ADDR_TYPE_VALID(name))
|
||||||
|
#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
|
||||||
|
SOCK_ADDR_TYPE_MATCH(name, sock))
|
||||||
|
#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NUM_SOCKETS MEMP_NUM_NETCONN
|
#define NUM_SOCKETS MEMP_NUM_NETCONN
|
||||||
|
|
||||||
/** Contains all internal pointers and states used for a socket */
|
/** Contains all internal pointers and states used for a socket */
|
||||||
@@ -105,8 +165,10 @@ struct lwip_select_cb {
|
|||||||
struct lwip_setgetsockopt_data {
|
struct lwip_setgetsockopt_data {
|
||||||
/** socket struct for which to change options */
|
/** socket struct for which to change options */
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
|
#ifdef LWIP_DEBUG
|
||||||
/** socket index for which to change options */
|
/** socket index for which to change options */
|
||||||
int s;
|
int s;
|
||||||
|
#endif /* LWIP_DEBUG */
|
||||||
/** level of the option to process */
|
/** level of the option to process */
|
||||||
int level;
|
int level;
|
||||||
/** name of the option to process */
|
/** name of the option to process */
|
||||||
@@ -120,6 +182,18 @@ struct lwip_setgetsockopt_data {
|
|||||||
err_t err;
|
err_t err;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A struct sockaddr replacement that has the same alignment as sockaddr_in/
|
||||||
|
* sockaddr_in6 if instantiated.
|
||||||
|
*/
|
||||||
|
union sockaddr_aligned {
|
||||||
|
struct sockaddr sa;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** The global array of available sockets */
|
/** The global array of available sockets */
|
||||||
static struct lwip_sock sockets[NUM_SOCKETS];
|
static struct lwip_sock sockets[NUM_SOCKETS];
|
||||||
/** The global list of tasks waiting for select */
|
/** The global list of tasks waiting for select */
|
||||||
@@ -139,14 +213,14 @@ static const int err_to_errno_table[] = {
|
|||||||
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||||
EINVAL, /* ERR_VAL -6 Illegal value. */
|
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||||
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||||
ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
|
EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||||
ECONNRESET, /* ERR_RST -9 Connection reset. */
|
EALREADY, /* ERR_ISCONN -9 Already connected. */
|
||||||
ESHUTDOWN, /* ERR_CLSD -10 Connection closed. */
|
ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
|
||||||
ENOTCONN, /* ERR_CONN -11 Not connected. */
|
ECONNRESET, /* ERR_RST -11 Connection reset. */
|
||||||
EIO, /* ERR_ARG -12 Illegal argument. */
|
ENOTCONN, /* ERR_CLSD -12 Connection closed. */
|
||||||
EADDRINUSE, /* ERR_USE -13 Address in use. */
|
ENOTCONN, /* ERR_CONN -13 Not connected. */
|
||||||
-1, /* ERR_IF -14 Low-level netif error */
|
EIO, /* ERR_ARG -14 Illegal argument. */
|
||||||
-1, /* ERR_ISCONN -15 Already connected. */
|
-1, /* ERR_IF -15 Low-level netif error */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ERR_TO_ERRNO_TABLE_SIZE \
|
#define ERR_TO_ERRNO_TABLE_SIZE \
|
||||||
@@ -257,7 +331,7 @@ alloc_socket(struct netconn *newconn, int accepted)
|
|||||||
sockets[i].rcvevent = 0;
|
sockets[i].rcvevent = 0;
|
||||||
/* TCP sendbuf is empty, but the socket is not yet writable until connected
|
/* TCP sendbuf is empty, but the socket is not yet writable until connected
|
||||||
* (unless it has been created by accept()). */
|
* (unless it has been created by accept()). */
|
||||||
sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
|
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
|
||||||
sockets[i].errevent = 0;
|
sockets[i].errevent = 0;
|
||||||
sockets[i].err = 0;
|
sockets[i].err = 0;
|
||||||
sockets[i].select_waiting = 0;
|
sockets[i].select_waiting = 0;
|
||||||
@@ -311,10 +385,9 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
{
|
{
|
||||||
struct lwip_sock *sock, *nsock;
|
struct lwip_sock *sock, *nsock;
|
||||||
struct netconn *newconn;
|
struct netconn *newconn;
|
||||||
ip_addr_t naddr;
|
ipX_addr_t naddr;
|
||||||
u16_t port;
|
u16_t port;
|
||||||
int newsock;
|
int newsock;
|
||||||
struct sockaddr_in sin;
|
|
||||||
err_t err;
|
err_t err;
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
SYS_ARCH_DECL_PROTECT(lev);
|
||||||
|
|
||||||
@@ -341,30 +414,26 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
/* Prevent automatic window updates, we do this on our own! */
|
/* Prevent automatic window updates, we do this on our own! */
|
||||||
netconn_set_noautorecved(newconn, 1);
|
netconn_set_noautorecved(newconn, 1);
|
||||||
|
|
||||||
/* get the IP address and port of the remote host */
|
|
||||||
err = netconn_peer(newconn, &naddr, &port);
|
|
||||||
if (err != ERR_OK) {
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
|
|
||||||
netconn_delete(newconn);
|
|
||||||
sock_set_errno(sock, err_to_errno(err));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that POSIX only requires us to check addr is non-NULL. addrlen must
|
/* Note that POSIX only requires us to check addr is non-NULL. addrlen must
|
||||||
* not be NULL if addr is valid.
|
* not be NULL if addr is valid.
|
||||||
*/
|
*/
|
||||||
if (NULL != addr) {
|
if (addr != NULL) {
|
||||||
|
union sockaddr_aligned tempaddr;
|
||||||
|
/* get the IP address and port of the remote host */
|
||||||
|
err = netconn_peer(newconn, ipX_2_ip(&naddr), &port);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
|
||||||
|
netconn_delete(newconn);
|
||||||
|
sock_set_errno(sock, err_to_errno(err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
|
LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
|
||||||
memset(&sin, 0, sizeof(sin));
|
|
||||||
sin.sin_len = sizeof(sin);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_port = htons(port);
|
|
||||||
inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
|
|
||||||
|
|
||||||
if (*addrlen > sizeof(sin))
|
IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(newconn->type), &tempaddr, &naddr, port);
|
||||||
*addrlen = sizeof(sin);
|
if (*addrlen > tempaddr.sa.sa_len) {
|
||||||
|
*addrlen = tempaddr.sa.sa_len;
|
||||||
MEMCPY(addr, &sin, *addrlen);
|
}
|
||||||
|
MEMCPY(addr, &tempaddr, *addrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
newsock = alloc_socket(newconn, 1);
|
newsock = alloc_socket(newconn, 1);
|
||||||
@@ -387,9 +456,12 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
newconn->socket = newsock;
|
newconn->socket = newsock;
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
if (addr != NULL) {
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" addr="));
|
||||||
|
ipX_addr_debug_print(NETCONNTYPE_ISIPV6(newconn->type), SOCKETS_DEBUG, &naddr);
|
||||||
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
|
||||||
|
}
|
||||||
|
|
||||||
sock_set_errno(sock, 0);
|
sock_set_errno(sock, 0);
|
||||||
return newsock;
|
return newsock;
|
||||||
@@ -399,30 +471,33 @@ int
|
|||||||
lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||||
{
|
{
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
ip_addr_t local_addr;
|
ipX_addr_t local_addr;
|
||||||
u16_t local_port;
|
u16_t local_port;
|
||||||
err_t err;
|
err_t err;
|
||||||
const struct sockaddr_in *name_in;
|
|
||||||
|
|
||||||
sock = get_socket(s);
|
sock = get_socket(s);
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
|
||||||
|
/* sockaddr does not match socket type (IPv4/IPv6) */
|
||||||
|
sock_set_errno(sock, err_to_errno(ERR_VAL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* check size, familiy and alignment of 'name' */
|
/* check size, familiy and alignment of 'name' */
|
||||||
LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
|
||||||
((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
|
IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
|
||||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||||
name_in = (const struct sockaddr_in *)(void*)name;
|
LWIP_UNUSED_ARG(namelen);
|
||||||
|
|
||||||
inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
|
|
||||||
local_port = name_in->sin_port;
|
|
||||||
|
|
||||||
|
SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &local_addr, local_port);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
|
ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &local_addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
|
||||||
|
|
||||||
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
|
err = netconn_bind(sock->conn, ipX_2_ip(&local_addr), local_port);
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
|
||||||
@@ -449,7 +524,7 @@ lwip_close(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(sock->conn != NULL) {
|
if(sock->conn != NULL) {
|
||||||
is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
|
is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
|
||||||
} else {
|
} else {
|
||||||
LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
|
LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
|
||||||
}
|
}
|
||||||
@@ -466,34 +541,35 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
|||||||
{
|
{
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
err_t err;
|
err_t err;
|
||||||
const struct sockaddr_in *name_in;
|
|
||||||
|
|
||||||
sock = get_socket(s);
|
sock = get_socket(s);
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check size, familiy and alignment of 'name' */
|
if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
|
||||||
LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
/* sockaddr does not match socket type (IPv4/IPv6) */
|
||||||
((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
|
sock_set_errno(sock, err_to_errno(ERR_VAL));
|
||||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
return -1;
|
||||||
name_in = (const struct sockaddr_in *)(void*)name;
|
}
|
||||||
|
|
||||||
if (name_in->sin_family == AF_UNSPEC) {
|
/* check size, familiy and alignment of 'name' */
|
||||||
|
LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
|
||||||
|
IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
|
||||||
|
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||||
|
LWIP_UNUSED_ARG(namelen);
|
||||||
|
if (name->sa_family == AF_UNSPEC) {
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
|
||||||
err = netconn_disconnect(sock->conn);
|
err = netconn_disconnect(sock->conn);
|
||||||
} else {
|
} else {
|
||||||
ip_addr_t remote_addr;
|
ipX_addr_t remote_addr;
|
||||||
u16_t remote_port;
|
u16_t remote_port;
|
||||||
|
SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &remote_addr, remote_port);
|
||||||
inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
|
|
||||||
remote_port = name_in->sin_port;
|
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
|
ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &remote_addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
|
||||||
|
|
||||||
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
|
err = netconn_connect(sock->conn, ipX_2_ip(&remote_addr), remote_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
@@ -545,15 +621,13 @@ lwip_listen(int s, int backlog)
|
|||||||
|
|
||||||
int
|
int
|
||||||
lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||||
struct sockaddr *from, socklen_t *fromlen)
|
struct sockaddr *from, socklen_t *fromlen)
|
||||||
{
|
{
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
u16_t buflen, copylen;
|
u16_t buflen, copylen;
|
||||||
int off = 0;
|
int off = 0;
|
||||||
ip_addr_t *addr;
|
|
||||||
u16_t port;
|
|
||||||
u8_t done = 0;
|
u8_t done = 0;
|
||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
@@ -586,7 +660,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
|
|
||||||
/* No data was left from the previous operation, so we try to get
|
/* No data was left from the previous operation, so we try to get
|
||||||
some from the network. */
|
some from the network. */
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
|
err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
|
||||||
} else {
|
} else {
|
||||||
err = netconn_recv(sock->conn, (struct netbuf **)&buf);
|
err = netconn_recv(sock->conn, (struct netbuf **)&buf);
|
||||||
@@ -616,7 +690,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
sock->lastdata = buf;
|
sock->lastdata = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
p = (struct pbuf *)buf;
|
p = (struct pbuf *)buf;
|
||||||
} else {
|
} else {
|
||||||
p = ((struct netbuf *)buf)->p;
|
p = ((struct netbuf *)buf)->p;
|
||||||
@@ -639,7 +713,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
|
|
||||||
off += copylen;
|
off += copylen;
|
||||||
|
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
|
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
|
||||||
len -= copylen;
|
len -= copylen;
|
||||||
if ( (len <= 0) ||
|
if ( (len <= 0) ||
|
||||||
@@ -654,47 +728,32 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
|
|
||||||
/* Check to see from where the data was.*/
|
/* Check to see from where the data was.*/
|
||||||
if (done) {
|
if (done) {
|
||||||
ip_addr_t fromaddr;
|
#if !SOCKETS_DEBUG
|
||||||
if (from && fromlen) {
|
if (from && fromlen)
|
||||||
struct sockaddr_in sin;
|
#endif /* !SOCKETS_DEBUG */
|
||||||
|
{
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
u16_t port;
|
||||||
addr = &fromaddr;
|
ipX_addr_t tmpaddr;
|
||||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
ipX_addr_t *fromaddr;
|
||||||
} else {
|
union sockaddr_aligned saddr;
|
||||||
addr = netbuf_fromaddr((struct netbuf *)buf);
|
|
||||||
port = netbuf_fromport((struct netbuf *)buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&sin, 0, sizeof(sin));
|
|
||||||
sin.sin_len = sizeof(sin);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_port = htons(port);
|
|
||||||
inet_addr_from_ipaddr(&sin.sin_addr, addr);
|
|
||||||
|
|
||||||
if (*fromlen > sizeof(sin)) {
|
|
||||||
*fromlen = sizeof(sin);
|
|
||||||
}
|
|
||||||
|
|
||||||
MEMCPY(from, &sin, *fromlen);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
fromaddr = &tmpaddr;
|
||||||
} else {
|
/* @todo: this does not work for IPv6, yet */
|
||||||
#if SOCKETS_DEBUG
|
netconn_getaddr(sock->conn, ipX_2_ip(fromaddr), &port, 0);
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
|
||||||
addr = &fromaddr;
|
|
||||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
|
||||||
} else {
|
} else {
|
||||||
addr = netbuf_fromaddr((struct netbuf *)buf);
|
|
||||||
port = netbuf_fromport((struct netbuf *)buf);
|
port = netbuf_fromport((struct netbuf *)buf);
|
||||||
|
fromaddr = netbuf_fromaddr_ipX((struct netbuf *)buf);
|
||||||
}
|
}
|
||||||
|
IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)),
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
&saddr, fromaddr, port);
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)),
|
||||||
|
SOCKETS_DEBUG, fromaddr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
||||||
#endif /* SOCKETS_DEBUG */
|
if (*fromlen > saddr.sa.sa_len) {
|
||||||
|
*fromlen = saddr.sa.sa_len;
|
||||||
|
}
|
||||||
|
MEMCPY(from, &saddr, *fromlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,7 +762,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
/* If this is a TCP socket, check if there is data left in the
|
/* If this is a TCP socket, check if there is data left in the
|
||||||
buffer. If so, it should be saved in the sock structure for next
|
buffer. If so, it should be saved in the sock structure for next
|
||||||
time around. */
|
time around. */
|
||||||
if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
|
if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
|
||||||
sock->lastdata = buf;
|
sock->lastdata = buf;
|
||||||
sock->lastoffset += copylen;
|
sock->lastoffset += copylen;
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
|
||||||
@@ -711,7 +770,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
sock->lastdata = NULL;
|
sock->lastdata = NULL;
|
||||||
sock->lastoffset = 0;
|
sock->lastoffset = 0;
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
|
||||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
pbuf_free((struct pbuf *)buf);
|
pbuf_free((struct pbuf *)buf);
|
||||||
} else {
|
} else {
|
||||||
netbuf_delete((struct netbuf *)buf);
|
netbuf_delete((struct netbuf *)buf);
|
||||||
@@ -720,7 +779,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
|
|
||||||
if (off > 0) {
|
if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)) {
|
||||||
/* update receive window */
|
/* update receive window */
|
||||||
netconn_recved(sock->conn, (u32_t)off);
|
netconn_recved(sock->conn, (u32_t)off);
|
||||||
}
|
}
|
||||||
@@ -755,7 +814,7 @@ lwip_send(int s, const void *data, size_t size, int flags)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->conn->type != NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
#if (LWIP_UDP || LWIP_RAW)
|
||||||
return lwip_sendto(s, data, size, flags, NULL, 0);
|
return lwip_sendto(s, data, size, flags, NULL, 0);
|
||||||
#else /* (LWIP_UDP || LWIP_RAW) */
|
#else /* (LWIP_UDP || LWIP_RAW) */
|
||||||
@@ -789,7 +848,6 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
err_t err;
|
err_t err;
|
||||||
u16_t short_size;
|
u16_t short_size;
|
||||||
const struct sockaddr_in *to_in;
|
|
||||||
u16_t remote_port;
|
u16_t remote_port;
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
#if !LWIP_TCPIP_CORE_LOCKING
|
||||||
struct netbuf buf;
|
struct netbuf buf;
|
||||||
@@ -800,36 +858,45 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->conn->type == NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
return lwip_send(s, data, size, flags);
|
return lwip_send(s, data, size, flags);
|
||||||
#else /* LWIP_TCP */
|
#else /* LWIP_TCP */
|
||||||
|
LWIP_UNUSED_ARG(flags);
|
||||||
sock_set_errno(sock, err_to_errno(ERR_ARG));
|
sock_set_errno(sock, err_to_errno(ERR_ARG));
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
|
||||||
|
/* sockaddr does not match socket type (IPv4/IPv6) */
|
||||||
|
sock_set_errno(sock, err_to_errno(ERR_VAL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* @todo: split into multiple sendto's? */
|
/* @todo: split into multiple sendto's? */
|
||||||
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
|
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
|
||||||
short_size = (u16_t)size;
|
short_size = (u16_t)size;
|
||||||
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
|
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
|
||||||
((tolen == sizeof(struct sockaddr_in)) &&
|
(IS_SOCK_ADDR_LEN_VALID(tolen) &&
|
||||||
((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
|
IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
|
||||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||||
to_in = (const struct sockaddr_in *)(void*)to;
|
LWIP_UNUSED_ARG(tolen);
|
||||||
|
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
/* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
|
/* Special speedup for fast UDP/RAW sending: call the raw API directly
|
||||||
|
instead of using the netconn functions. */
|
||||||
{
|
{
|
||||||
struct pbuf* p;
|
struct pbuf* p;
|
||||||
ip_addr_t *remote_addr;
|
ipX_addr_t *remote_addr;
|
||||||
|
ipX_addr_t remote_addr_tmp;
|
||||||
|
|
||||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
|
p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
u16_t chksum = 0;
|
u16_t chksum = 0;
|
||||||
if (sock->conn->type != NETCONN_RAW) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
|
||||||
chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
|
chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
@@ -840,25 +907,34 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
p->payload = (void*)data;
|
p->payload = (void*)data;
|
||||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
if (to_in != NULL) {
|
if (to != NULL) {
|
||||||
inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
|
SOCKADDR_TO_IPXADDR_PORT(to->sa_family == AF_INET6,
|
||||||
remote_port = ntohs(to_in->sin_port);
|
to, &remote_addr_tmp, remote_port);
|
||||||
|
remote_addr = &remote_addr_tmp;
|
||||||
} else {
|
} else {
|
||||||
remote_addr = IP_ADDR_ANY;
|
remote_addr = &sock->conn->pcb.raw->remote_ip;
|
||||||
remote_port = 0;
|
if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_RAW) {
|
||||||
|
remote_port = 0;
|
||||||
|
} else {
|
||||||
|
remote_port = sock->conn->pcb.udp->remote_port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_TCPIP_CORE();
|
LOCK_TCPIP_CORE();
|
||||||
if (sock->conn->type == NETCONN_RAW) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_RAW) {
|
||||||
err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
|
err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, ipX_2_ip(remote_addr));
|
||||||
} else {
|
} else {
|
||||||
|
#if LWIP_UDP
|
||||||
#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
|
#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
|
err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
|
||||||
remote_addr, remote_port, 1, chksum);
|
ipX_2_ip(remote_addr), remote_port, 1, chksum);
|
||||||
#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
|
#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
|
err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
|
||||||
remote_addr, remote_port);
|
ipX_2_ip(remote_addr), remote_port);
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
#else /* LWIP_UDP */
|
||||||
|
err = ERR_ARG;
|
||||||
|
#endif /* LWIP_UDP */
|
||||||
}
|
}
|
||||||
UNLOCK_TCPIP_CORE();
|
UNLOCK_TCPIP_CORE();
|
||||||
|
|
||||||
@@ -874,18 +950,18 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
buf.flags = 0;
|
buf.flags = 0;
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
if (to) {
|
if (to) {
|
||||||
inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
|
SOCKADDR_TO_IPXADDR_PORT((to->sa_family) == AF_INET6, to, &buf.addr, remote_port);
|
||||||
remote_port = ntohs(to_in->sin_port);
|
|
||||||
netbuf_fromport(&buf) = remote_port;
|
|
||||||
} else {
|
} else {
|
||||||
remote_port = 0;
|
remote_port = 0;
|
||||||
ip_addr_set_any(&buf.addr);
|
ipX_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
|
||||||
netbuf_fromport(&buf) = 0;
|
|
||||||
}
|
}
|
||||||
|
netbuf_fromport(&buf) = remote_port;
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
|
|
||||||
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
|
||||||
s, data, short_size, flags));
|
s, data, short_size, flags));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
|
ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)),
|
||||||
|
SOCKETS_DEBUG, &buf.addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
||||||
|
|
||||||
/* make the buffer point to the data that should be sent */
|
/* make the buffer point to the data that should be sent */
|
||||||
@@ -895,7 +971,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
err = ERR_MEM;
|
err = ERR_MEM;
|
||||||
} else {
|
} else {
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
if (sock->conn->type != NETCONN_RAW) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
|
||||||
u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
|
u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
|
||||||
netbuf_set_chksum(&buf, chksum);
|
netbuf_set_chksum(&buf, chksum);
|
||||||
err = ERR_OK;
|
err = ERR_OK;
|
||||||
@@ -926,23 +1002,27 @@ lwip_socket(int domain, int type, int protocol)
|
|||||||
struct netconn *conn;
|
struct netconn *conn;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(domain);
|
#if !LWIP_IPV6
|
||||||
|
LWIP_UNUSED_ARG(domain); /* @todo: check this */
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/* create a netconn */
|
/* create a netconn */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SOCK_RAW:
|
case SOCK_RAW:
|
||||||
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
|
conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
|
||||||
|
(u8_t)protocol, event_callback);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
|
||||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||||
break;
|
break;
|
||||||
case SOCK_DGRAM:
|
case SOCK_DGRAM:
|
||||||
conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
|
conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
|
||||||
NETCONN_UDPLITE : NETCONN_UDP, event_callback);
|
((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
|
||||||
|
event_callback);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
|
||||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||||
break;
|
break;
|
||||||
case SOCK_STREAM:
|
case SOCK_STREAM:
|
||||||
conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
|
conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
|
||||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||||
if (conn != NULL) {
|
if (conn != NULL) {
|
||||||
@@ -1181,6 +1261,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
|||||||
LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
|
LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
|
||||||
select_cb.prev->next = select_cb.next;
|
select_cb.prev->next = select_cb.next;
|
||||||
}
|
}
|
||||||
|
/* Increasing this counter tells even_callback that the list has changed. */
|
||||||
|
select_cb_ctr++;
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
|
|
||||||
sys_sem_free(&select_cb.sem);
|
sys_sem_free(&select_cb.sem);
|
||||||
@@ -1208,8 +1290,6 @@ return_copy_fdsets:
|
|||||||
if (exceptset) {
|
if (exceptset) {
|
||||||
*exceptset = lexceptset;
|
*exceptset = lexceptset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return nready;
|
return nready;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,6 +1303,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
|||||||
int s;
|
int s;
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
struct lwip_select_cb *scb;
|
struct lwip_select_cb *scb;
|
||||||
|
int last_select_cb_ctr;
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
SYS_ARCH_DECL_PROTECT(lev);
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(len);
|
LWIP_UNUSED_ARG(len);
|
||||||
@@ -1285,56 +1366,51 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
|
|
||||||
/* Now decide if anyone is waiting for this socket */
|
/* Now decide if anyone is waiting for this socket */
|
||||||
/* NOTE: This code is written this way to protect the select link list
|
/* NOTE: This code goes through the select_cb_list list multiple times
|
||||||
but to avoid a deadlock situation by releasing select_lock before
|
ONLY IF a select was actually waiting. We go through the list the number
|
||||||
signalling for the select. This means we need to go through the list
|
of waiting select calls + 1. This list is expected to be small. */
|
||||||
multiple times ONLY IF a select was actually waiting. We go through
|
|
||||||
the list the number of waiting select calls + 1. This list is
|
/* At this point, SYS_ARCH is still protected! */
|
||||||
expected to be small. */
|
again:
|
||||||
while (1) {
|
for (scb = select_cb_list; scb != NULL; scb = scb->next) {
|
||||||
int last_select_cb_ctr;
|
if (scb->sem_signalled == 0) {
|
||||||
SYS_ARCH_PROTECT(lev);
|
/* semaphore not signalled yet */
|
||||||
for (scb = select_cb_list; scb; scb = scb->next) {
|
int do_signal = 0;
|
||||||
/* @todo: unprotect with each loop and check for changes? */
|
/* Test this select call for our socket */
|
||||||
if (scb->sem_signalled == 0) {
|
if (sock->rcvevent > 0) {
|
||||||
/* Test this select call for our socket */
|
|
||||||
if (scb->readset && FD_ISSET(s, scb->readset)) {
|
if (scb->readset && FD_ISSET(s, scb->readset)) {
|
||||||
if (sock->rcvevent > 0) {
|
do_signal = 1;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (scb->writeset && FD_ISSET(s, scb->writeset)) {
|
|
||||||
if (sock->sendevent != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (scb->exceptset && FD_ISSET(s, scb->exceptset)) {
|
|
||||||
if (sock->errevent != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* unlock interrupts with each step */
|
if (sock->sendevent != 0) {
|
||||||
last_select_cb_ctr = select_cb_ctr;
|
if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
do_signal = 1;
|
||||||
SYS_ARCH_PROTECT(lev);
|
}
|
||||||
if (last_select_cb_ctr != select_cb_ctr) {
|
}
|
||||||
/* someone has changed select_cb_list, restart at the beginning */
|
if (sock->errevent != 0) {
|
||||||
scb = select_cb_list;
|
if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
|
||||||
|
do_signal = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (do_signal) {
|
||||||
|
scb->sem_signalled = 1;
|
||||||
|
/* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
|
||||||
|
lead to the select thread taking itself off the list, invalidagin the semaphore. */
|
||||||
|
sys_sem_signal(&scb->sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scb) {
|
/* unlock interrupts with each step */
|
||||||
scb->sem_signalled = 1;
|
last_select_cb_ctr = select_cb_ctr;
|
||||||
sys_sem_signal(&scb->sem);
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
/* this makes sure interrupt protection time is short */
|
||||||
} else {
|
SYS_ARCH_PROTECT(lev);
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
if (last_select_cb_ctr != select_cb_ctr) {
|
||||||
break;
|
/* someone has changed select_cb_list, restart at the beginning */
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1356,7 +1432,7 @@ lwip_shutdown(int s, int how)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sock->conn != NULL) {
|
if (sock->conn != NULL) {
|
||||||
if (netconn_type(sock->conn) != NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||||
sock_set_errno(sock, EOPNOTSUPP);
|
sock_set_errno(sock, EOPNOTSUPP);
|
||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
@@ -1386,33 +1462,31 @@ static int
|
|||||||
lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
||||||
{
|
{
|
||||||
struct lwip_sock *sock;
|
struct lwip_sock *sock;
|
||||||
struct sockaddr_in sin;
|
union sockaddr_aligned saddr;
|
||||||
ip_addr_t naddr;
|
ipX_addr_t naddr;
|
||||||
|
u16_t port;
|
||||||
|
|
||||||
sock = get_socket(s);
|
sock = get_socket(s);
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sin, 0, sizeof(sin));
|
|
||||||
sin.sin_len = sizeof(sin);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
|
|
||||||
/* get the IP address and port */
|
/* get the IP address and port */
|
||||||
netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
|
/* @todo: this does not work for IPv6, yet */
|
||||||
|
netconn_getaddr(sock->conn, ipX_2_ip(&naddr), &port, local);
|
||||||
|
IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)),
|
||||||
|
&saddr, &naddr, port);
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)),
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
|
SOCKETS_DEBUG, &naddr);
|
||||||
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port));
|
||||||
|
|
||||||
sin.sin_port = htons(sin.sin_port);
|
if (*namelen > saddr.sa.sa_len) {
|
||||||
inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
|
*namelen = saddr.sa.sa_len;
|
||||||
|
|
||||||
if (*namelen > sizeof(sin)) {
|
|
||||||
*namelen = sizeof(sin);
|
|
||||||
}
|
}
|
||||||
|
MEMCPY(name, &saddr, *namelen);
|
||||||
|
|
||||||
MEMCPY(name, &sin, *namelen);
|
|
||||||
sock_set_errno(sock, 0);
|
sock_set_errno(sock, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1486,7 +1560,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
if ((sock->conn->type != NETCONN_UDP) ||
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP ||
|
||||||
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
||||||
/* this flag is only available for UDP, not for UDP lite */
|
/* this flag is only available for UDP, not for UDP lite */
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
@@ -1528,7 +1602,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||||||
if (*optlen < sizeof(u8_t)) {
|
if (*optlen < sizeof(u8_t)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1550,7 +1624,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If this is no TCP socket, ignore any options. */
|
/* If this is no TCP socket, ignore any options. */
|
||||||
if (sock->conn->type != NETCONN_TCP)
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
@@ -1579,7 +1653,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If this is no UDP lite socket, ignore any options. */
|
/* If this is no UDP lite socket, ignore any options. */
|
||||||
if (sock->conn->type != NETCONN_UDPLITE) {
|
if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1610,6 +1684,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
|||||||
|
|
||||||
/* Now do the actual option processing */
|
/* Now do the actual option processing */
|
||||||
data.sock = sock;
|
data.sock = sock;
|
||||||
|
#ifdef LWIP_DEBUG
|
||||||
|
data.s = s;
|
||||||
|
#endif /* LWIP_DEBUG */
|
||||||
data.level = level;
|
data.level = level;
|
||||||
data.optname = optname;
|
data.optname = optname;
|
||||||
data.optval = optval;
|
data.optval = optval;
|
||||||
@@ -1670,7 +1747,7 @@ lwip_getsockopt_internal(void *arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_TYPE:
|
case SO_TYPE:
|
||||||
switch (NETCONNTYPE_GROUP(sock->conn->type)) {
|
switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
|
||||||
case NETCONN_RAW:
|
case NETCONN_RAW:
|
||||||
*(int*)optval = SOCK_RAW;
|
*(int*)optval = SOCK_RAW;
|
||||||
break;
|
break;
|
||||||
@@ -1681,18 +1758,18 @@ lwip_getsockopt_internal(void *arg)
|
|||||||
*(int*)optval = SOCK_DGRAM;
|
*(int*)optval = SOCK_DGRAM;
|
||||||
break;
|
break;
|
||||||
default: /* unrecognized socket type */
|
default: /* unrecognized socket type */
|
||||||
*(int*)optval = sock->conn->type;
|
*(int*)optval = netconn_type(sock->conn);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG,
|
LWIP_DEBUGF(SOCKETS_DEBUG,
|
||||||
("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
|
("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
|
||||||
s, *(int *)optval));
|
s, *(int *)optval));
|
||||||
} /* switch (sock->conn->type) */
|
} /* switch (netconn_type(sock->conn)) */
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
|
||||||
s, *(int *)optval));
|
s, *(int *)optval));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_ERROR:
|
case SO_ERROR:
|
||||||
/* only overwrite if ERR_OK before */
|
/* only overwrite ERR_OK or tempoary errors */
|
||||||
if (sock->err == 0) {
|
if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
|
||||||
sock_set_errno(sock, err_to_errno(sock->conn->last_err));
|
sock_set_errno(sock, err_to_errno(sock->conn->last_err));
|
||||||
}
|
}
|
||||||
*(int *)optval = sock->err;
|
*(int *)optval = sock->err;
|
||||||
@@ -1880,7 +1957,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
if ((sock->conn->type != NETCONN_UDP) ||
|
if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) ||
|
||||||
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
||||||
/* this flag is only available for UDP, not for UDP lite */
|
/* this flag is only available for UDP, not for UDP lite */
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
@@ -1911,7 +1988,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
if (optlen < sizeof(u8_t)) {
|
if (optlen < sizeof(u8_t)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1919,7 +1996,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
if (optlen < sizeof(struct in_addr)) {
|
if (optlen < sizeof(struct in_addr)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1927,7 +2004,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
if (optlen < sizeof(u8_t)) {
|
if (optlen < sizeof(u8_t)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1936,7 +2013,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
if (optlen < sizeof(struct ip_mreq)) {
|
if (optlen < sizeof(struct ip_mreq)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
}
|
}
|
||||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
err = EAFNOSUPPORT;
|
err = EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1957,7 +2034,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If this is no TCP socket, ignore any options. */
|
/* If this is no TCP socket, ignore any options. */
|
||||||
if (sock->conn->type != NETCONN_TCP)
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
@@ -1986,7 +2063,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If this is no UDP lite socket, ignore any options. */
|
/* If this is no UDP lite socket, ignore any options. */
|
||||||
if (sock->conn->type != NETCONN_UDPLITE)
|
if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
@@ -2017,6 +2094,9 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
|||||||
|
|
||||||
/* Now do the actual option processing */
|
/* Now do the actual option processing */
|
||||||
data.sock = sock;
|
data.sock = sock;
|
||||||
|
#ifdef LWIP_DEBUG
|
||||||
|
data.s = s;
|
||||||
|
#endif /* LWIP_DEBUG */
|
||||||
data.level = level;
|
data.level = level;
|
||||||
data.optname = optname;
|
data.optname = optname;
|
||||||
data.optval = (void*)optval;
|
data.optval = (void*)optval;
|
||||||
@@ -2239,15 +2319,18 @@ int
|
|||||||
lwip_ioctl(int s, long cmd, void *argp)
|
lwip_ioctl(int s, long cmd, void *argp)
|
||||||
{
|
{
|
||||||
struct lwip_sock *sock = get_socket(s);
|
struct lwip_sock *sock = get_socket(s);
|
||||||
|
u8_t val;
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
u16_t buflen = 0;
|
u16_t buflen = 0;
|
||||||
s16_t recv_avail;
|
s16_t recv_avail;
|
||||||
u8_t val;
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
#if LWIP_SO_RCVBUF
|
||||||
case FIONREAD:
|
case FIONREAD:
|
||||||
if (!argp) {
|
if (!argp) {
|
||||||
sock_set_errno(sock, EINVAL);
|
sock_set_errno(sock, EINVAL);
|
||||||
@@ -2263,7 +2346,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
|||||||
/* Check if there is data left from the last recv operation. /maq 041215 */
|
/* Check if there is data left from the last recv operation. /maq 041215 */
|
||||||
if (sock->lastdata) {
|
if (sock->lastdata) {
|
||||||
struct pbuf *p = (struct pbuf *)sock->lastdata;
|
struct pbuf *p = (struct pbuf *)sock->lastdata;
|
||||||
if (netconn_type(sock->conn) != NETCONN_TCP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||||
p = ((struct netbuf *)p)->p;
|
p = ((struct netbuf *)p)->p;
|
||||||
}
|
}
|
||||||
buflen = p->tot_len;
|
buflen = p->tot_len;
|
||||||
@@ -2275,6 +2358,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
|||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
|
||||||
sock_set_errno(sock, 0);
|
sock_set_errno(sock, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
|
|
||||||
case FIONBIO:
|
case FIONBIO:
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|||||||
@@ -103,6 +103,11 @@ tcpip_thread(void *arg)
|
|||||||
ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
|
ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_ETHERNET */
|
#endif /* LWIP_ETHERNET */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if ((*((unsigned char *)(msg->msg.inp.p->payload)) & 0xf0) == 0x60) {
|
||||||
|
ip6_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
{
|
{
|
||||||
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||||
}
|
}
|
||||||
@@ -117,12 +122,6 @@ tcpip_thread(void *arg)
|
|||||||
break;
|
break;
|
||||||
#endif /* LWIP_NETIF_API */
|
#endif /* LWIP_NETIF_API */
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#if LWIP_TCPIP_TIMEOUT
|
#if LWIP_TCPIP_TIMEOUT
|
||||||
case TCPIP_MSG_TIMEOUT:
|
case TCPIP_MSG_TIMEOUT:
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
|
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
|
||||||
@@ -136,6 +135,17 @@ tcpip_thread(void *arg)
|
|||||||
break;
|
break;
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||||
|
|
||||||
|
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:
|
default:
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
|
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
|
||||||
LWIP_ASSERT("tcpip_thread: invalid message", 0);
|
LWIP_ASSERT("tcpip_thread: invalid message", 0);
|
||||||
@@ -172,22 +182,22 @@ tcpip_input(struct pbuf *p, struct netif *inp)
|
|||||||
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||||
struct tcpip_msg *msg;
|
struct tcpip_msg *msg;
|
||||||
|
|
||||||
if (sys_mbox_valid(&mbox)) {
|
if (!sys_mbox_valid(&mbox)) {
|
||||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
|
return ERR_VAL;
|
||||||
if (msg == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->type = TCPIP_MSG_INPKT;
|
|
||||||
msg->msg.inp.p = p;
|
|
||||||
msg->msg.inp.netif = inp;
|
|
||||||
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
|
|
||||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
}
|
||||||
return ERR_VAL;
|
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;
|
||||||
|
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 */
|
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,6 +402,52 @@ tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
|
|||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
||||||
#endif /* LWIP_NETIF_API */
|
#endif /* LWIP_NETIF_API */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
memp_free(MEMP_TCPIP_MSG_API, 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)
|
||||||
|
{
|
||||||
|
if (!sys_mbox_valid(&mbox)) {
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
return sys_mbox_trypost(&mbox, msg);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this module:
|
* Initialize this module:
|
||||||
* - initialize all sub modules
|
* - initialize all sub modules
|
||||||
|
|||||||
@@ -76,7 +76,6 @@
|
|||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
#include "lwip/autoip.h"
|
#include "lwip/autoip.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
@@ -115,7 +114,7 @@
|
|||||||
#define DHCP_OPTION_IDX_T2 5
|
#define DHCP_OPTION_IDX_T2 5
|
||||||
#define DHCP_OPTION_IDX_SUBNET_MASK 6
|
#define DHCP_OPTION_IDX_SUBNET_MASK 6
|
||||||
#define DHCP_OPTION_IDX_ROUTER 7
|
#define DHCP_OPTION_IDX_ROUTER 7
|
||||||
#define DHCP_OPTION_IDX_DNS_SERVER 8
|
#define DHCP_OPTION_IDX_DNS_SERVER 8
|
||||||
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
||||||
|
|
||||||
/** Holds the decoded option values, only valid while in dhcp_recv.
|
/** Holds the decoded option values, only valid while in dhcp_recv.
|
||||||
@@ -126,6 +125,11 @@ u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
|
|||||||
@todo: move this into struct dhcp? */
|
@todo: move this into struct dhcp? */
|
||||||
u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
|
u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
|
||||||
|
|
||||||
|
#ifdef DHCP_GLOBAL_XID
|
||||||
|
static u32_t xid;
|
||||||
|
static u8_t xid_initialised;
|
||||||
|
#endif /* DHCP_GLOBAL_XID */
|
||||||
|
|
||||||
#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
|
#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
|
||||||
#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
|
#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
|
||||||
#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
|
#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
|
||||||
@@ -592,6 +596,23 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
|
|||||||
netif->dhcp = dhcp;
|
netif->dhcp = dhcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Removes a struct dhcp from a netif.
|
||||||
|
*
|
||||||
|
* ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
|
||||||
|
* struct dhcp since the memory is passed back to the heap.
|
||||||
|
*
|
||||||
|
* @param netif the netif from which to remove the struct dhcp
|
||||||
|
*/
|
||||||
|
void dhcp_cleanup(struct netif *netif)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
|
|
||||||
|
if (netif->dhcp != NULL) {
|
||||||
|
mem_free(netif->dhcp);
|
||||||
|
netif->dhcp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start DHCP negotiation for a network interface.
|
* Start DHCP negotiation for a network interface.
|
||||||
*
|
*
|
||||||
@@ -762,7 +783,10 @@ dhcp_network_changed(struct netif *netif)
|
|||||||
default:
|
default:
|
||||||
dhcp->tries = 0;
|
dhcp->tries = 0;
|
||||||
#if LWIP_DHCP_AUTOIP_COOP
|
#if LWIP_DHCP_AUTOIP_COOP
|
||||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
|
||||||
|
autoip_stop(netif);
|
||||||
|
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
||||||
|
}
|
||||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||||
dhcp_discover(netif);
|
dhcp_discover(netif);
|
||||||
break;
|
break;
|
||||||
@@ -945,11 +969,11 @@ dhcp_bind(struct netif *netif)
|
|||||||
/* subnet mask not given, choose a safe subnet mask given the network class */
|
/* subnet mask not given, choose a safe subnet mask given the network class */
|
||||||
u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
|
u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
|
||||||
if (first_octet <= 127) {
|
if (first_octet <= 127) {
|
||||||
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000));
|
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
|
||||||
} else if (first_octet >= 192) {
|
} else if (first_octet >= 192) {
|
||||||
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00));
|
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
|
||||||
} else {
|
} else {
|
||||||
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000));
|
ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -959,7 +983,7 @@ dhcp_bind(struct netif *netif)
|
|||||||
/* copy network address */
|
/* copy network address */
|
||||||
ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
|
ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
|
||||||
/* use first host address on network as gateway */
|
/* use first host address on network as gateway */
|
||||||
ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001));
|
ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_DHCP_AUTOIP_COOP
|
#if LWIP_DHCP_AUTOIP_COOP
|
||||||
@@ -1608,8 +1632,6 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||||||
* at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
|
* at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
|
||||||
static u32_t xid = 0xABCD0000;
|
static u32_t xid = 0xABCD0000;
|
||||||
#else
|
#else
|
||||||
static u32_t xid;
|
|
||||||
static u8_t xid_initialised = 0;
|
|
||||||
if (!xid_initialised) {
|
if (!xid_initialised) {
|
||||||
xid = DHCP_GLOBAL_XID;
|
xid = DHCP_GLOBAL_XID;
|
||||||
xid_initialised = !xid_initialised;
|
xid_initialised = !xid_initialised;
|
||||||
|
|||||||
@@ -922,6 +922,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
|||||||
* name is already in the local names table.
|
* name is already in the local names table.
|
||||||
* - ERR_INPROGRESS enqueue a request to be sent to the DNS server
|
* - ERR_INPROGRESS enqueue a request to be sent to the DNS server
|
||||||
* for resolution if no errors are present.
|
* for resolution if no errors are present.
|
||||||
|
* - ERR_ARG: dns client not initialized or invalid hostname
|
||||||
*
|
*
|
||||||
* @param hostname the hostname that is to be queried
|
* @param hostname the hostname that is to be queried
|
||||||
* @param addr pointer to a ip_addr_t where to store the address if it is already
|
* @param addr pointer to a ip_addr_t where to store the address if it is already
|
||||||
@@ -941,7 +942,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
|
|||||||
if ((dns_pcb == NULL) || (addr == NULL) ||
|
if ((dns_pcb == NULL) || (addr == NULL) ||
|
||||||
(!hostname) || (!hostname[0]) ||
|
(!hostname) || (!hostname[0]) ||
|
||||||
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
|
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
|
||||||
return ERR_VAL;
|
return ERR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_HAVE_LOOPIF
|
#if LWIP_HAVE_LOOPIF
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
# ifndef LWIP_CHKSUM_ALGORITHM
|
# ifndef LWIP_CHKSUM_ALGORITHM
|
||||||
# define LWIP_CHKSUM_ALGORITHM 2
|
# define LWIP_CHKSUM_ALGORITHM 2
|
||||||
# endif
|
# endif
|
||||||
|
u16_t lwip_standard_chksum(void *dataptr, int len);
|
||||||
#endif
|
#endif
|
||||||
/* If none set: */
|
/* If none set: */
|
||||||
#ifndef LWIP_CHKSUM_ALGORITHM
|
#ifndef LWIP_CHKSUM_ALGORITHM
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
* @note accumulator size limits summable length to 64k
|
* @note accumulator size limits summable length to 64k
|
||||||
* @note host endianess is irrelevant (p3 RFC1071)
|
* @note host endianess is irrelevant (p3 RFC1071)
|
||||||
*/
|
*/
|
||||||
static u16_t
|
u16_t
|
||||||
lwip_standard_chksum(void *dataptr, u16_t len)
|
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
@@ -131,7 +132,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
|||||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u16_t
|
u16_t
|
||||||
lwip_standard_chksum(void *dataptr, int len)
|
lwip_standard_chksum(void *dataptr, int len)
|
||||||
{
|
{
|
||||||
u8_t *pb = (u8_t *)dataptr;
|
u8_t *pb = (u8_t *)dataptr;
|
||||||
@@ -187,7 +188,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
|||||||
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u16_t
|
u16_t
|
||||||
lwip_standard_chksum(void *dataptr, int len)
|
lwip_standard_chksum(void *dataptr, int len)
|
||||||
{
|
{
|
||||||
u8_t *pb = (u8_t *)dataptr;
|
u8_t *pb = (u8_t *)dataptr;
|
||||||
@@ -256,30 +257,13 @@ lwip_standard_chksum(void *dataptr, int len)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* inet_chksum_pseudo:
|
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
||||||
*
|
static u16_t
|
||||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
|
||||||
* IP addresses are expected to be in network byte order.
|
|
||||||
*
|
|
||||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
|
||||||
* @param src source ip address (used for checksum of pseudo header)
|
|
||||||
* @param dst destination ip address (used for checksum of pseudo header)
|
|
||||||
* @param proto ip protocol (used for checksum of pseudo header)
|
|
||||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
|
||||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
|
||||||
*/
|
|
||||||
u16_t
|
|
||||||
inet_chksum_pseudo(struct pbuf *p,
|
|
||||||
ip_addr_t *src, ip_addr_t *dest,
|
|
||||||
u8_t proto, u16_t proto_len)
|
|
||||||
{
|
{
|
||||||
u32_t acc;
|
|
||||||
u32_t addr;
|
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
u8_t swapped;
|
u8_t swapped = 0;
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
swapped = 0;
|
|
||||||
/* iterate through all pbuf in chain */
|
/* iterate through all pbuf in chain */
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||||
@@ -299,12 +283,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
if (swapped) {
|
if (swapped) {
|
||||||
acc = SWAP_BYTES_IN_WORD(acc);
|
acc = SWAP_BYTES_IN_WORD(acc);
|
||||||
}
|
}
|
||||||
addr = ip4_addr_get_u32(src);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = ip4_addr_get_u32(dest);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
acc += (u32_t)htons((u16_t)proto);
|
acc += (u32_t)htons((u16_t)proto);
|
||||||
acc += (u32_t)htons(proto_len);
|
acc += (u32_t)htons(proto_len);
|
||||||
|
|
||||||
@@ -329,18 +308,69 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||||
*/
|
*/
|
||||||
u16_t
|
u16_t
|
||||||
inet_chksum_pseudo_partial(struct pbuf *p,
|
inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
ip_addr_t *src, ip_addr_t *dest,
|
ip_addr_t *src, ip_addr_t *dest)
|
||||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
|
||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
u32_t addr;
|
u32_t addr;
|
||||||
|
|
||||||
|
addr = ip4_addr_get_u32(src);
|
||||||
|
acc = (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
addr = ip4_addr_get_u32(dest);
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
/* fold down to 16 bits */
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
|
||||||
|
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
||||||
|
}
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||||
|
* IPv6 addresses are expected to be in network byte order.
|
||||||
|
*
|
||||||
|
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||||
|
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||||
|
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||||
|
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||||
|
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||||
|
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||||
|
*/
|
||||||
|
u16_t
|
||||||
|
ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
ip6_addr_t *src, ip6_addr_t *dest)
|
||||||
|
{
|
||||||
|
u32_t acc = 0;
|
||||||
|
u32_t addr;
|
||||||
|
u8_t addr_part;
|
||||||
|
|
||||||
|
for (addr_part = 0; addr_part < 4; addr_part++) {
|
||||||
|
addr = src->addr[addr_part];
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
addr = dest->addr[addr_part];
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
}
|
||||||
|
/* fold down to 16 bits */
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
|
||||||
|
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
|
||||||
|
static u16_t
|
||||||
|
inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
u16_t chksum_len, u32_t acc)
|
||||||
|
{
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
u8_t swapped;
|
u8_t swapped = 0;
|
||||||
u16_t chklen;
|
u16_t chklen;
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
swapped = 0;
|
|
||||||
/* iterate through all pbuf in chain */
|
/* iterate through all pbuf in chain */
|
||||||
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||||
@@ -365,12 +395,7 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
|||||||
if (swapped) {
|
if (swapped) {
|
||||||
acc = SWAP_BYTES_IN_WORD(acc);
|
acc = SWAP_BYTES_IN_WORD(acc);
|
||||||
}
|
}
|
||||||
addr = ip4_addr_get_u32(src);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
addr = ip4_addr_get_u32(dest);
|
|
||||||
acc += (addr & 0xffffUL);
|
|
||||||
acc += ((addr >> 16) & 0xffffUL);
|
|
||||||
acc += (u32_t)htons((u16_t)proto);
|
acc += (u32_t)htons((u16_t)proto);
|
||||||
acc += (u32_t)htons(proto_len);
|
acc += (u32_t)htons(proto_len);
|
||||||
|
|
||||||
@@ -382,6 +407,76 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
|||||||
return (u16_t)~(acc & 0xffffUL);
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* inet_chksum_pseudo_partial:
|
||||||
|
*
|
||||||
|
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||||
|
* IP addresses are expected to be in network byte order.
|
||||||
|
*
|
||||||
|
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||||
|
* @param src source ip address (used for checksum of pseudo header)
|
||||||
|
* @param dst destination ip address (used for checksum of pseudo header)
|
||||||
|
* @param proto ip protocol (used for checksum of pseudo header)
|
||||||
|
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||||
|
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||||
|
*/
|
||||||
|
u16_t
|
||||||
|
inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest)
|
||||||
|
{
|
||||||
|
u32_t acc;
|
||||||
|
u32_t addr;
|
||||||
|
|
||||||
|
addr = ip4_addr_get_u32(src);
|
||||||
|
acc = (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
addr = ip4_addr_get_u32(dest);
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
/* fold down to 16 bits */
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
|
||||||
|
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||||
|
* IPv6 addresses are expected to be in network byte order. Will only compute for a
|
||||||
|
* portion of the payload.
|
||||||
|
*
|
||||||
|
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||||
|
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||||
|
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||||
|
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||||
|
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||||
|
* @param chksum_len number of payload bytes used to compute chksum
|
||||||
|
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||||
|
*/
|
||||||
|
u16_t
|
||||||
|
ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest)
|
||||||
|
{
|
||||||
|
u32_t acc = 0;
|
||||||
|
u32_t addr;
|
||||||
|
u8_t addr_part;
|
||||||
|
|
||||||
|
for (addr_part = 0; addr_part < 4; addr_part++) {
|
||||||
|
addr = src->addr[addr_part];
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
addr = dest->addr[addr_part];
|
||||||
|
acc += (addr & 0xffffUL);
|
||||||
|
acc += ((addr >> 16) & 0xffffUL);
|
||||||
|
}
|
||||||
|
/* fold down to 16 bits */
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
acc = FOLD_U32T(acc);
|
||||||
|
|
||||||
|
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/* inet_chksum:
|
/* inet_chksum:
|
||||||
*
|
*
|
||||||
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
||||||
@@ -56,6 +56,9 @@
|
|||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#include "lwip/timers.h"
|
#include "lwip/timers.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
|
||||||
/* Compile-time sanity checks for configuration errors.
|
/* Compile-time sanity checks for configuration errors.
|
||||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||||
@@ -105,6 +108,9 @@
|
|||||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
||||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
|
||||||
|
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
||||||
|
#endif
|
||||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
||||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -172,8 +178,8 @@
|
|||||||
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
||||||
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_IGMP && !defined(LWIP_RAND)
|
#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
|
||||||
#error "When using IGMP, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
|
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
||||||
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
||||||
@@ -296,6 +302,13 @@ lwip_init(void)
|
|||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
dns_init();
|
dns_init();
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
ip6_init();
|
||||||
|
nd6_init();
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
mld6_init();
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#if LWIP_TIMERS
|
#if LWIP_TIMERS
|
||||||
sys_timeouts_init();
|
sys_timeouts_init();
|
||||||
|
|||||||
@@ -122,14 +122,6 @@ static err_t autoip_bind(struct netif *netif);
|
|||||||
/* start sending probes for llipaddr */
|
/* start sending probes for llipaddr */
|
||||||
static void autoip_start_probing(struct netif *netif);
|
static void autoip_start_probing(struct netif *netif);
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this module
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
autoip_init(void)
|
|
||||||
{
|
|
||||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set a statically allocated struct autoip to work with.
|
/** Set a statically allocated struct autoip to work with.
|
||||||
* Using this prevents autoip_start to allocate it using mem_malloc.
|
* Using this prevents autoip_start to allocate it using mem_malloc.
|
||||||
@@ -170,8 +162,8 @@ autoip_handle_arp_conflict(struct netif *netif)
|
|||||||
/* Somehow detect if we are defending or retreating */
|
/* Somehow detect if we are defending or retreating */
|
||||||
unsigned char defend = 1; /* tbd */
|
unsigned char defend = 1; /* tbd */
|
||||||
|
|
||||||
if(defend) {
|
if (defend) {
|
||||||
if(netif->autoip->lastconflict > 0) {
|
if (netif->autoip->lastconflict > 0) {
|
||||||
/* retreat, there was a conflicting ARP in the last
|
/* retreat, there was a conflicting ARP in the last
|
||||||
* DEFEND_INTERVAL seconds
|
* DEFEND_INTERVAL seconds
|
||||||
*/
|
*/
|
||||||
@@ -295,7 +287,7 @@ autoip_start(struct netif *netif)
|
|||||||
struct autoip *autoip = netif->autoip;
|
struct autoip *autoip = netif->autoip;
|
||||||
err_t result = ERR_OK;
|
err_t result = ERR_OK;
|
||||||
|
|
||||||
if(netif_is_up(netif)) {
|
if (netif_is_up(netif)) {
|
||||||
netif_set_down(netif);
|
netif_set_down(netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,12 +301,12 @@ autoip_start(struct netif *netif)
|
|||||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||||
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
|
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
|
||||||
netif->name[1], (u16_t)netif->num));
|
netif->name[1], (u16_t)netif->num));
|
||||||
if(autoip == NULL) {
|
if (autoip == NULL) {
|
||||||
/* no AutoIP client attached yet? */
|
/* no AutoIP client attached yet? */
|
||||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||||
("autoip_start(): starting new AUTOIP client\n"));
|
("autoip_start(): starting new AUTOIP client\n"));
|
||||||
autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
|
autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
|
||||||
if(autoip == NULL) {
|
if (autoip == NULL) {
|
||||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||||
("autoip_start(): could not allocate autoip\n"));
|
("autoip_start(): could not allocate autoip\n"));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
@@ -360,7 +352,7 @@ autoip_start_probing(struct netif *netif)
|
|||||||
* accquiring and probing address
|
* accquiring and probing address
|
||||||
* compliant to RFC 3927 Section 2.2.1
|
* compliant to RFC 3927 Section 2.2.1
|
||||||
*/
|
*/
|
||||||
if(autoip->tried_llipaddr > MAX_CONFLICTS) {
|
if (autoip->tried_llipaddr > MAX_CONFLICTS) {
|
||||||
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,7 +396,7 @@ autoip_tmr()
|
|||||||
while (netif != NULL) {
|
while (netif != NULL) {
|
||||||
/* only act on AutoIP configured interfaces */
|
/* only act on AutoIP configured interfaces */
|
||||||
if (netif->autoip != NULL) {
|
if (netif->autoip != NULL) {
|
||||||
if(netif->autoip->lastconflict > 0) {
|
if (netif->autoip->lastconflict > 0) {
|
||||||
netif->autoip->lastconflict--;
|
netif->autoip->lastconflict--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,10 +406,10 @@ autoip_tmr()
|
|||||||
|
|
||||||
switch(netif->autoip->state) {
|
switch(netif->autoip->state) {
|
||||||
case AUTOIP_STATE_PROBING:
|
case AUTOIP_STATE_PROBING:
|
||||||
if(netif->autoip->ttw > 0) {
|
if (netif->autoip->ttw > 0) {
|
||||||
netif->autoip->ttw--;
|
netif->autoip->ttw--;
|
||||||
} else {
|
} else {
|
||||||
if(netif->autoip->sent_num >= PROBE_NUM) {
|
if (netif->autoip->sent_num >= PROBE_NUM) {
|
||||||
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||||
netif->autoip->sent_num = 0;
|
netif->autoip->sent_num = 0;
|
||||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||||
@@ -439,10 +431,10 @@ autoip_tmr()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AUTOIP_STATE_ANNOUNCING:
|
case AUTOIP_STATE_ANNOUNCING:
|
||||||
if(netif->autoip->ttw > 0) {
|
if (netif->autoip->ttw > 0) {
|
||||||
netif->autoip->ttw--;
|
netif->autoip->ttw--;
|
||||||
} else {
|
} else {
|
||||||
if(netif->autoip->sent_num == 0) {
|
if (netif->autoip->sent_num == 0) {
|
||||||
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
|
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
|
||||||
* Now we can bind to an IP address and use it.
|
* Now we can bind to an IP address and use it.
|
||||||
*
|
*
|
||||||
@@ -458,7 +450,7 @@ autoip_tmr()
|
|||||||
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||||
netif->autoip->sent_num++;
|
netif->autoip->sent_num++;
|
||||||
|
|
||||||
if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
if (netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
||||||
netif->autoip->state = AUTOIP_STATE_BOUND;
|
netif->autoip->state = AUTOIP_STATE_BOUND;
|
||||||
netif->autoip->sent_num = 0;
|
netif->autoip->sent_num = 0;
|
||||||
netif->autoip->ttw = 0;
|
netif->autoip->ttw = 0;
|
||||||
@@ -494,12 +486,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||||||
*/
|
*/
|
||||||
ip_addr_t sipaddr, dipaddr;
|
ip_addr_t sipaddr, dipaddr;
|
||||||
struct eth_addr netifaddr;
|
struct eth_addr netifaddr;
|
||||||
netifaddr.addr[0] = netif->hwaddr[0];
|
ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
|
||||||
netifaddr.addr[1] = netif->hwaddr[1];
|
|
||||||
netifaddr.addr[2] = netif->hwaddr[2];
|
|
||||||
netifaddr.addr[3] = netif->hwaddr[3];
|
|
||||||
netifaddr.addr[4] = netif->hwaddr[4];
|
|
||||||
netifaddr.addr[5] = netif->hwaddr[5];
|
|
||||||
|
|
||||||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||||
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
|||||||
* Currently only processes icmp echo requests and sends
|
* Currently only processes icmp echo requests and sends
|
||||||
* out the echo response.
|
* out the echo response.
|
||||||
*
|
*
|
||||||
* @param p the icmp echo request packet, p->payload pointing to the ip header
|
* @param p the icmp echo request packet, p->payload pointing to the icmp header
|
||||||
* @param inp the netif on which this packet was received
|
* @param inp the netif on which this packet was received
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -87,10 +87,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
ICMP_STATS_INC(icmp.recv);
|
ICMP_STATS_INC(icmp.recv);
|
||||||
snmp_inc_icmpinmsgs();
|
snmp_inc_icmpinmsgs();
|
||||||
|
|
||||||
|
iphdr = (struct ip_hdr *)ip_current_header();
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
|
||||||
hlen = IPH_HL(iphdr) * 4;
|
hlen = IPH_HL(iphdr) * 4;
|
||||||
if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
|
if (p->len < sizeof(u16_t)*2) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||||
goto lenerr;
|
goto lenerr;
|
||||||
}
|
}
|
||||||
@@ -110,13 +109,13 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
int accepted = 1;
|
int accepted = 1;
|
||||||
#if !LWIP_MULTICAST_PING
|
#if !LWIP_MULTICAST_PING
|
||||||
/* multicast destination address? */
|
/* multicast destination address? */
|
||||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
if (ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||||
accepted = 0;
|
accepted = 0;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_MULTICAST_PING */
|
#endif /* LWIP_MULTICAST_PING */
|
||||||
#if !LWIP_BROADCAST_PING
|
#if !LWIP_BROADCAST_PING
|
||||||
/* broadcast destination address? */
|
/* broadcast destination address? */
|
||||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
if (ip_addr_isbroadcast(ip_current_dest_addr(), inp)) {
|
||||||
accepted = 0;
|
accepted = 0;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_BROADCAST_PING */
|
#endif /* LWIP_BROADCAST_PING */
|
||||||
@@ -191,7 +190,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
ip_addr_copy(iphdr->dest, *ip_current_src_addr());
|
ip_addr_copy(iphdr->dest, *ip_current_src_addr());
|
||||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||||
/* adjust the checksum */
|
/* adjust the checksum */
|
||||||
if (iecho->chksum >= PP_HTONS(0xffff - (ICMP_ECHO << 8))) {
|
if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
|
||||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
|
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
|
||||||
} else {
|
} else {
|
||||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
|
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ Steve Reynolds
|
|||||||
*/
|
*/
|
||||||
#define IGMP_TTL 1
|
#define IGMP_TTL 1
|
||||||
#define IGMP_MINLEN 8
|
#define IGMP_MINLEN 8
|
||||||
#define ROUTER_ALERT 0x9404
|
#define ROUTER_ALERT 0x9404U
|
||||||
#define ROUTER_ALERTLEN 4
|
#define ROUTER_ALERTLEN 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -139,7 +139,6 @@ static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
|
|||||||
static err_t igmp_remove_group(struct igmp_group *group);
|
static err_t igmp_remove_group(struct igmp_group *group);
|
||||||
static void igmp_timeout( struct igmp_group *group);
|
static void igmp_timeout( struct igmp_group *group);
|
||||||
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
|
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
|
||||||
static void igmp_stop_timer(struct igmp_group *group);
|
|
||||||
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
|
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
|
||||||
static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
|
static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
|
||||||
static void igmp_send(struct igmp_group *group, u8_t type);
|
static void igmp_send(struct igmp_group *group, u8_t type);
|
||||||
@@ -382,14 +381,13 @@ igmp_remove_group(struct igmp_group *group)
|
|||||||
/**
|
/**
|
||||||
* Called from ip_input() if a new IGMP packet is received.
|
* Called from ip_input() if a new IGMP packet is received.
|
||||||
*
|
*
|
||||||
* @param p received igmp packet, p->payload pointing to the ip header
|
* @param p received igmp packet, p->payload pointing to the igmp header
|
||||||
* @param inp network interface on which the packet was received
|
* @param inp network interface on which the packet was received
|
||||||
* @param dest destination ip address of the igmp packet
|
* @param dest destination ip address of the igmp packet
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
||||||
{
|
{
|
||||||
struct ip_hdr * iphdr;
|
|
||||||
struct igmp_msg* igmp;
|
struct igmp_msg* igmp;
|
||||||
struct igmp_group* group;
|
struct igmp_group* group;
|
||||||
struct igmp_group* groupref;
|
struct igmp_group* groupref;
|
||||||
@@ -397,8 +395,7 @@ igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
|||||||
IGMP_STATS_INC(igmp.recv);
|
IGMP_STATS_INC(igmp.recv);
|
||||||
|
|
||||||
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
|
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
if (p->len < IGMP_MINLEN) {
|
||||||
if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
IGMP_STATS_INC(igmp.lenerr);
|
IGMP_STATS_INC(igmp.lenerr);
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
|
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
|
||||||
@@ -406,9 +403,9 @@ igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
|
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
|
||||||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
|
ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->src));
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
|
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
|
||||||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
|
ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->dest));
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
|
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
|
||||||
|
|
||||||
/* Now calculate and check the checksum */
|
/* Now calculate and check the checksum */
|
||||||
@@ -706,17 +703,6 @@ igmp_start_timer(struct igmp_group *group, u8_t max_time)
|
|||||||
group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
|
group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop a timer for an igmp_group
|
|
||||||
*
|
|
||||||
* @param group the igmp_group for which to stop the timer
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
igmp_stop_timer(struct igmp_group *group)
|
|
||||||
{
|
|
||||||
group->timer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delaying membership report for a group if necessary
|
* Delaying membership report for a group if necessary
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -93,20 +93,8 @@
|
|||||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
|
#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
|
||||||
#endif /* LWIP_DHCP */
|
#endif /* LWIP_DHCP */
|
||||||
|
|
||||||
/**
|
/** Global data for both IPv4 and IPv6 */
|
||||||
* The interface that provided the packet for the current callback
|
struct ip_globals ip_data;
|
||||||
* invocation.
|
|
||||||
*/
|
|
||||||
struct netif *current_netif;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Header of the input packet currently being processed.
|
|
||||||
*/
|
|
||||||
const struct ip_hdr *current_header;
|
|
||||||
/** Source IP address of current_header */
|
|
||||||
ip_addr_t current_iphdr_src;
|
|
||||||
/** Destination IP address of current_header */
|
|
||||||
ip_addr_t current_iphdr_dest;
|
|
||||||
|
|
||||||
/** The IP header ID of the next outgoing IP packet */
|
/** The IP header ID of the next outgoing IP packet */
|
||||||
static u16_t ip_id;
|
static u16_t ip_id;
|
||||||
@@ -164,19 +152,19 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
/* RFC3927 2.7: do not forward link-local addresses */
|
/* RFC3927 2.7: do not forward link-local addresses */
|
||||||
if (ip_addr_islinklocal(¤t_iphdr_dest)) {
|
if (ip_addr_islinklocal(ip_current_dest_addr())) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||||
goto return_noroute;
|
goto return_noroute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find network interface where to forward this IP packet to. */
|
/* Find network interface where to forward this IP packet to. */
|
||||||
netif = ip_route(¤t_iphdr_dest);
|
netif = ip_route(ip_current_dest_addr());
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
|
||||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||||
goto return_noroute;
|
goto return_noroute;
|
||||||
}
|
}
|
||||||
/* Do not forward packets onto the same network interface on which
|
/* Do not forward packets onto the same network interface on which
|
||||||
@@ -201,15 +189,15 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Incrementally update the IP checksum. */
|
/* Incrementally update the IP checksum. */
|
||||||
if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffff - 0x100)) {
|
if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
|
||||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
|
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
|
||||||
} else {
|
} else {
|
||||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
|
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()),
|
||||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
|
||||||
|
|
||||||
IP_STATS_INC(ip.fw);
|
IP_STATS_INC(ip.fw);
|
||||||
IP_STATS_INC(ip.xmit);
|
IP_STATS_INC(ip.xmit);
|
||||||
@@ -217,7 +205,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
|
|
||||||
PERF_STOP("ip_forward");
|
PERF_STOP("ip_forward");
|
||||||
/* transmit pbuf on chosen interface */
|
/* transmit pbuf on chosen interface */
|
||||||
netif->output(netif, p, ¤t_iphdr_dest);
|
netif->output(netif, p, ip_current_dest_addr());
|
||||||
return;
|
return;
|
||||||
return_noroute:
|
return_noroute:
|
||||||
snmp_inc_ipoutnoroutes();
|
snmp_inc_ipoutnoroutes();
|
||||||
@@ -311,13 +299,13 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
pbuf_realloc(p, iphdr_len);
|
pbuf_realloc(p, iphdr_len);
|
||||||
|
|
||||||
/* copy IP addresses to aligned ip_addr_t */
|
/* copy IP addresses to aligned ip_addr_t */
|
||||||
ip_addr_copy(current_iphdr_dest, iphdr->dest);
|
ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest);
|
||||||
ip_addr_copy(current_iphdr_src, iphdr->src);
|
ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src);
|
||||||
|
|
||||||
/* match packet against an interface, i.e. is this packet for us? */
|
/* match packet against an interface, i.e. is this packet for us? */
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
if (ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||||
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_iphdr_dest))) {
|
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip_current_dest_addr()))) {
|
||||||
netif = inp;
|
netif = inp;
|
||||||
} else {
|
} else {
|
||||||
netif = NULL;
|
netif = NULL;
|
||||||
@@ -340,9 +328,9 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* interface is up and configured? */
|
/* interface is up and configured? */
|
||||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
|
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
|
||||||
/* unicast to this interface address? */
|
/* unicast to this interface address? */
|
||||||
if (ip_addr_cmp(¤t_iphdr_dest, &(netif->ip_addr)) ||
|
if (ip_addr_cmp(ip_current_dest_addr(), &(netif->ip_addr)) ||
|
||||||
/* or broadcast on this interface network address? */
|
/* or broadcast on this interface network address? */
|
||||||
ip_addr_isbroadcast(¤t_iphdr_dest, netif)) {
|
ip_addr_isbroadcast(ip_current_dest_addr(), netif)) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||||
netif->name[0], netif->name[1]));
|
netif->name[0], netif->name[1]));
|
||||||
/* break out of for loop */
|
/* break out of for loop */
|
||||||
@@ -352,7 +340,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* connections to link-local addresses must persist after changing
|
/* connections to link-local addresses must persist after changing
|
||||||
the netif's address (RFC3927 ch. 1.9) */
|
the netif's address (RFC3927 ch. 1.9) */
|
||||||
if ((netif->autoip != NULL) &&
|
if ((netif->autoip != NULL) &&
|
||||||
ip_addr_cmp(¤t_iphdr_dest, &(netif->autoip->llipaddr))) {
|
ip_addr_cmp(ip_current_dest_addr(), &(netif->autoip->llipaddr))) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
|
||||||
netif->name[0], netif->name[1]));
|
netif->name[0], netif->name[1]));
|
||||||
/* break out of for loop */
|
/* break out of for loop */
|
||||||
@@ -400,10 +388,10 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
|
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
|
||||||
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
||||||
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
|
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
|
||||||
if (check_ip_src && !ip_addr_isany(¤t_iphdr_src))
|
if (check_ip_src && !ip_addr_isany(ip_current_src_addr()))
|
||||||
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
||||||
{ if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) ||
|
{ if ((ip_addr_isbroadcast(ip_current_src_addr(), inp)) ||
|
||||||
(ip_addr_ismulticast(¤t_iphdr_src))) {
|
(ip_addr_ismulticast(ip_current_src_addr()))) {
|
||||||
/* packet source is not valid */
|
/* packet source is not valid */
|
||||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
|
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
|
||||||
/* free (drop) packet pbufs */
|
/* free (drop) packet pbufs */
|
||||||
@@ -421,7 +409,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
|
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
|
||||||
#if IP_FORWARD
|
#if IP_FORWARD
|
||||||
/* non-broadcast packet? */
|
/* non-broadcast packet? */
|
||||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp)) {
|
||||||
/* try to forward IP packet on (other) interfaces */
|
/* try to forward IP packet on (other) interfaces */
|
||||||
ip_forward(p, iphdr, inp);
|
ip_forward(p, iphdr, inp);
|
||||||
} else
|
} else
|
||||||
@@ -480,14 +468,16 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||||
|
|
||||||
current_netif = inp;
|
ip_data.current_netif = inp;
|
||||||
current_header = iphdr;
|
ip_data.current_ip4_header = iphdr;
|
||||||
|
ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4;
|
||||||
|
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
/* raw input did not eat the packet? */
|
/* raw input did not eat the packet? */
|
||||||
if (raw_input(p, inp) == 0)
|
if (raw_input(p, inp) == 0)
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
{
|
{
|
||||||
|
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||||
|
|
||||||
switch (IPH_PROTO(iphdr)) {
|
switch (IPH_PROTO(iphdr)) {
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
@@ -513,14 +503,15 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP */
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
case IP_PROTO_IGMP:
|
case IP_PROTO_IGMP:
|
||||||
igmp_input(p, inp, ¤t_iphdr_dest);
|
igmp_input(p, inp, ip_current_dest_addr());
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
default:
|
default:
|
||||||
#if LWIP_ICMP
|
#if LWIP_ICMP
|
||||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp) &&
|
if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) &&
|
||||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
!ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||||
|
pbuf_header(p, iphdr_hlen); /* Move to ip header, no check necessary. */
|
||||||
p->payload = iphdr;
|
p->payload = iphdr;
|
||||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||||
}
|
}
|
||||||
@@ -535,10 +526,12 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_netif = NULL;
|
/* @todo: this is not really necessary... */
|
||||||
current_header = NULL;
|
ip_data.current_netif = NULL;
|
||||||
ip_addr_set_any(¤t_iphdr_src);
|
ip_data.current_ip4_header = NULL;
|
||||||
ip_addr_set_any(¤t_iphdr_dest);
|
ip_data.current_ip_header_tot_len = 0;
|
||||||
|
ip_addr_set_any(ip_current_src_addr());
|
||||||
|
ip_addr_set_any(ip_current_dest_addr());
|
||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -625,7 +618,7 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
|||||||
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
|
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
|
||||||
}
|
}
|
||||||
#if CHECKSUM_GEN_IP_INLINE
|
#if CHECKSUM_GEN_IP_INLINE
|
||||||
for (i = 0; i < optlen_aligned; i += sizeof(u16_t)) {
|
for (i = 0; i < optlen_aligned/2; i++) {
|
||||||
chk_sum += ((u16_t*)p->payload)[i];
|
chk_sum += ((u16_t*)p->payload)[i];
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||||
@@ -801,9 +794,9 @@ ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
|||||||
return ERR_RTE;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
netif->addr_hint = addr_hint;
|
NETIF_SET_HWADDRHINT(netif, addr_hint);
|
||||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||||
netif->addr_hint = NULL;
|
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ ip4_addr_netmask_valid(u32_t netmask)
|
|||||||
u32_t nm_hostorder = lwip_htonl(netmask);
|
u32_t nm_hostorder = lwip_htonl(netmask);
|
||||||
|
|
||||||
/* first, check for the first zero */
|
/* first, check for the first zero */
|
||||||
for (mask = 1U << 31 ; mask != 0; mask >>= 1) {
|
for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
|
||||||
if ((nm_hostorder & mask) == 0) {
|
if ((nm_hostorder & mask) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Functions common to all TCP/IPv4 modules, such as the byte order functions.
|
|
||||||
*
|
*
|
||||||
|
* DHCPv6.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -32,11 +32,19 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
195
src/core/ipv6/ethip6.c
Normal file
195
src/core/ipv6/ethip6.c
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/**
|
||||||
|
* @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,
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ETHERNET
|
||||||
|
|
||||||
|
#include "lwip/ethip6.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/icmp6.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ETHTYPE_IPV6 0x86DD
|
||||||
|
|
||||||
|
/** The ethernet address */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct eth_addr {
|
||||||
|
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Ethernet header */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct eth_hdr {
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_FIELD(struct eth_addr dest);
|
||||||
|
PACK_STRUCT_FIELD(struct eth_addr src);
|
||||||
|
PACK_STRUCT_FIELD(u16_t type);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an IPv6 packet on the network using netif->linkoutput
|
||||||
|
* The ethernet header is filled in before sending.
|
||||||
|
*
|
||||||
|
* @params netif the lwIP network interface on which to send the packet
|
||||||
|
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
||||||
|
* @params src the source MAC address to be copied into the ethernet header
|
||||||
|
* @params dst the destination MAC address to be copied into the ethernet header
|
||||||
|
* @return ERR_OK if the packet was sent, any other err_t on failure
|
||||||
|
*/
|
||||||
|
static err_t
|
||||||
|
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
||||||
|
{
|
||||||
|
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
||||||
|
|
||||||
|
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
||||||
|
(netif->hwaddr_len == 6));
|
||||||
|
SMEMCPY(ðhdr->dest, dst, 6);
|
||||||
|
SMEMCPY(ðhdr->src, src, 6);
|
||||||
|
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
||||||
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
||||||
|
/* send the packet */
|
||||||
|
return netif->linkoutput(netif, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
||||||
|
*
|
||||||
|
* For IPv6 multicast, corresponding Ethernet addresses
|
||||||
|
* are selected and the packet is transmitted on the link.
|
||||||
|
*
|
||||||
|
* For unicast addresses, ...
|
||||||
|
*
|
||||||
|
* @TODO anycast addresses
|
||||||
|
*
|
||||||
|
* @param netif The lwIP network interface which the IP packet will be sent on.
|
||||||
|
* @param q The pbuf(s) containing the IP packet to be sent.
|
||||||
|
* @param ip6addr The IP address of the packet destination.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ERR_RTE No route to destination (no gateway to external networks),
|
||||||
|
* or the return type of either etharp_query() or etharp_send_ip().
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr)
|
||||||
|
{
|
||||||
|
struct eth_addr dest;
|
||||||
|
s8_t i;
|
||||||
|
|
||||||
|
/* make room for Ethernet header - should not fail */
|
||||||
|
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||||
|
/* bail out */
|
||||||
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
|
("etharp_output: could not allocate room for header.\n"));
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* multicast destination IP address? */
|
||||||
|
if (ip6_addr_ismulticast(ip6addr)) {
|
||||||
|
/* Hash IP multicast address to MAC address.*/
|
||||||
|
dest.addr[0] = 0x33;
|
||||||
|
dest.addr[1] = 0x33;
|
||||||
|
dest.addr[2] = ((u8_t *)(&(ip6addr->addr[3])))[0];
|
||||||
|
dest.addr[3] = ((u8_t *)(&(ip6addr->addr[3])))[1];
|
||||||
|
dest.addr[4] = ((u8_t *)(&(ip6addr->addr[3])))[2];
|
||||||
|
dest.addr[5] = ((u8_t *)(&(ip6addr->addr[3])))[3];
|
||||||
|
|
||||||
|
/* Send out. */
|
||||||
|
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have a unicast destination IP address */
|
||||||
|
/* TODO anycast? */
|
||||||
|
/* Get next hop record. */
|
||||||
|
i = nd6_get_next_hop_entry(ip6addr, netif);
|
||||||
|
if (i < 0) {
|
||||||
|
/* failed to get a next hop neighbor record. */
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now that we have a destination record, send or queue the packet. */
|
||||||
|
if (neighbor_cache[i].state == ND6_STALE) {
|
||||||
|
/* Switch to delay state. */
|
||||||
|
neighbor_cache[i].state = ND6_DELAY;
|
||||||
|
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||||
|
}
|
||||||
|
/* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */
|
||||||
|
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
|
||||||
|
(neighbor_cache[i].state == ND6_DELAY) ||
|
||||||
|
(neighbor_cache[i].state == ND6_PROBE)) {
|
||||||
|
|
||||||
|
/* Send out. */
|
||||||
|
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
|
||||||
|
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should queue packet on this interface. */
|
||||||
|
pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR);
|
||||||
|
nd6_queue_packet(i, q);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 version of ICMP, as per RFC 4443.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -26,154 +32,270 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Some ICMP messages should be passed to the transport protocols. This
|
|
||||||
is not implemented. */
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp6.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/ip6.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/inet_chksum.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LWIP_ICMP6_DATASIZE
|
||||||
|
#define LWIP_ICMP6_DATASIZE 8
|
||||||
|
#endif
|
||||||
|
#if LWIP_ICMP6_DATASIZE == 0
|
||||||
|
#define LWIP_ICMP6_DATASIZE 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an input ICMPv6 message. Called by ip6_input.
|
||||||
|
*
|
||||||
|
* Will generate a reply for echo requests. Other messages are forwarded
|
||||||
|
* to nd6_input, or mld6_input.
|
||||||
|
*
|
||||||
|
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
||||||
|
* @param inp the netif on which this packet was received
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
icmp6_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
u8_t type;
|
struct icmp6_hdr *icmp6hdr;
|
||||||
struct icmp_echo_hdr *iecho;
|
struct pbuf * r;
|
||||||
struct ip_hdr *iphdr;
|
ip6_addr_t * reply_src;
|
||||||
struct ip_addr tmpaddr;
|
|
||||||
|
|
||||||
ICMP_STATS_INC(icmp.recv);
|
ICMP6_STATS_INC(icmp6.recv);
|
||||||
|
|
||||||
/* TODO: check length before accessing payload! */
|
/* Check that ICMPv6 header fits in payload */
|
||||||
|
if (p->len < sizeof(struct icmp6_hdr)) {
|
||||||
|
/* drop short packets */
|
||||||
|
pbuf_free(p);
|
||||||
|
ICMP6_STATS_INC(icmp6.lenerr);
|
||||||
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
type = ((u8_t *)p->payload)[0];
|
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
||||||
|
|
||||||
switch (type) {
|
#if LWIP_ICMP6_CHECKSUM_CHECK
|
||||||
case ICMP6_ECHO:
|
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
ip6_current_dest_addr()) != 0) {
|
||||||
|
/* Checksum failed */
|
||||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
ICMP6_STATS_INC(icmp6.chkerr);
|
||||||
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_ICMP6_CHECKSUM_CHECK */
|
||||||
|
|
||||||
|
switch (icmp6hdr->type) {
|
||||||
|
case ICMP6_TYPE_NA: /* Neighbor advertisement */
|
||||||
|
case ICMP6_TYPE_NS: /* Neighbor solicitation */
|
||||||
|
case ICMP6_TYPE_RA: /* Router advertisement */
|
||||||
|
case ICMP6_TYPE_RD: /* Redirect */
|
||||||
|
case ICMP6_TYPE_PTB: /* Packet too big */
|
||||||
|
nd6_input(p, inp);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case ICMP6_TYPE_RS:
|
||||||
|
#if LWIP_IPV6_FORWARD
|
||||||
|
/* TODO implement router functionality */
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
case ICMP6_TYPE_MLQ:
|
||||||
|
case ICMP6_TYPE_MLR:
|
||||||
|
case ICMP6_TYPE_MLD:
|
||||||
|
mld6_input(p, inp);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case ICMP6_TYPE_EREQ:
|
||||||
|
#if !LWIP_MULTICAST_PING
|
||||||
|
/* multicast destination address? */
|
||||||
|
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||||
|
/* drop */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
ICMP_STATS_INC(icmp.lenerr);
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iecho = p->payload;
|
#endif /* LWIP_MULTICAST_PING */
|
||||||
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
|
|
||||||
if (inet_chksum_pbuf(p) != 0) {
|
/* Allocate reply. */
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
|
||||||
ICMP_STATS_INC(icmp.chkerr);
|
if (r == NULL) {
|
||||||
/* return;*/
|
/* drop */
|
||||||
}
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
|
ICMP6_STATS_INC(icmp6.memerr);
|
||||||
ip_addr_set(&tmpaddr, &(iphdr->src));
|
return;
|
||||||
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
}
|
||||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
|
||||||
iecho->type = ICMP6_ER;
|
/* Copy echo request. */
|
||||||
/* adjust the checksum */
|
if (pbuf_copy(r, p) != ERR_OK) {
|
||||||
if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
|
/* drop */
|
||||||
iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
|
pbuf_free(p);
|
||||||
} else {
|
pbuf_free(r);
|
||||||
iecho->chksum += htons(ICMP6_ECHO << 8);
|
ICMP6_STATS_INC(icmp6.err);
|
||||||
}
|
return;
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
}
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
|
||||||
|
/* Determine reply source IPv6 address. */
|
||||||
|
reply_src = ip6_select_source_address(inp, ip6_current_src_addr());
|
||||||
|
if (reply_src == NULL) {
|
||||||
|
/* drop */
|
||||||
|
pbuf_free(p);
|
||||||
|
pbuf_free(r);
|
||||||
|
ICMP6_STATS_INC(icmp6.rterr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set fields in reply. */
|
||||||
|
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
||||||
|
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
||||||
|
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
||||||
|
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
|
||||||
|
|
||||||
|
/* Send reply. */
|
||||||
|
ICMP6_STATS_INC(icmp6.xmit);
|
||||||
|
ip6_output_if(r, reply_src, ip6_current_src_addr(),
|
||||||
|
LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
|
||||||
|
pbuf_free(r);
|
||||||
|
|
||||||
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
|
||||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
|
||||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
|
ICMP6_STATS_INC(icmp6.proterr);
|
||||||
ICMP_STATS_INC(icmp.proterr);
|
ICMP6_STATS_INC(icmp6.drop);
|
||||||
ICMP_STATS_INC(icmp.drop);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an icmpv6 'destination unreachable' packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
|
* p->payload pointing to the IPv6 header
|
||||||
|
* @param c ICMPv6 code for the unreachable type
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR);
|
||||||
struct ip_hdr *iphdr;
|
|
||||||
struct icmp_dur_hdr *idur;
|
|
||||||
|
|
||||||
/* @todo: can this be PBUF_LINK instead of PBUF_IP? */
|
|
||||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
|
||||||
/* ICMP header + IP header + 8 bytes of data */
|
|
||||||
if (q == NULL) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
|
||||||
(q->len >= (8 + IP_HLEN + 8)));
|
|
||||||
|
|
||||||
iphdr = p->payload;
|
|
||||||
|
|
||||||
idur = q->payload;
|
|
||||||
idur->type = (u8_t)ICMP6_DUR;
|
|
||||||
idur->icode = (u8_t)t;
|
|
||||||
|
|
||||||
SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
|
||||||
|
|
||||||
/* calculate checksum */
|
|
||||||
idur->chksum = 0;
|
|
||||||
idur->chksum = inet_chksum(idur, q->len);
|
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
|
||||||
|
|
||||||
ip_output(q, NULL,
|
|
||||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an icmpv6 'packet too big' packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the 'packet too big' should be sent,
|
||||||
|
* p->payload pointing to the IPv6 header
|
||||||
|
* @param mtu the maximum mtu that we can accept
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
||||||
|
{
|
||||||
|
icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an icmpv6 'time exceeded' packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
|
* p->payload pointing to the IPv6 header
|
||||||
|
* @param c ICMPv6 code for the time exceeded type
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
||||||
|
{
|
||||||
|
icmp6_send_response(p, c, 0, ICMP6_TYPE_TE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an icmpv6 'parameter problem' packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the 'param problem' should be sent,
|
||||||
|
* p->payload pointing to the IP header
|
||||||
|
* @param c ICMPv6 code for the param problem type
|
||||||
|
* @param pointer the pointer to the byte where the parameter is found
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
||||||
|
{
|
||||||
|
icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an ICMPv6 packet in response to an incoming packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the response should be sent,
|
||||||
|
* p->payload pointing to the IPv6 header
|
||||||
|
* @param code Code of the ICMPv6 header
|
||||||
|
* @param data Additional 32-bit parameter in the ICMPv6 header
|
||||||
|
* @param type Type of the ICMPv6 header
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
struct ip_hdr *iphdr;
|
struct icmp6_hdr *icmp6hdr;
|
||||||
struct icmp_te_hdr *tehdr;
|
ip6_addr_t * reply_src;
|
||||||
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
|
/* ICMPv6 header + IPv6 header + data */
|
||||||
|
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
|
||||||
/* @todo: can this be PBUF_LINK instead of PBUF_IP? */
|
PBUF_RAM);
|
||||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
|
||||||
/* ICMP header + IP header + 8 bytes of data */
|
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
||||||
pbuf_free(p);
|
ICMP6_STATS_INC(icmp6.memerr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
|
||||||
(q->len >= (8 + IP_HLEN + 8)));
|
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
|
||||||
|
|
||||||
iphdr = p->payload;
|
icmp6hdr = (struct icmp6_hdr *)q->payload;
|
||||||
|
icmp6hdr->type = type;
|
||||||
tehdr = q->payload;
|
icmp6hdr->code = code;
|
||||||
tehdr->type = (u8_t)ICMP6_TE;
|
icmp6hdr->data = data;
|
||||||
tehdr->icode = (u8_t)t;
|
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
|
||||||
|
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
||||||
|
|
||||||
|
/* Select an address to use as source. */
|
||||||
|
reply_src = ip6_select_source_address(ip_current_netif(), ip6_current_src_addr());
|
||||||
|
if (reply_src == NULL) {
|
||||||
|
/* drop */
|
||||||
|
pbuf_free(q);
|
||||||
|
ICMP6_STATS_INC(icmp6.rterr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
icmp6hdr->chksum = 0;
|
||||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
reply_src, ip6_current_src_addr());
|
||||||
ip_output(q, NULL,
|
|
||||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
ICMP6_STATS_INC(icmp6.xmit);
|
||||||
|
ip6_output(q, reply_src, ip6_current_src_addr(), LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6);
|
||||||
pbuf_free(q);
|
pbuf_free(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Functions common to all TCP/IPv6 modules, such as the Internet checksum and the
|
|
||||||
* byte order functions.
|
|
||||||
*
|
*
|
||||||
|
* INET v6 addresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -33,131 +32,20 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet6.h"
|
||||||
|
|
||||||
/* chksum:
|
/** @see ip6_addr.c for implementation of functions. */
|
||||||
*
|
|
||||||
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
|
|
||||||
* This function is used by the other checksum functions.
|
|
||||||
*
|
|
||||||
* For now, this is not optimized. Must be optimized for the particular processor
|
|
||||||
* arcitecture on which it is to run. Preferebly coded in assembler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static u32_t
|
#endif /* LWIP_IPV6 */
|
||||||
chksum(void *dataptr, u16_t len)
|
|
||||||
{
|
|
||||||
u16_t *sdataptr = dataptr;
|
|
||||||
u32_t acc;
|
|
||||||
|
|
||||||
|
|
||||||
for(acc = 0; len > 1; len -= 2) {
|
|
||||||
acc += *sdataptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add up any odd byte */
|
|
||||||
if (len == 1) {
|
|
||||||
acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* inet_chksum_pseudo:
|
|
||||||
*
|
|
||||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
|
||||||
*/
|
|
||||||
|
|
||||||
u16_t
|
|
||||||
inet_chksum_pseudo(struct pbuf *p,
|
|
||||||
struct ip_addr *src, struct ip_addr *dest,
|
|
||||||
u8_t proto, u32_t proto_len)
|
|
||||||
{
|
|
||||||
u32_t acc;
|
|
||||||
struct pbuf *q;
|
|
||||||
u8_t swapped, i;
|
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
swapped = 0;
|
|
||||||
for(q = p; q != NULL; q = q->next) {
|
|
||||||
acc += chksum(q->payload, q->len);
|
|
||||||
while (acc >> 16) {
|
|
||||||
acc = (acc & 0xffff) + (acc >> 16);
|
|
||||||
}
|
|
||||||
if (q->len % 2 != 0) {
|
|
||||||
swapped = 1 - swapped;
|
|
||||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swapped) {
|
|
||||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 8; i++) {
|
|
||||||
acc += ((u16_t *)src->addr)[i] & 0xffff;
|
|
||||||
acc += ((u16_t *)dest->addr)[i] & 0xffff;
|
|
||||||
while (acc >> 16) {
|
|
||||||
acc = (acc & 0xffff) + (acc >> 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acc += (u16_t)htons((u16_t)proto);
|
|
||||||
acc += ((u16_t *)&proto_len)[0] & 0xffff;
|
|
||||||
acc += ((u16_t *)&proto_len)[1] & 0xffff;
|
|
||||||
|
|
||||||
while (acc >> 16) {
|
|
||||||
acc = (acc & 0xffff) + (acc >> 16);
|
|
||||||
}
|
|
||||||
return ~(acc & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* inet_chksum:
|
|
||||||
*
|
|
||||||
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
|
|
||||||
* and ICMP.
|
|
||||||
*/
|
|
||||||
|
|
||||||
u16_t
|
|
||||||
inet_chksum(void *dataptr, u16_t len)
|
|
||||||
{
|
|
||||||
u32_t acc, sum;
|
|
||||||
|
|
||||||
acc = chksum(dataptr, len);
|
|
||||||
sum = (acc & 0xffff) + (acc >> 16);
|
|
||||||
sum += (sum >> 16);
|
|
||||||
return ~(sum & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16_t
|
|
||||||
inet_chksum_pbuf(struct pbuf *p)
|
|
||||||
{
|
|
||||||
u32_t acc;
|
|
||||||
struct pbuf *q;
|
|
||||||
u8_t swapped;
|
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
swapped = 0;
|
|
||||||
for(q = p; q != NULL; q = q->next) {
|
|
||||||
acc += chksum(q->payload, q->len);
|
|
||||||
while (acc >> 16) {
|
|
||||||
acc = (acc & 0xffff) + (acc >> 16);
|
|
||||||
}
|
|
||||||
if (q->len % 2 != 0) {
|
|
||||||
swapped = 1 - swapped;
|
|
||||||
acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swapped) {
|
|
||||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
|
||||||
}
|
|
||||||
return ~(acc & 0xffff);
|
|
||||||
}
|
|
||||||
|
|||||||
1113
src/core/ipv6/ip6.c
1113
src/core/ipv6/ip6.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -26,47 +32,210 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||||
*
|
*
|
||||||
|
* Functions for handling IPv6 addresses.
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "lwip/inet.h"
|
|
||||||
|
|
||||||
u8_t
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
|
||||||
struct ip_addr *mask)
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
/* used by IP6_ADDR_ANY in ip6_addr.h */
|
||||||
|
const ip6_addr_t ip6_addr_any = { { 0ul, 0ul, 0ul, 0ul } };
|
||||||
|
|
||||||
|
#ifndef isprint
|
||||||
|
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||||
|
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||||
|
#define isdigit(c) in_range(c, '0', '9')
|
||||||
|
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||||
|
#define islower(c) in_range(c, 'a', 'z')
|
||||||
|
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||||
|
#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether "cp" is a valid ascii representation
|
||||||
|
* of an IPv6 address and convert to a binary address.
|
||||||
|
* Returns 1 if the address is valid, 0 if not.
|
||||||
|
*
|
||||||
|
* @param cp IPv6 address in ascii represenation (e.g. "FF01::1")
|
||||||
|
* @param addr pointer to which to save the ip address in network order
|
||||||
|
* @return 1 if cp could be converted to addr, 0 on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
||||||
{
|
{
|
||||||
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
u32_t addr_index, zero_blocks, current_block_index, current_block_value;
|
||||||
(addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) &&
|
const char * s;
|
||||||
(addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) &&
|
|
||||||
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
|
/* Count the number of colons, to count the number of blocks in a "::" sequence
|
||||||
|
zero_blocks may be 1 even if there are no :: sequences */
|
||||||
|
zero_blocks = 8;
|
||||||
|
for (s = cp; *s != 0; s++) {
|
||||||
|
if (*s == ':')
|
||||||
|
zero_blocks--;
|
||||||
|
else if (!isxdigit(*s))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse each block */
|
||||||
|
addr_index = 0;
|
||||||
|
current_block_index = 0;
|
||||||
|
current_block_value = 0;
|
||||||
|
for (s = cp; *s != 0; s++) {
|
||||||
|
if (*s == ':') {
|
||||||
|
if (current_block_index & 0x1) {
|
||||||
|
addr->addr[addr_index++] |= current_block_value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addr->addr[addr_index] = current_block_value << 16;
|
||||||
|
}
|
||||||
|
current_block_index++;
|
||||||
|
current_block_value = 0;
|
||||||
|
if (current_block_index > 7) {
|
||||||
|
/* address too long! */
|
||||||
|
return 0;
|
||||||
|
} if (s[1] == ':') {
|
||||||
|
s++;
|
||||||
|
/* "::" found, set zeros */
|
||||||
|
while (zero_blocks-- > 0) {
|
||||||
|
if (current_block_index & 0x1) {
|
||||||
|
addr_index++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addr->addr[addr_index] = 0;
|
||||||
|
}
|
||||||
|
current_block_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isxdigit(*s)) {
|
||||||
|
/* add current digit */
|
||||||
|
current_block_value = (current_block_value << 4) +
|
||||||
|
(isdigit(*s) ? *s - '0' :
|
||||||
|
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
|
||||||
|
} else {
|
||||||
|
/* unexpected digit, space? CRLF? */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_block_index & 0x1) {
|
||||||
|
addr->addr[addr_index++] |= current_block_value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addr->addr[addr_index] = current_block_value << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert to network byte order. */
|
||||||
|
for (addr_index = 0; addr_index < 4; addr_index++) {
|
||||||
|
addr->addr[addr_index] = htonl(addr->addr[addr_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_block_index != 7) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8_t
|
/**
|
||||||
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
* Convert numeric IPv6 address into ASCII representation.
|
||||||
|
* returns ptr to static buffer; not reentrant!
|
||||||
|
*
|
||||||
|
* @param addr ip6 address in network order to convert
|
||||||
|
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||||
|
* represenation of addr
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
ip6addr_ntoa(const ip6_addr_t *addr)
|
||||||
{
|
{
|
||||||
return(addr1->addr[0] == addr2->addr[0] &&
|
static char str[40];
|
||||||
addr1->addr[1] == addr2->addr[1] &&
|
return ip6addr_ntoa_r(addr, str, 40);
|
||||||
addr1->addr[2] == addr2->addr[2] &&
|
|
||||||
addr1->addr[3] == addr2->addr[3]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/**
|
||||||
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
|
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
||||||
|
*
|
||||||
|
* @param addr ip6 address in network order to convert
|
||||||
|
* @param buf target buffer where the string is stored
|
||||||
|
* @param buflen length of buf
|
||||||
|
* @return either pointer to buf which now holds the ASCII
|
||||||
|
* representation of addr or NULL if buf was too small
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
SMEMCPY(dest, src, sizeof(struct ip_addr));
|
u32_t current_block_index, current_block_value;
|
||||||
/* dest->addr[0] = src->addr[0];
|
s32_t zero_flag, i;
|
||||||
dest->addr[1] = src->addr[1];
|
|
||||||
dest->addr[2] = src->addr[2];
|
|
||||||
dest->addr[3] = src->addr[3];*/
|
|
||||||
}
|
|
||||||
|
|
||||||
u8_t
|
i = 0;
|
||||||
ip_addr_isany(struct ip_addr *addr)
|
zero_flag = 0; /* used to indicate a zero chain for "::' */
|
||||||
{
|
|
||||||
if (addr == NULL) return 1;
|
for (current_block_index = 0; current_block_index < 8; current_block_index++) {
|
||||||
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
|
/* get the current 16-bit block */
|
||||||
|
current_block_value = htonl(addr->addr[current_block_index >> 1]);
|
||||||
|
if ((current_block_index & 0x1) == 0) {
|
||||||
|
current_block_value = current_block_value >> 16;
|
||||||
|
}
|
||||||
|
current_block_value &= 0xffff;
|
||||||
|
|
||||||
|
if (current_block_value == 0) {
|
||||||
|
/* generate empty block "::" */
|
||||||
|
if (!zero_flag) {
|
||||||
|
if (current_block_index > 0) {
|
||||||
|
zero_flag = 1;
|
||||||
|
buf[i++] = ':';
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (current_block_index > 0) {
|
||||||
|
buf[i++] = ':';
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((current_block_value & 0xf000) == 0) {
|
||||||
|
zero_flag = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i++] = xchar((current_block_value & 0xf));
|
||||||
|
if (i >= buflen) return NULL;
|
||||||
|
|
||||||
|
zero_flag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i] = 0;
|
||||||
|
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|||||||
689
src/core/ipv6/ip6_frag.c
Normal file
689
src/core/ipv6/ip6_frag.c
Normal file
@@ -0,0 +1,689 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 fragmentation and reassembly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/ip6_frag.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/icmp6.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/memp.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
|
||||||
|
/** Setting this to 0, you can turn off checking the fragments for overlapping
|
||||||
|
* regions. The code gets a little smaller. Only use this if you know that
|
||||||
|
* overlapping won't occur on your network! */
|
||||||
|
#ifndef IP_REASS_CHECK_OVERLAP
|
||||||
|
#define IP_REASS_CHECK_OVERLAP 1
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
|
|
||||||
|
/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
|
||||||
|
* full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
|
||||||
|
* Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
|
||||||
|
* is set to 1, so one datagram can be reassembled at a time, only. */
|
||||||
|
#ifndef IP_REASS_FREE_OLDEST
|
||||||
|
#define IP_REASS_FREE_OLDEST 1
|
||||||
|
#endif /* IP_REASS_FREE_OLDEST */
|
||||||
|
|
||||||
|
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||||
|
|
||||||
|
/** This is a helper struct which holds the starting
|
||||||
|
* offset and the ending offset of this fragment to
|
||||||
|
* easily chain the fragments.
|
||||||
|
* It has the same packing requirements as the IPv6 header, since it replaces
|
||||||
|
* the Fragment Header in memory in incoming fragments to keep
|
||||||
|
* track of the various fragments.
|
||||||
|
*/
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip6_reass_helper {
|
||||||
|
PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
|
||||||
|
PACK_STRUCT_FIELD(u16_t start);
|
||||||
|
PACK_STRUCT_FIELD(u16_t end);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* static variables */
|
||||||
|
static struct ip6_reassdata *reassdatagrams;
|
||||||
|
static u16_t ip6_reass_pbufcount;
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr);
|
||||||
|
#if IP_REASS_FREE_OLDEST
|
||||||
|
static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed);
|
||||||
|
#endif /* IP_REASS_FREE_OLDEST */
|
||||||
|
|
||||||
|
void
|
||||||
|
ip6_reass_tmr(void)
|
||||||
|
{
|
||||||
|
struct ip6_reassdata *r, *tmp;
|
||||||
|
|
||||||
|
r = reassdatagrams;
|
||||||
|
while (r != NULL) {
|
||||||
|
/* Decrement the timer. Once it reaches 0,
|
||||||
|
* clean up the incomplete fragment assembly */
|
||||||
|
if (r->timer > 0) {
|
||||||
|
r->timer--;
|
||||||
|
r = r->next;
|
||||||
|
} else {
|
||||||
|
/* reassembly timed out */
|
||||||
|
tmp = r;
|
||||||
|
/* get the next pointer before freeing */
|
||||||
|
r = r->next;
|
||||||
|
/* free the helper struct and all enqueued pbufs */
|
||||||
|
ip6_reass_free_complete_datagram(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a datagram (struct ip6_reassdata) and all its pbufs.
|
||||||
|
* Updates the total count of enqueued pbufs (ip6_reass_pbufcount),
|
||||||
|
* sends an ICMP time exceeded packet.
|
||||||
|
*
|
||||||
|
* @param ipr datagram to free
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
||||||
|
{
|
||||||
|
struct ip6_reassdata *prev;
|
||||||
|
u16_t pbufs_freed = 0;
|
||||||
|
u8_t clen;
|
||||||
|
struct pbuf *p;
|
||||||
|
struct ip6_reass_helper *iprh;
|
||||||
|
|
||||||
|
#if LWIP_ICMP6
|
||||||
|
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
||||||
|
if (iprh->start == 0) {
|
||||||
|
/* The first fragment was received, send ICMP time exceeded. */
|
||||||
|
/* First, de-queue the first pbuf from r->p. */
|
||||||
|
p = ipr->p;
|
||||||
|
ipr->p = iprh->next_pbuf;
|
||||||
|
/* Then, move back to the original header (we are now pointing to Fragment header). */
|
||||||
|
pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr);
|
||||||
|
icmp6_time_exceeded(p, ICMP6_TE_FRAG);
|
||||||
|
clen = pbuf_clen(p);
|
||||||
|
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||||
|
pbufs_freed += clen;
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_ICMP6 */
|
||||||
|
|
||||||
|
/* First, free all received pbufs. The individual pbufs need to be released
|
||||||
|
separately as they have not yet been chained */
|
||||||
|
p = ipr->p;
|
||||||
|
while (p != NULL) {
|
||||||
|
struct pbuf *pcur;
|
||||||
|
iprh = (struct ip6_reass_helper *)p->payload;
|
||||||
|
pcur = p;
|
||||||
|
/* get the next pointer before freeing */
|
||||||
|
p = iprh->next_pbuf;
|
||||||
|
clen = pbuf_clen(pcur);
|
||||||
|
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||||
|
pbufs_freed += clen;
|
||||||
|
pbuf_free(pcur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then, unchain the struct ip6_reassdata from the list and free it. */
|
||||||
|
if (ipr == reassdatagrams) {
|
||||||
|
reassdatagrams = ipr->next;
|
||||||
|
} else {
|
||||||
|
prev = reassdatagrams;
|
||||||
|
while (prev != NULL) {
|
||||||
|
if (prev->next == ipr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev = prev->next;
|
||||||
|
}
|
||||||
|
if (prev != NULL) {
|
||||||
|
prev->next = ipr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memp_free(MEMP_IP6_REASSDATA, ipr);
|
||||||
|
|
||||||
|
/* Finally, update number of pbufs in reassembly queue */
|
||||||
|
LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
|
||||||
|
ip6_reass_pbufcount -= pbufs_freed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IP_REASS_FREE_OLDEST
|
||||||
|
/**
|
||||||
|
* Free the oldest datagram to make room for enqueueing new fragments.
|
||||||
|
* The datagram ipr is not freed!
|
||||||
|
*
|
||||||
|
* @param ipr ip6_reassdata for the current fragment
|
||||||
|
* @param pbufs_needed number of pbufs needed to enqueue
|
||||||
|
* (used for freeing other datagrams if not enough space)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed)
|
||||||
|
{
|
||||||
|
struct ip6_reassdata *r, *oldest;
|
||||||
|
|
||||||
|
/* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
|
||||||
|
* but don't free the current datagram! */
|
||||||
|
do {
|
||||||
|
r = oldest = reassdatagrams;
|
||||||
|
while (r != NULL) {
|
||||||
|
if (r != ipr) {
|
||||||
|
if (r->timer <= oldest->timer) {
|
||||||
|
/* older than the previous oldest */
|
||||||
|
oldest = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
if (oldest != NULL) {
|
||||||
|
ip6_reass_free_complete_datagram(oldest);
|
||||||
|
}
|
||||||
|
} while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL));
|
||||||
|
}
|
||||||
|
#endif /* IP_REASS_FREE_OLDEST */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reassembles incoming IPv6 fragments into an IPv6 datagram.
|
||||||
|
*
|
||||||
|
* @param p points to the IPv6 Fragment Header
|
||||||
|
* @param len the length of the payload (after Fragment Header)
|
||||||
|
* @return NULL if reassembly is incomplete, pbuf pointing to
|
||||||
|
* IPv6 Header if reassembly is complete
|
||||||
|
*/
|
||||||
|
struct pbuf *
|
||||||
|
ip6_reass(struct pbuf *p)
|
||||||
|
{
|
||||||
|
struct ip6_reassdata *ipr, *ipr_prev;
|
||||||
|
struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
||||||
|
struct ip6_frag_hdr * frag_hdr;
|
||||||
|
u16_t offset, len;
|
||||||
|
u8_t clen, valid = 1;
|
||||||
|
struct pbuf *q;
|
||||||
|
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.recv);
|
||||||
|
|
||||||
|
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
||||||
|
|
||||||
|
clen = pbuf_clen(p);
|
||||||
|
|
||||||
|
offset = ntohs(frag_hdr->_fragment_offset);
|
||||||
|
|
||||||
|
/* Calculate fragment length from IPv6 payload length.
|
||||||
|
* Adjust for headers before Fragment Header.
|
||||||
|
* And finally adjust by Fragment Header length. */
|
||||||
|
len = ntohs(ip6_current_header()->_plen);
|
||||||
|
len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN;
|
||||||
|
len -= IP6_FRAG_HLEN;
|
||||||
|
|
||||||
|
/* Look for the datagram the fragment belongs to in the current datagram queue,
|
||||||
|
* remembering the previous in the queue for later dequeueing. */
|
||||||
|
for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) {
|
||||||
|
/* Check if the incoming fragment matches the one currently present
|
||||||
|
in the reassembly buffer. If so, we proceed with copying the
|
||||||
|
fragment into the buffer. */
|
||||||
|
if ((frag_hdr->_identification == ipr->identification) &&
|
||||||
|
ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) &&
|
||||||
|
ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) {
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.cachehit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ipr_prev = ipr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipr == NULL) {
|
||||||
|
/* Enqueue a new datagram into the datagram queue */
|
||||||
|
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
||||||
|
if (ipr == NULL) {
|
||||||
|
#if IP_REASS_FREE_OLDEST
|
||||||
|
/* Make room and try again. */
|
||||||
|
ip6_reass_remove_oldest_datagram(ipr, clen);
|
||||||
|
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
||||||
|
if (ipr == NULL)
|
||||||
|
#endif /* IP_REASS_FREE_OLDEST */
|
||||||
|
{
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ipr, 0, sizeof(struct ip6_reassdata));
|
||||||
|
ipr->timer = IP_REASS_MAXAGE;
|
||||||
|
|
||||||
|
/* enqueue the new structure to the front of the list */
|
||||||
|
ipr->next = reassdatagrams;
|
||||||
|
reassdatagrams = ipr;
|
||||||
|
|
||||||
|
/* Use the current IPv6 header for src/dest address reference.
|
||||||
|
* Eventually, we will replace it when we get the first fragment
|
||||||
|
* (it might be this one, in any case, it is done later). */
|
||||||
|
ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
|
||||||
|
|
||||||
|
/* copy the fragmented packet id. */
|
||||||
|
ipr->identification = frag_hdr->_identification;
|
||||||
|
|
||||||
|
/* copy the nexth field */
|
||||||
|
ipr->nexth = frag_hdr->_nexth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we are allowed to enqueue more datagrams. */
|
||||||
|
if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
|
||||||
|
#if IP_REASS_FREE_OLDEST
|
||||||
|
ip6_reass_remove_oldest_datagram(ipr, clen);
|
||||||
|
if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)
|
||||||
|
#endif /* IP_REASS_FREE_OLDEST */
|
||||||
|
{
|
||||||
|
/* @todo: send ICMPv6 time exceeded here? */
|
||||||
|
/* drop this pbuf */
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overwrite Fragment Header with our own helper struct. */
|
||||||
|
iprh = (struct ip6_reass_helper *)p->payload;
|
||||||
|
iprh->next_pbuf = NULL;
|
||||||
|
iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
|
||||||
|
iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
|
||||||
|
|
||||||
|
/* find the right place to insert this pbuf */
|
||||||
|
/* Iterate through until we either get to the end of the list (append),
|
||||||
|
* or we find on with a larger offset (insert). */
|
||||||
|
for (q = ipr->p; q != NULL;) {
|
||||||
|
iprh_tmp = (struct ip6_reass_helper*)q->payload;
|
||||||
|
if (iprh->start < iprh_tmp->start) {
|
||||||
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
|
if (iprh->end > iprh_tmp->start) {
|
||||||
|
/* fragment overlaps with following, throw away */
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
if (iprh_prev != NULL) {
|
||||||
|
if (iprh->start < iprh_prev->end) {
|
||||||
|
/* fragment overlaps with previous, throw away */
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
|
/* the new pbuf should be inserted before this */
|
||||||
|
iprh->next_pbuf = q;
|
||||||
|
if (iprh_prev != NULL) {
|
||||||
|
/* not the fragment with the lowest offset */
|
||||||
|
iprh_prev->next_pbuf = p;
|
||||||
|
} else {
|
||||||
|
/* fragment with the lowest offset */
|
||||||
|
ipr->p = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if(iprh->start == iprh_tmp->start) {
|
||||||
|
/* received the same datagram twice: no need to keep the datagram */
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
|
} else if(iprh->start < iprh_tmp->end) {
|
||||||
|
/* overlap: no need to keep the new datagram */
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||||
|
goto nullreturn;
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
|
} else {
|
||||||
|
/* Check if the fragments received so far have no gaps. */
|
||||||
|
if (iprh_prev != NULL) {
|
||||||
|
if (iprh_prev->end != iprh_tmp->start) {
|
||||||
|
/* There is a fragment missing between the current
|
||||||
|
* and the previous fragment */
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q = iprh_tmp->next_pbuf;
|
||||||
|
iprh_prev = iprh_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If q is NULL, then we made it to the end of the list. Determine what to do now */
|
||||||
|
if (q == NULL) {
|
||||||
|
if (iprh_prev != NULL) {
|
||||||
|
/* this is (for now), the fragment with the highest offset:
|
||||||
|
* chain it to the last fragment */
|
||||||
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
|
LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
|
iprh_prev->next_pbuf = p;
|
||||||
|
if (iprh_prev->end != iprh->start) {
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
|
LWIP_ASSERT("no previous fragment, this must be the first fragment!",
|
||||||
|
ipr->p == NULL);
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
|
/* this is the first fragment we ever received for this ip datagram */
|
||||||
|
ipr->p = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||||
|
the number of fragments that may be enqueued at any one time */
|
||||||
|
ip6_reass_pbufcount += clen;
|
||||||
|
|
||||||
|
/* Remember IPv6 header if this is the first fragment. */
|
||||||
|
if (iprh->start == 0) {
|
||||||
|
ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is the last fragment, calculate total packet length. */
|
||||||
|
if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
|
||||||
|
ipr->datagram_len = iprh->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional validity tests: we have received first and last fragment. */
|
||||||
|
iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload;
|
||||||
|
if (iprh_tmp->start != 0) {
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
if (ipr->datagram_len == 0) {
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Final validity test: no gaps between current and last fragment. */
|
||||||
|
iprh_prev = iprh;
|
||||||
|
q = iprh->next_pbuf;
|
||||||
|
while (q != NULL) {
|
||||||
|
iprh = (struct ip6_reass_helper*)q->payload;
|
||||||
|
if (iprh_prev->end != iprh->start) {
|
||||||
|
valid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iprh_prev = iprh;
|
||||||
|
q = iprh->next_pbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
/* All fragments have been received */
|
||||||
|
|
||||||
|
/* chain together the pbufs contained within the ip6_reassdata list. */
|
||||||
|
iprh = (struct ip6_reass_helper*) ipr->p->payload;
|
||||||
|
while(iprh != NULL) {
|
||||||
|
|
||||||
|
if (iprh->next_pbuf != NULL) {
|
||||||
|
/* Save next helper struct (will be hidden in next step). */
|
||||||
|
iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload;
|
||||||
|
|
||||||
|
/* hide the fragment header for every succeding fragment */
|
||||||
|
pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN);
|
||||||
|
pbuf_cat(ipr->p, iprh->next_pbuf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iprh_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
iprh = iprh_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust datagram length by adding header lengths. */
|
||||||
|
ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr)
|
||||||
|
+ IP6_FRAG_HLEN
|
||||||
|
- IP6_HLEN ;
|
||||||
|
|
||||||
|
/* Set payload length in ip header. */
|
||||||
|
ipr->iphdr->_plen = htons(ipr->datagram_len);
|
||||||
|
|
||||||
|
/* Get the furst pbuf. */
|
||||||
|
p = ipr->p;
|
||||||
|
|
||||||
|
/* Restore Fragment Header in first pbuf. Mark as "single fragment"
|
||||||
|
* packet. Restore nexth. */
|
||||||
|
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
||||||
|
frag_hdr->_nexth = ipr->nexth;
|
||||||
|
frag_hdr->reserved = 0;
|
||||||
|
frag_hdr->_fragment_offset = 0;
|
||||||
|
frag_hdr->_identification = 0;
|
||||||
|
|
||||||
|
/* Move pbuf back to IPv6 header. */
|
||||||
|
pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr);
|
||||||
|
|
||||||
|
/* release the sources allocate for the fragment queue entry */
|
||||||
|
if (reassdatagrams == ipr) {
|
||||||
|
/* it was the first in the list */
|
||||||
|
reassdatagrams = ipr->next;
|
||||||
|
} else {
|
||||||
|
/* it wasn't the first, so it must have a valid 'prev' */
|
||||||
|
LWIP_ASSERT("sanity check linked list", ipr_prev != NULL);
|
||||||
|
ipr_prev->next = ipr->next;
|
||||||
|
}
|
||||||
|
memp_free(MEMP_IP6_REASSDATA, ipr);
|
||||||
|
|
||||||
|
/* and adjust the number of pbufs currently queued for reassembly. */
|
||||||
|
ip6_reass_pbufcount -= pbuf_clen(p);
|
||||||
|
|
||||||
|
/* Return the pbuf chain */
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
/* the datagram is not (yet?) reassembled completely */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nullreturn:
|
||||||
|
pbuf_free(p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 ^^ LWIP_IPV6_REASS */
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_FRAG
|
||||||
|
|
||||||
|
/** Allocate a new struct pbuf_custom_ref */
|
||||||
|
static struct pbuf_custom_ref*
|
||||||
|
ip6_frag_alloc_pbuf_custom_ref(void)
|
||||||
|
{
|
||||||
|
return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free a struct pbuf_custom_ref */
|
||||||
|
static void
|
||||||
|
ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
|
||||||
|
{
|
||||||
|
LWIP_ASSERT("p != NULL", p != NULL);
|
||||||
|
memp_free(MEMP_FRAG_PBUF, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free-callback function to free a 'struct pbuf_custom_ref', called by
|
||||||
|
* pbuf_free. */
|
||||||
|
static void
|
||||||
|
ip6_frag_free_pbuf_custom(struct pbuf *p)
|
||||||
|
{
|
||||||
|
struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
|
||||||
|
LWIP_ASSERT("pcr != NULL", pcr != NULL);
|
||||||
|
LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
|
||||||
|
if (pcr->original != NULL) {
|
||||||
|
pbuf_free(pcr->original);
|
||||||
|
}
|
||||||
|
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
||||||
|
*
|
||||||
|
* Chop the datagram in MTU sized chunks and send them in order
|
||||||
|
* by pointing PBUF_REFs into p
|
||||||
|
*
|
||||||
|
* @param p ipv6 packet to send
|
||||||
|
* @param netif the netif on which to send
|
||||||
|
* @param dest destination ipv6 address to which to send
|
||||||
|
*
|
||||||
|
* @return ERR_OK if sent successfully, err_t otherwise
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest)
|
||||||
|
{
|
||||||
|
struct ip6_hdr *original_ip6hdr;
|
||||||
|
struct ip6_hdr *ip6hdr;
|
||||||
|
struct ip6_frag_hdr * frag_hdr;
|
||||||
|
struct pbuf *rambuf;
|
||||||
|
struct pbuf *newpbuf;
|
||||||
|
static u32_t identification;
|
||||||
|
u16_t nfb;
|
||||||
|
u16_t left, cop;
|
||||||
|
u16_t mtu;
|
||||||
|
u16_t fragment_offset = 0;
|
||||||
|
u16_t last;
|
||||||
|
u16_t poff = IP6_HLEN;
|
||||||
|
u16_t newpbuflen = 0;
|
||||||
|
u16_t left_to_copy;
|
||||||
|
|
||||||
|
identification++;
|
||||||
|
|
||||||
|
original_ip6hdr = (struct ip6_hdr *)p->payload;
|
||||||
|
|
||||||
|
mtu = nd6_get_destination_mtu(dest, netif);
|
||||||
|
|
||||||
|
/* TODO we assume there are no options in the unfragmentable part (IPv6 header). */
|
||||||
|
left = p->tot_len - IP6_HLEN;
|
||||||
|
|
||||||
|
nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;
|
||||||
|
|
||||||
|
while (left) {
|
||||||
|
last = (left <= nfb);
|
||||||
|
|
||||||
|
/* Fill this fragment */
|
||||||
|
cop = last ? left : nfb;
|
||||||
|
|
||||||
|
/* When not using a static buffer, create a chain of pbufs.
|
||||||
|
* The first will be a PBUF_RAM holding the link, IPv6, and Fragment header.
|
||||||
|
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
|
||||||
|
* but limited to the size of an mtu.
|
||||||
|
*/
|
||||||
|
rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM);
|
||||||
|
if (rambuf == NULL) {
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
LWIP_ASSERT("this needs a pbuf in one piece!",
|
||||||
|
(p->len >= (IP6_HLEN + IP6_FRAG_HLEN)));
|
||||||
|
SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
|
||||||
|
ip6hdr = (struct ip6_hdr *)rambuf->payload;
|
||||||
|
frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);
|
||||||
|
|
||||||
|
/* Can just adjust p directly for needed offset. */
|
||||||
|
p->payload = (u8_t *)p->payload + poff;
|
||||||
|
p->len -= poff;
|
||||||
|
p->tot_len -= poff;
|
||||||
|
|
||||||
|
left_to_copy = cop;
|
||||||
|
while (left_to_copy) {
|
||||||
|
struct pbuf_custom_ref *pcr;
|
||||||
|
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
|
||||||
|
/* Is this pbuf already empty? */
|
||||||
|
if (!newpbuflen) {
|
||||||
|
p = p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pcr = ip6_frag_alloc_pbuf_custom_ref();
|
||||||
|
if (pcr == NULL) {
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
/* Mirror this pbuf, although we might not need all of it. */
|
||||||
|
newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
|
||||||
|
if (newpbuf == NULL) {
|
||||||
|
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
pbuf_ref(p);
|
||||||
|
pcr->original = p;
|
||||||
|
pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;
|
||||||
|
|
||||||
|
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
|
||||||
|
* so that it is removed when pbuf_dechain is later called on rambuf.
|
||||||
|
*/
|
||||||
|
pbuf_cat(rambuf, newpbuf);
|
||||||
|
left_to_copy -= newpbuflen;
|
||||||
|
if (left_to_copy) {
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poff = newpbuflen;
|
||||||
|
|
||||||
|
/* Set headers */
|
||||||
|
frag_hdr->_nexth = original_ip6hdr->_nexth;
|
||||||
|
frag_hdr->reserved = 0;
|
||||||
|
frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
|
||||||
|
frag_hdr->_identification = htonl(identification);
|
||||||
|
|
||||||
|
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
||||||
|
IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
|
||||||
|
|
||||||
|
/* No need for separate header pbuf - we allowed room for it in rambuf
|
||||||
|
* when allocated.
|
||||||
|
*/
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.xmit);
|
||||||
|
netif->output_ip6(netif, rambuf, dest);
|
||||||
|
|
||||||
|
/* Unfortunately we can't reuse rambuf - the hardware may still be
|
||||||
|
* using the buffer. Instead we free it (and the ensuing chain) and
|
||||||
|
* recreate it next time round the loop. If we're lucky the hardware
|
||||||
|
* will have already sent the packet, the free will really free, and
|
||||||
|
* there will be zero memory penalty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
left -= cop;
|
||||||
|
fragment_offset += cop;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */
|
||||||
578
src/core/ipv6/mld6.c
Normal file
578
src/core/ipv6/mld6.c
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||||
|
* No support for MLDv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Based on igmp.c implementation of igmp v2 protocol */
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
#include "lwip/icmp6.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/memp.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MLD constants
|
||||||
|
*/
|
||||||
|
#define MLD6_HL 1
|
||||||
|
#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500)
|
||||||
|
|
||||||
|
#define MLD6_GROUP_NON_MEMBER 0
|
||||||
|
#define MLD6_GROUP_DELAYING_MEMBER 1
|
||||||
|
#define MLD6_GROUP_IDLE_MEMBER 2
|
||||||
|
|
||||||
|
|
||||||
|
/* The list of joined groups. */
|
||||||
|
static struct mld_group* mld_group_list;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
static struct mld_group * mld6_new_group(struct netif *ifp, ip6_addr_t *addr);
|
||||||
|
static err_t mld6_free_group(struct mld_group *group);
|
||||||
|
static void mld6_delayed_report(struct mld_group *group, u16_t maxresp);
|
||||||
|
static void mld6_send(struct mld_group *group, u8_t type);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop MLD processing on interface
|
||||||
|
*
|
||||||
|
* @param netif network interface on which stop MLD processing
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
mld6_stop(struct netif *netif)
|
||||||
|
{
|
||||||
|
struct mld_group *group = mld_group_list;
|
||||||
|
struct mld_group *prev = NULL;
|
||||||
|
struct mld_group *next;
|
||||||
|
|
||||||
|
/* look for groups joined on this interface further down the list */
|
||||||
|
while (group != NULL) {
|
||||||
|
next = group->next;
|
||||||
|
/* is it a group joined on this interface? */
|
||||||
|
if (group->netif == netif) {
|
||||||
|
/* is it the first group of the list? */
|
||||||
|
if (group == mld_group_list) {
|
||||||
|
mld_group_list = next;
|
||||||
|
}
|
||||||
|
/* is there a "previous" group defined? */
|
||||||
|
if (prev != NULL) {
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
/* disable the group at the MAC level */
|
||||||
|
if (netif->mld_mac_filter != NULL) {
|
||||||
|
netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER);
|
||||||
|
}
|
||||||
|
/* free group */
|
||||||
|
memp_free(MEMP_MLD6_GROUP, group);
|
||||||
|
} else {
|
||||||
|
/* change the "previous" */
|
||||||
|
prev = group;
|
||||||
|
}
|
||||||
|
/* move to "next" */
|
||||||
|
group = next;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report MLD memberships for this interface
|
||||||
|
*
|
||||||
|
* @param netif network interface on which report MLD memberships
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mld6_report_groups(struct netif *netif)
|
||||||
|
{
|
||||||
|
struct mld_group *group = mld_group_list;
|
||||||
|
|
||||||
|
while (group != NULL) {
|
||||||
|
if (group->netif == netif) {
|
||||||
|
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||||
|
}
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for a group that is joined on a netif
|
||||||
|
*
|
||||||
|
* @param ifp the network interface for which to look
|
||||||
|
* @param addr the group ipv6 address to search for
|
||||||
|
* @return a struct mld_group* if the group has been found,
|
||||||
|
* NULL if the group wasn't found.
|
||||||
|
*/
|
||||||
|
struct mld_group *
|
||||||
|
mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr)
|
||||||
|
{
|
||||||
|
struct mld_group *group = mld_group_list;
|
||||||
|
|
||||||
|
while (group != NULL) {
|
||||||
|
if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a new group
|
||||||
|
*
|
||||||
|
* @param ifp the network interface for which to create
|
||||||
|
* @param addr the new group ipv6
|
||||||
|
* @return a struct mld_group*,
|
||||||
|
* NULL on memory error.
|
||||||
|
*/
|
||||||
|
static struct mld_group *
|
||||||
|
mld6_new_group(struct netif *ifp, ip6_addr_t *addr)
|
||||||
|
{
|
||||||
|
struct mld_group *group;
|
||||||
|
|
||||||
|
group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP);
|
||||||
|
if (group != NULL) {
|
||||||
|
group->netif = ifp;
|
||||||
|
ip6_addr_set(&(group->group_address), addr);
|
||||||
|
group->timer = 0; /* Not running */
|
||||||
|
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||||
|
group->last_reporter_flag = 0;
|
||||||
|
group->use = 0;
|
||||||
|
group->next = mld_group_list;
|
||||||
|
|
||||||
|
mld_group_list = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a group in the mld_group_list and free
|
||||||
|
*
|
||||||
|
* @param group the group to remove
|
||||||
|
* @return ERR_OK if group was removed from the list, an err_t otherwise
|
||||||
|
*/
|
||||||
|
static err_t
|
||||||
|
mld6_free_group(struct mld_group *group)
|
||||||
|
{
|
||||||
|
err_t err = ERR_OK;
|
||||||
|
|
||||||
|
/* Is it the first group? */
|
||||||
|
if (mld_group_list == group) {
|
||||||
|
mld_group_list = group->next;
|
||||||
|
} else {
|
||||||
|
/* look for group further down the list */
|
||||||
|
struct mld_group *tmpGroup;
|
||||||
|
for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
||||||
|
if (tmpGroup->next == group) {
|
||||||
|
tmpGroup->next = group->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Group not find group */
|
||||||
|
if (tmpGroup == NULL)
|
||||||
|
err = ERR_ARG;
|
||||||
|
}
|
||||||
|
/* free group */
|
||||||
|
memp_free(MEMP_MLD6_GROUP, group);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an input MLD message. Called by icmp6_input.
|
||||||
|
*
|
||||||
|
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
||||||
|
* @param inp the netif on which this packet was received
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mld6_input(struct pbuf *p, struct netif *inp)
|
||||||
|
{
|
||||||
|
struct mld_header * mld_hdr;
|
||||||
|
struct mld_group* group;
|
||||||
|
|
||||||
|
MLD6_STATS_INC(mld6.recv);
|
||||||
|
|
||||||
|
/* Check that mld header fits in packet. */
|
||||||
|
if (p->len < sizeof(struct mld_header)) {
|
||||||
|
/* TODO debug message */
|
||||||
|
pbuf_free(p);
|
||||||
|
MLD6_STATS_INC(mld6.lenerr);
|
||||||
|
MLD6_STATS_INC(mld6.drop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mld_hdr = (struct mld_header *)p->payload;
|
||||||
|
|
||||||
|
switch (mld_hdr->type) {
|
||||||
|
case ICMP6_TYPE_MLQ: /* Multicast listener query. */
|
||||||
|
{
|
||||||
|
/* Is it a general query? */
|
||||||
|
if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
|
||||||
|
ip6_addr_isany(&(mld_hdr->multicast_address))) {
|
||||||
|
MLD6_STATS_INC(mld6.rx_general);
|
||||||
|
/* Report all groups, except all nodes group, and if-local groups. */
|
||||||
|
group = mld_group_list;
|
||||||
|
while (group != NULL) {
|
||||||
|
if ((group->netif == inp) &&
|
||||||
|
(!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
|
||||||
|
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
|
||||||
|
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
||||||
|
}
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Have we joined this group?
|
||||||
|
* We use IP6 destination address to have a memory aligned copy.
|
||||||
|
* mld_hdr->multicast_address should be the same. */
|
||||||
|
MLD6_STATS_INC(mld6.rx_group);
|
||||||
|
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
||||||
|
if (group != NULL) {
|
||||||
|
/* Schedule a report. */
|
||||||
|
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; /* ICMP6_TYPE_MLQ */
|
||||||
|
}
|
||||||
|
case ICMP6_TYPE_MLR: /* Multicast listener report. */
|
||||||
|
{
|
||||||
|
/* Have we joined this group?
|
||||||
|
* We use IP6 destination address to have a memory aligned copy.
|
||||||
|
* mld_hdr->multicast_address should be the same. */
|
||||||
|
MLD6_STATS_INC(mld6.rx_report);
|
||||||
|
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
||||||
|
if (group != NULL) {
|
||||||
|
/* If we are waiting to report, cancel it. */
|
||||||
|
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
||||||
|
group->timer = 0; /* stopped */
|
||||||
|
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||||
|
group->last_reporter_flag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; /* ICMP6_TYPE_MLR */
|
||||||
|
}
|
||||||
|
case ICMP6_TYPE_MLD: /* Multicast listener done. */
|
||||||
|
{
|
||||||
|
/* Do nothing, router will query us. */
|
||||||
|
break; /* ICMP6_TYPE_MLD */
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
MLD6_STATS_INC(mld6.proterr);
|
||||||
|
MLD6_STATS_INC(mld6.drop);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join a group on a network interface.
|
||||||
|
*
|
||||||
|
* @param srcaddr ipv6 address of the network interface which should
|
||||||
|
* join a new group. If IP6_ADDR_ANY, join on all netifs
|
||||||
|
* @param groupaddr the ipv6 address of the group to join
|
||||||
|
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr)
|
||||||
|
{
|
||||||
|
err_t err = ERR_VAL; /* no matching interface */
|
||||||
|
struct mld_group *group;
|
||||||
|
struct netif *netif;
|
||||||
|
u8_t match;
|
||||||
|
u8_t i;
|
||||||
|
|
||||||
|
/* loop through netif's */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
/* Should we join this interface ? */
|
||||||
|
match = 0;
|
||||||
|
if (ip6_addr_isany(srcaddr)) {
|
||||||
|
match = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
|
if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
/* find group or create a new one if not found */
|
||||||
|
group = mld6_lookfor_group(netif, groupaddr);
|
||||||
|
|
||||||
|
if (group == NULL) {
|
||||||
|
/* Joining a new group. Create a new group entry. */
|
||||||
|
group = mld6_new_group(netif, groupaddr);
|
||||||
|
if (group == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Activate this address on the MAC layer. */
|
||||||
|
if (netif->mld_mac_filter != NULL) {
|
||||||
|
netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report our membership. */
|
||||||
|
MLD6_STATS_INC(mld6.tx_report);
|
||||||
|
mld6_send(group, ICMP6_TYPE_MLR);
|
||||||
|
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment group use */
|
||||||
|
group->use++;
|
||||||
|
err = ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* proceed to next network interface */
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leave a group on a network interface.
|
||||||
|
*
|
||||||
|
* @param srcaddr ipv6 address of the network interface which should
|
||||||
|
* leave the group. If IP6_ISANY, leave on all netifs
|
||||||
|
* @param groupaddr the ipv6 address of the group to leave
|
||||||
|
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr)
|
||||||
|
{
|
||||||
|
err_t err = ERR_VAL; /* no matching interface */
|
||||||
|
struct mld_group *group;
|
||||||
|
struct netif *netif;
|
||||||
|
u8_t match;
|
||||||
|
u8_t i;
|
||||||
|
|
||||||
|
/* loop through netif's */
|
||||||
|
netif = netif_list;
|
||||||
|
while (netif != NULL) {
|
||||||
|
/* Should we leave this interface ? */
|
||||||
|
match = 0;
|
||||||
|
if (ip6_addr_isany(srcaddr)) {
|
||||||
|
match = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
|
if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
/* find group */
|
||||||
|
group = mld6_lookfor_group(netif, groupaddr);
|
||||||
|
|
||||||
|
if (group != NULL) {
|
||||||
|
/* Leave if there is no other use of the group */
|
||||||
|
if (group->use <= 1) {
|
||||||
|
/* If we are the last reporter for this group */
|
||||||
|
if (group->last_reporter_flag) {
|
||||||
|
MLD6_STATS_INC(mld6.tx_leave);
|
||||||
|
mld6_send(group, ICMP6_TYPE_MLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable the group at the MAC level */
|
||||||
|
if (netif->mld_mac_filter != NULL) {
|
||||||
|
netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the group */
|
||||||
|
mld6_free_group(group);
|
||||||
|
} else {
|
||||||
|
/* Decrement group use */
|
||||||
|
group->use--;
|
||||||
|
}
|
||||||
|
/* Leave on this interface */
|
||||||
|
err = ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* proceed to next network interface */
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Periodic timer for mld processing. Must be called every
|
||||||
|
* MLD6_TMR_INTERVAL milliseconds (100).
|
||||||
|
*
|
||||||
|
* When a delaying member expires, a membership report is sent.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mld6_tmr(void)
|
||||||
|
{
|
||||||
|
struct mld_group *group = mld_group_list;
|
||||||
|
|
||||||
|
while (group != NULL) {
|
||||||
|
if (group->timer > 0) {
|
||||||
|
group->timer--;
|
||||||
|
if (group->timer == 0) {
|
||||||
|
/* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
|
||||||
|
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
||||||
|
MLD6_STATS_INC(mld6.tx_report);
|
||||||
|
mld6_send(group, ICMP6_TYPE_MLR);
|
||||||
|
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a delayed membership report for a group
|
||||||
|
*
|
||||||
|
* @param group the mld_group for which "delaying" membership report
|
||||||
|
* should be sent
|
||||||
|
* @param maxresp the max resp delay provided in the query
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
mld6_delayed_report(struct mld_group *group, u16_t maxresp)
|
||||||
|
{
|
||||||
|
/* Convert maxresp from milliseconds to tmr ticks */
|
||||||
|
maxresp = maxresp / MLD6_TMR_INTERVAL;
|
||||||
|
if (maxresp == 0) {
|
||||||
|
maxresp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Randomize maxresp. */
|
||||||
|
maxresp = (LWIP_RAND() % (maxresp - 1)) + 1;
|
||||||
|
|
||||||
|
/* Apply timer value if no report has been scheduled already. */
|
||||||
|
if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) ||
|
||||||
|
((group->group_state == MLD6_GROUP_DELAYING_MEMBER) &&
|
||||||
|
((group->timer == 0) || (maxresp < group->timer)))) {
|
||||||
|
group->timer = maxresp;
|
||||||
|
group->group_state = MLD6_GROUP_DELAYING_MEMBER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a MLD message (report or done).
|
||||||
|
*
|
||||||
|
* An IPv6 hop-by-hop options header with a router alert option
|
||||||
|
* is prepended.
|
||||||
|
*
|
||||||
|
* @param group the group to report or quit
|
||||||
|
* @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
mld6_send(struct mld_group *group, u8_t type)
|
||||||
|
{
|
||||||
|
struct mld_header * mld_hdr;
|
||||||
|
struct pbuf * p;
|
||||||
|
ip6_addr_t * src_addr;
|
||||||
|
|
||||||
|
/* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */
|
||||||
|
p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM);
|
||||||
|
if ((p == NULL) || (p->len < (sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr)))) {
|
||||||
|
/* We couldn't allocate a suitable pbuf. drop it. */
|
||||||
|
if (p != NULL) {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
MLD6_STATS_INC(mld6.memerr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to make room for Hop-by-hop options header. */
|
||||||
|
if (pbuf_header(p, -IP6_HBH_HLEN)) {
|
||||||
|
pbuf_free(p);
|
||||||
|
MLD6_STATS_INC(mld6.lenerr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select our source address. */
|
||||||
|
if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
|
||||||
|
/* This is a special case, when we are performing duplicate address detection.
|
||||||
|
* We must join the multicast group, but we don't have a valid address yet. */
|
||||||
|
src_addr = IP6_ADDR_ANY;
|
||||||
|
} else {
|
||||||
|
/* Use link-local address as source address. */
|
||||||
|
src_addr = netif_ip6_addr(group->netif, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MLD message header pointer. */
|
||||||
|
mld_hdr = (struct mld_header *)p->payload;
|
||||||
|
|
||||||
|
/* Set fields. */
|
||||||
|
mld_hdr->type = type;
|
||||||
|
mld_hdr->code = 0;
|
||||||
|
mld_hdr->chksum = 0;
|
||||||
|
mld_hdr->max_resp_delay = 0;
|
||||||
|
mld_hdr->reserved = 0;
|
||||||
|
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
|
||||||
|
|
||||||
|
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
|
||||||
|
src_addr, &(group->group_address));
|
||||||
|
|
||||||
|
/* Add hop-by-hop headers options: router alert with MLD value. */
|
||||||
|
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
|
||||||
|
|
||||||
|
/* Send the packet out. */
|
||||||
|
MLD6_STATS_INC(mld6.xmit);
|
||||||
|
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
|
||||||
|
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif);
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
1730
src/core/ipv6/nd6.c
Normal file
1730
src/core/ipv6/nd6.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -78,9 +78,10 @@
|
|||||||
void *
|
void *
|
||||||
mem_malloc(mem_size_t size)
|
mem_malloc(mem_size_t size)
|
||||||
{
|
{
|
||||||
|
void *ret;
|
||||||
struct memp_malloc_helper *element;
|
struct memp_malloc_helper *element;
|
||||||
memp_t poolnr;
|
memp_t poolnr;
|
||||||
mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
|
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
||||||
|
|
||||||
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
|
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
|
||||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
||||||
@@ -113,9 +114,9 @@ again:
|
|||||||
/* save the pool number this element came from */
|
/* save the pool number this element came from */
|
||||||
element->poolnr = poolnr;
|
element->poolnr = poolnr;
|
||||||
/* and return a pointer to the memory directly after the struct memp_malloc_helper */
|
/* and return a pointer to the memory directly after the struct memp_malloc_helper */
|
||||||
element++;
|
ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
||||||
|
|
||||||
return element;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,13 +129,13 @@ again:
|
|||||||
void
|
void
|
||||||
mem_free(void *rmem)
|
mem_free(void *rmem)
|
||||||
{
|
{
|
||||||
struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
|
struct memp_malloc_helper *hmem;
|
||||||
|
|
||||||
LWIP_ASSERT("rmem != NULL", (rmem != NULL));
|
LWIP_ASSERT("rmem != NULL", (rmem != NULL));
|
||||||
LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
|
LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
|
||||||
|
|
||||||
/* get the original struct memp_malloc_helper */
|
/* get the original struct memp_malloc_helper */
|
||||||
hmem--;
|
hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)));
|
||||||
|
|
||||||
LWIP_ASSERT("hmem != NULL", (hmem != NULL));
|
LWIP_ASSERT("hmem != NULL", (hmem != NULL));
|
||||||
LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
|
LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
|
||||||
@@ -190,7 +191,9 @@ static struct mem *ram_end;
|
|||||||
static struct mem *lfree;
|
static struct mem *lfree;
|
||||||
|
|
||||||
/** concurrent access protection */
|
/** concurrent access protection */
|
||||||
|
#if !NO_SYS
|
||||||
static sys_mutex_t mem_mutex;
|
static sys_mutex_t mem_mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,9 @@
|
|||||||
#include "lwip/snmp_msg.h"
|
#include "lwip/snmp_msg.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#include "netif/ppp_oe.h"
|
#include "netif/ppp_oe.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/ip6_frag.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|||||||
126
src/core/netif.c
126
src/core/netif.c
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/tcp_impl.h"
|
#include "lwip/tcp_impl.h"
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
#endif /* LWIP_DHCP */
|
#endif /* LWIP_DHCP */
|
||||||
|
#if LWIP_IPV6_DHCP6
|
||||||
|
#include "lwip/dhcp6.h"
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
#if LWIP_NETIF_STATUS_CALLBACK
|
||||||
#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
|
#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
|
||||||
@@ -75,6 +82,8 @@
|
|||||||
struct netif *netif_list;
|
struct netif *netif_list;
|
||||||
struct netif *netif_default;
|
struct netif *netif_default;
|
||||||
|
|
||||||
|
static u8_t netif_num;
|
||||||
|
|
||||||
#if LWIP_HAVE_LOOPIF
|
#if LWIP_HAVE_LOOPIF
|
||||||
static struct netif loop_netif;
|
static struct netif loop_netif;
|
||||||
|
|
||||||
@@ -137,7 +146,9 @@ struct netif *
|
|||||||
netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||||
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
|
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
|
||||||
{
|
{
|
||||||
static u8_t netifnum = 0;
|
#if LWIP_IPV6
|
||||||
|
u32_t i;
|
||||||
|
#endif
|
||||||
|
|
||||||
LWIP_ASSERT("No init function given", init != NULL);
|
LWIP_ASSERT("No init function given", init != NULL);
|
||||||
|
|
||||||
@@ -145,6 +156,12 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
|||||||
ip_addr_set_zero(&netif->ip_addr);
|
ip_addr_set_zero(&netif->ip_addr);
|
||||||
ip_addr_set_zero(&netif->netmask);
|
ip_addr_set_zero(&netif->netmask);
|
||||||
ip_addr_set_zero(&netif->gw);
|
ip_addr_set_zero(&netif->gw);
|
||||||
|
#if LWIP_IPV6
|
||||||
|
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
|
ip6_addr_set_zero(&netif->ip6_addr[i]);
|
||||||
|
netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
netif->flags = 0;
|
netif->flags = 0;
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
/* netif not under DHCP control by default */
|
/* netif not under DHCP control by default */
|
||||||
@@ -154,6 +171,17 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
|||||||
/* netif not under AutoIP control by default */
|
/* netif not under AutoIP control by default */
|
||||||
netif->autoip = NULL;
|
netif->autoip = NULL;
|
||||||
#endif /* LWIP_AUTOIP */
|
#endif /* LWIP_AUTOIP */
|
||||||
|
#if LWIP_IPV6_AUTOCONFIG
|
||||||
|
/* IPv6 address autoconfiguration not enabled by default */
|
||||||
|
netif->ip6_autoconfig_enabled = 0;
|
||||||
|
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||||
|
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||||
|
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
|
||||||
|
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||||
|
#if LWIP_IPV6_DHCP6
|
||||||
|
/* netif not under DHCPv6 control by default */
|
||||||
|
netif->dhcp6 = NULL;
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
#if LWIP_NETIF_STATUS_CALLBACK
|
||||||
netif->status_callback = NULL;
|
netif->status_callback = NULL;
|
||||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||||
@@ -163,6 +191,9 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
|||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
netif->igmp_mac_filter = NULL;
|
netif->igmp_mac_filter = NULL;
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
netif->mld_mac_filter = NULL;
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
#if ENABLE_LOOPBACK
|
#if ENABLE_LOOPBACK
|
||||||
netif->loop_first = NULL;
|
netif->loop_first = NULL;
|
||||||
netif->loop_last = NULL;
|
netif->loop_last = NULL;
|
||||||
@@ -170,11 +201,9 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
|||||||
|
|
||||||
/* remember netif specific state information data */
|
/* remember netif specific state information data */
|
||||||
netif->state = state;
|
netif->state = state;
|
||||||
netif->num = netifnum++;
|
netif->num = netif_num++;
|
||||||
netif->input = input;
|
netif->input = input;
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||||
netif->addr_hint = NULL;
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
|
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
|
||||||
netif->loop_cnt_current = 0;
|
netif->loop_cnt_current = 0;
|
||||||
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
|
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
|
||||||
@@ -245,6 +274,10 @@ netif_remove(struct netif *netif)
|
|||||||
igmp_stop(netif);
|
igmp_stop(netif);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
/* stop MLD processing */
|
||||||
|
mld6_stop(netif);
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
if (netif_is_up(netif)) {
|
if (netif_is_up(netif)) {
|
||||||
/* set netif down before removing (call callback function) */
|
/* set netif down before removing (call callback function) */
|
||||||
netif_set_down(netif);
|
netif_set_down(netif);
|
||||||
@@ -331,10 +364,10 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
|||||||
pcb = tcp_active_pcbs;
|
pcb = tcp_active_pcbs;
|
||||||
while (pcb != NULL) {
|
while (pcb != NULL) {
|
||||||
/* PCB bound to current local interface address? */
|
/* PCB bound to current local interface address? */
|
||||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
|
if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr))
|
||||||
#if LWIP_AUTOIP
|
#if LWIP_AUTOIP
|
||||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||||
&& !ip_addr_islinklocal(&(pcb->local_ip))
|
&& !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip))
|
||||||
#endif /* LWIP_AUTOIP */
|
#endif /* LWIP_AUTOIP */
|
||||||
) {
|
) {
|
||||||
/* this connection must be aborted */
|
/* this connection must be aborted */
|
||||||
@@ -348,11 +381,11 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
|||||||
}
|
}
|
||||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||||
/* PCB bound to current local interface address? */
|
/* PCB bound to current local interface address? */
|
||||||
if ((!(ip_addr_isany(&(lpcb->local_ip)))) &&
|
if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) &&
|
||||||
(ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {
|
(ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) {
|
||||||
/* The PCB is listening to the old ipaddr and
|
/* The PCB is listening to the old ipaddr and
|
||||||
* is set to listen to the new one instead */
|
* is set to listen to the new one instead */
|
||||||
ip_addr_set(&(lpcb->local_ip), ipaddr);
|
ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,6 +504,16 @@ void netif_set_up(struct netif *netif)
|
|||||||
igmp_report_groups( netif);
|
igmp_report_groups( netif);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
/* send mld memberships */
|
||||||
|
mld6_report_groups( netif);
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
|
|
||||||
|
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||||
|
/* Send Router Solicitation messages. */
|
||||||
|
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
|
||||||
|
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,6 +584,10 @@ void netif_set_link_up(struct netif *netif )
|
|||||||
igmp_report_groups( netif);
|
igmp_report_groups( netif);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
/* send mld memberships */
|
||||||
|
mld6_report_groups( netif);
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
}
|
}
|
||||||
NETIF_LINK_CALLBACK(netif);
|
NETIF_LINK_CALLBACK(netif);
|
||||||
}
|
}
|
||||||
@@ -750,3 +797,62 @@ netif_poll_all(void)
|
|||||||
}
|
}
|
||||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
#endif /* ENABLE_LOOPBACK */
|
#endif /* ENABLE_LOOPBACK */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
s8_t
|
||||||
|
netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr)
|
||||||
|
{
|
||||||
|
s8_t i;
|
||||||
|
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
|
if (ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit)
|
||||||
|
{
|
||||||
|
u8_t i, addr_index;
|
||||||
|
|
||||||
|
/* Link-local prefix. */
|
||||||
|
netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul);
|
||||||
|
netif->ip6_addr[0].addr[1] = 0;
|
||||||
|
|
||||||
|
/* Generate interface ID. */
|
||||||
|
if (from_mac_48bit) {
|
||||||
|
/* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
|
||||||
|
netif->ip6_addr[0].addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
|
||||||
|
((u32_t)(netif->hwaddr[1]) << 16) |
|
||||||
|
((u32_t)(netif->hwaddr[2]) << 8) |
|
||||||
|
(0xff));
|
||||||
|
netif->ip6_addr[0].addr[3] = htonl((0xfeul << 24) |
|
||||||
|
((u32_t)(netif->hwaddr[3]) << 16) |
|
||||||
|
((u32_t)(netif->hwaddr[4]) << 8) |
|
||||||
|
(netif->hwaddr[5]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Use hwaddr directly as interface ID. */
|
||||||
|
netif->ip6_addr[0].addr[2] = 0;
|
||||||
|
netif->ip6_addr[0].addr[3] = 0;
|
||||||
|
|
||||||
|
addr_index = 3;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (i == 4) {
|
||||||
|
addr_index--;
|
||||||
|
}
|
||||||
|
netif->ip6_addr[0].addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set address state. */
|
||||||
|
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||||
|
/* Will perform duplicate address detection (DAD). */
|
||||||
|
netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
|
||||||
|
#else
|
||||||
|
/* Consider address valid. */
|
||||||
|
netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
|
||||||
|
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|||||||
@@ -190,21 +190,21 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
|
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||||
|
|
||||||
/* determine header offset */
|
/* determine header offset */
|
||||||
offset = 0;
|
|
||||||
switch (layer) {
|
switch (layer) {
|
||||||
case PBUF_TRANSPORT:
|
case PBUF_TRANSPORT:
|
||||||
/* add room for transport (often TCP) layer header */
|
/* add room for transport (often TCP) layer header */
|
||||||
offset += PBUF_TRANSPORT_HLEN;
|
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||||
/* FALLTHROUGH */
|
break;
|
||||||
case PBUF_IP:
|
case PBUF_IP:
|
||||||
/* add room for IP layer header */
|
/* add room for IP layer header */
|
||||||
offset += PBUF_IP_HLEN;
|
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||||
/* FALLTHROUGH */
|
break;
|
||||||
case PBUF_LINK:
|
case PBUF_LINK:
|
||||||
/* add room for link layer header */
|
/* add room for link layer header */
|
||||||
offset += PBUF_LINK_HLEN;
|
offset = PBUF_LINK_HLEN;
|
||||||
break;
|
break;
|
||||||
case PBUF_RAW:
|
case PBUF_RAW:
|
||||||
|
offset = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
||||||
@@ -348,21 +348,21 @@ pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_cust
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
|
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
|
||||||
|
|
||||||
/* determine header offset */
|
/* determine header offset */
|
||||||
offset = 0;
|
|
||||||
switch (l) {
|
switch (l) {
|
||||||
case PBUF_TRANSPORT:
|
case PBUF_TRANSPORT:
|
||||||
/* add room for transport (often TCP) layer header */
|
/* add room for transport (often TCP) layer header */
|
||||||
offset += PBUF_TRANSPORT_HLEN;
|
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||||
/* FALLTHROUGH */
|
break;
|
||||||
case PBUF_IP:
|
case PBUF_IP:
|
||||||
/* add room for IP layer header */
|
/* add room for IP layer header */
|
||||||
offset += PBUF_IP_HLEN;
|
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||||
/* FALLTHROUGH */
|
break;
|
||||||
case PBUF_LINK:
|
case PBUF_LINK:
|
||||||
/* add room for link layer header */
|
/* add room for link layer header */
|
||||||
offset += PBUF_LINK_HLEN;
|
offset = PBUF_LINK_HLEN;
|
||||||
break;
|
break;
|
||||||
case PBUF_RAW:
|
case PBUF_RAW:
|
||||||
|
offset = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
|
LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
|
||||||
|
|||||||
139
src/core/raw.c
139
src/core/raw.c
@@ -49,6 +49,8 @@
|
|||||||
#include "lwip/raw.h"
|
#include "lwip/raw.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "arch/perf.h"
|
#include "arch/perf.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -79,29 +81,47 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
s16_t proto;
|
s16_t proto;
|
||||||
u8_t eaten = 0;
|
u8_t eaten = 0;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct ip6_hdr *ip6hdr;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(inp);
|
LWIP_UNUSED_ARG(inp);
|
||||||
|
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
iphdr = (struct ip_hdr *)p->payload;
|
||||||
proto = IPH_PROTO(iphdr);
|
#if LWIP_IPV6
|
||||||
|
if (IPH_V(iphdr) == 6) {
|
||||||
|
ip6hdr = (struct ip6_hdr *)p->payload;
|
||||||
|
proto = IP6H_NEXTH(ip6hdr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
proto = IPH_PROTO(iphdr);
|
||||||
|
}
|
||||||
|
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
pcb = raw_pcbs;
|
pcb = raw_pcbs;
|
||||||
/* loop through all raw pcbs until the packet is eaten by one */
|
/* loop through all raw pcbs until the packet is eaten by one */
|
||||||
/* this allows multiple pcbs to match against the packet by design */
|
/* this allows multiple pcbs to match against the packet by design */
|
||||||
while ((eaten == 0) && (pcb != NULL)) {
|
while ((eaten == 0) && (pcb != NULL)) {
|
||||||
if ((pcb->protocol == proto) &&
|
if ((pcb->protocol == proto) && IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
(ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip) ||
|
||||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) {
|
ipX_addr_cmp(PCB_ISIPV6(pcb), &(pcb->local_ip), ipX_current_dest_addr()))) {
|
||||||
#if IP_SOF_BROADCAST_RECV
|
#if IP_SOF_BROADCAST_RECV
|
||||||
/* broadcast filter? */
|
/* broadcast filter? */
|
||||||
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp))
|
if (((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp))
|
||||||
|
#if LWIP_IPV6
|
||||||
|
&& !PCB_ISIPV6(pcb)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
)
|
||||||
#endif /* IP_SOF_BROADCAST_RECV */
|
#endif /* IP_SOF_BROADCAST_RECV */
|
||||||
{
|
{
|
||||||
/* receive callback function available? */
|
/* receive callback function available? */
|
||||||
if (pcb->recv != NULL) {
|
if (pcb->recv.ip4 != NULL) {
|
||||||
/* the receive callback function did not eat the packet? */
|
/* the receive callback function did not eat the packet? */
|
||||||
if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) {
|
eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||||
|
if (eaten != 0) {
|
||||||
/* receive function ate the packet */
|
/* receive function ate the packet */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
eaten = 1;
|
eaten = 1;
|
||||||
@@ -141,7 +161,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
err_t
|
err_t
|
||||||
raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||||
{
|
{
|
||||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +181,7 @@ raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
|||||||
err_t
|
err_t
|
||||||
raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||||
{
|
{
|
||||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +203,7 @@ void
|
|||||||
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
|
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
|
||||||
{
|
{
|
||||||
/* remember recv() callback and user data */
|
/* remember recv() callback and user data */
|
||||||
pcb->recv = recv;
|
pcb->recv.ip4 = recv;
|
||||||
pcb->recv_arg = recv_arg;
|
pcb->recv_arg = recv_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,13 +224,21 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
|||||||
{
|
{
|
||||||
err_t err;
|
err_t err;
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
ip_addr_t *src_ip;
|
ipX_addr_t *src_ip;
|
||||||
struct pbuf *q; /* q will be sent down the stack */
|
struct pbuf *q; /* q will be sent down the stack */
|
||||||
|
s16_t header_size;
|
||||||
|
ipX_addr_t *dst_ip = ip_2_ipX(ipaddr);
|
||||||
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||||
|
|
||||||
|
header_size = (
|
||||||
|
#if LWIP_IPV6
|
||||||
|
PCB_ISIPV6(pcb) ? IP6_HLEN :
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
IP_HLEN);
|
||||||
|
|
||||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||||
if (pbuf_header(p, IP_HLEN)) {
|
if (pbuf_header(p, header_size)) {
|
||||||
/* allocate header in new pbuf */
|
/* allocate header in new pbuf */
|
||||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||||
/* new header pbuf could not be allocated? */
|
/* new header pbuf could not be allocated? */
|
||||||
@@ -218,22 +246,25 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
|||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
/* chain header q in front of given pbuf p */
|
if (p->tot_len != 0) {
|
||||||
pbuf_chain(q, p);
|
/* chain header q in front of given pbuf p */
|
||||||
|
pbuf_chain(q, p);
|
||||||
|
}
|
||||||
/* { first pbuf q points to header pbuf } */
|
/* { first pbuf q points to header pbuf } */
|
||||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||||
} else {
|
} else {
|
||||||
/* first pbuf q equals given pbuf */
|
/* first pbuf q equals given pbuf */
|
||||||
q = p;
|
q = p;
|
||||||
if(pbuf_header(q, -IP_HLEN)) {
|
if(pbuf_header(q, -header_size)) {
|
||||||
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip);
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
if (netif == NULL) {
|
||||||
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
|
||||||
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
|
||||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||||
if (q != p) {
|
if (q != p) {
|
||||||
pbuf_free(q);
|
pbuf_free(q);
|
||||||
@@ -242,32 +273,42 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if IP_SOF_BROADCAST
|
#if IP_SOF_BROADCAST
|
||||||
/* broadcast filter? */
|
#if LWIP_IPV6
|
||||||
if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
|
/* @todo: why does IPv6 not filter broadcast with SOF_BROADCAST enabled? */
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
if (!PCB_ISIPV6(pcb))
|
||||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
#endif /* LWIP_IPV6 */
|
||||||
if (q != p) {
|
{
|
||||||
pbuf_free(q);
|
/* broadcast filter? */
|
||||||
|
if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
|
||||||
|
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||||
|
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||||
|
if (q != p) {
|
||||||
|
pbuf_free(q);
|
||||||
|
}
|
||||||
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
return ERR_VAL;
|
|
||||||
}
|
}
|
||||||
#endif /* IP_SOF_BROADCAST */
|
#endif /* IP_SOF_BROADCAST */
|
||||||
|
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
|
||||||
/* use outgoing network interface IP address as source address */
|
/* use outgoing network interface IP address as source address */
|
||||||
src_ip = &(netif->ip_addr);
|
src_ip = ipX_netif_get_local_ipX(PCB_ISIPV6(pcb), netif, dst_ip);
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if (src_ip == NULL) {
|
||||||
|
if (q != p) {
|
||||||
|
pbuf_free(q);
|
||||||
|
}
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
} else {
|
} else {
|
||||||
/* use RAW PCB local IP address as source address */
|
/* use RAW PCB local IP address as source address */
|
||||||
src_ip = &(pcb->local_ip);
|
src_ip = &pcb->local_ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
||||||
netif->addr_hint = &(pcb->addr_hint);
|
err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
netif->addr_hint = NULL;
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
|
|
||||||
/* did we chain a header earlier? */
|
/* did we chain a header earlier? */
|
||||||
if (q != p) {
|
if (q != p) {
|
||||||
@@ -287,7 +328,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
|||||||
err_t
|
err_t
|
||||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||||
{
|
{
|
||||||
return raw_sendto(pcb, p, &pcb->remote_ip);
|
return raw_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,4 +390,26 @@ raw_new(u8_t proto)
|
|||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Create a RAW PCB for IPv6.
|
||||||
|
*
|
||||||
|
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||||
|
* could not be allocated.
|
||||||
|
*
|
||||||
|
* @param proto the protocol number (next header) of the IPv6 packet payload
|
||||||
|
* (e.g. IP6_NEXTH_ICMP6)
|
||||||
|
*
|
||||||
|
* @see raw_remove()
|
||||||
|
*/
|
||||||
|
struct raw_pcb *
|
||||||
|
raw_new_ip6(u8_t proto)
|
||||||
|
{
|
||||||
|
struct raw_pcb *pcb;
|
||||||
|
pcb = raw_new(proto);
|
||||||
|
ip_set_v6(pcb, 1);
|
||||||
|
return pcb;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
|
|||||||
@@ -43,10 +43,12 @@
|
|||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/ip_frag.h"
|
#include "lwip/ip_frag.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
#include "lwip/tcp_impl.h"
|
#include "lwip/tcp_impl.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/snmp_asn1.h"
|
#include "lwip/snmp_asn1.h"
|
||||||
#include "lwip/snmp_structs.h"
|
#include "lwip/snmp_structs.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +73,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SNMP_GET_SYSUPTIME
|
#ifndef SNMP_GET_SYSUPTIME
|
||||||
#define SNMP_GET_SYSUPTIME(sysuptime)
|
#define SNMP_GET_SYSUPTIME(sysuptime) (sysuptime = (sys_now() / 10))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||||
@@ -1795,7 +1797,7 @@ void snmp_insert_udpidx_tree(struct udp_pcb *pcb)
|
|||||||
u8_t level;
|
u8_t level;
|
||||||
|
|
||||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||||
snmp_iptooid(&pcb->local_ip, &udpidx[0]);
|
snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]);
|
||||||
udpidx[4] = pcb->local_port;
|
udpidx[4] = pcb->local_port;
|
||||||
|
|
||||||
udp_rn = &udp_root;
|
udp_rn = &udp_root;
|
||||||
@@ -1848,7 +1850,7 @@ void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
|
|||||||
u8_t bindings, fc, level, del_cnt;
|
u8_t bindings, fc, level, del_cnt;
|
||||||
|
|
||||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||||
snmp_iptooid(&pcb->local_ip, &udpidx[0]);
|
snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]);
|
||||||
udpidx[4] = pcb->local_port;
|
udpidx[4] = pcb->local_port;
|
||||||
|
|
||||||
/* count PCBs for a given binding
|
/* count PCBs for a given binding
|
||||||
@@ -1857,7 +1859,7 @@ void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
|
|||||||
npcb = udp_pcbs;
|
npcb = udp_pcbs;
|
||||||
while ((npcb != NULL))
|
while ((npcb != NULL))
|
||||||
{
|
{
|
||||||
if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) &&
|
if (ipX_addr_cmp(0, &npcb->local_ip, &pcb->local_ip) &&
|
||||||
(npcb->local_port == udpidx[4]))
|
(npcb->local_port == udpidx[4]))
|
||||||
{
|
{
|
||||||
bindings++;
|
bindings++;
|
||||||
@@ -3879,17 +3881,17 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
|
|||||||
{
|
{
|
||||||
u8_t id;
|
u8_t id;
|
||||||
struct udp_pcb *pcb;
|
struct udp_pcb *pcb;
|
||||||
ip_addr_t ip;
|
ipX_addr_t ip;
|
||||||
u16_t port;
|
u16_t port;
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(len);
|
LWIP_UNUSED_ARG(len);
|
||||||
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
|
snmp_oidtoip(&od->id_inst_ptr[1], (ip_addr_t*)&ip);
|
||||||
LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff));
|
LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff));
|
||||||
port = (u16_t)od->id_inst_ptr[5];
|
port = (u16_t)od->id_inst_ptr[5];
|
||||||
|
|
||||||
pcb = udp_pcbs;
|
pcb = udp_pcbs;
|
||||||
while ((pcb != NULL) &&
|
while ((pcb != NULL) &&
|
||||||
!(ip_addr_cmp(&pcb->local_ip, &ip) &&
|
!(ipX_addr_cmp(0, &pcb->local_ip, &ip) &&
|
||||||
(pcb->local_port == port)))
|
(pcb->local_port == port)))
|
||||||
{
|
{
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
@@ -3903,8 +3905,8 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
|
|||||||
{
|
{
|
||||||
case 1: /* udpLocalAddress */
|
case 1: /* udpLocalAddress */
|
||||||
{
|
{
|
||||||
ip_addr_t *dst = (ip_addr_t*)value;
|
ipX_addr_t *dst = (ipX_addr_t*)value;
|
||||||
*dst = pcb->local_ip;
|
ipX_addr_copy(0, *dst, pcb->local_ip);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: /* udpLocalPort */
|
case 2: /* udpLocalPort */
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void stats_init(void)
|
|||||||
|
|
||||||
#if LWIP_STATS_DISPLAY
|
#if LWIP_STATS_DISPLAY
|
||||||
void
|
void
|
||||||
stats_display_proto(struct stats_proto *proto, char *name)
|
stats_display_proto(struct stats_proto *proto, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
||||||
@@ -88,9 +88,9 @@ stats_display_proto(struct stats_proto *proto, char *name)
|
|||||||
|
|
||||||
#if IGMP_STATS
|
#if IGMP_STATS
|
||||||
void
|
void
|
||||||
stats_display_igmp(struct stats_igmp *igmp)
|
stats_display_igmp(struct stats_igmp *igmp, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\nIGMP\n\t"));
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
||||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
||||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
||||||
@@ -110,7 +110,7 @@ stats_display_igmp(struct stats_igmp *igmp)
|
|||||||
|
|
||||||
#if MEM_STATS || MEMP_STATS
|
#if MEM_STATS || MEMP_STATS
|
||||||
void
|
void
|
||||||
stats_display_mem(struct stats_mem *mem, char *name)
|
stats_display_mem(struct stats_mem *mem, const char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
||||||
@@ -159,9 +159,14 @@ stats_display(void)
|
|||||||
LINK_STATS_DISPLAY();
|
LINK_STATS_DISPLAY();
|
||||||
ETHARP_STATS_DISPLAY();
|
ETHARP_STATS_DISPLAY();
|
||||||
IPFRAG_STATS_DISPLAY();
|
IPFRAG_STATS_DISPLAY();
|
||||||
|
IP6_FRAG_STATS_DISPLAY();
|
||||||
IP_STATS_DISPLAY();
|
IP_STATS_DISPLAY();
|
||||||
|
ND6_STATS_DISPLAY();
|
||||||
|
IP6_STATS_DISPLAY();
|
||||||
IGMP_STATS_DISPLAY();
|
IGMP_STATS_DISPLAY();
|
||||||
|
MLD6_STATS_DISPLAY();
|
||||||
ICMP_STATS_DISPLAY();
|
ICMP_STATS_DISPLAY();
|
||||||
|
ICMP6_STATS_DISPLAY();
|
||||||
UDP_STATS_DISPLAY();
|
UDP_STATS_DISPLAY();
|
||||||
TCP_STATS_DISPLAY();
|
TCP_STATS_DISPLAY();
|
||||||
MEM_STATS_DISPLAY();
|
MEM_STATS_DISPLAY();
|
||||||
|
|||||||
220
src/core/tcp.c
220
src/core/tcp.c
@@ -52,6 +52,9 @@
|
|||||||
#include "lwip/tcp_impl.h"
|
#include "lwip/tcp_impl.h"
|
||||||
#include "lwip/debug.h"
|
#include "lwip/debug.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -91,7 +94,7 @@ struct tcp_pcb *tcp_tw_pcbs;
|
|||||||
#define NUM_TCP_PCB_LISTS 4
|
#define NUM_TCP_PCB_LISTS 4
|
||||||
#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
|
#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
|
||||||
/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
|
/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
|
||||||
struct tcp_pcb **tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
|
struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
|
||||||
&tcp_active_pcbs, &tcp_tw_pcbs};
|
&tcp_active_pcbs, &tcp_tw_pcbs};
|
||||||
|
|
||||||
/** Only used for temporary storage. */
|
/** Only used for temporary storage. */
|
||||||
@@ -148,7 +151,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
|||||||
/* don't call tcp_abort here: we must not deallocate the pcb since
|
/* don't call tcp_abort here: we must not deallocate the pcb since
|
||||||
that might not be expected when calling tcp_close */
|
that might not be expected when calling tcp_close */
|
||||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->local_port, pcb->remote_port);
|
pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb));
|
||||||
|
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
|
|
||||||
@@ -173,7 +176,9 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
|||||||
* is erroneous, but this should never happen as the pcb has in those cases
|
* is erroneous, but this should never happen as the pcb has in those cases
|
||||||
* been freed, and so any remaining handles are bogus. */
|
* been freed, and so any remaining handles are bogus. */
|
||||||
err = ERR_OK;
|
err = ERR_OK;
|
||||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
if (pcb->local_port != 0) {
|
||||||
|
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||||
|
}
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
pcb = NULL;
|
pcb = NULL;
|
||||||
break;
|
break;
|
||||||
@@ -316,8 +321,6 @@ void
|
|||||||
tcp_abandon(struct tcp_pcb *pcb, int reset)
|
tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||||
{
|
{
|
||||||
u32_t seqno, ackno;
|
u32_t seqno, ackno;
|
||||||
u16_t remote_port, local_port;
|
|
||||||
ip_addr_t remote_ip, local_ip;
|
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
tcp_err_fn errf;
|
tcp_err_fn errf;
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
@@ -335,10 +338,6 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
|||||||
} else {
|
} else {
|
||||||
seqno = pcb->snd_nxt;
|
seqno = pcb->snd_nxt;
|
||||||
ackno = pcb->rcv_nxt;
|
ackno = pcb->rcv_nxt;
|
||||||
ip_addr_copy(local_ip, pcb->local_ip);
|
|
||||||
ip_addr_copy(remote_ip, pcb->remote_ip);
|
|
||||||
local_port = pcb->local_port;
|
|
||||||
remote_port = pcb->remote_port;
|
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
errf = pcb->errf;
|
errf = pcb->errf;
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
@@ -355,12 +354,12 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
|||||||
tcp_segs_free(pcb->ooseq);
|
tcp_segs_free(pcb->ooseq);
|
||||||
}
|
}
|
||||||
#endif /* TCP_QUEUE_OOSEQ */
|
#endif /* TCP_QUEUE_OOSEQ */
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
|
||||||
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
|
||||||
if (reset) {
|
if (reset) {
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||||
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
|
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb));
|
||||||
}
|
}
|
||||||
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
|
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,6 +390,7 @@ tcp_abort(struct tcp_pcb *pcb)
|
|||||||
* to any local address
|
* to any local address
|
||||||
* @param port the local port to bind to
|
* @param port the local port to bind to
|
||||||
* @return ERR_USE if the port is already in use
|
* @return ERR_USE if the port is already in use
|
||||||
|
* ERR_VAL if bind failed because the PCB is not in a valid state
|
||||||
* ERR_OK if bound
|
* ERR_OK if bound
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
@@ -400,7 +400,7 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
int max_pcb_list = NUM_TCP_PCB_LISTS;
|
int max_pcb_list = NUM_TCP_PCB_LISTS;
|
||||||
struct tcp_pcb *cpcb;
|
struct tcp_pcb *cpcb;
|
||||||
|
|
||||||
LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
|
LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL);
|
||||||
|
|
||||||
#if SO_REUSE
|
#if SO_REUSE
|
||||||
/* Unless the REUSEADDR flag is set,
|
/* Unless the REUSEADDR flag is set,
|
||||||
@@ -408,11 +408,9 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
We do not dump TIME_WAIT pcb's; they can still be matched by incoming
|
We do not dump TIME_WAIT pcb's; they can still be matched by incoming
|
||||||
packets using both local and remote IP addresses and ports to distinguish.
|
packets using both local and remote IP addresses and ports to distinguish.
|
||||||
*/
|
*/
|
||||||
#if SO_REUSE
|
|
||||||
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
|
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
|
||||||
max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
|
max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
|
||||||
}
|
}
|
||||||
#endif /* SO_REUSE */
|
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
@@ -431,9 +429,11 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
((cpcb->so_options & SOF_REUSEADDR) == 0))
|
((cpcb->so_options & SOF_REUSEADDR) == 0))
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
{
|
{
|
||||||
if (ip_addr_isany(&(cpcb->local_ip)) ||
|
/* @todo: check accept_any_ip_version */
|
||||||
ip_addr_isany(ipaddr) ||
|
if (IP_PCB_IPVER_EQ(pcb, cpcb) &&
|
||||||
ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
(ipX_addr_isany(PCB_ISIPV6(pcb), &cpcb->local_ip) ||
|
||||||
|
ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr)) ||
|
||||||
|
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, ip_2_ipX(ipaddr)))) {
|
||||||
return ERR_USE;
|
return ERR_USE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,8 +441,8 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ip_addr_isany(ipaddr)) {
|
if (!ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr))) {
|
||||||
pcb->local_ip = *ipaddr;
|
ipX_addr_set(PCB_ISIPV6(pcb), &pcb->local_ip, ip_2_ipX(ipaddr));
|
||||||
}
|
}
|
||||||
pcb->local_port = port;
|
pcb->local_port = port;
|
||||||
TCP_REG(&tcp_bound_pcbs, pcb);
|
TCP_REG(&tcp_bound_pcbs, pcb);
|
||||||
@@ -496,8 +496,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||||||
is declared (listen-/connection-pcb), we have to make sure now that
|
is declared (listen-/connection-pcb), we have to make sure now that
|
||||||
this port is only used once for every local IP. */
|
this port is only used once for every local IP. */
|
||||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||||
if (lpcb->local_port == pcb->local_port) {
|
if ((lpcb->local_port == pcb->local_port) &&
|
||||||
if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
IP_PCB_IPVER_EQ(pcb, lpcb)) {
|
||||||
|
if (ipX_addr_cmp(PCB_ISIPV6(pcb), &lpcb->local_ip, &pcb->local_ip)) {
|
||||||
/* this address/port is already used */
|
/* this address/port is already used */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -517,8 +518,14 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||||||
lpcb->so_options |= SOF_ACCEPTCONN;
|
lpcb->so_options |= SOF_ACCEPTCONN;
|
||||||
lpcb->ttl = pcb->ttl;
|
lpcb->ttl = pcb->ttl;
|
||||||
lpcb->tos = pcb->tos;
|
lpcb->tos = pcb->tos;
|
||||||
ip_addr_copy(lpcb->local_ip, pcb->local_ip);
|
#if LWIP_IPV6
|
||||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
PCB_ISIPV6(lpcb) = PCB_ISIPV6(pcb);
|
||||||
|
lpcb->accept_any_ip_version = 0;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip);
|
||||||
|
if (pcb->local_port != 0) {
|
||||||
|
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||||
|
}
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
lpcb->accept = tcp_accept_null;
|
lpcb->accept = tcp_accept_null;
|
||||||
@@ -531,7 +538,28 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||||||
return (struct tcp_pcb *)lpcb;
|
return (struct tcp_pcb *)lpcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Same as tcp_listen_with_backlog, but allows to accept IPv4 and IPv6
|
||||||
|
* connections, if the pcb's local address is set to ANY.
|
||||||
|
*/
|
||||||
|
struct tcp_pcb *
|
||||||
|
tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||||
|
{
|
||||||
|
struct tcp_pcb *lpcb;
|
||||||
|
|
||||||
|
if (!ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lpcb = tcp_listen_with_backlog(pcb, backlog);
|
||||||
|
if (lpcb != NULL) {
|
||||||
|
((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1;
|
||||||
|
}
|
||||||
|
return lpcb;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
/**
|
||||||
* Update the state that tracks the available window space to advertise.
|
* Update the state that tracks the available window space to advertise.
|
||||||
*
|
*
|
||||||
* Returns how much extra window would be advertised if we sent an
|
* Returns how much extra window would be advertised if we sent an
|
||||||
@@ -573,6 +601,9 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
|||||||
{
|
{
|
||||||
int wnd_inflation;
|
int wnd_inflation;
|
||||||
|
|
||||||
|
/* pcb->state LISTEN not allowed here */
|
||||||
|
LWIP_ASSERT("don't call tcp_recved for listen-pcbs",
|
||||||
|
pcb->state != LISTEN);
|
||||||
LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n",
|
LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n",
|
||||||
len <= 0xffff - pcb->rcv_wnd );
|
len <= 0xffff - pcb->rcv_wnd );
|
||||||
|
|
||||||
@@ -608,17 +639,19 @@ tcp_new_port(void)
|
|||||||
int i;
|
int i;
|
||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
#ifndef TCP_LOCAL_PORT_RANGE_START
|
#ifndef TCP_LOCAL_PORT_RANGE_START
|
||||||
#define TCP_LOCAL_PORT_RANGE_START 4096
|
/* From http://www.iana.org/assignments/port-numbers:
|
||||||
#define TCP_LOCAL_PORT_RANGE_END 0x7fff
|
"The Dynamic and/or Private Ports are those from 49152 through 65535" */
|
||||||
|
#define TCP_LOCAL_PORT_RANGE_START 0xc000
|
||||||
|
#define TCP_LOCAL_PORT_RANGE_END 0xffff
|
||||||
#endif
|
#endif
|
||||||
static u16_t port = TCP_LOCAL_PORT_RANGE_START;
|
static u16_t port = TCP_LOCAL_PORT_RANGE_START;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (++port > TCP_LOCAL_PORT_RANGE_END) {
|
if (port++ == TCP_LOCAL_PORT_RANGE_END) {
|
||||||
port = TCP_LOCAL_PORT_RANGE_START;
|
port = TCP_LOCAL_PORT_RANGE_START;
|
||||||
}
|
}
|
||||||
/* Check all PCB lists. */
|
/* Check all PCB lists. */
|
||||||
for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {
|
for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
|
||||||
for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
|
for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
|
||||||
if (pcb->local_port == port) {
|
if (pcb->local_port == port) {
|
||||||
goto again;
|
goto again;
|
||||||
@@ -646,30 +679,34 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
{
|
{
|
||||||
err_t ret;
|
err_t ret;
|
||||||
u32_t iss;
|
u32_t iss;
|
||||||
|
u16_t old_local_port;
|
||||||
|
|
||||||
LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
|
LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
||||||
if (ipaddr != NULL) {
|
if (ipaddr != NULL) {
|
||||||
pcb->remote_ip = *ipaddr;
|
ipX_addr_set(PCB_ISIPV6(pcb), &pcb->remote_ip, ip_2_ipX(ipaddr));
|
||||||
} else {
|
} else {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
pcb->remote_port = port;
|
pcb->remote_port = port;
|
||||||
|
|
||||||
/* check if we have a route to the remote host */
|
/* check if we have a route to the remote host */
|
||||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
|
||||||
/* no local IP address set, yet. */
|
/* no local IP address set, yet. */
|
||||||
struct netif *netif = ip_route(&(pcb->remote_ip));
|
struct netif *netif;
|
||||||
if (netif == NULL) {
|
ipX_addr_t *local_ip;
|
||||||
|
ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
||||||
|
if ((netif == NULL) || (local_ip == NULL)) {
|
||||||
/* Don't even try to send a SYN packet if we have no route
|
/* Don't even try to send a SYN packet if we have no route
|
||||||
since that will fail. */
|
since that will fail. */
|
||||||
return ERR_RTE;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
/* Use the netif's IP address as local address. */
|
/* Use the address as local address of the pcb. */
|
||||||
ip_addr_copy(pcb->local_ip, netif->ip_addr);
|
ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_local_port = pcb->local_port;
|
||||||
if (pcb->local_port == 0) {
|
if (pcb->local_port == 0) {
|
||||||
pcb->local_port = tcp_new_port();
|
pcb->local_port = tcp_new_port();
|
||||||
}
|
}
|
||||||
@@ -679,13 +716,14 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
now that the 5-tuple is unique. */
|
now that the 5-tuple is unique. */
|
||||||
struct tcp_pcb *cpcb;
|
struct tcp_pcb *cpcb;
|
||||||
int i;
|
int i;
|
||||||
/* Don't check listen PCBs, check bound-, active- and TIME-WAIT PCBs. */
|
/* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */
|
||||||
for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {
|
for (i = 2; i < NUM_TCP_PCB_LISTS; i++) {
|
||||||
for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
||||||
if ((cpcb->local_port == pcb->local_port) &&
|
if ((cpcb->local_port == pcb->local_port) &&
|
||||||
(cpcb->remote_port == port) &&
|
(cpcb->remote_port == port) &&
|
||||||
ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
|
IP_PCB_IPVER_EQ(cpcb, pcb) &&
|
||||||
ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
|
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, &pcb->local_ip) &&
|
||||||
|
ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->remote_ip, ip_2_ipX(ipaddr))) {
|
||||||
/* linux returns EISCONN here, but ERR_USE should be OK for us */
|
/* linux returns EISCONN here, but ERR_USE should be OK for us */
|
||||||
return ERR_USE;
|
return ERR_USE;
|
||||||
}
|
}
|
||||||
@@ -706,13 +744,13 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
The send MSS is updated when an MSS option is received. */
|
The send MSS is updated when an MSS option is received. */
|
||||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
|
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb));
|
||||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||||
pcb->cwnd = 1;
|
pcb->cwnd = 1;
|
||||||
pcb->ssthresh = pcb->mss * 10;
|
pcb->ssthresh = pcb->mss * 10;
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
pcb->connected = connected;
|
pcb->connected = connected;
|
||||||
#else /* LWIP_CALLBACK_API */
|
#else /* LWIP_CALLBACK_API */
|
||||||
LWIP_UNUSED_ARG(connected);
|
LWIP_UNUSED_ARG(connected);
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
|
|
||||||
@@ -721,7 +759,9 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
if (ret == ERR_OK) {
|
if (ret == ERR_OK) {
|
||||||
/* SYN segment was enqueued, changed the pcbs state now */
|
/* SYN segment was enqueued, changed the pcbs state now */
|
||||||
pcb->state = SYN_SENT;
|
pcb->state = SYN_SENT;
|
||||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
if (old_local_port != 0) {
|
||||||
|
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||||
|
}
|
||||||
TCP_REG(&tcp_active_pcbs, pcb);
|
TCP_REG(&tcp_active_pcbs, pcb);
|
||||||
snmp_inc_tcpactiveopens();
|
snmp_inc_tcpactiveopens();
|
||||||
|
|
||||||
@@ -740,7 +780,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
void
|
void
|
||||||
tcp_slowtmr(void)
|
tcp_slowtmr(void)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb, *pcb2, *prev;
|
struct tcp_pcb *pcb, *prev;
|
||||||
u16_t eff_wnd;
|
u16_t eff_wnd;
|
||||||
u8_t pcb_remove; /* flag if a PCB should be removed */
|
u8_t pcb_remove; /* flag if a PCB should be removed */
|
||||||
u8_t pcb_reset; /* flag if a RST should be sent when removing */
|
u8_t pcb_reset; /* flag if a RST should be sent when removing */
|
||||||
@@ -843,9 +883,9 @@ tcp_slowtmr(void)
|
|||||||
(pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
|
(pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
|
||||||
#endif /* LWIP_TCP_KEEPALIVE */
|
#endif /* LWIP_TCP_KEEPALIVE */
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to "));
|
||||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip);
|
||||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||||
|
|
||||||
++pcb_remove;
|
++pcb_remove;
|
||||||
++pcb_reset;
|
++pcb_reset;
|
||||||
@@ -896,6 +936,7 @@ tcp_slowtmr(void)
|
|||||||
|
|
||||||
/* If the PCB should be removed, do it. */
|
/* If the PCB should be removed, do it. */
|
||||||
if (pcb_remove) {
|
if (pcb_remove) {
|
||||||
|
struct tcp_pcb *pcb2;
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
/* Remove PCB from tcp_active_pcbs list. */
|
/* Remove PCB from tcp_active_pcbs list. */
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
@@ -910,12 +951,12 @@ tcp_slowtmr(void)
|
|||||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
|
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
|
||||||
if (pcb_reset) {
|
if (pcb_reset) {
|
||||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->local_port, pcb->remote_port);
|
pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb));
|
||||||
}
|
}
|
||||||
|
|
||||||
pcb2 = pcb->next;
|
pcb2 = pcb;
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
pcb = pcb->next;
|
||||||
pcb = pcb2;
|
memp_free(MEMP_TCP_PCB, pcb2);
|
||||||
} else {
|
} else {
|
||||||
/* get the 'next' element now and work with 'prev' below (in case of abort) */
|
/* get the 'next' element now and work with 'prev' below (in case of abort) */
|
||||||
prev = pcb;
|
prev = pcb;
|
||||||
@@ -937,7 +978,7 @@ tcp_slowtmr(void)
|
|||||||
|
|
||||||
|
|
||||||
/* Steps through all of the TIME-WAIT PCBs. */
|
/* Steps through all of the TIME-WAIT PCBs. */
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
pcb = tcp_tw_pcbs;
|
pcb = tcp_tw_pcbs;
|
||||||
while (pcb != NULL) {
|
while (pcb != NULL) {
|
||||||
LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||||
@@ -952,6 +993,7 @@ tcp_slowtmr(void)
|
|||||||
|
|
||||||
/* If the PCB should be removed, do it. */
|
/* If the PCB should be removed, do it. */
|
||||||
if (pcb_remove) {
|
if (pcb_remove) {
|
||||||
|
struct tcp_pcb *pcb2;
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
/* Remove PCB from tcp_tw_pcbs list. */
|
/* Remove PCB from tcp_tw_pcbs list. */
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
@@ -962,9 +1004,9 @@ tcp_slowtmr(void)
|
|||||||
LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
|
LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
|
||||||
tcp_tw_pcbs = pcb->next;
|
tcp_tw_pcbs = pcb->next;
|
||||||
}
|
}
|
||||||
pcb2 = pcb->next;
|
pcb2 = pcb;
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
pcb = pcb->next;
|
||||||
pcb = pcb2;
|
memp_free(MEMP_TCP_PCB, pcb2);
|
||||||
} else {
|
} else {
|
||||||
prev = pcb;
|
prev = pcb;
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
@@ -999,7 +1041,7 @@ tcp_fasttmr(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send delayed ACKs */
|
/* send delayed ACKs */
|
||||||
if (pcb && (pcb->flags & TF_ACK_DELAY)) {
|
if (pcb && (pcb->flags & TF_ACK_DELAY)) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
@@ -1100,7 +1142,8 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
|||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kills the oldest active connection that has lower priority than prio.
|
* Kills the oldest active connection that has the same or lower priority than
|
||||||
|
* 'prio'.
|
||||||
*
|
*
|
||||||
* @param prio minimum priority
|
* @param prio minimum priority
|
||||||
*/
|
*/
|
||||||
@@ -1255,6 +1298,24 @@ tcp_new(void)
|
|||||||
return tcp_alloc(TCP_PRIO_NORMAL);
|
return tcp_alloc(TCP_PRIO_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Creates a new TCP-over-IPv6 protocol control block but doesn't
|
||||||
|
* place it on any of the TCP PCB lists.
|
||||||
|
* The pcb is not put on any list until binding using tcp_bind().
|
||||||
|
*
|
||||||
|
* @return a new tcp_pcb that initially is in state CLOSED
|
||||||
|
*/
|
||||||
|
struct tcp_pcb *
|
||||||
|
tcp_new_ip6(void)
|
||||||
|
{
|
||||||
|
struct tcp_pcb * pcb;
|
||||||
|
pcb = tcp_alloc(TCP_PRIO_NORMAL);
|
||||||
|
ip_set_v6(pcb, 1);
|
||||||
|
return pcb;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to specify the argument that should be passed callback
|
* Used to specify the argument that should be passed callback
|
||||||
* functions.
|
* functions.
|
||||||
@@ -1264,7 +1325,9 @@ tcp_new(void)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
tcp_arg(struct tcp_pcb *pcb, void *arg)
|
tcp_arg(struct tcp_pcb *pcb, void *arg)
|
||||||
{
|
{
|
||||||
|
/* This function is allowed to be called for both listen pcbs and
|
||||||
|
connection pcbs. */
|
||||||
pcb->callback_arg = arg;
|
pcb->callback_arg = arg;
|
||||||
}
|
}
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
@@ -1279,6 +1342,7 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
|
|||||||
void
|
void
|
||||||
tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
|
tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN);
|
||||||
pcb->recv = recv;
|
pcb->recv = recv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,6 +1356,7 @@ tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
|
|||||||
void
|
void
|
||||||
tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
|
tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN);
|
||||||
pcb->sent = sent;
|
pcb->sent = sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1306,6 +1371,7 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
|
|||||||
void
|
void
|
||||||
tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
|
tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN);
|
||||||
pcb->errf = err;
|
pcb->errf = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1320,6 +1386,8 @@ tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
|
|||||||
void
|
void
|
||||||
tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
|
tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
|
||||||
{
|
{
|
||||||
|
/* This function is allowed to be called for both listen pcbs and
|
||||||
|
connection pcbs. */
|
||||||
pcb->accept = accept;
|
pcb->accept = accept;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
@@ -1334,6 +1402,7 @@ tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
|
|||||||
void
|
void
|
||||||
tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)
|
tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN);
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
pcb->poll = poll;
|
pcb->poll = poll;
|
||||||
#else /* LWIP_CALLBACK_API */
|
#else /* LWIP_CALLBACK_API */
|
||||||
@@ -1365,8 +1434,9 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
|||||||
tcp_listen_pcbs.listen_pcbs != NULL);
|
tcp_listen_pcbs.listen_pcbs != NULL);
|
||||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||||
if ((lpcb->local_port == pcb->local_port) &&
|
if ((lpcb->local_port == pcb->local_port) &&
|
||||||
(ip_addr_isany(&lpcb->local_ip) ||
|
IP_PCB_IPVER_EQ(pcb, lpcb) &&
|
||||||
ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
|
(ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) ||
|
||||||
|
ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) {
|
||||||
/* port and address of the listen pcb match the timed-out pcb */
|
/* port and address of the listen pcb match the timed-out pcb */
|
||||||
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
||||||
lpcb->accepts_pending > 0);
|
lpcb->accepts_pending > 0);
|
||||||
@@ -1465,14 +1535,36 @@ tcp_next_iss(void)
|
|||||||
* calculating the minimum of TCP_MSS and that netif's mtu (if set).
|
* calculating the minimum of TCP_MSS and that netif's mtu (if set).
|
||||||
*/
|
*/
|
||||||
u16_t
|
u16_t
|
||||||
tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
|
tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
|
||||||
|
#if LWIP_IPV6
|
||||||
|
, ipX_addr_t *src, u8_t isipv6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
u16_t mss_s;
|
u16_t mss_s;
|
||||||
struct netif *outif;
|
struct netif *outif;
|
||||||
|
s16_t mtu;
|
||||||
|
|
||||||
outif = ip_route(addr);
|
outif = ipX_route(isipv6, src, dest);
|
||||||
if ((outif != NULL) && (outif->mtu != 0)) {
|
#if LWIP_IPV6
|
||||||
mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
|
if (isipv6) {
|
||||||
|
/* First look in destination cache, to see if there is a Path MTU. */
|
||||||
|
mtu = nd6_get_destination_mtu(ipX_2_ip6(dest), outif);
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
if (outif == NULL) {
|
||||||
|
return sendmss;
|
||||||
|
}
|
||||||
|
mtu = outif->mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtu != 0) {
|
||||||
|
mss_s = mtu - IP_HLEN - TCP_HLEN;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/* for IPv6, substract the difference in header size */
|
||||||
|
mss_s -= (IP6_HLEN - IP_HLEN);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
/* RFC 1122, chap 4.2.2.6:
|
/* RFC 1122, chap 4.2.2.6:
|
||||||
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
||||||
* We correct for TCP options in tcp_write(), and don't support IP options.
|
* We correct for TCP options in tcp_write(), and don't support IP options.
|
||||||
|
|||||||
@@ -55,13 +55,18 @@
|
|||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
#include "arch/perf.h"
|
#include "arch/perf.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
|
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||||
|
|
||||||
/* These variables are global to all functions involved in the input
|
/* These variables are global to all functions involved in the input
|
||||||
processing of TCP segments. They are set by the tcp_input()
|
processing of TCP segments. They are set by the tcp_input()
|
||||||
function. */
|
function. */
|
||||||
static struct tcp_seg inseg;
|
static struct tcp_seg inseg;
|
||||||
static struct tcp_hdr *tcphdr;
|
static struct tcp_hdr *tcphdr;
|
||||||
static struct ip_hdr *iphdr;
|
|
||||||
static u32_t seqno, ackno;
|
static u32_t seqno, ackno;
|
||||||
static u8_t flags;
|
static u8_t flags;
|
||||||
static u16_t tcplen;
|
static u16_t tcplen;
|
||||||
@@ -85,7 +90,7 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
|
|||||||
* the TCP finite state machine. This function is called by the IP layer (in
|
* the TCP finite state machine. This function is called by the IP layer (in
|
||||||
* ip_input()).
|
* ip_input()).
|
||||||
*
|
*
|
||||||
* @param p received TCP segment to process (p->payload pointing to the IP header)
|
* @param p received TCP segment to process (p->payload pointing to the TCP header)
|
||||||
* @param inp network interface on which this segment was received
|
* @param inp network interface on which this segment was received
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -99,57 +104,46 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
u8_t hdrlen;
|
u8_t hdrlen;
|
||||||
err_t err;
|
err_t err;
|
||||||
|
u16_t chksum;
|
||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
TCP_STATS_INC(tcp.recv);
|
TCP_STATS_INC(tcp.recv);
|
||||||
snmp_inc_tcpinsegs();
|
snmp_inc_tcpinsegs();
|
||||||
|
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
tcphdr = (struct tcp_hdr *)p->payload;
|
||||||
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
|
|
||||||
|
|
||||||
#if TCP_INPUT_DEBUG
|
#if TCP_INPUT_DEBUG
|
||||||
tcp_debug_print(tcphdr);
|
tcp_debug_print(tcphdr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* remove header from payload */
|
/* Check that TCP header fits in payload */
|
||||||
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
|
if (p->len < sizeof(struct tcp_hdr)) {
|
||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||||
TCP_STATS_INC(tcp.lenerr);
|
TCP_STATS_INC(tcp.lenerr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
goto dropped;
|
||||||
snmp_inc_tcpinerrs();
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't even process incoming broadcasts/multicasts. */
|
/* Don't even process incoming broadcasts/multicasts. */
|
||||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) ||
|
if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) ||
|
||||||
ip_addr_ismulticast(¤t_iphdr_dest)) {
|
ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) {
|
||||||
TCP_STATS_INC(tcp.proterr);
|
TCP_STATS_INC(tcp.proterr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
goto dropped;
|
||||||
snmp_inc_tcpinerrs();
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CHECKSUM_CHECK_TCP
|
#if CHECKSUM_CHECK_TCP
|
||||||
/* Verify TCP checksum. */
|
/* Verify TCP checksum. */
|
||||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len,
|
||||||
IP_PROTO_TCP, p->tot_len) != 0) {
|
ipX_current_src_addr(), ipX_current_dest_addr());
|
||||||
|
if (chksum != 0) {
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||||
inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
chksum));
|
||||||
IP_PROTO_TCP, p->tot_len)));
|
|
||||||
#if TCP_DEBUG
|
|
||||||
tcp_debug_print(tcphdr);
|
tcp_debug_print(tcphdr);
|
||||||
#endif /* TCP_DEBUG */
|
|
||||||
TCP_STATS_INC(tcp.chkerr);
|
TCP_STATS_INC(tcp.chkerr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
goto dropped;
|
||||||
snmp_inc_tcpinerrs();
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CHECKSUM_CHECK_TCP */
|
||||||
|
|
||||||
/* Move the payload pointer in the pbuf so that it points to the
|
/* Move the payload pointer in the pbuf so that it points to the
|
||||||
TCP data instead of the TCP header. */
|
TCP data instead of the TCP header. */
|
||||||
@@ -158,10 +152,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
|
||||||
TCP_STATS_INC(tcp.lenerr);
|
TCP_STATS_INC(tcp.lenerr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
goto dropped;
|
||||||
snmp_inc_tcpinerrs();
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert fields in TCP header to host byte order. */
|
/* Convert fields in TCP header to host byte order. */
|
||||||
@@ -184,10 +175,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||||
if (pcb->remote_port == tcphdr->src &&
|
if (pcb->remote_port == tcphdr->src &&
|
||||||
pcb->local_port == tcphdr->dest &&
|
pcb->local_port == tcphdr->dest &&
|
||||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
|
||||||
|
ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
|
||||||
/* Move this PCB to the front of the list so that subsequent
|
/* Move this PCB to the front of the list so that subsequent
|
||||||
lookups will be faster (we exploit locality in TCP segment
|
lookups will be faster (we exploit locality in TCP segment
|
||||||
arrivals). */
|
arrivals). */
|
||||||
@@ -209,9 +200,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||||
if (pcb->remote_port == tcphdr->src &&
|
if (pcb->remote_port == tcphdr->src &&
|
||||||
pcb->local_port == tcphdr->dest &&
|
pcb->local_port == tcphdr->dest &&
|
||||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
|
||||||
|
ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
|
||||||
/* We don't really care enough to move this PCB to the front
|
/* We don't really care enough to move this PCB to the front
|
||||||
of the list since we are not very likely to receive that
|
of the list since we are not very likely to receive that
|
||||||
many segments for connections in TIME-WAIT. */
|
many segments for connections in TIME-WAIT. */
|
||||||
@@ -227,22 +219,31 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
prev = NULL;
|
prev = NULL;
|
||||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||||
if (lpcb->local_port == tcphdr->dest) {
|
if (lpcb->local_port == tcphdr->dest) {
|
||||||
#if SO_REUSE
|
#if LWIP_IPV6
|
||||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) {
|
if (lpcb->accept_any_ip_version) {
|
||||||
/* found an exact match */
|
|
||||||
break;
|
|
||||||
} else if(ip_addr_isany(&(lpcb->local_ip))) {
|
|
||||||
/* found an ANY-match */
|
/* found an ANY-match */
|
||||||
|
#if SO_REUSE
|
||||||
lpcb_any = lpcb;
|
lpcb_any = lpcb;
|
||||||
lpcb_prev = prev;
|
lpcb_prev = prev;
|
||||||
}
|
|
||||||
#else /* SO_REUSE */
|
#else /* SO_REUSE */
|
||||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) ||
|
|
||||||
ip_addr_isany(&(lpcb->local_ip))) {
|
|
||||||
/* found a match */
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) {
|
||||||
|
if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) {
|
||||||
|
/* found an exact match */
|
||||||
|
break;
|
||||||
|
} else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) {
|
||||||
|
/* found an ANY-match */
|
||||||
|
#if SO_REUSE
|
||||||
|
lpcb_any = lpcb;
|
||||||
|
lpcb_prev = prev;
|
||||||
|
#else /* SO_REUSE */
|
||||||
|
break;
|
||||||
|
#endif /* SO_REUSE */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prev = (struct tcp_pcb *)lpcb;
|
prev = (struct tcp_pcb *)lpcb;
|
||||||
}
|
}
|
||||||
@@ -291,7 +292,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* Set up a tcp_seg structure. */
|
/* Set up a tcp_seg structure. */
|
||||||
inseg.next = NULL;
|
inseg.next = NULL;
|
||||||
inseg.len = p->tot_len;
|
inseg.len = p->tot_len;
|
||||||
inseg.dataptr = p->payload;
|
|
||||||
inseg.p = p;
|
inseg.p = p;
|
||||||
inseg.tcphdr = tcphdr;
|
inseg.tcphdr = tcphdr;
|
||||||
|
|
||||||
@@ -305,14 +305,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
pcb->refused_data = NULL;
|
pcb->refused_data = NULL;
|
||||||
} else {
|
} else if ((err == ERR_ABRT) || (tcplen > 0)) {
|
||||||
/* if err == ERR_ABRT, 'pcb' is already deallocated */
|
/* if err == ERR_ABRT, 'pcb' is already deallocated */
|
||||||
/* drop incoming packets, because pcb is "full" */
|
/* Drop incoming packets because pcb is "full" (only if the incoming
|
||||||
|
segment contains data). */
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
||||||
TCP_STATS_INC(tcp.drop);
|
goto dropped;
|
||||||
snmp_inc_tcpinerrs();
|
|
||||||
pbuf_free(p);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcp_input_pcb = pcb;
|
tcp_input_pcb = pcb;
|
||||||
@@ -346,6 +344,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recv_data != NULL) {
|
if (recv_data != NULL) {
|
||||||
|
LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
|
||||||
if (pcb->flags & TF_RXCLOSED) {
|
if (pcb->flags & TF_RXCLOSED) {
|
||||||
/* received data although already closed -> abort (send RST) to
|
/* received data although already closed -> abort (send RST) to
|
||||||
notify the remote host that not all data has been processed */
|
notify the remote host that not all data has been processed */
|
||||||
@@ -414,15 +413,19 @@ aborted:
|
|||||||
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
||||||
TCP_STATS_INC(tcp.proterr);
|
TCP_STATS_INC(tcp.proterr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
TCP_STATS_INC(tcp.drop);
|
||||||
tcp_rst(ackno, seqno + tcplen,
|
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||||
ip_current_dest_addr(), ip_current_src_addr(),
|
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||||
tcphdr->dest, tcphdr->src);
|
|
||||||
}
|
}
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
||||||
PERF_STOP("tcp_input");
|
PERF_STOP("tcp_input");
|
||||||
|
return;
|
||||||
|
dropped:
|
||||||
|
TCP_STATS_INC(tcp.drop);
|
||||||
|
snmp_inc_tcpinerrs();
|
||||||
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,9 +452,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
/* For incoming segments with the ACK flag set, respond with a
|
/* For incoming segments with the ACK flag set, respond with a
|
||||||
RST. */
|
RST. */
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
||||||
tcp_rst(ackno + 1, seqno + tcplen,
|
tcp_rst(ackno + 1, seqno + tcplen, ipX_current_dest_addr(),
|
||||||
ip_current_dest_addr(), ip_current_src_addr(),
|
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||||
tcphdr->dest, tcphdr->src);
|
|
||||||
} else if (flags & TCP_SYN) {
|
} else if (flags & TCP_SYN) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
@@ -473,9 +475,12 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
pcb->accepts_pending++;
|
pcb->accepts_pending++;
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
#endif /* TCP_LISTEN_BACKLOG */
|
||||||
/* Set up the new PCB. */
|
/* Set up the new PCB. */
|
||||||
ip_addr_copy(npcb->local_ip, current_iphdr_dest);
|
#if LWIP_IPV6
|
||||||
|
PCB_ISIPV6(npcb) = ip_current_is_v6();
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr());
|
||||||
|
ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr());
|
||||||
npcb->local_port = pcb->local_port;
|
npcb->local_port = pcb->local_port;
|
||||||
ip_addr_copy(npcb->remote_ip, current_iphdr_src);
|
|
||||||
npcb->remote_port = tcphdr->src;
|
npcb->remote_port = tcphdr->src;
|
||||||
npcb->state = SYN_RCVD;
|
npcb->state = SYN_RCVD;
|
||||||
npcb->rcv_nxt = seqno + 1;
|
npcb->rcv_nxt = seqno + 1;
|
||||||
@@ -496,7 +501,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
/* Parse any options in the SYN. */
|
/* Parse any options in the SYN. */
|
||||||
tcp_parseopt(npcb);
|
tcp_parseopt(npcb);
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
|
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip,
|
||||||
|
&npcb->remote_ip, PCB_ISIPV6(npcb));
|
||||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||||
|
|
||||||
snmp_inc_tcppassiveopens();
|
snmp_inc_tcppassiveopens();
|
||||||
@@ -538,8 +544,8 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
|||||||
should be sent in reply */
|
should be sent in reply */
|
||||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||||
/* If the SYN is in the window it is an error, send a reset */
|
/* If the SYN is in the window it is an error, send a reset */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||||
tcphdr->dest, tcphdr->src);
|
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
} else if (flags & TCP_FIN) {
|
} else if (flags & TCP_FIN) {
|
||||||
@@ -636,7 +642,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
pcb->state = ESTABLISHED;
|
pcb->state = ESTABLISHED;
|
||||||
|
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
|
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip,
|
||||||
|
PCB_ISIPV6(pcb));
|
||||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||||
|
|
||||||
/* Set ssthresh again after changing pcb->mss (already set in tcp_connect
|
/* Set ssthresh again after changing pcb->mss (already set in tcp_connect
|
||||||
@@ -672,8 +679,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
/* received ACK? possibly a half-open connection */
|
/* received ACK? possibly a half-open connection */
|
||||||
else if (flags & TCP_ACK) {
|
else if (flags & TCP_ACK) {
|
||||||
/* send a RST to bring the other side in a non-synchronized state. */
|
/* send a RST to bring the other side in a non-synchronized state. */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||||
tcphdr->dest, tcphdr->src);
|
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SYN_RCVD:
|
case SYN_RCVD:
|
||||||
@@ -715,8 +722,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* incorrect ACK number, send RST */
|
/* incorrect ACK number, send RST */
|
||||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
|
||||||
tcphdr->dest, tcphdr->src);
|
ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
|
||||||
}
|
}
|
||||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||||
/* Looks like another copy of the SYN - retransmit our SYN-ACK */
|
/* Looks like another copy of the SYN - retransmit our SYN-ACK */
|
||||||
@@ -1018,6 +1025,13 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
pcb->rtime = 0;
|
pcb->rtime = 0;
|
||||||
|
|
||||||
pcb->polltmr = 0;
|
pcb->polltmr = 0;
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
|
if (PCB_ISIPV6(pcb)) {
|
||||||
|
/* Inform neighbor reachability of forward progress. */
|
||||||
|
nd6_reachability_hint(ip6_current_src_addr());
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
|
||||||
} else {
|
} else {
|
||||||
/* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
|
/* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
|
||||||
pcb->acked = 0;
|
pcb->acked = 0;
|
||||||
@@ -1165,9 +1179,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
LWIP_ASSERT("pbuf_header failed", 0);
|
LWIP_ASSERT("pbuf_header failed", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* KJM following line changed to use p->payload rather than inseg->p->payload
|
|
||||||
to fix bug #9076 */
|
|
||||||
inseg.dataptr = p->payload;
|
|
||||||
inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
|
inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
|
||||||
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
|
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
|
||||||
}
|
}
|
||||||
@@ -1338,6 +1349,13 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
/* Acknowledge the segment(s). */
|
/* Acknowledge the segment(s). */
|
||||||
tcp_ack(pcb);
|
tcp_ack(pcb);
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
|
if (PCB_ISIPV6(pcb)) {
|
||||||
|
/* Inform neighbor reachability of forward progress. */
|
||||||
|
nd6_reachability_hint(ip6_current_src_addr());
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* We get here if the incoming segment is out-of-sequence. */
|
/* We get here if the incoming segment is out-of-sequence. */
|
||||||
tcp_send_empty_ack(pcb);
|
tcp_send_empty_ack(pcb);
|
||||||
|
|||||||
@@ -46,12 +46,17 @@
|
|||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
|
#if LWIP_TCP_TIMESTAMPS
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -166,7 +171,6 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
|
|||||||
seg->flags = optflags;
|
seg->flags = optflags;
|
||||||
seg->next = NULL;
|
seg->next = NULL;
|
||||||
seg->p = p;
|
seg->p = p;
|
||||||
seg->dataptr = p->payload;
|
|
||||||
seg->len = p->tot_len - optlen;
|
seg->len = p->tot_len - optlen;
|
||||||
#if TCP_OVERSIZE_DBGCHECK
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
seg->oversize_left = 0;
|
seg->oversize_left = 0;
|
||||||
@@ -590,10 +594,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
seg->chksum_swapped = chksum_swapped;
|
seg->chksum_swapped = chksum_swapped;
|
||||||
seg->flags |= TF_SEG_DATA_CHECKSUMMED;
|
seg->flags |= TF_SEG_DATA_CHECKSUMMED;
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||||
/* Fix dataptr for the nocopy case */
|
|
||||||
if ((apiflags & TCP_WRITE_FLAG_COPY) == 0) {
|
|
||||||
seg->dataptr = (u8_t*)arg + pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* first segment of to-be-queued data? */
|
/* first segment of to-be-queued data? */
|
||||||
if (queue == NULL) {
|
if (queue == NULL) {
|
||||||
@@ -773,6 +773,7 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
|
|||||||
TCP_STATS_INC(tcp.memerr);
|
TCP_STATS_INC(tcp.memerr);
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
|
||||||
LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
|
LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
|
||||||
@@ -814,7 +815,6 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
|
|||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_TCP_TIMESTAMPS
|
#if LWIP_TCP_TIMESTAMPS
|
||||||
/* Build a timestamp option (12 bytes long) at the specified options pointer)
|
/* Build a timestamp option (12 bytes long) at the specified options pointer)
|
||||||
@@ -870,14 +870,14 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CHECKSUM_GEN_TCP
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len,
|
||||||
IP_PROTO_TCP, p->tot_len);
|
&pcb->local_ip, &pcb->remote_ip);
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP);
|
IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -901,6 +901,10 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
s16_t i = 0;
|
s16_t i = 0;
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
|
||||||
|
/* pcb->state LISTEN not allowed here */
|
||||||
|
LWIP_ASSERT("don't call tcp_output for listen-pcbs",
|
||||||
|
pcb->state != LISTEN);
|
||||||
|
|
||||||
/* First, check if we are invoked by the TCP input processing
|
/* First, check if we are invoked by the TCP input processing
|
||||||
code. If so, we do not output anything. Instead, we rely on the
|
code. If so, we do not output anything. Instead, we rely on the
|
||||||
input processing code to call us when input processing is done
|
input processing code to call us when input processing is done
|
||||||
@@ -1050,7 +1054,6 @@ static void
|
|||||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
u16_t len;
|
u16_t len;
|
||||||
struct netif *netif;
|
|
||||||
u32_t *opts;
|
u32_t *opts;
|
||||||
|
|
||||||
/** @bug Exclude retransmitted segments from this count. */
|
/** @bug Exclude retransmitted segments from this count. */
|
||||||
@@ -1067,7 +1070,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
/* Add any requested options. NB MSS option is only set on SYN
|
/* Add any requested options. NB MSS option is only set on SYN
|
||||||
packets, so ignore it here */
|
packets, so ignore it here */
|
||||||
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)(seg->tcphdr + 1) % 4) == 0);
|
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
|
||||||
opts = (u32_t *)(void *)(seg->tcphdr + 1);
|
opts = (u32_t *)(void *)(seg->tcphdr + 1);
|
||||||
if (seg->flags & TF_SEG_OPTS_MSS) {
|
if (seg->flags & TF_SEG_OPTS_MSS) {
|
||||||
TCP_BUILD_MSS_OPTION(*opts);
|
TCP_BUILD_MSS_OPTION(*opts);
|
||||||
@@ -1082,19 +1085,22 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we don't have a local IP address, we get one by
|
/* Set retransmission timer running if it is not currently enabled
|
||||||
calling ip_route(). */
|
This must be set before checking the route. */
|
||||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
if (pcb->rtime == -1) {
|
||||||
netif = ip_route(&(pcb->remote_ip));
|
pcb->rtime = 0;
|
||||||
if (netif == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ip_addr_copy(pcb->local_ip, netif->ip_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set retransmission timer running if it is not currently enabled */
|
/* If we don't have a local IP address, we get one by
|
||||||
if(pcb->rtime == -1) {
|
calling ip_route(). */
|
||||||
pcb->rtime = 0;
|
if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
|
||||||
|
struct netif *netif;
|
||||||
|
ipX_addr_t *local_ip;
|
||||||
|
ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
||||||
|
if ((netif == NULL) || (local_ip == NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcb->rttest == 0) {
|
if (pcb->rttest == 0) {
|
||||||
@@ -1115,14 +1121,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
seg->p->payload = seg->tcphdr;
|
seg->p->payload = seg->tcphdr;
|
||||||
|
|
||||||
seg->tcphdr->chksum = 0;
|
seg->tcphdr->chksum = 0;
|
||||||
#if CHECKSUM_GEN_TCP
|
|
||||||
#if TCP_CHECKSUM_ON_COPY
|
#if TCP_CHECKSUM_ON_COPY
|
||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
|
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
|
||||||
u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
|
u16_t chksum_slow = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||||
&(pcb->remote_ip),
|
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
|
||||||
IP_PROTO_TCP, seg->p->tot_len);
|
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||||
if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
|
if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
|
||||||
LWIP_ASSERT("data included but not checksummed",
|
LWIP_ASSERT("data included but not checksummed",
|
||||||
@@ -1130,9 +1134,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* rebuild TCP header checksum (TCP header changes for retransmissions!) */
|
/* rebuild TCP header checksum (TCP header changes for retransmissions!) */
|
||||||
acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip),
|
acc = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||||
&(pcb->remote_ip),
|
seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
|
||||||
IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
|
||||||
/* add payload checksum */
|
/* add payload checksum */
|
||||||
if (seg->chksum_swapped) {
|
if (seg->chksum_swapped) {
|
||||||
seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
|
seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
|
||||||
@@ -1150,19 +1153,19 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||||
}
|
}
|
||||||
#else /* TCP_CHECKSUM_ON_COPY */
|
#else /* TCP_CHECKSUM_ON_COPY */
|
||||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
|
#if CHECKSUM_GEN_TCP
|
||||||
&(pcb->remote_ip),
|
seg->tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP,
|
||||||
IP_PROTO_TCP, seg->p->tot_len);
|
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
|
||||||
#endif /* CHECKSUM_GEN_TCP */
|
#endif /* CHECKSUM_GEN_TCP */
|
||||||
|
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
|
||||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
IP_PROTO_TCP);
|
pcb->tos, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1187,9 +1190,13 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
* @param remote_port the remote TCP port to send the segment to
|
* @param remote_port the remote TCP port to send the segment to
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
tcp_rst(u32_t seqno, u32_t ackno,
|
tcp_rst_impl(u32_t seqno, u32_t ackno,
|
||||||
ip_addr_t *local_ip, ip_addr_t *remote_ip,
|
ipX_addr_t *local_ip, ipX_addr_t *remote_ip,
|
||||||
u16_t local_port, u16_t remote_port)
|
u16_t local_port, u16_t remote_port
|
||||||
|
#if LWIP_IPV6
|
||||||
|
, u8_t isipv6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
@@ -1211,14 +1218,15 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
|||||||
tcphdr->chksum = 0;
|
tcphdr->chksum = 0;
|
||||||
tcphdr->urgp = 0;
|
tcphdr->urgp = 0;
|
||||||
|
|
||||||
#if CHECKSUM_GEN_TCP
|
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
|
||||||
IP_PROTO_TCP, p->tot_len);
|
|
||||||
#endif
|
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
snmp_inc_tcpoutrsts();
|
snmp_inc_tcpoutrsts();
|
||||||
/* Send output with hardcoded TTL since we have no access to the pcb */
|
|
||||||
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
#if CHECKSUM_GEN_TCP
|
||||||
|
tcphdr->chksum = ipX_chksum_pseudo(isipv6, p, IP_PROTO_TCP, p->tot_len,
|
||||||
|
local_ip, remote_ip);
|
||||||
|
#endif
|
||||||
|
/* Send output with hardcoded TTL/HL since we have no access to the pcb */
|
||||||
|
ipX_output(isipv6, p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||||
}
|
}
|
||||||
@@ -1354,9 +1362,9 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
|
||||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip);
|
||||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
|
||||||
tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
|
tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
|
||||||
@@ -1369,18 +1377,17 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
tcphdr = (struct tcp_hdr *)p->payload;
|
tcphdr = (struct tcp_hdr *)p->payload;
|
||||||
|
|
||||||
#if CHECKSUM_GEN_TCP
|
tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len,
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
|
&pcb->local_ip, &pcb->remote_ip);
|
||||||
IP_PROTO_TCP, p->tot_len);
|
|
||||||
#endif
|
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
/* Send output to IP */
|
/* Send output to IP */
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
|
||||||
&(pcb->addr_hint));
|
pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
|
0, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -1407,11 +1414,9 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
u16_t len;
|
u16_t len;
|
||||||
u8_t is_fin;
|
u8_t is_fin;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG,
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
|
||||||
("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip);
|
||||||
U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
|
||||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG,
|
LWIP_DEBUGF(TCP_DEBUG,
|
||||||
("tcp_zero_window_probe: tcp_ticks %"U32_F
|
("tcp_zero_window_probe: tcp_ticks %"U32_F
|
||||||
@@ -1443,21 +1448,23 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
|
TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
|
||||||
} else {
|
} else {
|
||||||
/* Data segment, copy in one byte from the head of the unacked queue */
|
/* Data segment, copy in one byte from the head of the unacked queue */
|
||||||
*((char *)p->payload + TCP_HLEN) = *(char *)seg->dataptr;
|
struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload;
|
||||||
|
char *d = ((char *)p->payload + TCP_HLEN);
|
||||||
|
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CHECKSUM_GEN_TCP
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
|
tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len,
|
||||||
IP_PROTO_TCP, p->tot_len);
|
&pcb->local_ip, &pcb->remote_ip);
|
||||||
#endif
|
#endif
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
/* Send output to IP */
|
/* Send output to IP */
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
&(pcb->addr_hint));
|
0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/timers.h"
|
#include "lwip/timers.h"
|
||||||
|
#include "lwip/tcp_impl.h"
|
||||||
|
|
||||||
#if LWIP_TIMERS
|
#if LWIP_TIMERS
|
||||||
|
|
||||||
@@ -49,14 +50,16 @@
|
|||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/tcpip.h"
|
#include "lwip/tcpip.h"
|
||||||
|
|
||||||
#include "lwip/tcp_impl.h"
|
|
||||||
#include "lwip/ip_frag.h"
|
#include "lwip/ip_frag.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
#include "lwip/autoip.h"
|
#include "lwip/autoip.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/ip6_frag.h"
|
||||||
|
#include "lwip/mld6.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
/** The one and only timeout list */
|
/** The one and only timeout list */
|
||||||
static struct sys_timeo *next_timeout;
|
static struct sys_timeo *next_timeout;
|
||||||
@@ -217,6 +220,54 @@ dns_timer(void *arg)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Timer callback function that calls nd6_tmr() and reschedules itself.
|
||||||
|
*
|
||||||
|
* @param arg unused argument
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
nd6_timer(void *arg)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n"));
|
||||||
|
nd6_tmr();
|
||||||
|
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6_REASS
|
||||||
|
/**
|
||||||
|
* Timer callback function that calls ip6_reass_tmr() and reschedules itself.
|
||||||
|
*
|
||||||
|
* @param arg unused argument
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ip6_reass_timer(void *arg)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n"));
|
||||||
|
ip6_reass_tmr();
|
||||||
|
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6_REASS */
|
||||||
|
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
/**
|
||||||
|
* Timer callback function that calls mld6_tmr() and reschedules itself.
|
||||||
|
*
|
||||||
|
* @param arg unused argument
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
mld6_timer(void *arg)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n"));
|
||||||
|
mld6_tmr();
|
||||||
|
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/** Initialize this module */
|
/** Initialize this module */
|
||||||
void sys_timeouts_init(void)
|
void sys_timeouts_init(void)
|
||||||
{
|
{
|
||||||
@@ -239,6 +290,15 @@ void sys_timeouts_init(void)
|
|||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
|
||||||
|
#if LWIP_IPV6_REASS
|
||||||
|
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
|
||||||
|
#endif /* LWIP_IPV6_REASS */
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#if NO_SYS
|
#if NO_SYS
|
||||||
/* Initialise timestamp for sys_check_timeouts */
|
/* Initialise timestamp for sys_check_timeouts */
|
||||||
|
|||||||
458
src/core/udp.c
458
src/core/udp.c
@@ -55,8 +55,12 @@
|
|||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/inet_chksum.h"
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
|
#include "lwip/icmp6.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
#include "arch/perf.h"
|
#include "arch/perf.h"
|
||||||
@@ -76,7 +80,7 @@ struct udp_pcb *udp_pcbs;
|
|||||||
* recv function. If no pcb is found or the datagram is incorrect, the
|
* recv function. If no pcb is found or the datagram is incorrect, the
|
||||||
* pbuf is freed.
|
* pbuf is freed.
|
||||||
*
|
*
|
||||||
* @param p pbuf to be demultiplexed to a UDP PCB.
|
* @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header)
|
||||||
* @param inp network interface on which the datagram was received.
|
* @param inp network interface on which the datagram was received.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -86,20 +90,17 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
struct udp_hdr *udphdr;
|
struct udp_hdr *udphdr;
|
||||||
struct udp_pcb *pcb, *prev;
|
struct udp_pcb *pcb, *prev;
|
||||||
struct udp_pcb *uncon_pcb;
|
struct udp_pcb *uncon_pcb;
|
||||||
struct ip_hdr *iphdr;
|
|
||||||
u16_t src, dest;
|
u16_t src, dest;
|
||||||
u8_t local_match;
|
u8_t local_match;
|
||||||
u8_t broadcast;
|
u8_t broadcast;
|
||||||
|
u8_t for_us;
|
||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
UDP_STATS_INC(udp.recv);
|
UDP_STATS_INC(udp.recv);
|
||||||
|
|
||||||
iphdr = (struct ip_hdr *)p->payload;
|
/* Check minimum length (UDP header) */
|
||||||
|
if (p->len < UDP_HLEN) {
|
||||||
/* Check minimum length (IP header + UDP header)
|
|
||||||
* and move payload pointer to UDP header */
|
|
||||||
if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
|
|
||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(UDP_DEBUG,
|
LWIP_DEBUGF(UDP_DEBUG,
|
||||||
("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||||
@@ -113,7 +114,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
udphdr = (struct udp_hdr *)p->payload;
|
udphdr = (struct udp_hdr *)p->payload;
|
||||||
|
|
||||||
/* is broadcast packet ? */
|
/* is broadcast packet ? */
|
||||||
broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp);
|
#if LWIP_IPV6
|
||||||
|
broadcast = !ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||||
|
|
||||||
@@ -124,13 +129,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
udp_debug_print(udphdr);
|
udp_debug_print(udphdr);
|
||||||
|
|
||||||
/* print the UDP source and destination */
|
/* print the UDP source and destination */
|
||||||
LWIP_DEBUGF(UDP_DEBUG,
|
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
|
||||||
("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
|
ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_dest_addr());
|
||||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest)));
|
||||||
ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
|
ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_src_addr());
|
||||||
ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
|
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src)));
|
||||||
ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
|
|
||||||
ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
|
|
||||||
|
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
pcb = NULL;
|
pcb = NULL;
|
||||||
@@ -142,9 +145,10 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
|
if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
|
||||||
/* accept the packe if
|
/* accept the packe if
|
||||||
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
|
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
|
||||||
- inp->dhcp->pcb->remote == ANY or iphdr->src */
|
- inp->dhcp->pcb->remote == ANY or iphdr->src
|
||||||
if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
|
(no need to check for IPv6 since the dhcp struct always uses IPv4) */
|
||||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) {
|
if (ipX_addr_isany(0, &inp->dhcp->pcb->remote_ip) ||
|
||||||
|
ip_addr_cmp(ipX_2_ip(&(inp->dhcp->pcb->remote_ip)), ip_current_src_addr())) {
|
||||||
pcb = inp->dhcp->pcb;
|
pcb = inp->dhcp->pcb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,25 +166,35 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
local_match = 0;
|
local_match = 0;
|
||||||
/* print the PCB local and remote address */
|
/* print the PCB local and remote address */
|
||||||
LWIP_DEBUGF(UDP_DEBUG,
|
LWIP_DEBUGF(UDP_DEBUG, ("pcb ("));
|
||||||
("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->local_ip);
|
||||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port));
|
||||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->remote_ip);
|
||||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
|
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port));
|
||||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
|
||||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
|
|
||||||
|
|
||||||
/* compare PCB local addr+port to UDP destination addr+port */
|
/* compare PCB local addr+port to UDP destination addr+port */
|
||||||
if ((pcb->local_port == dest) &&
|
if ((pcb->local_port == dest) &&
|
||||||
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
|
#if LWIP_IPV6
|
||||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) ||
|
((PCB_ISIPV6(pcb) && (ip_current_is_v6()) &&
|
||||||
|
(ip6_addr_isany(ipX_2_ip6(&pcb->local_ip)) ||
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
ip6_addr_cmp(ipX_2_ip6(&pcb->local_ip), ip6_current_dest_addr()))) ||
|
||||||
|
(!PCB_ISIPV6(pcb) &&
|
||||||
|
(ip_current_header() != NULL) &&
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
((
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
((!broadcast && ipX_addr_isany(0, &pcb->local_ip)) ||
|
||||||
|
ip_addr_cmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr()) ||
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
#if IP_SOF_BROADCAST_RECV
|
#if IP_SOF_BROADCAST_RECV
|
||||||
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
|
(broadcast && (pcb->so_options & SOF_BROADCAST)))))) {
|
||||||
#else /* IP_SOF_BROADCAST_RECV */
|
#else /* IP_SOF_BROADCAST_RECV */
|
||||||
(broadcast))) {
|
(broadcast))))) {
|
||||||
#endif /* IP_SOF_BROADCAST_RECV */
|
#endif /* IP_SOF_BROADCAST_RECV */
|
||||||
local_match = 1;
|
local_match = 1;
|
||||||
if ((uncon_pcb == NULL) &&
|
if ((uncon_pcb == NULL) &&
|
||||||
@@ -191,9 +205,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
/* compare PCB remote addr+port to UDP source addr+port */
|
/* compare PCB remote addr+port to UDP source addr+port */
|
||||||
if ((local_match != 0) &&
|
if ((local_match != 0) &&
|
||||||
(pcb->remote_port == src) &&
|
(pcb->remote_port == src) && IP_PCB_IPVER_INPUT_MATCH(pcb) &&
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
(ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->remote_ip) ||
|
||||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) {
|
ipX_addr_cmp(PCB_ISIPV6(pcb), &pcb->remote_ip, ipX_current_src_addr()))) {
|
||||||
/* the first fully matching PCB */
|
/* the first fully matching PCB */
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
/* move the pcb to the front of udp_pcbs so that is
|
/* move the pcb to the front of udp_pcbs so that is
|
||||||
@@ -215,12 +229,24 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check checksum if this is a match or if it was directed at us. */
|
/* Check checksum if this is a match or if it was directed at us. */
|
||||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) {
|
if (pcb != NULL) {
|
||||||
|
for_us = 1;
|
||||||
|
} else {
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if (ip_current_is_v6()) {
|
||||||
|
for_us = netif_matches_ip6_addr(inp, ip6_current_dest_addr());
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
for_us = ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (for_us) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||||
#if LWIP_UDPLITE
|
|
||||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
|
||||||
/* Do the UDP Lite checksum */
|
|
||||||
#if CHECKSUM_CHECK_UDP
|
#if CHECKSUM_CHECK_UDP
|
||||||
|
#if LWIP_UDPLITE
|
||||||
|
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
|
||||||
|
/* Do the UDP Lite checksum */
|
||||||
u16_t chklen = ntohs(udphdr->len);
|
u16_t chklen = ntohs(udphdr->len);
|
||||||
if (chklen < sizeof(struct udp_hdr)) {
|
if (chklen < sizeof(struct udp_hdr)) {
|
||||||
if (chklen == 0) {
|
if (chklen == 0) {
|
||||||
@@ -230,42 +256,26 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else {
|
} else {
|
||||||
/* At least the UDP-Lite header must be covered by the
|
/* At least the UDP-Lite header must be covered by the
|
||||||
checksum! (Again, see RFC 3828 chap. 3.1) */
|
checksum! (Again, see RFC 3828 chap. 3.1) */
|
||||||
UDP_STATS_INC(udp.chkerr);
|
goto chkerr;
|
||||||
UDP_STATS_INC(udp.drop);
|
|
||||||
snmp_inc_udpinerrors();
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest,
|
if (ipX_chksum_pseudo_partial(ip_current_is_v6(), p, IP_PROTO_UDPLITE,
|
||||||
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
|
p->tot_len, chklen,
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
ipX_current_src_addr(), ipX_current_dest_addr()) != 0) {
|
||||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
goto chkerr;
|
||||||
UDP_STATS_INC(udp.chkerr);
|
|
||||||
UDP_STATS_INC(udp.drop);
|
|
||||||
snmp_inc_udpinerrors();
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_CHECK_UDP */
|
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_UDPLITE */
|
#endif /* LWIP_UDPLITE */
|
||||||
{
|
{
|
||||||
#if CHECKSUM_CHECK_UDP
|
|
||||||
if (udphdr->chksum != 0) {
|
if (udphdr->chksum != 0) {
|
||||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len,
|
||||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
ipX_current_src_addr(),
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
ipX_current_dest_addr()) != 0) {
|
||||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
goto chkerr;
|
||||||
UDP_STATS_INC(udp.chkerr);
|
|
||||||
UDP_STATS_INC(udp.drop);
|
|
||||||
snmp_inc_udpinerrors();
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_CHECK_UDP */
|
|
||||||
}
|
}
|
||||||
|
#endif /* CHECKSUM_CHECK_UDP */
|
||||||
if(pbuf_header(p, -UDP_HLEN)) {
|
if(pbuf_header(p, -UDP_HLEN)) {
|
||||||
/* Can we cope with this failing? Just assert for now */
|
/* Can we cope with this failing? Just assert for now */
|
||||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||||
@@ -277,32 +287,45 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
if (pcb != NULL) {
|
if (pcb != NULL) {
|
||||||
snmp_inc_udpindatagrams();
|
snmp_inc_udpindatagrams();
|
||||||
#if SO_REUSE && SO_REUSE_RXTOALL
|
#if SO_REUSE && SO_REUSE_RXTOALL
|
||||||
if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) &&
|
if ((broadcast ||
|
||||||
|
#if LWIP_IPV6
|
||||||
|
ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
ip_addr_ismulticast(ip_current_dest_addr())) &&
|
||||||
((pcb->so_options & SOF_REUSEADDR) != 0)) {
|
((pcb->so_options & SOF_REUSEADDR) != 0)) {
|
||||||
/* pass broadcast- or multicast packets to all multicast pcbs
|
/* pass broadcast- or multicast packets to all multicast pcbs
|
||||||
if SOF_REUSEADDR is set on the first match */
|
if SOF_REUSEADDR is set on the first match */
|
||||||
struct udp_pcb *mpcb;
|
struct udp_pcb *mpcb;
|
||||||
u8_t p_header_changed = 0;
|
u8_t p_header_changed = 0;
|
||||||
|
s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN);
|
||||||
for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
|
for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
|
||||||
if (mpcb != pcb) {
|
if (mpcb != pcb) {
|
||||||
/* compare PCB local addr+port to UDP destination addr+port */
|
/* compare PCB local addr+port to UDP destination addr+port */
|
||||||
if ((mpcb->local_port == dest) &&
|
if ((mpcb->local_port == dest) &&
|
||||||
((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
|
#if LWIP_IPV6
|
||||||
ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) ||
|
((PCB_ISIPV6(mpcb) &&
|
||||||
|
(ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||||
|
ip6_addr_cmp(ipX_2_ip6(&mpcb->local_ip), ip6_current_dest_addr()))) ||
|
||||||
|
(!PCB_ISIPV6(mpcb) &&
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
((
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
((!broadcast && ipX_addr_isany(0, &mpcb->local_ip)) ||
|
||||||
|
ip_addr_cmp(ipX_2_ip(&mpcb->local_ip), ip_current_dest_addr()) ||
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
#if IP_SOF_BROADCAST_RECV
|
#if IP_SOF_BROADCAST_RECV
|
||||||
(broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
|
(broadcast && (mpcb->so_options & SOF_BROADCAST)))))) {
|
||||||
#else /* IP_SOF_BROADCAST_RECV */
|
#else /* IP_SOF_BROADCAST_RECV */
|
||||||
(broadcast))) {
|
(broadcast))))) {
|
||||||
#endif /* IP_SOF_BROADCAST_RECV */
|
#endif /* IP_SOF_BROADCAST_RECV */
|
||||||
/* pass a copy of the packet to all local matches */
|
/* pass a copy of the packet to all local matches */
|
||||||
if (mpcb->recv != NULL) {
|
if (mpcb->recv.ip4 != NULL) {
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
/* for that, move payload to IP header again */
|
/* for that, move payload to IP header again */
|
||||||
if (p_header_changed == 0) {
|
if (p_header_changed == 0) {
|
||||||
pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
pbuf_header(p, hdrs_len);
|
||||||
p_header_changed = 1;
|
p_header_changed = 1;
|
||||||
}
|
}
|
||||||
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||||
@@ -310,8 +333,16 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
err_t err = pbuf_copy(q, p);
|
err_t err = pbuf_copy(q, p);
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
/* move payload to UDP data */
|
/* move payload to UDP data */
|
||||||
pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
pbuf_header(q, -hdrs_len);
|
||||||
mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
|
#if LWIP_IPV6
|
||||||
|
if (PCB_ISIPV6(mpcb)) {
|
||||||
|
mpcb->recv.ip6(mpcb->recv_arg, mpcb, q, ip6_current_src_addr(), src);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
mpcb->recv.ip4(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,14 +351,22 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
if (p_header_changed) {
|
if (p_header_changed) {
|
||||||
/* and move payload to UDP data again */
|
/* and move payload to UDP data again */
|
||||||
pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
pbuf_header(p, -hdrs_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SO_REUSE && SO_REUSE_RXTOALL */
|
#endif /* SO_REUSE && SO_REUSE_RXTOALL */
|
||||||
/* callback */
|
/* callback */
|
||||||
if (pcb->recv != NULL) {
|
if (pcb->recv.ip4 != NULL) {
|
||||||
/* now the recv function is responsible for freeing p */
|
/* now the recv function is responsible for freeing p */
|
||||||
pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
|
#if LWIP_IPV6
|
||||||
|
if (PCB_ISIPV6(pcb)) {
|
||||||
|
pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr(), src);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* no recv function registered? then we have to free the pbuf! */
|
/* no recv function registered? then we have to free the pbuf! */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -336,17 +375,19 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
|
||||||
|
|
||||||
#if LWIP_ICMP
|
#if LWIP_ICMP || LWIP_ICMP6
|
||||||
/* No match was found, send ICMP destination port unreachable unless
|
/* No match was found, send ICMP destination port unreachable unless
|
||||||
destination address was broadcast/multicast. */
|
destination address was broadcast/multicast. */
|
||||||
if (!broadcast &&
|
if (!broadcast &&
|
||||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
#if LWIP_IPV6
|
||||||
|
!ip6_addr_ismulticast(ip6_current_dest_addr()) &&
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
!ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||||
/* move payload pointer back to ip header */
|
/* move payload pointer back to ip header */
|
||||||
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
|
pbuf_header(p, ip_current_header_tot_len() + UDP_HLEN);
|
||||||
LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
|
icmp_port_unreach(ip_current_is_v6(), p);
|
||||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
|
||||||
}
|
}
|
||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
||||||
UDP_STATS_INC(udp.proterr);
|
UDP_STATS_INC(udp.proterr);
|
||||||
UDP_STATS_INC(udp.drop);
|
UDP_STATS_INC(udp.drop);
|
||||||
snmp_inc_udpnoports();
|
snmp_inc_udpnoports();
|
||||||
@@ -357,6 +398,15 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
PERF_STOP("udp_input");
|
PERF_STOP("udp_input");
|
||||||
|
return;
|
||||||
|
chkerr:
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
|
("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n"));
|
||||||
|
UDP_STATS_INC(udp.chkerr);
|
||||||
|
UDP_STATS_INC(udp.drop);
|
||||||
|
snmp_inc_udpinerrors();
|
||||||
|
pbuf_free(p);
|
||||||
|
PERF_STOP("udp_input");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,7 +431,7 @@ err_t
|
|||||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||||
{
|
{
|
||||||
/* send to the packet using remote ip and port stored in the pcb */
|
/* send to the packet using remote ip and port stored in the pcb */
|
||||||
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
|
return udp_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
@@ -392,7 +442,7 @@ udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
u8_t have_chksum, u16_t chksum)
|
u8_t have_chksum, u16_t chksum)
|
||||||
{
|
{
|
||||||
/* send to the packet using remote ip and port stored in the pcb */
|
/* send to the packet using remote ip and port stored in the pcb */
|
||||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
|
return udp_sendto_chksum(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port,
|
||||||
have_chksum, chksum);
|
have_chksum, chksum);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
@@ -429,20 +479,34 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
{
|
{
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
ipX_addr_t *dst_ip_route = ip_2_ipX(dst_ip);
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||||
|
|
||||||
/* find the outgoing network interface for this packet */
|
#if LWIP_IPV6 || LWIP_IGMP
|
||||||
|
if (ipX_addr_ismulticast(PCB_ISIPV6(pcb), dst_ip_route)) {
|
||||||
|
/* For multicast, find a netif based on source address. */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if (PCB_ISIPV6(pcb)) {
|
||||||
|
dst_ip_route = &pcb->local_ip;
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
|
dst_ip_route = ip_2_ipX(&pcb->multicast_ip);
|
||||||
#else
|
|
||||||
netif = ip_route(dst_ip);
|
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 || LWIP_IGMP */
|
||||||
|
|
||||||
|
/* find the outgoing network interface for this packet */
|
||||||
|
netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip_route);
|
||||||
|
|
||||||
/* no outgoing network interface could be found? */
|
/* no outgoing network interface could be found? */
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to "));
|
||||||
ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ip_2_ipX(dst_ip));
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG, ("\n"));
|
||||||
UDP_STATS_INC(udp.rterr);
|
UDP_STATS_INC(udp.rterr);
|
||||||
return ERR_RTE;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
@@ -491,10 +555,15 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
ip_addr_t *src_ip;
|
ip_addr_t *src_ip;
|
||||||
err_t err;
|
err_t err;
|
||||||
struct pbuf *q; /* q will be sent down the stack */
|
struct pbuf *q; /* q will be sent down the stack */
|
||||||
|
u8_t ip_proto;
|
||||||
|
|
||||||
#if IP_SOF_BROADCAST
|
#if IP_SOF_BROADCAST
|
||||||
/* broadcast filter? */
|
/* broadcast filter? */
|
||||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
|
if ( ((pcb->so_options & SOF_BROADCAST) == 0) &&
|
||||||
|
#if LWIP_IPV6
|
||||||
|
!PCB_ISIPV6(pcb) &&
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
@@ -504,7 +573,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
/* if the PCB is not yet bound to a port, bind it here */
|
/* if the PCB is not yet bound to a port, bind it here */
|
||||||
if (pcb->local_port == 0) {
|
if (pcb->local_port == 0) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
|
||||||
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
|
||||||
return err;
|
return err;
|
||||||
@@ -520,8 +589,10 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
/* chain header q in front of given pbuf p */
|
if (p->tot_len != 0) {
|
||||||
pbuf_chain(q, p);
|
/* chain header q in front of given pbuf p (only if p contains data) */
|
||||||
|
pbuf_chain(q, p);
|
||||||
|
}
|
||||||
/* first pbuf q points to header pbuf */
|
/* first pbuf q points to header pbuf */
|
||||||
LWIP_DEBUGF(UDP_DEBUG,
|
LWIP_DEBUGF(UDP_DEBUG,
|
||||||
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||||
@@ -542,20 +613,60 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
|
|
||||||
/* Multicast Loop? */
|
/* Multicast Loop? */
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
|
if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) &&
|
||||||
|
#if LWIP_IPV6
|
||||||
|
(
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
(PCB_ISIPV6(pcb) &&
|
||||||
|
ip6_addr_ismulticast(ip_2_ip6(dst_ip))) ||
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
(!PCB_ISIPV6(pcb) &&
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
((
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
ip_addr_ismulticast(dst_ip)))) {
|
||||||
q->flags |= PBUF_FLAG_MCASTLOOP;
|
q->flags |= PBUF_FLAG_MCASTLOOP;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
|
||||||
|
|
||||||
/* PCB local address is IP_ANY_ADDR? */
|
/* PCB local address is IP_ANY_ADDR? */
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
#if LWIP_IPV6
|
||||||
|
if (PCB_ISIPV6(pcb)) {
|
||||||
|
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||||
|
src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip)));
|
||||||
|
if (src_ip == NULL) {
|
||||||
|
/* No suitable source address was found. */
|
||||||
|
if (q != p) {
|
||||||
|
/* free the header pbuf */
|
||||||
|
pbuf_free(q);
|
||||||
|
/* p is still referenced by the caller, and will live on */
|
||||||
|
}
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* use UDP PCB local IPv6 address as source address, if still valid. */
|
||||||
|
if (netif_matches_ip6_addr(netif, ipX_2_ip6(&pcb->local_ip)) < 0) {
|
||||||
|
/* Address isn't valid anymore. */
|
||||||
|
if (q != p) {
|
||||||
|
/* free the header pbuf */
|
||||||
|
pbuf_free(q);
|
||||||
|
/* p is still referenced by the caller, and will live on */
|
||||||
|
}
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
src_ip = ipX_2_ip(&pcb->local_ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||||
/* use outgoing network interface IP address as source address */
|
/* use outgoing network interface IP address as source address */
|
||||||
src_ip = &(netif->ip_addr);
|
src_ip = &(netif->ip_addr);
|
||||||
} else {
|
} else {
|
||||||
/* check if UDP PCB local IP address is correct
|
/* check if UDP PCB local IP address is correct
|
||||||
* this could be an old address if netif->ip_addr has changed */
|
* this could be an old address if netif->ip_addr has changed */
|
||||||
if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) {
|
||||||
/* local_ip doesn't match, drop the packet */
|
/* local_ip doesn't match, drop the packet */
|
||||||
if (q != p) {
|
if (q != p) {
|
||||||
/* free the header pbuf */
|
/* free the header pbuf */
|
||||||
@@ -566,7 +677,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
/* use UDP PCB local IP address as source address */
|
/* use UDP PCB local IP address as source address */
|
||||||
src_ip = &(pcb->local_ip);
|
src_ip = ipX_2_ip(&(pcb->local_ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||||
@@ -594,33 +705,28 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
udphdr->len = htons(chklen_hdr);
|
udphdr->len = htons(chklen_hdr);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
#if CHECKSUM_GEN_UDP
|
#if CHECKSUM_GEN_UDP
|
||||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
IP_PROTO_UDPLITE, q->tot_len,
|
if (have_chksum) {
|
||||||
#if !LWIP_CHECKSUM_ON_COPY
|
chklen = UDP_HLEN;
|
||||||
chklen);
|
}
|
||||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
(have_chksum ? UDP_HLEN : chklen));
|
udphdr->chksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDPLITE,
|
||||||
|
q->tot_len, chklen, ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||||
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
if (have_chksum) {
|
if (have_chksum) {
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||||
udphdr->chksum = FOLD_U32T(acc);
|
udphdr->chksum = FOLD_U32T(acc);
|
||||||
}
|
}
|
||||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
|
|
||||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||||
if (udphdr->chksum == 0x0000) {
|
if (udphdr->chksum == 0x0000) {
|
||||||
udphdr->chksum = 0xffff;
|
udphdr->chksum = 0xffff;
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_GEN_UDP */
|
#endif /* CHECKSUM_GEN_UDP */
|
||||||
/* output to IP */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
ip_proto = IP_PROTO_UDPLITE;
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
netif->addr_hint = &(pcb->addr_hint);
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
netif->addr_hint = NULL;
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_UDPLITE */
|
#endif /* LWIP_UDPLITE */
|
||||||
{ /* UDP */
|
{ /* UDP */
|
||||||
@@ -628,19 +734,21 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
udphdr->len = htons(q->tot_len);
|
udphdr->len = htons(q->tot_len);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
#if CHECKSUM_GEN_UDP
|
#if CHECKSUM_GEN_UDP
|
||||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
/* Checksum is mandatory over IPv6. */
|
||||||
|
if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||||
u16_t udpchksum;
|
u16_t udpchksum;
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
if (have_chksum) {
|
if (have_chksum) {
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
udpchksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDP,
|
||||||
q->tot_len, UDP_HLEN);
|
q->tot_len, UDP_HLEN, ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||||
acc = udpchksum + (u16_t)~(chksum);
|
acc = udpchksum + (u16_t)~(chksum);
|
||||||
udpchksum = FOLD_U32T(acc);
|
udpchksum = FOLD_U32T(acc);
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
{
|
{
|
||||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
udpchksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, q->tot_len,
|
||||||
|
ip_2_ipX(src_ip), ip_2_ipX(dst_ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||||
@@ -650,17 +758,16 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
|||||||
udphdr->chksum = udpchksum;
|
udphdr->chksum = udpchksum;
|
||||||
}
|
}
|
||||||
#endif /* CHECKSUM_GEN_UDP */
|
#endif /* CHECKSUM_GEN_UDP */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
ip_proto = IP_PROTO_UDP;
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
|
||||||
/* output to IP */
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
netif->addr_hint = &(pcb->addr_hint);
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
netif->addr_hint = NULL;
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto));
|
||||||
|
/* output to IP */
|
||||||
|
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
|
||||||
|
err = ipX_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif);
|
||||||
|
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||||
|
|
||||||
/* TODO: must this be increased even if error occured? */
|
/* TODO: must this be increased even if error occured? */
|
||||||
snmp_inc_udpoutdatagrams();
|
snmp_inc_udpoutdatagrams();
|
||||||
|
|
||||||
@@ -702,7 +809,7 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
u8_t rebind;
|
u8_t rebind;
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
|
||||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE, ip_2_ipX(ipaddr));
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
|
||||||
|
|
||||||
rebind = 0;
|
rebind = 0;
|
||||||
@@ -726,11 +833,11 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
/* port matches that of PCB in list and REUSEADDR not set -> reject */
|
/* port matches that of PCB in list and REUSEADDR not set -> reject */
|
||||||
else {
|
else {
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
if ((ipcb->local_port == port) &&
|
if ((ipcb->local_port == port) && IP_PCB_IPVER_EQ(pcb, ipcb) &&
|
||||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||||
(ip_addr_isany(&(ipcb->local_ip)) ||
|
(ipX_addr_isany(PCB_ISIPV6(ipcb), &(ipcb->local_ip)) ||
|
||||||
ip_addr_isany(ipaddr) ||
|
ipX_addr_isany(PCB_ISIPV6(ipcb), ip_2_ipX(ipaddr)) ||
|
||||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
ipX_addr_cmp(PCB_ISIPV6(ipcb), &(ipcb->local_ip), ip_2_ipX(ipaddr)))) {
|
||||||
/* other PCB already binds to this local IP and port */
|
/* other PCB already binds to this local IP and port */
|
||||||
LWIP_DEBUGF(UDP_DEBUG,
|
LWIP_DEBUGF(UDP_DEBUG,
|
||||||
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||||
@@ -739,13 +846,15 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr);
|
||||||
|
|
||||||
/* no port specified? */
|
/* no port specified? */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
#ifndef UDP_LOCAL_PORT_RANGE_START
|
||||||
#define UDP_LOCAL_PORT_RANGE_START 4096
|
/* From http://www.iana.org/assignments/port-numbers:
|
||||||
#define UDP_LOCAL_PORT_RANGE_END 0x7fff
|
"The Dynamic and/or Private Ports are those from 49152 through 65535" */
|
||||||
|
#define UDP_LOCAL_PORT_RANGE_START 0xc000
|
||||||
|
#define UDP_LOCAL_PORT_RANGE_END 0xffff
|
||||||
#endif
|
#endif
|
||||||
port = UDP_LOCAL_PORT_RANGE_START;
|
port = UDP_LOCAL_PORT_RANGE_START;
|
||||||
ipcb = udp_pcbs;
|
ipcb = udp_pcbs;
|
||||||
@@ -774,13 +883,12 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
pcb->next = udp_pcbs;
|
pcb->next = udp_pcbs;
|
||||||
udp_pcbs = pcb;
|
udp_pcbs = pcb;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to "));
|
||||||
("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip);
|
||||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port));
|
||||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
|
||||||
pcb->local_port));
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect an UDP PCB.
|
* Connect an UDP PCB.
|
||||||
*
|
*
|
||||||
@@ -804,39 +912,44 @@ udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
struct udp_pcb *ipcb;
|
struct udp_pcb *ipcb;
|
||||||
|
|
||||||
if (pcb->local_port == 0) {
|
if (pcb->local_port == 0) {
|
||||||
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
err_t err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr);
|
||||||
pcb->remote_port = port;
|
pcb->remote_port = port;
|
||||||
pcb->flags |= UDP_FLAGS_CONNECTED;
|
pcb->flags |= UDP_FLAGS_CONNECTED;
|
||||||
/** TODO: this functionality belongs in upper layers */
|
/** TODO: this functionality belongs in upper layers */
|
||||||
#ifdef LWIP_UDP_TODO
|
#ifdef LWIP_UDP_TODO
|
||||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
#if LWIP_IPV6
|
||||||
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
|
if (!PCB_ISIPV6(pcb))
|
||||||
struct netif *netif;
|
#endif /* LWIP_IPV6 */
|
||||||
|
{
|
||||||
|
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||||
|
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip)) && !ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) {
|
||||||
|
struct netif *netif;
|
||||||
|
|
||||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
if ((netif = ip_route(ipX_2_ip(&pcb->remote_ip))) == NULL) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n",
|
||||||
UDP_STATS_INC(udp.rterr);
|
ip4_addr_get_u32(ipX_2_ip(&pcb->remote_ip))));
|
||||||
return ERR_RTE;
|
UDP_STATS_INC(udp.rterr);
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||||
|
is used to route output packets to the remote address. However, we
|
||||||
|
might want to accept incoming packets on any interface! */
|
||||||
|
ipX_addr_copy(0, pcb->local_ip, netif->ip_addr);
|
||||||
|
} else if (ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) {
|
||||||
|
ipX_addr_set_any(0, &pcb->local_ip);
|
||||||
}
|
}
|
||||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
|
||||||
is used to route output packets to the remote address. However, we
|
|
||||||
might want to accept incoming packets on any interface! */
|
|
||||||
pcb->local_ip = netif->ip_addr;
|
|
||||||
} else if (ip_addr_isany(&pcb->remote_ip)) {
|
|
||||||
pcb->local_ip.addr = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to "));
|
||||||
("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
&pcb->remote_ip);
|
||||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port));
|
||||||
pcb->local_port));
|
|
||||||
|
|
||||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||||
@@ -860,7 +973,7 @@ void
|
|||||||
udp_disconnect(struct udp_pcb *pcb)
|
udp_disconnect(struct udp_pcb *pcb)
|
||||||
{
|
{
|
||||||
/* reset remote address association */
|
/* reset remote address association */
|
||||||
ip_addr_set_any(&pcb->remote_ip);
|
ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->remote_ip);
|
||||||
pcb->remote_port = 0;
|
pcb->remote_port = 0;
|
||||||
/* mark PCB as unconnected */
|
/* mark PCB as unconnected */
|
||||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||||
@@ -879,7 +992,7 @@ void
|
|||||||
udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
|
udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
|
||||||
{
|
{
|
||||||
/* remember recv() callback and user data */
|
/* remember recv() callback and user data */
|
||||||
pcb->recv = recv;
|
pcb->recv.ip4 = recv;
|
||||||
pcb->recv_arg = recv_arg;
|
pcb->recv_arg = recv_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -939,6 +1052,25 @@ udp_new(void)
|
|||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/**
|
||||||
|
* Create a UDP PCB for IPv6.
|
||||||
|
*
|
||||||
|
* @return The UDP PCB which was created. NULL if the PCB data structure
|
||||||
|
* could not be allocated.
|
||||||
|
*
|
||||||
|
* @see udp_remove()
|
||||||
|
*/
|
||||||
|
struct udp_pcb *
|
||||||
|
udp_new_ip6(void)
|
||||||
|
{
|
||||||
|
struct udp_pcb *pcb;
|
||||||
|
pcb = udp_new();
|
||||||
|
ip_set_v6(pcb, 1);
|
||||||
|
return pcb;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
/**
|
/**
|
||||||
* Print UDP header information for debug purposes.
|
* Print UDP header information for debug purposes.
|
||||||
|
|||||||
@@ -89,8 +89,7 @@ struct autoip
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Init srand, has to be called before entering mainloop */
|
#define autoip_init() /* Compatibility define, no init needed. */
|
||||||
void autoip_init(void);
|
|
||||||
|
|
||||||
/** Set a struct autoip allocated by the application to work with */
|
/** Set a struct autoip allocated by the application to work with */
|
||||||
void autoip_set_struct(struct netif *netif, struct autoip *autoip);
|
void autoip_set_struct(struct netif *netif, struct autoip *autoip);
|
||||||
|
|||||||
@@ -37,33 +37,37 @@
|
|||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ICMP6
|
||||||
|
#include "lwip/icmp6.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ICMP_ER 0 /* echo reply */
|
#define ICMP_ER 0 /* echo reply */
|
||||||
#define ICMP_DUR 3 /* destination unreachable */
|
#define ICMP_DUR 3 /* destination unreachable */
|
||||||
#define ICMP_SQ 4 /* source quench */
|
#define ICMP_SQ 4 /* source quench */
|
||||||
#define ICMP_RD 5 /* redirect */
|
#define ICMP_RD 5 /* redirect */
|
||||||
#define ICMP_ECHO 8 /* echo */
|
#define ICMP_ECHO 8 /* echo */
|
||||||
#define ICMP_TE 11 /* time exceeded */
|
#define ICMP_TE 11 /* time exceeded */
|
||||||
#define ICMP_PP 12 /* parameter problem */
|
#define ICMP_PP 12 /* parameter problem */
|
||||||
#define ICMP_TS 13 /* timestamp */
|
#define ICMP_TS 13 /* timestamp */
|
||||||
#define ICMP_TSR 14 /* timestamp reply */
|
#define ICMP_TSR 14 /* timestamp reply */
|
||||||
#define ICMP_IRQ 15 /* information request */
|
#define ICMP_IRQ 15 /* information request */
|
||||||
#define ICMP_IR 16 /* information reply */
|
#define ICMP_IR 16 /* information reply */
|
||||||
|
|
||||||
enum icmp_dur_type {
|
enum icmp_dur_type {
|
||||||
ICMP_DUR_NET = 0, /* net unreachable */
|
ICMP_DUR_NET = 0, /* net unreachable */
|
||||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
||||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||||
ICMP_DUR_SR = 5 /* source route failed */
|
ICMP_DUR_SR = 5 /* source route failed */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum icmp_te_type {
|
enum icmp_te_type {
|
||||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,6 +108,16 @@ void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
|||||||
|
|
||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP */
|
||||||
|
|
||||||
|
#if (LWIP_IPV6 && LWIP_ICMP6)
|
||||||
|
#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \
|
||||||
|
icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \
|
||||||
|
icmp_dest_unreach(pbuf, ICMP_DUR_PORT))
|
||||||
|
#elif LWIP_ICMP
|
||||||
|
#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT)
|
||||||
|
#else /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/
|
||||||
|
#define icmp_port_unreach(isipv6, pbuf)
|
||||||
|
#endif /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,14 +29,15 @@
|
|||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef __LWIP_IP_H__
|
#ifndef __LWIP_IP4_H__
|
||||||
#define __LWIP_IP_H__
|
#define __LWIP_IP4_H__
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
@@ -55,59 +56,6 @@ extern "C" {
|
|||||||
#define IP_PROTO_UDPLITE 136
|
#define IP_PROTO_UDPLITE 136
|
||||||
#define IP_PROTO_TCP 6
|
#define IP_PROTO_TCP 6
|
||||||
|
|
||||||
/* This is passed as the destination address to ip_output_if (not
|
|
||||||
to ip_output), meaning that an IP header already is constructed
|
|
||||||
in the pbuf. This is used when TCP retransmits. */
|
|
||||||
#ifdef IP_HDRINCL
|
|
||||||
#undef IP_HDRINCL
|
|
||||||
#endif /* IP_HDRINCL */
|
|
||||||
#define IP_HDRINCL NULL
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
#define IP_PCB_ADDRHINT ;u8_t addr_hint
|
|
||||||
#else
|
|
||||||
#define IP_PCB_ADDRHINT
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
|
|
||||||
/* This is the common part of all PCB types. It needs to be at the
|
|
||||||
beginning of a PCB type definition. It is located here so that
|
|
||||||
changes to this common part are made in one location instead of
|
|
||||||
having to change all PCB structs. */
|
|
||||||
#define IP_PCB \
|
|
||||||
/* ip addresses in network byte order */ \
|
|
||||||
ip_addr_t local_ip; \
|
|
||||||
ip_addr_t remote_ip; \
|
|
||||||
/* Socket options */ \
|
|
||||||
u8_t so_options; \
|
|
||||||
/* Type Of Service */ \
|
|
||||||
u8_t tos; \
|
|
||||||
/* Time To Live */ \
|
|
||||||
u8_t ttl \
|
|
||||||
/* link layer address resolution hint */ \
|
|
||||||
IP_PCB_ADDRHINT
|
|
||||||
|
|
||||||
struct ip_pcb {
|
|
||||||
/* Common members of all PCB types */
|
|
||||||
IP_PCB;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Option flags per-socket. These are the same like SO_XXX.
|
|
||||||
*/
|
|
||||||
/*#define SOF_DEBUG (u8_t)0x01U Unimplemented: turn on debugging info recording */
|
|
||||||
#define SOF_ACCEPTCONN (u8_t)0x02U /* socket has had listen() */
|
|
||||||
#define SOF_REUSEADDR (u8_t)0x04U /* allow local address reuse */
|
|
||||||
#define SOF_KEEPALIVE (u8_t)0x08U /* keep connections alive */
|
|
||||||
/*#define SOF_DONTROUTE (u8_t)0x10U Unimplemented: just use interface addresses */
|
|
||||||
#define SOF_BROADCAST (u8_t)0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
|
||||||
/*#define SOF_USELOOPBACK (u8_t)0x40U Unimplemented: bypass hardware when possible */
|
|
||||||
#define SOF_LINGER (u8_t)0x80U /* linger on close if data present */
|
|
||||||
/*#define SOF_OOBINLINE (u16_t)0x0100U Unimplemented: leave received OOB data in line */
|
|
||||||
/*#define SOF_REUSEPORT (u16_t)0x0200U Unimplemented: allow local address & port reuse */
|
|
||||||
|
|
||||||
/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
|
|
||||||
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
# include "arch/bpstruct.h"
|
# include "arch/bpstruct.h"
|
||||||
@@ -122,10 +70,10 @@ struct ip_hdr {
|
|||||||
PACK_STRUCT_FIELD(u16_t _id);
|
PACK_STRUCT_FIELD(u16_t _id);
|
||||||
/* fragment offset field */
|
/* fragment offset field */
|
||||||
PACK_STRUCT_FIELD(u16_t _offset);
|
PACK_STRUCT_FIELD(u16_t _offset);
|
||||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
#define IP_RF 0x8000U /* reserved fragment flag */
|
||||||
#define IP_DF 0x4000 /* dont fragment flag */
|
#define IP_DF 0x4000U /* dont fragment flag */
|
||||||
#define IP_MF 0x2000 /* more fragments flag */
|
#define IP_MF 0x2000U /* more fragments flag */
|
||||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */
|
||||||
/* time to live */
|
/* time to live */
|
||||||
PACK_STRUCT_FIELD(u8_t _ttl);
|
PACK_STRUCT_FIELD(u8_t _ttl);
|
||||||
/* protocol*/
|
/* protocol*/
|
||||||
@@ -159,16 +107,8 @@ PACK_STRUCT_END
|
|||||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
|
#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
|
||||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||||
|
|
||||||
/** The interface that provided the packet for the current callback invocation. */
|
|
||||||
extern struct netif *current_netif;
|
|
||||||
/** Header of the input packet currently being processed. */
|
|
||||||
extern const struct ip_hdr *current_header;
|
|
||||||
/** Source IP address of current_header */
|
|
||||||
extern ip_addr_t current_iphdr_src;
|
|
||||||
/** Destination IP address of current_header */
|
|
||||||
extern ip_addr_t current_iphdr_dest;
|
|
||||||
|
|
||||||
#define ip_init() /* Compatibility define, not init needed. */
|
#define ip_init() /* Compatibility define, no init needed. */
|
||||||
struct netif *ip_route(ip_addr_t *dest);
|
struct netif *ip_route(ip_addr_t *dest);
|
||||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||||
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||||
@@ -185,18 +125,8 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
|||||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||||
u16_t optlen);
|
u16_t optlen);
|
||||||
#endif /* IP_OPTIONS_SEND */
|
#endif /* IP_OPTIONS_SEND */
|
||||||
/** Get the interface that received the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
#define ip_netif_get_local_ipX(netif) (((netif) != NULL) ? ip_2_ipX(&((netif)->ip_addr)) : NULL)
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip_current_netif() (current_netif)
|
|
||||||
/** Get the IP header of the current packet.
|
|
||||||
* This function must only be called from a receive callback (udp_recv,
|
|
||||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
|
||||||
#define ip_current_header() (current_header)
|
|
||||||
/** Source IP address of current_header */
|
|
||||||
#define ip_current_src_addr() (¤t_iphdr_src)
|
|
||||||
/** Destination IP address of current_header */
|
|
||||||
#define ip_current_dest_addr() (¤t_iphdr_dest)
|
|
||||||
|
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
void ip_debug_print(struct pbuf *p);
|
void ip_debug_print(struct pbuf *p);
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef __LWIP_IP_ADDR_H__
|
#ifndef __LWIP_IP4_ADDR_H__
|
||||||
#define __LWIP_IP_ADDR_H__
|
#define __LWIP_IP4_ADDR_H__
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
@@ -70,12 +70,15 @@ struct pbuf * ip_reass(struct pbuf *p);
|
|||||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
||||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
||||||
* that points into the original pbuf. */
|
* that points into the original pbuf. */
|
||||||
|
#ifndef __LWIP_PBUF_CUSTOM_REF__
|
||||||
|
#define __LWIP_PBUF_CUSTOM_REF__
|
||||||
struct pbuf_custom_ref {
|
struct pbuf_custom_ref {
|
||||||
/** 'base class' */
|
/** 'base class' */
|
||||||
struct pbuf_custom pc;
|
struct pbuf_custom pc;
|
||||||
/** pointer to the original pbuf that is referenced */
|
/** pointer to the original pbuf that is referenced */
|
||||||
struct pbuf *original;
|
struct pbuf *original;
|
||||||
};
|
};
|
||||||
|
#endif /* __LWIP_PBUF_CUSTOM_REF__ */
|
||||||
#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
|
err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
|
||||||
|
|||||||
58
src/include/ipv6/lwip/dhcp6.h
Normal file
58
src/include/ipv6/lwip/dhcp6.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 address autoconfiguration as per RFC 4862.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
* IPv6 address autoconfiguration as per RFC 4862.
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LWIP_IP6_DHCP6_H__
|
||||||
|
#define __LWIP_IP6_DHCP6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
|
||||||
|
struct dhcp6
|
||||||
|
{
|
||||||
|
//TODO: implement DHCP6
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP6_DHCP6_H__ */
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
@@ -11,58 +17,52 @@
|
|||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
* 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
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* 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
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* 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_INET_H__
|
|
||||||
#define __LWIP_INET_H__
|
#ifndef __LWIP_ETHIP6_H__
|
||||||
|
#define __LWIP_ETHIP6_H__
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u16_t inet_chksum(void *data, u16_t len);
|
|
||||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
|
||||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
|
||||||
struct ip_addr *src, struct ip_addr *dest,
|
|
||||||
u8_t proto, u32_t proto_len);
|
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
err_t ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr);
|
||||||
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
|
||||||
|
|
||||||
#ifndef _MACHINE_ENDIAN_H_
|
|
||||||
#ifndef _NETINET_IN_H
|
|
||||||
#ifndef _LINUX_BYTEORDER_GENERIC_H
|
|
||||||
u16_t htons(u16_t n);
|
|
||||||
u16_t ntohs(u16_t n);
|
|
||||||
u32_t htonl(u32_t n);
|
|
||||||
u32_t ntohl(u32_t n);
|
|
||||||
#endif /* _LINUX_BYTEORDER_GENERIC_H */
|
|
||||||
#endif /* _NETINET_IN_H */
|
|
||||||
#endif /* _MACHINE_ENDIAN_H_ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __LWIP_INET_H__ */
|
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||||
|
|
||||||
|
#endif /* __LWIP_ETHIP6_H__ */
|
||||||
@@ -1,100 +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: Adam Dunkels <adam@sics.se>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef __LWIP_ICMP_H__
|
|
||||||
#define __LWIP_ICMP_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ICMP6_DUR 1
|
|
||||||
#define ICMP6_TE 3
|
|
||||||
#define ICMP6_ECHO 128 /* echo */
|
|
||||||
#define ICMP6_ER 129 /* echo reply */
|
|
||||||
|
|
||||||
|
|
||||||
enum icmp_dur_type {
|
|
||||||
ICMP_DUR_NET = 0, /* net unreachable */
|
|
||||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
|
||||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
|
||||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
|
||||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
|
||||||
ICMP_DUR_SR = 5 /* source route failed */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum icmp_te_type {
|
|
||||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
|
||||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
|
||||||
};
|
|
||||||
|
|
||||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
|
||||||
|
|
||||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
|
||||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
|
||||||
|
|
||||||
struct icmp_echo_hdr {
|
|
||||||
u8_t type;
|
|
||||||
u8_t icode;
|
|
||||||
u16_t chksum;
|
|
||||||
u16_t id;
|
|
||||||
u16_t seqno;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct icmp_dur_hdr {
|
|
||||||
u8_t type;
|
|
||||||
u8_t icode;
|
|
||||||
u16_t chksum;
|
|
||||||
u32_t unused;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct icmp_te_hdr {
|
|
||||||
u8_t type;
|
|
||||||
u8_t icode;
|
|
||||||
u16_t chksum;
|
|
||||||
u32_t unused;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LWIP_ICMP */
|
|
||||||
|
|
||||||
#endif /* __LWIP_ICMP_H__ */
|
|
||||||
|
|
||||||
152
src/include/ipv6/lwip/icmp6.h
Normal file
152
src/include/ipv6/lwip/icmp6.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 version of ICMP, as per RFC 4443.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_ICMP6_H__
|
||||||
|
#define __LWIP_ICMP6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum icmp6_type {
|
||||||
|
ICMP6_TYPE_DUR = 1, /* Destination unreachable */
|
||||||
|
ICMP6_TYPE_PTB = 2, /* Packet too big */
|
||||||
|
ICMP6_TYPE_TE = 3, /* Time exceeded */
|
||||||
|
ICMP6_TYPE_PP = 4, /* Parameter problem */
|
||||||
|
ICMP6_TYPE_PE1 = 100, /* Private experimentation */
|
||||||
|
ICMP6_TYPE_PE2 = 101, /* Private experimentation */
|
||||||
|
ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */
|
||||||
|
|
||||||
|
ICMP6_TYPE_EREQ = 128, /* Echo request */
|
||||||
|
ICMP6_TYPE_EREP = 129, /* Echo reply */
|
||||||
|
ICMP6_TYPE_MLQ = 130, /* Multicast listener query */
|
||||||
|
ICMP6_TYPE_MLR = 131, /* Multicast listener report */
|
||||||
|
ICMP6_TYPE_MLD = 132, /* Multicast listener done */
|
||||||
|
ICMP6_TYPE_RS = 133, /* Router solicitation */
|
||||||
|
ICMP6_TYPE_RA = 134, /* Router advertisement */
|
||||||
|
ICMP6_TYPE_NS = 135, /* Neighbor solicitation */
|
||||||
|
ICMP6_TYPE_NA = 136, /* Neighbor advertisement */
|
||||||
|
ICMP6_TYPE_RD = 137, /* Redirect */
|
||||||
|
ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */
|
||||||
|
ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */
|
||||||
|
ICMP6_TYPE_MRT = 153, /* Multicast router termination */
|
||||||
|
ICMP6_TYPE_PE3 = 200, /* Private experimentation */
|
||||||
|
ICMP6_TYPE_PE4 = 201, /* Private experimentation */
|
||||||
|
ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icmp6_dur_code {
|
||||||
|
ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */
|
||||||
|
ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */
|
||||||
|
ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */
|
||||||
|
ICMP6_DUR_ADDRESS = 3, /* Address unreachable */
|
||||||
|
ICMP6_DUR_PORT = 4, /* Port unreachable */
|
||||||
|
ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */
|
||||||
|
ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icmp6_te_code {
|
||||||
|
ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */
|
||||||
|
ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icmp6_pp_code {
|
||||||
|
ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */
|
||||||
|
ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */
|
||||||
|
ICMP6_PP_OPTION = 2, /* Unrecognized IPv6 option encountered */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** This is the standard ICMP6 header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct icmp6_hdr {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u32_t data);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** This is the ICMP6 header adapted for echo req/resp. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct icmp6_echo_hdr {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u16_t id);
|
||||||
|
PACK_STRUCT_FIELD(u16_t seqno);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
void icmp6_input(struct pbuf *p, struct netif *inp);
|
||||||
|
void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c);
|
||||||
|
void icmp6_packet_too_big(struct pbuf *p, u32_t mtu);
|
||||||
|
void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c);
|
||||||
|
void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer);
|
||||||
|
|
||||||
|
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __LWIP_ICMP6_H__ */
|
||||||
89
src/include/ipv6/lwip/inet6.h
Normal file
89
src/include/ipv6/lwip/inet6.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* INET v6 addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_INET6_H__
|
||||||
|
#define __LWIP_INET6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** For compatibility with BSD code */
|
||||||
|
struct in6_addr {
|
||||||
|
u32_t s_addr[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IN6ADDR_ANY_INIT {0,0,0,0}
|
||||||
|
#define IN6ADDR_LOOPBACK_INIT {0,0,0,PP_HTONL(1)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s_addr[0] = (source_ip6addr)->addr[0]; \
|
||||||
|
(target_in6addr)->s_addr[1] = (source_ip6addr)->addr[1]; \
|
||||||
|
(target_in6addr)->s_addr[2] = (source_ip6addr)->addr[2]; \
|
||||||
|
(target_in6addr)->s_addr[3] = (source_ip6addr)->addr[3];}
|
||||||
|
#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||||
|
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||||
|
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||||
|
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0];}
|
||||||
|
/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */
|
||||||
|
#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr))
|
||||||
|
|
||||||
|
/* directly map this to the lwip internal functions */
|
||||||
|
#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr)
|
||||||
|
#define inet6_ntoa(addr) ip6addr_ntoa((ip6_addr_t*)&(addr))
|
||||||
|
#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((ip6_addr_t*)&(addr), buf, buflen)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_INET6_H__ */
|
||||||
|
|
||||||
@@ -1,130 +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: Adam Dunkels <adam@sics.se>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef __LWIP_IP_H__
|
|
||||||
#define __LWIP_IP_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/def.h"
|
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
#include "lwip/err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP_HLEN 40
|
|
||||||
|
|
||||||
#define IP_PROTO_ICMP 58
|
|
||||||
#define IP_PROTO_UDP 17
|
|
||||||
#define IP_PROTO_UDPLITE 136
|
|
||||||
#define IP_PROTO_TCP 6
|
|
||||||
|
|
||||||
/* This is passed as the destination address to ip_output_if (not
|
|
||||||
to ip_output), meaning that an IP header already is constructed
|
|
||||||
in the pbuf. This is used when TCP retransmits. */
|
|
||||||
#ifdef IP_HDRINCL
|
|
||||||
#undef IP_HDRINCL
|
|
||||||
#endif /* IP_HDRINCL */
|
|
||||||
#define IP_HDRINCL NULL
|
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
|
||||||
#define IP_PCB_ADDRHINT ;u8_t addr_hint
|
|
||||||
#else
|
|
||||||
#define IP_PCB_ADDRHINT
|
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
|
||||||
|
|
||||||
/* This is the common part of all PCB types. It needs to be at the
|
|
||||||
beginning of a PCB type definition. It is located here so that
|
|
||||||
changes to this common part are made in one location instead of
|
|
||||||
having to change all PCB structs. */
|
|
||||||
#define IP_PCB struct ip_addr local_ip; \
|
|
||||||
struct ip_addr remote_ip; \
|
|
||||||
/* Socket options */ \
|
|
||||||
u16_t so_options; \
|
|
||||||
/* Type Of Service */ \
|
|
||||||
u8_t tos; \
|
|
||||||
/* Time To Live */ \
|
|
||||||
u8_t ttl; \
|
|
||||||
/* link layer address resolution hint */ \
|
|
||||||
IP_PCB_ADDRHINT
|
|
||||||
|
|
||||||
|
|
||||||
/* The IPv6 header. */
|
|
||||||
struct ip_hdr {
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
u8_t tclass1:4, v:4;
|
|
||||||
u8_t flow1:4, tclass2:4;
|
|
||||||
#else
|
|
||||||
u8_t v:4, tclass1:4;
|
|
||||||
u8_t tclass2:8, flow1:4;
|
|
||||||
#endif
|
|
||||||
u16_t flow2;
|
|
||||||
u16_t len; /* payload length */
|
|
||||||
u8_t nexthdr; /* next header */
|
|
||||||
u8_t hoplim; /* hop limit (TTL) */
|
|
||||||
struct ip_addr src, dest; /* source and destination IP addresses */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IPH_PROTO(hdr) (iphdr->nexthdr)
|
|
||||||
|
|
||||||
void ip_init(void);
|
|
||||||
|
|
||||||
#include "lwip/netif.h"
|
|
||||||
|
|
||||||
struct netif *ip_route(struct ip_addr *dest);
|
|
||||||
|
|
||||||
void ip_input(struct pbuf *p, struct netif *inp);
|
|
||||||
|
|
||||||
/* source and destination addresses in network byte order, please */
|
|
||||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|
||||||
u8_t ttl, u8_t proto);
|
|
||||||
|
|
||||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|
||||||
u8_t ttl, u8_t proto,
|
|
||||||
struct netif *netif);
|
|
||||||
|
|
||||||
#define ip_current_netif() NULL
|
|
||||||
#define ip_current_header() NULL
|
|
||||||
|
|
||||||
#if IP_DEBUG
|
|
||||||
void ip_debug_print(struct pbuf *p);
|
|
||||||
#endif /* IP_DEBUG */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __LWIP_IP_H__ */
|
|
||||||
|
|
||||||
|
|
||||||
197
src/include/ipv6/lwip/ip6.h
Normal file
197
src/include/ipv6/lwip/ip6.h
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 layer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_IP6_H__
|
||||||
|
#define __LWIP_IP6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IP6_HLEN 40
|
||||||
|
|
||||||
|
#define IP6_NEXTH_HOPBYHOP 0
|
||||||
|
#define IP6_NEXTH_TCP 6
|
||||||
|
#define IP6_NEXTH_UDP 17
|
||||||
|
#define IP6_NEXTH_ENCAPS 41
|
||||||
|
#define IP6_NEXTH_ROUTING 43
|
||||||
|
#define IP6_NEXTH_FRAGMENT 44
|
||||||
|
#define IP6_NEXTH_ICMP6 58
|
||||||
|
#define IP6_NEXTH_NONE 59
|
||||||
|
#define IP6_NEXTH_DESTOPTS 60
|
||||||
|
#define IP6_NEXTH_UDPLITE 136
|
||||||
|
|
||||||
|
|
||||||
|
/* The IPv6 header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip6_hdr {
|
||||||
|
/* version / traffic class / flow label */
|
||||||
|
PACK_STRUCT_FIELD(u32_t _v_tc_fl);
|
||||||
|
/* payload length */
|
||||||
|
PACK_STRUCT_FIELD(u16_t _plen);
|
||||||
|
/* next header */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||||
|
/* hop limit */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _hoplim);
|
||||||
|
/* source and destination IP addresses */
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t src);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t dest);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Hop-by-hop router alert option. */
|
||||||
|
#define IP6_HBH_HLEN 8
|
||||||
|
#define IP6_PAD1_OPTION 0
|
||||||
|
#define IP6_PADN_ALERT_OPTION 1
|
||||||
|
#define IP6_ROUTER_ALERT_OPTION 5
|
||||||
|
#define IP6_ROUTER_ALERT_VALUE_MLD 0
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip6_hbh_hdr {
|
||||||
|
/* next header */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||||
|
/* header length */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _hlen);
|
||||||
|
/* router alert option type */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _ra_opt_type);
|
||||||
|
/* router alert option data len */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _ra_opt_dlen);
|
||||||
|
/* router alert option data */
|
||||||
|
PACK_STRUCT_FIELD(u16_t _ra_opt_data);
|
||||||
|
/* PadN option type */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _padn_opt_type);
|
||||||
|
/* PadN option data len */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _padn_opt_dlen);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Fragment header. */
|
||||||
|
#define IP6_FRAG_HLEN 8
|
||||||
|
#define IP6_FRAG_OFFSET_MASK 0xfff8
|
||||||
|
#define IP6_FRAG_MORE_FLAG 0x0001
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip6_frag_hdr {
|
||||||
|
/* next header */
|
||||||
|
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||||
|
/* reserved */
|
||||||
|
PACK_STRUCT_FIELD(u8_t reserved);
|
||||||
|
/* fragment offset */
|
||||||
|
PACK_STRUCT_FIELD(u16_t _fragment_offset);
|
||||||
|
/* fragmented packet identification */
|
||||||
|
PACK_STRUCT_FIELD(u32_t _identification);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f)
|
||||||
|
#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff)
|
||||||
|
#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff)
|
||||||
|
#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen))
|
||||||
|
#define IP6H_NEXTH(hdr) ((hdr)->_nexth)
|
||||||
|
#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6)
|
||||||
|
#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim)
|
||||||
|
|
||||||
|
#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl(((v) << 28) | ((tc) << 20) | (fl)))
|
||||||
|
#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen)
|
||||||
|
#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth)
|
||||||
|
#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl)
|
||||||
|
|
||||||
|
|
||||||
|
#define ip6_init() /* TODO should we init current addresses and header pointer? */
|
||||||
|
struct netif *ip6_route(struct ip6_addr *src, struct ip6_addr *dest);
|
||||||
|
ip6_addr_t *ip6_select_source_address(struct netif *netif, ip6_addr_t * dest);
|
||||||
|
err_t ip6_input(struct pbuf *p, struct netif *inp);
|
||||||
|
err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||||
|
u8_t hl, u8_t tc, u8_t nexth);
|
||||||
|
err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||||
|
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
||||||
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
|
err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||||
|
u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint);
|
||||||
|
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value);
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
|
||||||
|
#define ip6_netif_get_local_ipX(netif, dest) (((netif) != NULL) ? \
|
||||||
|
ip6_2_ipX(ip6_select_source_address(netif, dest)) : NULL)
|
||||||
|
|
||||||
|
#if IP6_DEBUG
|
||||||
|
void ip6_debug_print(struct pbuf *p);
|
||||||
|
#else
|
||||||
|
#define ip6_debug_print(p)
|
||||||
|
#endif /* IP6_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP6_H__ */
|
||||||
282
src/include/ipv6/lwip/ip6_addr.h
Normal file
282
src/include/ipv6/lwip/ip6_addr.h
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
* Structs and macros for handling IPv6 addresses.
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_IP6_ADDR_H__
|
||||||
|
#define __LWIP_IP6_ADDR_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the aligned version of ip6_addr_t,
|
||||||
|
used as local variable, on the stack, etc. */
|
||||||
|
struct ip6_addr {
|
||||||
|
u32_t addr[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This is the packed version of ip6_addr_t,
|
||||||
|
used in network headers that are itself packed */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip6_addr_packed {
|
||||||
|
PACK_STRUCT_FIELD(u32_t addr[4]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** ip6_addr_t uses a struct for convenience only, so that the same defines can
|
||||||
|
* operate both on ip6_addr_t as well as on ip6_addr_p_t. */
|
||||||
|
typedef struct ip6_addr ip6_addr_t;
|
||||||
|
typedef struct ip6_addr_packed ip6_addr_p_t;
|
||||||
|
|
||||||
|
|
||||||
|
/** IP6_ADDR_ANY can be used as a fixed IPv6 address
|
||||||
|
* for the wildcard
|
||||||
|
*/
|
||||||
|
extern const ip6_addr_t ip6_addr_any;
|
||||||
|
#define IP6_ADDR_ANY ((ip6_addr_t *)&ip6_addr_any)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
/** Set an IPv6 partial address given by byte-parts. */
|
||||||
|
#define IP6_ADDR(ip6addr, index, a,b,c,d) \
|
||||||
|
(ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \
|
||||||
|
((u32_t)((b) & 0xff) << 16) | \
|
||||||
|
((u32_t)((c) & 0xff) << 8) | \
|
||||||
|
(u32_t)((d) & 0xff)
|
||||||
|
#else
|
||||||
|
/** Set an IPv6 partial address given by byte-parts.
|
||||||
|
Little-endian version, stored in network order (no htonl). */
|
||||||
|
#define IP6_ADDR(ip6addr, index, a,b,c,d) \
|
||||||
|
(ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \
|
||||||
|
((u32_t)((c) & 0xff) << 16) | \
|
||||||
|
((u32_t)((b) & 0xff) << 8) | \
|
||||||
|
(u32_t)((a) & 0xff)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Access address in 16-bit block */
|
||||||
|
#define IP6_ADDR_BLOCK1(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK2(ip6addr) ((htonl((ip6addr)->addr[0])) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK3(ip6addr) ((htonl((ip6addr)->addr[1]) >> 16) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK4(ip6addr) ((htonl((ip6addr)->addr[1])) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK5(ip6addr) ((htonl((ip6addr)->addr[2]) >> 16) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK6(ip6addr) ((htonl((ip6addr)->addr[2])) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK7(ip6addr) ((htonl((ip6addr)->addr[3]) >> 16) & 0xffff)
|
||||||
|
#define IP6_ADDR_BLOCK8(ip6addr) ((htonl((ip6addr)->addr[3])) & 0xffff)
|
||||||
|
|
||||||
|
/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */
|
||||||
|
#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \
|
||||||
|
(dest).addr[1] = (src).addr[1]; \
|
||||||
|
(dest).addr[2] = (src).addr[2]; \
|
||||||
|
(dest).addr[3] = (src).addr[3];}while(0)
|
||||||
|
/** Safely copy one IPv6 address to another (src may be NULL) */
|
||||||
|
#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \
|
||||||
|
(dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \
|
||||||
|
(dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \
|
||||||
|
(dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0)
|
||||||
|
|
||||||
|
/** Set complete address to zero */
|
||||||
|
#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[2] = 0; \
|
||||||
|
(ip6addr)->addr[3] = 0;}while(0)
|
||||||
|
|
||||||
|
/** Set address to ipv6 'any' (no need for htonl()) */
|
||||||
|
#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr)
|
||||||
|
/** Set address to ipv6 loopback address */
|
||||||
|
#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[2] = 0; \
|
||||||
|
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0)
|
||||||
|
/** Safely copy one IPv6 address to another and change byte order
|
||||||
|
* from host- to network-order. */
|
||||||
|
#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \
|
||||||
|
(dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \
|
||||||
|
(dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \
|
||||||
|
(dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if two IPv6 address are on the same network.
|
||||||
|
*
|
||||||
|
* @arg addr1 IPv6 address 1
|
||||||
|
* @arg addr2 IPv6 address 2
|
||||||
|
* @return !0 if the network identifiers of both address match
|
||||||
|
*/
|
||||||
|
#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
||||||
|
((addr1)->addr[1] == (addr2)->addr[1]))
|
||||||
|
|
||||||
|
#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
||||||
|
((addr1)->addr[1] == (addr2)->addr[1]) && \
|
||||||
|
((addr1)->addr[2] == (addr2)->addr[2]) && \
|
||||||
|
((addr1)->addr[3] == (addr2)->addr[3]))
|
||||||
|
|
||||||
|
#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL)
|
||||||
|
|
||||||
|
#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || \
|
||||||
|
(((ip6addr)->addr[0] == 0) && \
|
||||||
|
((ip6addr)->addr[1] == 0) && \
|
||||||
|
((ip6addr)->addr[2] == 0) && \
|
||||||
|
((ip6addr)->addr[3] == 0)))
|
||||||
|
|
||||||
|
|
||||||
|
#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL))
|
||||||
|
|
||||||
|
#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL))
|
||||||
|
|
||||||
|
#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL))
|
||||||
|
|
||||||
|
#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL))
|
||||||
|
|
||||||
|
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL))
|
||||||
|
#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))
|
||||||
|
#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL))
|
||||||
|
#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL))
|
||||||
|
#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf)
|
||||||
|
#define IP6_MULTICAST_SCOPE_RESERVED 0x0
|
||||||
|
#define IP6_MULTICAST_SCOPE_RESERVED0 0x0
|
||||||
|
#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1
|
||||||
|
#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2
|
||||||
|
#define IP6_MULTICAST_SCOPE_RESERVED3 0x3
|
||||||
|
#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4
|
||||||
|
#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5
|
||||||
|
#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8
|
||||||
|
#define IP6_MULTICAST_SCOPE_GLOBAL 0xe
|
||||||
|
#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf
|
||||||
|
#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff010000UL))
|
||||||
|
#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff020000UL))
|
||||||
|
#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff040000UL))
|
||||||
|
#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff050000UL))
|
||||||
|
#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff080000UL))
|
||||||
|
#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff0e0000UL))
|
||||||
|
|
||||||
|
/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */
|
||||||
|
#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \
|
||||||
|
((ip6addr)->addr[1] == 0UL) && \
|
||||||
|
((ip6addr)->addr[2] == 0UL) && \
|
||||||
|
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
||||||
|
|
||||||
|
#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||||
|
((ip6addr)->addr[1] == 0UL) && \
|
||||||
|
((ip6addr)->addr[2] == 0UL) && \
|
||||||
|
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
||||||
|
#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[2] = 0; \
|
||||||
|
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0)
|
||||||
|
|
||||||
|
#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||||
|
((ip6addr)->addr[1] == 0UL) && \
|
||||||
|
((ip6addr)->addr[2] == 0UL) && \
|
||||||
|
((ip6addr)->addr[3] == PP_HTONL(0x00000002UL)))
|
||||||
|
#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[2] = 0; \
|
||||||
|
(ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0)
|
||||||
|
|
||||||
|
#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||||
|
((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \
|
||||||
|
(((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) )
|
||||||
|
|
||||||
|
#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \
|
||||||
|
(ip6addr)->addr[3] = htonl(0xff000000UL | (htonl(if_id) & 0x00ffffffUL));}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
/* IPv6 address states. */
|
||||||
|
#define IP6_ADDR_INVALID 0x00
|
||||||
|
#define IP6_ADDR_TENTATIVE 0x08
|
||||||
|
#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */
|
||||||
|
#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */
|
||||||
|
#define IP6_ADDR_VALID 0x10
|
||||||
|
#define IP6_ADDR_PREFERRED 0x30
|
||||||
|
#define IP6_ADDR_DEPRECATED 0x50
|
||||||
|
|
||||||
|
#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID)
|
||||||
|
#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE)
|
||||||
|
#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */
|
||||||
|
#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED)
|
||||||
|
#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED)
|
||||||
|
|
||||||
|
#define ip6_addr_debug_print(debug, ipaddr) \
|
||||||
|
LWIP_DEBUGF(debug, ("%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \
|
||||||
|
ipaddr != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0))
|
||||||
|
|
||||||
|
int ip6addr_aton(const char *cp, ip6_addr_t *addr);
|
||||||
|
/** returns ptr to static buffer; not reentrant! */
|
||||||
|
char *ip6addr_ntoa(const ip6_addr_t *addr);
|
||||||
|
char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP6_ADDR_H__ */
|
||||||
102
src/include/ipv6/lwip/ip6_frag.h
Normal file
102
src/include/ipv6/lwip/ip6_frag.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* IPv6 fragmentation and reassembly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_IP6_FRAG_H__
|
||||||
|
#define __LWIP_IP6_FRAG_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
/* The IPv6 reassembly timer interval in milliseconds. */
|
||||||
|
#define IP6_REASS_TMR_INTERVAL 1000
|
||||||
|
|
||||||
|
/* IPv6 reassembly helper struct.
|
||||||
|
* This is exported because memp needs to know the size.
|
||||||
|
*/
|
||||||
|
struct ip6_reassdata {
|
||||||
|
struct ip6_reassdata *next;
|
||||||
|
struct pbuf *p;
|
||||||
|
struct ip6_hdr * iphdr;
|
||||||
|
u32_t identification;
|
||||||
|
u16_t datagram_len;
|
||||||
|
u8_t nexth;
|
||||||
|
u8_t timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ip6_reass_init() /* Compatibility define */
|
||||||
|
void ip6_reass_tmr(void);
|
||||||
|
struct pbuf * ip6_reass(struct pbuf *p);
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
||||||
|
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
||||||
|
* that points into the original pbuf. */
|
||||||
|
#ifndef __LWIP_PBUF_CUSTOM_REF__
|
||||||
|
#define __LWIP_PBUF_CUSTOM_REF__
|
||||||
|
struct pbuf_custom_ref {
|
||||||
|
/** 'base class' */
|
||||||
|
struct pbuf_custom pc;
|
||||||
|
/** pointer to the original pbuf that is referenced */
|
||||||
|
struct pbuf *original;
|
||||||
|
};
|
||||||
|
#endif /* __LWIP_PBUF_CUSTOM_REF__ */
|
||||||
|
|
||||||
|
err_t ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest);
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP6_FRAG_H__ */
|
||||||
@@ -1,97 +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: Adam Dunkels <adam@sics.se>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef __LWIP_IP_ADDR_H__
|
|
||||||
#define __LWIP_IP_ADDR_H__
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP_ADDR_ANY 0
|
|
||||||
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip_addr {
|
|
||||||
PACK_STRUCT_FIELD(u32_t addr[4]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* struct ipaddr2 is used in the definition of the ARP packet format in
|
|
||||||
* order to support compilers that don't have structure packing.
|
|
||||||
*/
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip_addr2 {
|
|
||||||
PACK_STRUCT_FIELD(u16_t addrw[2]);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \
|
|
||||||
(ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \
|
|
||||||
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
|
||||||
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
|
||||||
|
|
||||||
u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
|
||||||
struct ip_addr *mask);
|
|
||||||
u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
|
||||||
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
|
||||||
u8_t ip_addr_isany(struct ip_addr *addr);
|
|
||||||
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) \
|
|
||||||
LWIP_DEBUGF(debug, ("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F"\n", \
|
|
||||||
(ntohl(ipaddr->addr[0]) >> 16) & 0xffff, \
|
|
||||||
ntohl(ipaddr->addr[0]) & 0xffff, \
|
|
||||||
(ntohl(ipaddr->addr[1]) >> 16) & 0xffff, \
|
|
||||||
ntohl(ipaddr->addr[1]) & 0xffff, \
|
|
||||||
(ntohl(ipaddr->addr[2]) >> 16) & 0xffff, \
|
|
||||||
ntohl(ipaddr->addr[2]) & 0xffff, \
|
|
||||||
(ntohl(ipaddr->addr[3]) >> 16) & 0xffff, \
|
|
||||||
ntohl(ipaddr->addr[3]) & 0xffff));
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __LWIP_IP_ADDR_H__ */
|
|
||||||
118
src/include/ipv6/lwip/mld6.h
Normal file
118
src/include/ipv6/lwip/mld6.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||||
|
* No support for MLDv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LWIP_MLD6_H__
|
||||||
|
#define __LWIP_MLD6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mld_group {
|
||||||
|
/** next link */
|
||||||
|
struct mld_group *next;
|
||||||
|
/** interface on which the group is active */
|
||||||
|
struct netif *netif;
|
||||||
|
/** multicast address */
|
||||||
|
ip6_addr_t group_address;
|
||||||
|
/** signifies we were the last person to report */
|
||||||
|
u8_t last_reporter_flag;
|
||||||
|
/** current state of the group */
|
||||||
|
u8_t group_state;
|
||||||
|
/** timer for reporting */
|
||||||
|
u16_t timer;
|
||||||
|
/** counter of simultaneous uses */
|
||||||
|
u8_t use;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Multicast listener report/query/done message header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct mld_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u16_t max_resp_delay);
|
||||||
|
PACK_STRUCT_FIELD(u16_t reserved);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t multicast_address);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MLD6_TMR_INTERVAL 100 /* Milliseconds */
|
||||||
|
|
||||||
|
/* MAC Filter Actions, these are passed to a netif's
|
||||||
|
* mld_mac_filter callback function. */
|
||||||
|
#define MLD6_DEL_MAC_FILTER 0
|
||||||
|
#define MLD6_ADD_MAC_FILTER 1
|
||||||
|
|
||||||
|
|
||||||
|
#define mld6_init() /* TODO should we init tables? */
|
||||||
|
err_t mld6_stop(struct netif *netif);
|
||||||
|
void mld6_report_groups(struct netif *netif);
|
||||||
|
void mld6_tmr(void);
|
||||||
|
struct mld_group *mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr);
|
||||||
|
void mld6_input(struct pbuf *p, struct netif *inp);
|
||||||
|
err_t mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr);
|
||||||
|
err_t mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_MLD6_H__ */
|
||||||
368
src/include/ipv6/lwip/nd6.h
Normal file
368
src/include/ipv6/lwip/nd6.h
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Neighbor discovery and stateless address autoconfiguration for IPv6.
|
||||||
|
* Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
||||||
|
* (Address autoconfiguration).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||||
|
* 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: Ivan Delamer <delamer@inicotech.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Please coordinate changes and requests with Ivan Delamer
|
||||||
|
* <delamer@inicotech.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LWIP_ND6_H__
|
||||||
|
#define __LWIP_ND6_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#if LWIP_IPV6 /* 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
|
||||||
|
|
||||||
|
/* Struct for tables. */
|
||||||
|
struct nd6_neighbor_cache_entry {
|
||||||
|
ip6_addr_t next_hop_address;
|
||||||
|
struct netif * netif;
|
||||||
|
u8_t lladdr[NETIF_MAX_HWADDR_LEN];
|
||||||
|
/*u32_t pmtu;*/
|
||||||
|
#if LWIP_ND6_QUEUEING
|
||||||
|
/** Pointer to queue of pending outgoing packets on this entry. */
|
||||||
|
struct nd6_q_entry *q;
|
||||||
|
#endif /* LWIP_ND6_QUEUEING */
|
||||||
|
u8_t state;
|
||||||
|
u8_t isrouter;
|
||||||
|
union {
|
||||||
|
u32_t reachable_time;
|
||||||
|
u32_t delay_time;
|
||||||
|
u32_t probes_sent;
|
||||||
|
u32_t stale_time;
|
||||||
|
} counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nd6_destination_cache_entry {
|
||||||
|
ip6_addr_t destination_addr;
|
||||||
|
ip6_addr_t next_hop_addr;
|
||||||
|
u32_t pmtu;
|
||||||
|
u32_t age;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nd6_prefix_list_entry {
|
||||||
|
ip6_addr_t prefix;
|
||||||
|
struct netif * netif;
|
||||||
|
u32_t invalidation_timer;
|
||||||
|
#if LWIP_IPV6_AUTOCONFIG
|
||||||
|
u8_t flags;
|
||||||
|
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
|
||||||
|
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
|
||||||
|
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
|
||||||
|
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nd6_router_list_entry {
|
||||||
|
struct nd6_neighbor_cache_entry * neighbor_entry;
|
||||||
|
u32_t invalidation_timer;
|
||||||
|
u8_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum nd6_neighbor_cache_entry_state {
|
||||||
|
ND6_NO_ENTRY = 0,
|
||||||
|
ND6_INCOMPLETE,
|
||||||
|
ND6_REACHABLE,
|
||||||
|
ND6_STALE,
|
||||||
|
ND6_DELAY,
|
||||||
|
ND6_PROBE
|
||||||
|
};
|
||||||
|
|
||||||
|
#if LWIP_ND6_QUEUEING
|
||||||
|
/** struct for queueing outgoing packets for unknown address
|
||||||
|
* defined here to be accessed by memp.h
|
||||||
|
*/
|
||||||
|
struct nd6_q_entry {
|
||||||
|
struct nd6_q_entry *next;
|
||||||
|
struct pbuf *p;
|
||||||
|
};
|
||||||
|
#endif /* LWIP_ND6_QUEUEING */
|
||||||
|
|
||||||
|
/** Neighbor solicitation message header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ns_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reserved);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Neighbor advertisement message header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct na_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u8_t flags);
|
||||||
|
PACK_STRUCT_FIELD(u8_t reserved[3]);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
#define ND6_FLAG_ROUTER (0x80)
|
||||||
|
#define ND6_FLAG_SOLICITED (0x40)
|
||||||
|
#define ND6_FLAG_OVERRIDE (0x20)
|
||||||
|
|
||||||
|
/** Router solicitation message header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct rs_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reserved);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Router advertisement message header. */
|
||||||
|
#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80)
|
||||||
|
#define ND6_RA_FLAG_OTHER_STATEFUL_CONFIG (0x40)
|
||||||
|
#define ND6_RA_FLAG_HOME_AGENT (0x20)
|
||||||
|
#define ND6_RA_PREFERENCE_MASK (0x18)
|
||||||
|
#define ND6_RA_PREFERENCE_HIGH (0x08)
|
||||||
|
#define ND6_RA_PREFERENCE_MEDIUM (0x00)
|
||||||
|
#define ND6_RA_PREFERENCE_LOW (0x18)
|
||||||
|
#define ND6_RA_PREFERENCE_DISABLED (0x10)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ra_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u8_t current_hop_limit);
|
||||||
|
PACK_STRUCT_FIELD(u8_t flags);
|
||||||
|
PACK_STRUCT_FIELD(u16_t router_lifetime);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reachable_time);
|
||||||
|
PACK_STRUCT_FIELD(u32_t retrans_timer);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Redirect message header. */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct redirect_header {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
|
PACK_STRUCT_FIELD(u32_t reserved);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t destination_address);
|
||||||
|
/* Options follow. */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Link-layer address option. */
|
||||||
|
#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01)
|
||||||
|
#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct lladdr_option {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t addr[NETIF_MAX_HWADDR_LEN]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Prefix information option. */
|
||||||
|
#define ND6_OPTION_TYPE_PREFIX_INFO (0x03)
|
||||||
|
#define ND6_PREFIX_FLAG_ON_LINK (0x80)
|
||||||
|
#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40)
|
||||||
|
#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20)
|
||||||
|
#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct prefix_option {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t prefix_length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t flags);
|
||||||
|
PACK_STRUCT_FIELD(u32_t valid_lifetime);
|
||||||
|
PACK_STRUCT_FIELD(u32_t preferred_lifetime);
|
||||||
|
PACK_STRUCT_FIELD(u8_t reserved2[3]);
|
||||||
|
PACK_STRUCT_FIELD(u8_t site_prefix_length);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t prefix);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Redirected header option. */
|
||||||
|
#define ND6_OPTION_TYPE_REDIR_HDR (0x04)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct redirected_header_option {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t reserved[6]);
|
||||||
|
/* Portion of redirected packet follows. */
|
||||||
|
/* PACK_STRUCT_FIELD(u8_t redirected[8]); */
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** MTU option. */
|
||||||
|
#define ND6_OPTION_TYPE_MTU (0x05)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct mtu_option {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u16_t reserved);
|
||||||
|
PACK_STRUCT_FIELD(u32_t mtu);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Route information option. */
|
||||||
|
#define ND6_OPTION_TYPE_ROUTE_INFO (24)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct route_option {
|
||||||
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t prefix_length);
|
||||||
|
PACK_STRUCT_FIELD(u8_t preference);
|
||||||
|
PACK_STRUCT_FIELD(u32_t route_lifetime);
|
||||||
|
PACK_STRUCT_FIELD(ip6_addr_p_t prefix);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the possible states of an IP address */
|
||||||
|
#define IP6_ADDRESS_STATE_INVALID (0)
|
||||||
|
#define IP6_ADDRESS_STATE_VALID (0x4)
|
||||||
|
#define IP6_ADDRESS_STATE_PREFERRED (0x5) /* includes valid */
|
||||||
|
#define IP6_ADDRESS_STATE_DEPRECATED (0x6) /* includes valid */
|
||||||
|
#define IP6_ADDRESS_STATE_TENTATIV (0x8)
|
||||||
|
|
||||||
|
/** 1 second period */
|
||||||
|
#define ND6_TMR_INTERVAL 1000
|
||||||
|
|
||||||
|
/* Router tables. */
|
||||||
|
/* TODO make these static? and entries accessible through API? */
|
||||||
|
extern struct nd6_neighbor_cache_entry neighbor_cache[];
|
||||||
|
extern struct nd6_destination_cache_entry destination_cache[];
|
||||||
|
extern struct nd6_prefix_list_entry prefix_list[];
|
||||||
|
extern struct nd6_router_list_entry default_router_list[];
|
||||||
|
|
||||||
|
/* Default values, can be updated by a RA message. */
|
||||||
|
extern u32_t reachable_time;
|
||||||
|
extern u32_t retrans_timer;
|
||||||
|
|
||||||
|
#define nd6_init() /* TODO should we init tables? */
|
||||||
|
void nd6_tmr(void);
|
||||||
|
void nd6_input(struct pbuf *p, struct netif *inp);
|
||||||
|
s8_t nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif);
|
||||||
|
s8_t nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif);
|
||||||
|
u16_t nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif);
|
||||||
|
#if LWIP_ND6_QUEUEING
|
||||||
|
err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p);
|
||||||
|
#endif /* LWIP_ND6_QUEUEING */
|
||||||
|
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
|
void nd6_reachability_hint(ip6_addr_t * ip6addr);
|
||||||
|
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* __LWIP_ND6_H__ */
|
||||||
@@ -76,20 +76,40 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
/* Helpers to process several netconn_types by the same code */
|
/* Helpers to process several netconn_types by the same code */
|
||||||
#define NETCONNTYPE_GROUP(t) (t&0xF0)
|
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
|
||||||
#define NETCONNTYPE_DATAGRAM(t) (t&0xE0)
|
#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0)
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define NETCONN_TYPE_IPV6 0x08
|
||||||
|
#define NETCONNTYPE_ISIPV6(t) ((t)&0x08)
|
||||||
|
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF7) == NETCONN_UDPLITE)
|
||||||
|
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF7) == NETCONN_UDPNOCHKSUM)
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
|
||||||
|
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/** Protocol family and type of the netconn */
|
/** Protocol family and type of the netconn */
|
||||||
enum netconn_type {
|
enum netconn_type {
|
||||||
NETCONN_INVALID = 0,
|
NETCONN_INVALID = 0,
|
||||||
/* NETCONN_TCP Group */
|
/* NETCONN_TCP Group */
|
||||||
NETCONN_TCP = 0x10,
|
NETCONN_TCP = 0x10,
|
||||||
|
#if LWIP_IPV6
|
||||||
|
NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */,
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
/* NETCONN_UDP Group */
|
/* NETCONN_UDP Group */
|
||||||
NETCONN_UDP = 0x20,
|
NETCONN_UDP = 0x20,
|
||||||
NETCONN_UDPLITE = 0x21,
|
NETCONN_UDPLITE = 0x21,
|
||||||
NETCONN_UDPNOCHKSUM= 0x22,
|
NETCONN_UDPNOCHKSUM = 0x22,
|
||||||
|
#if LWIP_IPV6
|
||||||
|
NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */,
|
||||||
|
NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */,
|
||||||
|
NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */,
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
/* NETCONN_RAW Group */
|
/* NETCONN_RAW Group */
|
||||||
NETCONN_RAW = 0x40
|
NETCONN_RAW = 0x40,
|
||||||
|
#if LWIP_IPV6
|
||||||
|
NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */,
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Current state of the netconn. Non-TCP netconns are always
|
/** Current state of the netconn. Non-TCP netconns are always
|
||||||
@@ -111,13 +131,13 @@ enum netconn_evt {
|
|||||||
NETCONN_EVT_ERROR
|
NETCONN_EVT_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
/** Used for netconn_join_leave_group() */
|
/** Used for netconn_join_leave_group() */
|
||||||
enum netconn_igmp {
|
enum netconn_igmp {
|
||||||
NETCONN_JOIN,
|
NETCONN_JOIN,
|
||||||
NETCONN_LEAVE
|
NETCONN_LEAVE
|
||||||
};
|
};
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
|
|
||||||
/* forward-declare some structs to avoid to include their headers */
|
/* forward-declare some structs to avoid to include their headers */
|
||||||
struct ip_pcb;
|
struct ip_pcb;
|
||||||
@@ -168,12 +188,11 @@ struct netconn {
|
|||||||
/** maximum amount of bytes queued in recvmbox
|
/** maximum amount of bytes queued in recvmbox
|
||||||
not used for TCP: adjust TCP_WND instead! */
|
not used for TCP: adjust TCP_WND instead! */
|
||||||
int recv_bufsize;
|
int recv_bufsize;
|
||||||
#endif /* LWIP_SO_RCVBUF */
|
|
||||||
/** number of bytes currently in recvmbox to be received,
|
/** number of bytes currently in recvmbox to be received,
|
||||||
tested against recv_bufsize to limit bytes on recvmbox
|
tested against recv_bufsize to limit bytes on recvmbox
|
||||||
for UDP and RAW
|
for UDP and RAW, used for FIONREAD */
|
||||||
@todo: should only be necessary with LWIP_SO_RCVBUF==1 */
|
|
||||||
s16_t recv_avail;
|
s16_t recv_avail;
|
||||||
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
||||||
u8_t flags;
|
u8_t flags;
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
@@ -236,13 +255,27 @@ err_t netconn_write(struct netconn *conn, const void *dataptr, size_t size,
|
|||||||
err_t netconn_close(struct netconn *conn);
|
err_t netconn_close(struct netconn *conn);
|
||||||
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
|
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
|
||||||
|
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
|
err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
|
||||||
ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
|
ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
|
||||||
|
#define netconn_bind_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \
|
||||||
|
netconn_bind(conn, ip6_2_ip(ip6addr), port) : ERR_VAL)
|
||||||
|
#define netconn_connect_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \
|
||||||
|
netconn_connect(conn, ip6_2_ip(ip6addr), port) : ERR_VAL)
|
||||||
|
#define netconn_sendto_ip6(conn, buf, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \
|
||||||
|
netconn_sendto(conn, buf, ip6_2_ip(ip6addr), port) : ERR_VAL)
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
#define netconn_join_leave_group_ip6(conn, multiaddr, srcaddr, join_or_leave) (NETCONNTYPE_ISIPV6((conn)->type) ? \
|
||||||
|
netconn_join_leave_group(conn, ip6_2_ip(multiaddr), ip6_2_ip(srcaddr), join_or_leave) :\
|
||||||
|
ERR_VAL)
|
||||||
|
#endif /* LWIP_IPV6_MLD*/
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#define netconn_err(conn) ((conn)->last_err)
|
#define netconn_err(conn) ((conn)->last_err)
|
||||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
||||||
|
|||||||
@@ -48,9 +48,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* For the netconn API, these values are use as a bitmask! */
|
||||||
#define NETCONN_SHUT_RD 1
|
#define NETCONN_SHUT_RD 1
|
||||||
#define NETCONN_SHUT_WR 2
|
#define NETCONN_SHUT_WR 2
|
||||||
#define NETCONN_SHUT_RDWR 3
|
#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
|
||||||
|
|
||||||
/* IP addresses and port numbers are expected to be in
|
/* IP addresses and port numbers are expected to be in
|
||||||
* the same byte order as in the corresponding pcb.
|
* the same byte order as in the corresponding pcb.
|
||||||
@@ -79,7 +80,7 @@ struct api_msg_msg {
|
|||||||
} bc;
|
} bc;
|
||||||
/** used for do_getaddr */
|
/** used for do_getaddr */
|
||||||
struct {
|
struct {
|
||||||
ip_addr_t *ipaddr;
|
ipX_addr_t *ipaddr;
|
||||||
u16_t *port;
|
u16_t *port;
|
||||||
u8_t local;
|
u8_t local;
|
||||||
} ad;
|
} ad;
|
||||||
@@ -97,14 +98,14 @@ struct api_msg_msg {
|
|||||||
struct {
|
struct {
|
||||||
u8_t shut;
|
u8_t shut;
|
||||||
} sd;
|
} sd;
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
/** used for do_join_leave_group */
|
/** used for do_join_leave_group */
|
||||||
struct {
|
struct {
|
||||||
ip_addr_t *multiaddr;
|
ipX_addr_t *multiaddr;
|
||||||
ip_addr_t *netif_addr;
|
ipX_addr_t *netif_addr;
|
||||||
enum netconn_igmp join_or_leave;
|
enum netconn_igmp join_or_leave;
|
||||||
} jl;
|
} jl;
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
struct {
|
struct {
|
||||||
u8_t backlog;
|
u8_t backlog;
|
||||||
@@ -153,9 +154,9 @@ void do_write ( struct api_msg_msg *msg);
|
|||||||
void do_getaddr ( struct api_msg_msg *msg);
|
void do_getaddr ( struct api_msg_msg *msg);
|
||||||
void do_close ( struct api_msg_msg *msg);
|
void do_close ( struct api_msg_msg *msg);
|
||||||
void do_shutdown ( struct api_msg_msg *msg);
|
void do_shutdown ( struct api_msg_msg *msg);
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
void do_join_leave_group( struct api_msg_msg *msg);
|
void do_join_leave_group( struct api_msg_msg *msg);
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||||
|
|
||||||
#if LWIP_DNS
|
#if LWIP_DNS
|
||||||
void do_gethostbyname(void *arg);
|
void do_gethostbyname(void *arg);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#define __LWIP_DEBUG_H__
|
#define __LWIP_DEBUG_H__
|
||||||
|
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
/** lower two bits indicate debug level
|
/** lower two bits indicate debug level
|
||||||
* - 0 all
|
* - 0 all
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ PACK_STRUCT_END
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||||
|
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
||||||
|
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
||||||
|
void dhcp_cleanup(struct netif *netif);
|
||||||
/** start DHCP configuration */
|
/** start DHCP configuration */
|
||||||
err_t dhcp_start(struct netif *netif);
|
err_t dhcp_start(struct netif *netif);
|
||||||
/** enforce early lease renewal (not needed normally)*/
|
/** enforce early lease renewal (not needed normally)*/
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
|
|
||||||
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/** DNS timer period */
|
/** DNS timer period */
|
||||||
#define DNS_TMR_INTERVAL 1000
|
#define DNS_TMR_INTERVAL 1000
|
||||||
|
|
||||||
@@ -111,6 +115,10 @@ int dns_local_removehost(const char *hostname, const ip_addr_t *addr)
|
|||||||
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
|
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
|
||||||
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
|
||||||
#endif /* __LWIP_DNS_H__ */
|
#endif /* __LWIP_DNS_H__ */
|
||||||
|
|||||||
@@ -57,20 +57,19 @@ typedef s8_t err_t;
|
|||||||
#define ERR_INPROGRESS -5 /* Operation in progress */
|
#define ERR_INPROGRESS -5 /* Operation in progress */
|
||||||
#define ERR_VAL -6 /* Illegal value. */
|
#define ERR_VAL -6 /* Illegal value. */
|
||||||
#define ERR_WOULDBLOCK -7 /* Operation would block. */
|
#define ERR_WOULDBLOCK -7 /* Operation would block. */
|
||||||
|
#define ERR_USE -8 /* Address in use. */
|
||||||
|
#define ERR_ISCONN -9 /* Already connected. */
|
||||||
|
|
||||||
#define ERR_IS_FATAL(e) ((e) < ERR_VAL)
|
#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN)
|
||||||
|
|
||||||
#define ERR_ABRT -8 /* Connection aborted. */
|
#define ERR_ABRT -10 /* Connection aborted. */
|
||||||
#define ERR_RST -9 /* Connection reset. */
|
#define ERR_RST -11 /* Connection reset. */
|
||||||
#define ERR_CLSD -10 /* Connection closed. */
|
#define ERR_CLSD -12 /* Connection closed. */
|
||||||
#define ERR_CONN -11 /* Not connected. */
|
#define ERR_CONN -13 /* Not connected. */
|
||||||
|
|
||||||
#define ERR_ARG -12 /* Illegal argument. */
|
#define ERR_ARG -14 /* Illegal argument. */
|
||||||
|
|
||||||
#define ERR_USE -13 /* Address in use. */
|
#define ERR_IF -15 /* Low-level netif error */
|
||||||
|
|
||||||
#define ERR_IF -14 /* Low-level netif error */
|
|
||||||
#define ERR_ISCONN -15 /* Already connected. */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
|
|||||||
@@ -72,16 +72,38 @@ extern "C" {
|
|||||||
|
|
||||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
ip_addr_t *src, ip_addr_t *dest,
|
ip_addr_t *src, ip_addr_t *dest);
|
||||||
u8_t proto, u16_t proto_len);
|
u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto,
|
||||||
u16_t inet_chksum_pseudo_partial(struct pbuf *p,
|
u16_t proto_len, u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest);
|
||||||
ip_addr_t *src, ip_addr_t *dest,
|
|
||||||
u8_t proto, u16_t proto_len, u16_t chksum_len);
|
|
||||||
#if LWIP_CHKSUM_COPY_ALGORITHM
|
#if LWIP_CHKSUM_COPY_ALGORITHM
|
||||||
u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len);
|
u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len);
|
||||||
#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
ip6_addr_t *src, ip6_addr_t *dest);
|
||||||
|
u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
|
||||||
|
u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest);
|
||||||
|
|
||||||
|
#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_chksum_pseudo(p, proto, proto_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\
|
||||||
|
inet_chksum_pseudo(p, proto, proto_len, ipX_2_ip(src), ipX_2_ip(dest)))
|
||||||
|
#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\
|
||||||
|
inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip(src), ipX_2_ip(dest)))
|
||||||
|
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \
|
||||||
|
inet_chksum_pseudo(p, proto, proto_len, src, dest)
|
||||||
|
#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \
|
||||||
|
inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, src, dest)
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -43,11 +43,11 @@ extern "C" {
|
|||||||
/** x.X.x: Minor version of the stack */
|
/** x.X.x: Minor version of the stack */
|
||||||
#define LWIP_VERSION_MINOR 4U
|
#define LWIP_VERSION_MINOR 4U
|
||||||
/** x.x.X: Revision of the stack */
|
/** x.x.X: Revision of the stack */
|
||||||
#define LWIP_VERSION_REVISION 0U
|
#define LWIP_VERSION_REVISION 1U
|
||||||
/** For release candidates, this is set to 1..254
|
/** For release candidates, this is set to 1..254
|
||||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||||
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||||
#define LWIP_VERSION_RC 1U
|
#define LWIP_VERSION_RC 0U
|
||||||
|
|
||||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||||
#define LWIP_RC_RELEASE 255U
|
#define LWIP_RC_RELEASE 255U
|
||||||
|
|||||||
247
src/include/lwip/ip.h
Normal file
247
src/include/lwip/ip.h
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_IP_H__
|
||||||
|
#define __LWIP_IP_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/ip4.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This is passed as the destination address to ip_output_if (not
|
||||||
|
to ip_output), meaning that an IP header already is constructed
|
||||||
|
in the pbuf. This is used when TCP retransmits. */
|
||||||
|
#ifdef IP_HDRINCL
|
||||||
|
#undef IP_HDRINCL
|
||||||
|
#endif /* IP_HDRINCL */
|
||||||
|
#define IP_HDRINCL NULL
|
||||||
|
|
||||||
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
|
#define IP_PCB_ADDRHINT ;u8_t addr_hint
|
||||||
|
#else
|
||||||
|
#define IP_PCB_ADDRHINT
|
||||||
|
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define IP_PCB_ISIPV6_MEMBER u8_t isipv6;
|
||||||
|
#define IP_PCB_IPVER_EQ(pcb1, pcb2) ((pcb1)->isipv6 == (pcb2)->isipv6)
|
||||||
|
#define IP_PCB_IPVER_INPUT_MATCH(pcb) (ip_current_is_v6() ? \
|
||||||
|
((pcb)->isipv6 != 0) : \
|
||||||
|
((pcb)->isipv6 == 0))
|
||||||
|
#define PCB_ISIPV6(pcb) ((pcb)->isipv6)
|
||||||
|
#else
|
||||||
|
#define IP_PCB_ISIPV6_MEMBER
|
||||||
|
#define IP_PCB_IPVER_EQ(pcb1, pcb2) 1
|
||||||
|
#define IP_PCB_IPVER_INPUT_MATCH(pcb) 1
|
||||||
|
#define PCB_ISIPV6(pcb) 0
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
/* This is the common part of all PCB types. It needs to be at the
|
||||||
|
beginning of a PCB type definition. It is located here so that
|
||||||
|
changes to this common part are made in one location instead of
|
||||||
|
having to change all PCB structs. */
|
||||||
|
#define IP_PCB \
|
||||||
|
IP_PCB_ISIPV6_MEMBER \
|
||||||
|
/* ip addresses in network byte order */ \
|
||||||
|
ipX_addr_t local_ip; \
|
||||||
|
ipX_addr_t remote_ip; \
|
||||||
|
/* Socket options */ \
|
||||||
|
u8_t so_options; \
|
||||||
|
/* Type Of Service */ \
|
||||||
|
u8_t tos; \
|
||||||
|
/* Time To Live */ \
|
||||||
|
u8_t ttl \
|
||||||
|
/* link layer address resolution hint */ \
|
||||||
|
IP_PCB_ADDRHINT
|
||||||
|
|
||||||
|
struct ip_pcb {
|
||||||
|
/* Common members of all PCB types */
|
||||||
|
IP_PCB;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Option flags per-socket. These are the same like SO_XXX.
|
||||||
|
*/
|
||||||
|
/*#define SOF_DEBUG (u8_t)0x01U Unimplemented: turn on debugging info recording */
|
||||||
|
#define SOF_ACCEPTCONN (u8_t)0x02U /* socket has had listen() */
|
||||||
|
#define SOF_REUSEADDR (u8_t)0x04U /* allow local address reuse */
|
||||||
|
#define SOF_KEEPALIVE (u8_t)0x08U /* keep connections alive */
|
||||||
|
/*#define SOF_DONTROUTE (u8_t)0x10U Unimplemented: just use interface addresses */
|
||||||
|
#define SOF_BROADCAST (u8_t)0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||||
|
/*#define SOF_USELOOPBACK (u8_t)0x40U Unimplemented: bypass hardware when possible */
|
||||||
|
#define SOF_LINGER (u8_t)0x80U /* linger on close if data present */
|
||||||
|
/*#define SOF_OOBINLINE (u16_t)0x0100U Unimplemented: leave received OOB data in line */
|
||||||
|
/*#define SOF_REUSEPORT (u16_t)0x0200U Unimplemented: allow local address & port reuse */
|
||||||
|
|
||||||
|
/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
|
||||||
|
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
|
||||||
|
|
||||||
|
/* Global variables of this module, kept in a struct for efficient access using base+index. */
|
||||||
|
struct ip_globals
|
||||||
|
{
|
||||||
|
/** The interface that provided the packet for the current callback invocation. */
|
||||||
|
struct netif *current_netif;
|
||||||
|
/** Header of the input packet currently being processed. */
|
||||||
|
const struct ip_hdr *current_ip4_header;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Header of the input IPv6 packet currently being processed. */
|
||||||
|
const struct ip6_hdr *current_ip6_header;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
/** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */
|
||||||
|
u16_t current_ip_header_tot_len;
|
||||||
|
/** Source IP address of current_header */
|
||||||
|
ipX_addr_t current_iphdr_src;
|
||||||
|
/** Destination IP address of current_header */
|
||||||
|
ipX_addr_t current_iphdr_dest;
|
||||||
|
};
|
||||||
|
extern struct ip_globals ip_data;
|
||||||
|
|
||||||
|
|
||||||
|
/** Get the interface that received the current packet.
|
||||||
|
* This function must only be called from a receive callback (udp_recv,
|
||||||
|
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||||
|
#define ip_current_netif() (ip_data.current_netif)
|
||||||
|
/** Get the IP header of the current packet.
|
||||||
|
* This function must only be called from a receive callback (udp_recv,
|
||||||
|
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||||
|
#define ip_current_header() (ip_data.current_ip4_header)
|
||||||
|
/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */
|
||||||
|
#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len)
|
||||||
|
/** Source IP address of current_header */
|
||||||
|
#define ipX_current_src_addr() (&ip_data.current_iphdr_src)
|
||||||
|
/** Destination IP address of current_header */
|
||||||
|
#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest)
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Get the IPv6 header of the current packet.
|
||||||
|
* This function must only be called from a receive callback (udp_recv,
|
||||||
|
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||||
|
#define ip6_current_header() (ip_data.current_ip6_header)
|
||||||
|
/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */
|
||||||
|
#define ip_current_is_v6() (ip6_current_header() != NULL)
|
||||||
|
/** Source IPv6 address of current_header */
|
||||||
|
#define ip6_current_src_addr() (ipX_2_ip6(&ip_data.current_iphdr_src))
|
||||||
|
/** Destination IPv6 address of current_header */
|
||||||
|
#define ip6_current_dest_addr() (ipX_2_ip6(&ip_data.current_iphdr_dest))
|
||||||
|
/** Get the transport layer protocol */
|
||||||
|
#define ip_current_header_proto() (ip_current_is_v6() ? \
|
||||||
|
IP6H_NEXTH(ip6_current_header()) :\
|
||||||
|
IPH_PROTO(ip_current_header()))
|
||||||
|
/** Get the transport layer header */
|
||||||
|
#define ipX_next_header_ptr() ((void*)((ip_current_is_v6() ? \
|
||||||
|
(u8_t*)ip6_current_header() : (u8_t*)ip_current_header()) + ip_current_header_tot_len()))
|
||||||
|
|
||||||
|
/** Set an IP_PCB to IPv6 (IPv4 is the default) */
|
||||||
|
#define ip_set_v6(pcb, val) do{if(pcb != NULL) { pcb->isipv6 = val; }}while(0)
|
||||||
|
|
||||||
|
/** Source IP4 address of current_header */
|
||||||
|
#define ip_current_src_addr() (ipX_2_ip(&ip_data.current_iphdr_src))
|
||||||
|
/** Destination IP4 address of current_header */
|
||||||
|
#define ip_current_dest_addr() (ipX_2_ip(&ip_data.current_iphdr_dest))
|
||||||
|
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
/** Always returns FALSE when only supporting IPv4 */
|
||||||
|
#define ip_current_is_v6() 0
|
||||||
|
/** Get the transport layer protocol */
|
||||||
|
#define ip_current_header_proto() IPH_PROTO(ip_current_header())
|
||||||
|
/** Get the transport layer header */
|
||||||
|
#define ipX_next_header_ptr() ((void*)((u8_t*)ip_current_header() + ip_current_header_tot_len()))
|
||||||
|
/** Source IP4 address of current_header */
|
||||||
|
#define ip_current_src_addr() (&ip_data.current_iphdr_src)
|
||||||
|
/** Destination IP4 address of current_header */
|
||||||
|
#define ip_current_dest_addr() (&ip_data.current_iphdr_dest)
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
/** Union source address of current_header */
|
||||||
|
#define ipX_current_src_addr() (&ip_data.current_iphdr_src)
|
||||||
|
/** Union destination address of current_header */
|
||||||
|
#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest)
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_output(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto) : \
|
||||||
|
ip_output(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto))
|
||||||
|
#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \
|
||||||
|
ip_output_if(p, (src), (dest), ttl, tos, proto, netif))
|
||||||
|
#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_output_hinted(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto, addr_hint) : \
|
||||||
|
ip_output_hinted(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto, addr_hint))
|
||||||
|
#define ipX_route(isipv6, src, dest) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_route(ipX_2_ip6(src), ipX_2_ip6(dest)) : \
|
||||||
|
ip_route(ipX_2_ip(dest)))
|
||||||
|
#define ipX_netif_get_local_ipX(isipv6, netif, dest) \
|
||||||
|
((isipv6) ? \
|
||||||
|
ip6_netif_get_local_ipX(netif, ipX_2_ip6(dest)) : \
|
||||||
|
ip_netif_get_local_ipX(netif))
|
||||||
|
#define ipX_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip_debug_print(p))
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \
|
||||||
|
ip_output(p, src, dest, ttl, tos, proto)
|
||||||
|
#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \
|
||||||
|
ip_output_if(p, src, dest, ttl, tos, proto, netif)
|
||||||
|
#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \
|
||||||
|
ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint)
|
||||||
|
#define ipX_route(isipv6, src, dest) \
|
||||||
|
ip_route(ipX_2_ip(dest))
|
||||||
|
#define ipX_netif_get_local_ipX(isipv6, netif, dest) \
|
||||||
|
ip_netif_get_local_ipX(netif)
|
||||||
|
#define ipX_debug_print(is_ipv6, p) ip_debug_print(p)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#define ipX_route_get_local_ipX(isipv6, src, dest, netif, ipXaddr) do { \
|
||||||
|
(netif) = ipX_route(isipv6, src, dest); \
|
||||||
|
(ipXaddr) = ipX_netif_get_local_ipX(isipv6, netif, dest); \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP_H__ */
|
||||||
|
|
||||||
|
|
||||||
130
src/include/lwip/ip_addr.h
Normal file
130
src/include/lwip/ip_addr.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __LWIP_IP_ADDR_H__
|
||||||
|
#define __LWIP_IP_ADDR_H__
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
#include "lwip/ip4_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/* A union struct for both IP version's addresses. */
|
||||||
|
typedef union {
|
||||||
|
ip_addr_t ip4;
|
||||||
|
ip6_addr_t ip6;
|
||||||
|
} ipX_addr_t;
|
||||||
|
|
||||||
|
/** These functions only exist for type-safe conversion from ip_addr_t to
|
||||||
|
ip6_addr_t and back */
|
||||||
|
#if LWIP_ALLOW_STATIC_FN_IN_HEADER
|
||||||
|
static ip6_addr_t* ip_2_ip6(ip_addr_t *ipaddr)
|
||||||
|
{ return (ip6_addr_t*)ipaddr;}
|
||||||
|
static ip_addr_t* ip6_2_ip(ip6_addr_t *ip6addr)
|
||||||
|
{ return (ip_addr_t*)ip6addr; }
|
||||||
|
static ipX_addr_t* ip_2_ipX(ip_addr_t *ipaddr)
|
||||||
|
{ return (ipX_addr_t*)ipaddr; }
|
||||||
|
static ipX_addr_t* ip6_2_ipX(ip6_addr_t *ip6addr)
|
||||||
|
{ return (ipX_addr_t*)ip6addr; }
|
||||||
|
#else /* LWIP_ALLOW_STATIC_FN_IN_HEADER */
|
||||||
|
#define ip_2_ip6(ipaddr) ((ip6_addr_t*)(ipaddr))
|
||||||
|
#define ip6_2_ip(ip6addr) ((ip_addr_t*)(ip6addr))
|
||||||
|
#define ip_2_ipX(ipaddr) ((ipX_addr_t*)ipaddr)
|
||||||
|
#define ip6_2_ipX(ip6addr) ((ipX_addr_t*)ip6addr)
|
||||||
|
#endif /* LWIP_ALLOW_STATIC_FN_IN_HEADER*/
|
||||||
|
#define ipX_2_ip6(ip6addr) (&((ip6addr)->ip6))
|
||||||
|
#define ipX_2_ip(ipaddr) (&((ipaddr)->ip4))
|
||||||
|
|
||||||
|
#define ipX_addr_copy(is_ipv6, dest, src) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_copy((dest).ip6, (src).ip6); }else{ \
|
||||||
|
ip_addr_copy((dest).ip4, (src).ip4); }}while(0)
|
||||||
|
#define ipX_addr_set(is_ipv6, dest, src) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set(ipX_2_ip6(dest), ipX_2_ip6(src)); }else{ \
|
||||||
|
ip_addr_set(ipX_2_ip(dest), ipX_2_ip(src)); }}while(0)
|
||||||
|
#define ipX_addr_set_ipaddr(is_ipv6, dest, src) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set(ipX_2_ip6(dest), ip_2_ip6(src)); }else{ \
|
||||||
|
ip_addr_set(ipX_2_ip(dest), src); }}while(0)
|
||||||
|
#define ipX_addr_set_zero(is_ipv6, ipaddr) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set_zero(ipX_2_ip6(ipaddr)); }else{ \
|
||||||
|
ip_addr_set_zero(ipX_2_ip(ipaddr)); }}while(0)
|
||||||
|
#define ipX_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set_any(ipX_2_ip6(ipaddr)); }else{ \
|
||||||
|
ip_addr_set_any(ipX_2_ip(ipaddr)); }}while(0)
|
||||||
|
#define ipX_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set_loopback(ipX_2_ip6(ipaddr)); }else{ \
|
||||||
|
ip_addr_set_loopback(ipX_2_ip(ipaddr)); }}while(0)
|
||||||
|
#define ipX_addr_set_hton(is_ipv6, dest, src) do{if(is_ipv6){ \
|
||||||
|
ip6_addr_set_hton(ipX_2_ip6(ipaddr), (src)) ;}else{ \
|
||||||
|
ip_addr_set_hton(ipX_2_ip(ipaddr), (src));}}while(0)
|
||||||
|
#define ipX_addr_cmp(is_ipv6, addr1, addr2) ((is_ipv6) ? \
|
||||||
|
ip6_addr_cmp(ipX_2_ip6(addr1), ipX_2_ip6(addr2)) : \
|
||||||
|
ip_addr_cmp(ipX_2_ip(addr1), ipX_2_ip(addr2)))
|
||||||
|
#define ipX_addr_isany(is_ipv6, ipaddr) ((is_ipv6) ? \
|
||||||
|
ip6_addr_isany(ipX_2_ip6(ipaddr)) : \
|
||||||
|
ip_addr_isany(ipX_2_ip(ipaddr)))
|
||||||
|
#define ipX_addr_ismulticast(is_ipv6, ipaddr) ((is_ipv6) ? \
|
||||||
|
ip6_addr_ismulticast(ipX_2_ip6(ipaddr)) : \
|
||||||
|
ip_addr_ismulticast(ipX_2_ip(ipaddr)))
|
||||||
|
#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) do { if(is_ipv6) { \
|
||||||
|
ip6_addr_debug_print(debug, ipX_2_ip6(ipaddr)); } else { \
|
||||||
|
ip_addr_debug_print(debug, ipX_2_ip(ipaddr)); }}while(0)
|
||||||
|
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
typedef ip_addr_t ipX_addr_t;
|
||||||
|
#define ipX_2_ip(ipaddr) (ipaddr)
|
||||||
|
#define ip_2_ipX(ipaddr) (ipaddr)
|
||||||
|
|
||||||
|
#define ipX_addr_copy(is_ipv6, dest, src) ip_addr_copy(dest, src)
|
||||||
|
#define ipX_addr_set(is_ipv6, dest, src) ip_addr_set(dest, src)
|
||||||
|
#define ipX_addr_set_ipaddr(is_ipv6, dest, src) ip_addr_set(dest, src)
|
||||||
|
#define ipX_addr_set_zero(is_ipv6, ipaddr) ip_addr_set_zero(ipaddr)
|
||||||
|
#define ipX_addr_set_any(is_ipv6, ipaddr) ip_addr_set_any(ipaddr)
|
||||||
|
#define ipX_addr_set_loopback(is_ipv6, ipaddr) ip_addr_set_loopback(ipaddr)
|
||||||
|
#define ipX_addr_set_hton(is_ipv6, dest, src) ip_addr_set_hton(dest, src)
|
||||||
|
#define ipX_addr_cmp(is_ipv6, addr1, addr2) ip_addr_cmp(addr1, addr2)
|
||||||
|
#define ipX_addr_isany(is_ipv6, ipaddr) ip_addr_isany(ipaddr)
|
||||||
|
#define ipX_addr_ismulticast(is_ipv6, ipaddr) ip_addr_ismulticast(ipaddr)
|
||||||
|
#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) ip_addr_debug_print(debug, ipaddr)
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LWIP_IP_ADDR_H__ */
|
||||||
@@ -68,7 +68,7 @@ typedef size_t mem_size_t;
|
|||||||
/* MEM_SIZE would have to be aligned, but using 64000 here instead of
|
/* MEM_SIZE would have to be aligned, but using 64000 here instead of
|
||||||
* 65535 leaves some room for alignment...
|
* 65535 leaves some room for alignment...
|
||||||
*/
|
*/
|
||||||
#if MEM_SIZE > 64000l
|
#if MEM_SIZE > 64000L
|
||||||
typedef u32_t mem_size_t;
|
typedef u32_t mem_size_t;
|
||||||
#define MEM_SIZE_F U32_F
|
#define MEM_SIZE_F U32_F
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg),
|
|||||||
#if IP_REASSEMBLY
|
#if IP_REASSEMBLY
|
||||||
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
|
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
|
||||||
#endif /* IP_REASSEMBLY */
|
#endif /* IP_REASSEMBLY */
|
||||||
#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || LWIP_IPv6_FRAG
|
||||||
LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
|
LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
|
||||||
#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
@@ -91,6 +91,19 @@ LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE,
|
|||||||
LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
|
LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
|
||||||
#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
|
#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_ND6_QUEUEING
|
||||||
|
LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE")
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_REASS
|
||||||
|
LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA")
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP")
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A list of pools of pbuf's used by LWIP.
|
* A list of pools of pbuf's used by LWIP.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -47,7 +48,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct netbuf {
|
struct netbuf {
|
||||||
struct pbuf *p, *ptr;
|
struct pbuf *p, *ptr;
|
||||||
ip_addr_t addr;
|
ipX_addr_t addr;
|
||||||
u16_t port;
|
u16_t port;
|
||||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
@@ -55,7 +56,7 @@ struct netbuf {
|
|||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
u16_t toport_chksum;
|
u16_t toport_chksum;
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
ip_addr_t toaddr;
|
ipX_addr_t toaddr;
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||||
};
|
};
|
||||||
@@ -81,12 +82,12 @@ void netbuf_first (struct netbuf *buf);
|
|||||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||||
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
||||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||||
#define netbuf_fromaddr(buf) (&((buf)->addr))
|
#define netbuf_fromaddr(buf) (ipX_2_ip(&((buf)->addr)))
|
||||||
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr)
|
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(ipX_2_ip(&((buf)->addr)), fromaddr)
|
||||||
#define netbuf_fromport(buf) ((buf)->port)
|
#define netbuf_fromport(buf) ((buf)->port)
|
||||||
#if LWIP_NETBUF_RECVINFO
|
#if LWIP_NETBUF_RECVINFO
|
||||||
#define netbuf_destaddr(buf) (&((buf)->toaddr))
|
#define netbuf_destaddr(buf) (ipX_2_ip(&((buf)->toaddr)))
|
||||||
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr)
|
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(ipX_2_ip(&((buf)->toaddr)), destaddr)
|
||||||
#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
|
#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
|
||||||
#endif /* LWIP_NETBUF_RECVINFO */
|
#endif /* LWIP_NETBUF_RECVINFO */
|
||||||
#if LWIP_CHECKSUM_ON_COPY
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
@@ -94,6 +95,16 @@ void netbuf_first (struct netbuf *buf);
|
|||||||
(buf)->toport_chksum = chksum; } while(0)
|
(buf)->toport_chksum = chksum; } while(0)
|
||||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define netbuf_fromaddr_ip6(buf) (ipX_2_ip6(&((buf)->addr)))
|
||||||
|
#define netbuf_set_fromaddr_ip6(buf, fromaddr) ip6_addr_set(ipX_2_ip6(&((buf)->addr)), fromaddr)
|
||||||
|
#define netbuf_destaddr_ip6(buf) (ipX_2_ip6(&((buf)->toaddr)))
|
||||||
|
#define netbuf_set_destaddr_ip6(buf, destaddr) ip6_addr_set(ipX_2_ip6(&((buf)->toaddr)), destaddr)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#define netbuf_fromaddr_ipX(buf) (&((buf)->addr))
|
||||||
|
#define netbuf_destaddr_ipX(buf) (&((buf)->toaddr))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* some rarely used options */
|
/* some rarely used options */
|
||||||
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
|
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
|
||||||
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
|
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
|
||||||
@@ -111,6 +115,10 @@ int lwip_getaddrinfo(const char *nodename,
|
|||||||
lwip_getaddrinfo(nodname, servname, hints, res)
|
lwip_getaddrinfo(nodname, servname, hints, res)
|
||||||
#endif /* LWIP_COMPAT_SOCKETS */
|
#endif /* LWIP_COMPAT_SOCKETS */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||||
|
|
||||||
#endif /* __LWIP_NETDB_H__ */
|
#endif /* __LWIP_NETDB_H__ */
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
@@ -48,6 +49,9 @@ struct dhcp;
|
|||||||
#if LWIP_AUTOIP
|
#if LWIP_AUTOIP
|
||||||
struct autoip;
|
struct autoip;
|
||||||
#endif
|
#endif
|
||||||
|
#if LWIP_IPV6_DHCP6
|
||||||
|
#include "lwip/dhcp6.h"
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -117,6 +121,18 @@ typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
|
|||||||
*/
|
*/
|
||||||
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
|
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
|
||||||
ip_addr_t *ipaddr);
|
ip_addr_t *ipaddr);
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet
|
||||||
|
* shall be sent. For ethernet netif, set this to 'nd_output' and set
|
||||||
|
* 'linkoutput'.
|
||||||
|
*
|
||||||
|
* @param netif The netif which shall send a packet
|
||||||
|
* @param p The packet to send (p->payload points to IP header)
|
||||||
|
* @param ipaddr The IPv6 address to which the packet shall be sent
|
||||||
|
*/
|
||||||
|
typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p,
|
||||||
|
ip6_addr_t *ipaddr);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
/** Function prototype for netif->linkoutput functions. Only used for ethernet
|
/** Function prototype for netif->linkoutput functions. Only used for ethernet
|
||||||
* netifs. This function is called by ARP when a packet shall be sent.
|
* netifs. This function is called by ARP when a packet shall be sent.
|
||||||
*
|
*
|
||||||
@@ -129,6 +145,11 @@ typedef void (*netif_status_callback_fn)(struct netif *netif);
|
|||||||
/** Function prototype for netif igmp_mac_filter functions */
|
/** Function prototype for netif igmp_mac_filter functions */
|
||||||
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
|
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
|
||||||
ip_addr_t *group, u8_t action);
|
ip_addr_t *group, u8_t action);
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
/** Function prototype for netif mld_mac_filter functions */
|
||||||
|
typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif,
|
||||||
|
ip6_addr_t *group, u8_t action);
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
|
|
||||||
/** Generic data structure used for all lwIP network interfaces.
|
/** Generic data structure used for all lwIP network interfaces.
|
||||||
* The following fields should be filled in by the initialization
|
* The following fields should be filled in by the initialization
|
||||||
@@ -142,6 +163,13 @@ struct netif {
|
|||||||
ip_addr_t netmask;
|
ip_addr_t netmask;
|
||||||
ip_addr_t gw;
|
ip_addr_t gw;
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Array of IPv6 addresses for this netif. */
|
||||||
|
ip6_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
|
||||||
|
/** The state of each IPv6 address (Tentative, Preferred, etc).
|
||||||
|
* @see ip6_addr.h */
|
||||||
|
u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
/** This function is called by the network device driver
|
/** This function is called by the network device driver
|
||||||
* to pass a packet up the TCP/IP stack. */
|
* to pass a packet up the TCP/IP stack. */
|
||||||
netif_input_fn input;
|
netif_input_fn input;
|
||||||
@@ -153,6 +181,12 @@ struct netif {
|
|||||||
* to send a packet on the interface. This function outputs
|
* to send a packet on the interface. This function outputs
|
||||||
* the pbuf as-is on the link medium. */
|
* the pbuf as-is on the link medium. */
|
||||||
netif_linkoutput_fn linkoutput;
|
netif_linkoutput_fn linkoutput;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** This function is called by the IPv6 module when it wants
|
||||||
|
* to send a packet on the interface. This function typically
|
||||||
|
* first resolves the hardware address, then sends the packet. */
|
||||||
|
netif_output_ip6_fn output_ip6;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
#if LWIP_NETIF_STATUS_CALLBACK
|
||||||
/** This function is called when the netif state is set to up or down
|
/** This function is called when the netif state is set to up or down
|
||||||
*/
|
*/
|
||||||
@@ -174,6 +208,18 @@ struct netif {
|
|||||||
/** the AutoIP client state information for this netif */
|
/** the AutoIP client state information for this netif */
|
||||||
struct autoip *autoip;
|
struct autoip *autoip;
|
||||||
#endif
|
#endif
|
||||||
|
#if LWIP_IPV6_AUTOCONFIG
|
||||||
|
/** is this netif enabled for IPv6 autoconfiguration */
|
||||||
|
u8_t ip6_autoconfig_enabled;
|
||||||
|
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||||
|
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||||
|
/** Number of Router Solicitation messages that remain to be sent. */
|
||||||
|
u8_t rs_count;
|
||||||
|
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||||
|
#if LWIP_IPV6_DHCP6
|
||||||
|
/** the DHCPv6 client state information for this netif */
|
||||||
|
struct dhcp6 *dhcp6;
|
||||||
|
#endif /* LWIP_IPV6_DHCP6 */
|
||||||
#if LWIP_NETIF_HOSTNAME
|
#if LWIP_NETIF_HOSTNAME
|
||||||
/* the hostname for this netif, NULL is a valid value */
|
/* the hostname for this netif, NULL is a valid value */
|
||||||
char* hostname;
|
char* hostname;
|
||||||
@@ -208,10 +254,15 @@ struct netif {
|
|||||||
u32_t ifoutdiscards;
|
u32_t ifoutdiscards;
|
||||||
#endif /* LWIP_SNMP */
|
#endif /* LWIP_SNMP */
|
||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
/** This function could be called to add or delete a entry in the multicast
|
/** This function could be called to add or delete an entry in the multicast
|
||||||
filter table of the ethernet MAC.*/
|
filter table of the ethernet MAC.*/
|
||||||
netif_igmp_mac_filter_fn igmp_mac_filter;
|
netif_igmp_mac_filter_fn igmp_mac_filter;
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||||
|
/** This function could be called to add or delete an entry in the IPv6 multicast
|
||||||
|
filter table of the ethernet MAC. */
|
||||||
|
netif_mld_mac_filter_fn mld_mac_filter;
|
||||||
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
u8_t *addr_hint;
|
u8_t *addr_hint;
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||||
@@ -308,6 +359,20 @@ void netif_poll_all(void);
|
|||||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
#endif /* ENABLE_LOOPBACK */
|
#endif /* ENABLE_LOOPBACK */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define netif_ip6_addr(netif, i) (&(netif->ip6_addr[(i)]))
|
||||||
|
#define netif_ip6_addr_state(netif, i) (netif->ip6_addr_state[(i)])
|
||||||
|
#define netif_ip6_addr_set_state(netif, i, state) (netif->ip6_addr_state[(i)] = (state))
|
||||||
|
s8_t netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr);
|
||||||
|
void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
|
#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint))
|
||||||
|
#else /* LWIP_NETIF_HWADDRHINT */
|
||||||
|
#define NETIF_SET_HWADDRHINT(netif, hint)
|
||||||
|
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -432,11 +432,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ARP_QUEUEING==1: Outgoing packets are queued during hardware address
|
* ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
|
||||||
* resolution.
|
* resolution. By default, only the most recent packet is queued per IP address.
|
||||||
|
* This is sufficient for most protocols and mainly reduces TCP connection
|
||||||
|
* startup time. Set this to 1 if you know your application sends more than one
|
||||||
|
* packet in a row to an IP address that is not in the ARP cache.
|
||||||
*/
|
*/
|
||||||
#ifndef ARP_QUEUEING
|
#ifndef ARP_QUEUEING
|
||||||
#define ARP_QUEUEING 1
|
#define ARP_QUEUEING 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -954,7 +957,7 @@
|
|||||||
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
|
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
|
||||||
*/
|
*/
|
||||||
#ifndef TCP_SND_QUEUELEN
|
#ifndef TCP_SND_QUEUELEN
|
||||||
#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
|
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1541,6 +1544,41 @@
|
|||||||
#define SYS_STATS (NO_SYS == 0)
|
#define SYS_STATS (NO_SYS == 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP6_STATS==1: Enable IPv6 stats.
|
||||||
|
*/
|
||||||
|
#ifndef IP6_STATS
|
||||||
|
#define IP6_STATS (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ICMP6_STATS==1: Enable ICMP for IPv6 stats.
|
||||||
|
*/
|
||||||
|
#ifndef ICMP6_STATS
|
||||||
|
#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats.
|
||||||
|
*/
|
||||||
|
#ifndef IP6_FRAG_STATS
|
||||||
|
#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MLD6_STATS==1: Enable MLD for IPv6 stats.
|
||||||
|
*/
|
||||||
|
#ifndef MLD6_STATS
|
||||||
|
#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ND6_STATS==1: Enable Neighbor discovery for IPv6 stats.
|
||||||
|
*/
|
||||||
|
#ifndef ND6_STATS
|
||||||
|
#define ND6_STATS (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define LINK_STATS 0
|
#define LINK_STATS 0
|
||||||
@@ -1554,6 +1592,11 @@
|
|||||||
#define MEMP_STATS 0
|
#define MEMP_STATS 0
|
||||||
#define SYS_STATS 0
|
#define SYS_STATS 0
|
||||||
#define LWIP_STATS_DISPLAY 0
|
#define LWIP_STATS_DISPLAY 0
|
||||||
|
#define IP6_STATS 0
|
||||||
|
#define ICMP6_STATS 0
|
||||||
|
#define IP6_FRAG_STATS 0
|
||||||
|
#define MLD6_STATS 0
|
||||||
|
#define ND6_STATS 0
|
||||||
|
|
||||||
#endif /* LWIP_STATS */
|
#endif /* LWIP_STATS */
|
||||||
|
|
||||||
@@ -1776,6 +1819,231 @@
|
|||||||
#define LWIP_CHECKSUM_ON_COPY 0
|
#define LWIP_CHECKSUM_ON_COPY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
---------------------------------------
|
||||||
|
---------- IPv6 options ---------------
|
||||||
|
---------------------------------------
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6==1: Enable IPv6
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6
|
||||||
|
#define LWIP_IPV6 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_NUM_ADDRESSES
|
||||||
|
#define LWIP_IPV6_NUM_ADDRESSES 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_FORWARD
|
||||||
|
#define LWIP_IPV6_FORWARD 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC)
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ICMP6
|
||||||
|
#define LWIP_ICMP6 (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
|
||||||
|
* ICMPv6 error messages.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ICMP6_DATASIZE
|
||||||
|
#define LWIP_ICMP6_DATASIZE 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ICMP6_HL: default hop limit for ICMPv6 messages
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ICMP6_HL
|
||||||
|
#define LWIP_ICMP6_HL 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ICMP6_CHECKSUM_CHECK==1: verify checksum on ICMPv6 packets
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ICMP6_CHECKSUM_CHECK
|
||||||
|
#define LWIP_ICMP6_CHECKSUM_CHECK 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_MLD
|
||||||
|
#define LWIP_IPV6_MLD (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined.
|
||||||
|
*/
|
||||||
|
#ifndef MEMP_NUM_MLD6_GROUP
|
||||||
|
#define MEMP_NUM_MLD6_GROUP 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_FRAG
|
||||||
|
#define LWIP_IPV6_FRAG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_REASS
|
||||||
|
#define LWIP_IPV6_REASS (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address
|
||||||
|
* is being resolved.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_QUEUEING
|
||||||
|
#define LWIP_ND6_QUEUEING (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution.
|
||||||
|
*/
|
||||||
|
#ifndef MEMP_NUM_ND6_QUEUE
|
||||||
|
#define MEMP_NUM_ND6_QUEUE 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_NUM_NEIGHBORS
|
||||||
|
#define LWIP_ND6_NUM_NEIGHBORS 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_NUM_DESTINATIONS
|
||||||
|
#define LWIP_ND6_NUM_DESTINATIONS 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_NUM_PREFIXES
|
||||||
|
#define LWIP_ND6_NUM_PREFIXES 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_NUM_ROUTERS
|
||||||
|
#define LWIP_ND6_NUM_ROUTERS 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send
|
||||||
|
* (neighbor solicit and router solicit)
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_MAX_MULTICAST_SOLICIT
|
||||||
|
#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages
|
||||||
|
* to send during neighbor reachability detection.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_MAX_UNICAST_SOLICIT
|
||||||
|
#define LWIP_ND6_MAX_UNICAST_SOLICIT 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unused: See ND RFC (time in milliseconds).
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_MAX_ANYCAST_DELAY_TIME
|
||||||
|
#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unused: See ND RFC
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT
|
||||||
|
#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds).
|
||||||
|
* May be updated by router advertisement messages.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_REACHABLE_TIME
|
||||||
|
#define LWIP_ND6_REACHABLE_TIME 30000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_RETRANS_TIMER
|
||||||
|
#define LWIP_ND6_RETRANS_TIMER 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation
|
||||||
|
* message is sent, during neighbor reachability detection.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_DELAY_FIRST_PROBE_TIME
|
||||||
|
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update
|
||||||
|
* Reachable time and retransmission timers, and netif MTU.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_ALLOW_RA_UPDATES
|
||||||
|
#define LWIP_ND6_ALLOW_RA_UPDATES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during
|
||||||
|
* network startup.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||||
|
#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery
|
||||||
|
* with reachability hints for connected destinations. This helps avoid sending
|
||||||
|
* unicast neighbor solicitation messages.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
|
#define LWIP_ND6_TCP_REACHABILITY_HINTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_AUTOCONFIG
|
||||||
|
#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||||
|
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_IPV6_DHCP6
|
||||||
|
#define LWIP_IPV6_DHCP6 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
---------- Debugging options ----------
|
---------- Debugging options ----------
|
||||||
@@ -2037,4 +2305,11 @@
|
|||||||
#define DNS_DEBUG LWIP_DBG_OFF
|
#define DNS_DEBUG LWIP_DBG_OFF
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP6_DEBUG: Enable debugging for IPv6.
|
||||||
|
*/
|
||||||
|
#ifndef IP6_DEBUG
|
||||||
|
#define IP6_DEBUG LWIP_DBG_OFF
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __LWIP_OPT_H__ */
|
#endif /* __LWIP_OPT_H__ */
|
||||||
|
|||||||
@@ -44,8 +44,15 @@ extern "C" {
|
|||||||
* of IP_FRAG */
|
* of IP_FRAG */
|
||||||
#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
|
#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
|
||||||
|
|
||||||
|
/* @todo: We need a mechanism to prevent wasting memory in every pbuf
|
||||||
|
(TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */
|
||||||
|
|
||||||
#define PBUF_TRANSPORT_HLEN 20
|
#define PBUF_TRANSPORT_HLEN 20
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define PBUF_IP_HLEN 40
|
||||||
|
#else
|
||||||
#define PBUF_IP_HLEN 20
|
#define PBUF_IP_HLEN 20
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PBUF_TRANSPORT,
|
PBUF_TRANSPORT,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -60,6 +61,27 @@ struct raw_pcb;
|
|||||||
typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||||
ip_addr_t *addr);
|
ip_addr_t *addr);
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Function prototype for raw pcb IPv6 receive callback functions.
|
||||||
|
* @param arg user supplied argument (raw_pcb.recv_arg)
|
||||||
|
* @param pcb the raw_pcb which received data
|
||||||
|
* @param p the packet buffer that was received
|
||||||
|
* @param addr the remote IPv6 address from which the packet was received
|
||||||
|
* @return 1 if the packet was 'eaten' (aka. deleted),
|
||||||
|
* 0 if the packet lives on
|
||||||
|
* If returning 1, the callback is responsible for freeing the pbuf
|
||||||
|
* if it's not used any more.
|
||||||
|
*/
|
||||||
|
typedef u8_t (*raw_recv_ip6_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||||
|
ip6_addr_t *addr);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define RAW_PCB_RECV_IP6 raw_recv_ip6_fn ip6;
|
||||||
|
#else
|
||||||
|
#define RAW_PCB_RECV_IP6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
struct raw_pcb {
|
struct raw_pcb {
|
||||||
/* Common members of all PCB types */
|
/* Common members of all PCB types */
|
||||||
IP_PCB;
|
IP_PCB;
|
||||||
@@ -69,7 +91,10 @@ struct raw_pcb {
|
|||||||
u8_t protocol;
|
u8_t protocol;
|
||||||
|
|
||||||
/** receive callback function */
|
/** receive callback function */
|
||||||
raw_recv_fn recv;
|
union {
|
||||||
|
raw_recv_fn ip4;
|
||||||
|
RAW_PCB_RECV_IP6
|
||||||
|
} recv;
|
||||||
/* user-supplied argument for the recv callback */
|
/* user-supplied argument for the recv callback */
|
||||||
void *recv_arg;
|
void *recv_arg;
|
||||||
};
|
};
|
||||||
@@ -85,6 +110,14 @@ void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *re
|
|||||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr);
|
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr);
|
||||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct raw_pcb * raw_new_ip6 (u8_t proto);
|
||||||
|
#define raw_bind_ip6(pcb, ip6addr) raw_bind(pcb, ip6_2_ip(ip6addr))
|
||||||
|
#define raw_connect_ip6(pcb, ip6addr) raw_connect(pcb, ip6_2_ip(ip6addr))
|
||||||
|
#define raw_recv_ip6(pcb, recv_ip6_fn, recv_arg) raw_recv(pcb, (raw_recv_fn)recv_ip6_fn, recv_arg)
|
||||||
|
#define raw_sendto_ip6(pcb, pbuf, ip6addr) raw_sendto(pcb, pbuf, ip6_2_ip(ip6addr))
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/* The following functions are the lower layer interface to RAW. */
|
/* The following functions are the lower layer interface to RAW. */
|
||||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||||
#define raw_init() /* Compatibility define, not init needed. */
|
#define raw_init() /* Compatibility define, not init needed. */
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
#include "lwip/inet6.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -53,13 +54,28 @@ struct sockaddr_in {
|
|||||||
u8_t sin_family;
|
u8_t sin_family;
|
||||||
u16_t sin_port;
|
u16_t sin_port;
|
||||||
struct in_addr sin_addr;
|
struct in_addr sin_addr;
|
||||||
char sin_zero[8];
|
#define SIN_ZERO_LEN 8
|
||||||
|
char sin_zero[SIN_ZERO_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct sockaddr_in6 {
|
||||||
|
u8_t sin6_len; /* length of this structure */
|
||||||
|
u8_t sin6_family; /* AF_INET6 */
|
||||||
|
u16_t sin6_port; /* Transport layer port # */
|
||||||
|
u32_t sin6_flowinfo; /* IPv6 flow information */
|
||||||
|
struct in6_addr sin6_addr; /* IPv6 address */
|
||||||
|
};
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
struct sockaddr {
|
struct sockaddr {
|
||||||
u8_t sa_len;
|
u8_t sa_len;
|
||||||
u8_t sa_family;
|
u8_t sa_family;
|
||||||
u16_t sa_data[14];
|
#if LWIP_IPV6
|
||||||
|
u8_t sa_data[22];
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
u8_t sa_data[14];
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef socklen_t
|
#ifndef socklen_t
|
||||||
@@ -118,7 +134,13 @@ struct linger {
|
|||||||
|
|
||||||
#define AF_UNSPEC 0
|
#define AF_UNSPEC 0
|
||||||
#define AF_INET 2
|
#define AF_INET 2
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define AF_INET6 10
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define AF_INET6 AF_UNSPEC
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
#define PF_INET AF_INET
|
#define PF_INET AF_INET
|
||||||
|
#define PF_INET6 AF_INET6
|
||||||
#define PF_UNSPEC AF_UNSPEC
|
#define PF_UNSPEC AF_UNSPEC
|
||||||
|
|
||||||
#define IPPROTO_IP 0
|
#define IPPROTO_IP 0
|
||||||
@@ -280,9 +302,9 @@ typedef struct ip_mreq {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SHUT_RD
|
#ifndef SHUT_RD
|
||||||
#define SHUT_RD 1
|
#define SHUT_RD 0
|
||||||
#define SHUT_WR 2
|
#define SHUT_WR 1
|
||||||
#define SHUT_RDWR 3
|
#define SHUT_RDWR 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FD_SET used for lwip_select */
|
/* FD_SET used for lwip_select */
|
||||||
|
|||||||
@@ -144,6 +144,21 @@ struct stats_ {
|
|||||||
#if SYS_STATS
|
#if SYS_STATS
|
||||||
struct stats_sys sys;
|
struct stats_sys sys;
|
||||||
#endif
|
#endif
|
||||||
|
#if IP6_STATS
|
||||||
|
struct stats_proto ip6;
|
||||||
|
#endif
|
||||||
|
#if ICMP6_STATS
|
||||||
|
struct stats_proto icmp6;
|
||||||
|
#endif
|
||||||
|
#if IP6_FRAG_STATS
|
||||||
|
struct stats_proto ip6_frag;
|
||||||
|
#endif
|
||||||
|
#if MLD6_STATS
|
||||||
|
struct stats_igmp mld6;
|
||||||
|
#endif
|
||||||
|
#if ND6_STATS
|
||||||
|
struct stats_proto nd6;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct stats_ lwip_stats;
|
extern struct stats_ lwip_stats;
|
||||||
@@ -190,7 +205,7 @@ void stats_init(void);
|
|||||||
|
|
||||||
#if IGMP_STATS
|
#if IGMP_STATS
|
||||||
#define IGMP_STATS_INC(x) STATS_INC(x)
|
#define IGMP_STATS_INC(x) STATS_INC(x)
|
||||||
#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
|
#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP")
|
||||||
#else
|
#else
|
||||||
#define IGMP_STATS_INC(x)
|
#define IGMP_STATS_INC(x)
|
||||||
#define IGMP_STATS_DISPLAY()
|
#define IGMP_STATS_DISPLAY()
|
||||||
@@ -268,18 +283,58 @@ void stats_init(void);
|
|||||||
#define SYS_STATS_DISPLAY()
|
#define SYS_STATS_DISPLAY()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IP6_STATS
|
||||||
|
#define IP6_STATS_INC(x) STATS_INC(x)
|
||||||
|
#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6")
|
||||||
|
#else
|
||||||
|
#define IP6_STATS_INC(x)
|
||||||
|
#define IP6_STATS_DISPLAY()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ICMP6_STATS
|
||||||
|
#define ICMP6_STATS_INC(x) STATS_INC(x)
|
||||||
|
#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6")
|
||||||
|
#else
|
||||||
|
#define ICMP6_STATS_INC(x)
|
||||||
|
#define ICMP6_STATS_DISPLAY()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IP6_FRAG_STATS
|
||||||
|
#define IP6_FRAG_STATS_INC(x) STATS_INC(x)
|
||||||
|
#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG")
|
||||||
|
#else
|
||||||
|
#define IP6_FRAG_STATS_INC(x)
|
||||||
|
#define IP6_FRAG_STATS_DISPLAY()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MLD6_STATS
|
||||||
|
#define MLD6_STATS_INC(x) STATS_INC(x)
|
||||||
|
#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1")
|
||||||
|
#else
|
||||||
|
#define MLD6_STATS_INC(x)
|
||||||
|
#define MLD6_STATS_DISPLAY()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ND6_STATS
|
||||||
|
#define ND6_STATS_INC(x) STATS_INC(x)
|
||||||
|
#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND")
|
||||||
|
#else
|
||||||
|
#define ND6_STATS_INC(x)
|
||||||
|
#define ND6_STATS_DISPLAY()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Display of statistics */
|
/* Display of statistics */
|
||||||
#if LWIP_STATS_DISPLAY
|
#if LWIP_STATS_DISPLAY
|
||||||
void stats_display(void);
|
void stats_display(void);
|
||||||
void stats_display_proto(struct stats_proto *proto, char *name);
|
void stats_display_proto(struct stats_proto *proto, const char *name);
|
||||||
void stats_display_igmp(struct stats_igmp *igmp);
|
void stats_display_igmp(struct stats_igmp *igmp, const char *name);
|
||||||
void stats_display_mem(struct stats_mem *mem, char *name);
|
void stats_display_mem(struct stats_mem *mem, const char *name);
|
||||||
void stats_display_memp(struct stats_mem *mem, int index);
|
void stats_display_memp(struct stats_mem *mem, int index);
|
||||||
void stats_display_sys(struct stats_sys *sys);
|
void stats_display_sys(struct stats_sys *sys);
|
||||||
#else /* LWIP_STATS_DISPLAY */
|
#else /* LWIP_STATS_DISPLAY */
|
||||||
#define stats_display()
|
#define stats_display()
|
||||||
#define stats_display_proto(proto, name)
|
#define stats_display_proto(proto, name)
|
||||||
#define stats_display_igmp(igmp)
|
#define stats_display_igmp(igmp, name)
|
||||||
#define stats_display_mem(mem, name)
|
#define stats_display_mem(mem, name)
|
||||||
#define stats_display_memp(mem, index)
|
#define stats_display_memp(mem, index)
|
||||||
#define stats_display_sys(sys)
|
#define stats_display_sys(sys)
|
||||||
|
|||||||
@@ -36,12 +36,13 @@
|
|||||||
|
|
||||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -156,11 +157,11 @@ enum tcp_state {
|
|||||||
*/
|
*/
|
||||||
#define TCP_PCB_COMMON(type) \
|
#define TCP_PCB_COMMON(type) \
|
||||||
type *next; /* for the linked list */ \
|
type *next; /* for the linked list */ \
|
||||||
enum tcp_state state; /* TCP state */ \
|
|
||||||
u8_t prio; \
|
|
||||||
void *callback_arg; \
|
void *callback_arg; \
|
||||||
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
|
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
|
||||||
DEF_ACCEPT_CALLBACK \
|
DEF_ACCEPT_CALLBACK \
|
||||||
|
enum tcp_state state; /* TCP state */ \
|
||||||
|
u8_t prio; \
|
||||||
/* ports are in host byte order */ \
|
/* ports are in host byte order */ \
|
||||||
u16_t local_port
|
u16_t local_port
|
||||||
|
|
||||||
@@ -187,21 +188,22 @@ struct tcp_pcb {
|
|||||||
|
|
||||||
/* the rest of the fields are in host byte order
|
/* the rest of the fields are in host byte order
|
||||||
as we have to do some math with them */
|
as we have to do some math with them */
|
||||||
|
|
||||||
|
/* Timers */
|
||||||
|
u8_t polltmr, pollinterval;
|
||||||
|
u32_t tmr;
|
||||||
|
|
||||||
/* receiver variables */
|
/* receiver variables */
|
||||||
u32_t rcv_nxt; /* next seqno expected */
|
u32_t rcv_nxt; /* next seqno expected */
|
||||||
u16_t rcv_wnd; /* receiver window available */
|
u16_t rcv_wnd; /* receiver window available */
|
||||||
u16_t rcv_ann_wnd; /* receiver window to announce */
|
u16_t rcv_ann_wnd; /* receiver window to announce */
|
||||||
u32_t rcv_ann_right_edge; /* announced right edge of window */
|
u32_t rcv_ann_right_edge; /* announced right edge of window */
|
||||||
|
|
||||||
/* Timers */
|
|
||||||
u32_t tmr;
|
|
||||||
u8_t polltmr, pollinterval;
|
|
||||||
|
|
||||||
/* Retransmission timer. */
|
/* Retransmission timer. */
|
||||||
s16_t rtime;
|
s16_t rtime;
|
||||||
|
|
||||||
u16_t mss; /* maximum segment size */
|
u16_t mss; /* maximum segment size */
|
||||||
|
|
||||||
/* RTT (round trip time) estimation variables */
|
/* RTT (round trip time) estimation variables */
|
||||||
u32_t rttest; /* RTT estimate in 500ms ticks */
|
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||||
u32_t rtseq; /* sequence number being timed */
|
u32_t rtseq; /* sequence number being timed */
|
||||||
@@ -211,24 +213,24 @@ struct tcp_pcb {
|
|||||||
u8_t nrtx; /* number of retransmissions */
|
u8_t nrtx; /* number of retransmissions */
|
||||||
|
|
||||||
/* fast retransmit/recovery */
|
/* fast retransmit/recovery */
|
||||||
u32_t lastack; /* Highest acknowledged seqno. */
|
|
||||||
u8_t dupacks;
|
u8_t dupacks;
|
||||||
|
u32_t lastack; /* Highest acknowledged seqno. */
|
||||||
|
|
||||||
/* congestion avoidance/control variables */
|
/* congestion avoidance/control variables */
|
||||||
u16_t cwnd;
|
u16_t cwnd;
|
||||||
u16_t ssthresh;
|
u16_t ssthresh;
|
||||||
|
|
||||||
/* sender variables */
|
/* sender variables */
|
||||||
u32_t snd_nxt; /* next new seqno to be sent */
|
u32_t snd_nxt; /* next new seqno to be sent */
|
||||||
u16_t snd_wnd; /* sender window */
|
|
||||||
u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
|
u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
|
||||||
window update. */
|
window update. */
|
||||||
u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
|
u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||||
|
u16_t snd_wnd; /* sender window */
|
||||||
|
|
||||||
u16_t acked;
|
u16_t acked;
|
||||||
|
|
||||||
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
|
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
|
||||||
#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
|
#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)
|
||||||
u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
|
u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
|
||||||
|
|
||||||
#if TCP_OVERSIZE
|
#if TCP_OVERSIZE
|
||||||
@@ -279,7 +281,7 @@ struct tcp_pcb {
|
|||||||
u8_t keep_cnt_sent;
|
u8_t keep_cnt_sent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tcp_pcb_listen {
|
struct tcp_pcb_listen {
|
||||||
/* Common members of all PCB types */
|
/* Common members of all PCB types */
|
||||||
IP_PCB;
|
IP_PCB;
|
||||||
/* Protocol specific PCB members */
|
/* Protocol specific PCB members */
|
||||||
@@ -289,6 +291,9 @@ struct tcp_pcb_listen {
|
|||||||
u8_t backlog;
|
u8_t backlog;
|
||||||
u8_t accepts_pending;
|
u8_t accepts_pending;
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
#endif /* TCP_LISTEN_BACKLOG */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
u8_t accept_any_ip_version;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LWIP_EVENT_API
|
#if LWIP_EVENT_API
|
||||||
@@ -367,6 +372,19 @@ err_t tcp_output (struct tcp_pcb *pcb);
|
|||||||
|
|
||||||
const char* tcp_debug_state_str(enum tcp_state s);
|
const char* tcp_debug_state_str(enum tcp_state s);
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct tcp_pcb * tcp_new_ip6 (void);
|
||||||
|
#define tcp_bind_ip6(pcb, ip6addr, port) \
|
||||||
|
tcp_bind(pcb, ip6_2_ip(ip6addr), port)
|
||||||
|
#define tcp_connect_ip6(pcb, ip6addr, port, connected) \
|
||||||
|
tcp_connect(pcb, ip6_2_ip(ip6addr), port, connected)
|
||||||
|
struct tcp_pcb * tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||||
|
#define tcp_listen_dual(pcb) tcp_listen_dual_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define tcp_listen_dual_with_backlog(pcb, backlog) tcp_listen_with_backlog(pcb, backlog)
|
||||||
|
#define tcp_listen_dual(pcb) tcp_listen(pcb)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,13 @@
|
|||||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -278,7 +279,6 @@ PACK_STRUCT_END
|
|||||||
struct tcp_seg {
|
struct tcp_seg {
|
||||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||||
struct pbuf *p; /* buffer containing data + TCP header */
|
struct pbuf *p; /* buffer containing data + TCP header */
|
||||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
|
||||||
u16_t len; /* the TCP length of this segment */
|
u16_t len; /* the TCP length of this segment */
|
||||||
#if TCP_OVERSIZE_DBGCHECK
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
u16_t oversize_left; /* Extra bytes available at the end of the last
|
u16_t oversize_left; /* Extra bytes available at the end of the last
|
||||||
@@ -427,9 +427,20 @@ err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
|
|||||||
|
|
||||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||||
|
|
||||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
void tcp_rst_impl(u32_t seqno, u32_t ackno,
|
||||||
ip_addr_t *local_ip, ip_addr_t *remote_ip,
|
ipX_addr_t *local_ip, ipX_addr_t *remote_ip,
|
||||||
u16_t local_port, u16_t remote_port);
|
u16_t local_port, u16_t remote_port
|
||||||
|
#if LWIP_IPV6
|
||||||
|
, u8_t isipv6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
);
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \
|
||||||
|
tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6)
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \
|
||||||
|
tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
u32_t tcp_next_iss(void);
|
u32_t tcp_next_iss(void);
|
||||||
|
|
||||||
@@ -437,7 +448,16 @@ void tcp_keepalive(struct tcp_pcb *pcb);
|
|||||||
void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||||
|
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr);
|
u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
|
||||||
|
#if LWIP_IPV6
|
||||||
|
, ipX_addr_t *src, u8_t isipv6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
);
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest, src, isipv6)
|
||||||
|
#else /* LWIP_IPV6 */
|
||||||
|
#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest)
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||||
|
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ typedef void (*tcpip_init_done_fn)(void *arg);
|
|||||||
/** Function prototype for functions passed to tcpip_callback() */
|
/** Function prototype for functions passed to tcpip_callback() */
|
||||||
typedef void (*tcpip_callback_fn)(void *ctx);
|
typedef void (*tcpip_callback_fn)(void *ctx);
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
struct tcpip_callback_msg;
|
||||||
|
|
||||||
void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg);
|
void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg);
|
||||||
|
|
||||||
#if LWIP_NETCONN
|
#if LWIP_NETCONN
|
||||||
@@ -98,6 +101,10 @@ err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg);
|
|||||||
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block);
|
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block);
|
||||||
#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1)
|
#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1)
|
||||||
|
|
||||||
|
struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx);
|
||||||
|
void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg);
|
||||||
|
err_t tcpip_trycallback(struct tcpip_callback_msg* msg);
|
||||||
|
|
||||||
/* free pbufs or heap memory from another context without blocking */
|
/* free pbufs or heap memory from another context without blocking */
|
||||||
err_t pbuf_free_callback(struct pbuf *p);
|
err_t pbuf_free_callback(struct pbuf *p);
|
||||||
err_t mem_free_callback(void *m);
|
err_t mem_free_callback(void *m);
|
||||||
@@ -119,7 +126,8 @@ enum tcpip_msg_type {
|
|||||||
TCPIP_MSG_TIMEOUT,
|
TCPIP_MSG_TIMEOUT,
|
||||||
TCPIP_MSG_UNTIMEOUT,
|
TCPIP_MSG_UNTIMEOUT,
|
||||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||||
TCPIP_MSG_CALLBACK
|
TCPIP_MSG_CALLBACK,
|
||||||
|
TCPIP_MSG_CALLBACK_STATIC
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tcpip_msg {
|
struct tcpip_msg {
|
||||||
|
|||||||
@@ -41,7 +41,9 @@
|
|||||||
#if LWIP_TIMERS
|
#if LWIP_TIMERS
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
#if !NO_SYS
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/ip6_addr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -87,6 +88,26 @@ struct udp_pcb;
|
|||||||
typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||||
ip_addr_t *addr, u16_t port);
|
ip_addr_t *addr, u16_t port);
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
/** Function prototype for udp pcb IPv6 receive callback functions
|
||||||
|
* The callback is responsible for freeing the pbuf
|
||||||
|
* if it's not used any more.
|
||||||
|
*
|
||||||
|
* @param arg user supplied argument (udp_pcb.recv_arg)
|
||||||
|
* @param pcb the udp_pcb which received data
|
||||||
|
* @param p the packet buffer that was received
|
||||||
|
* @param addr the remote IPv6 address from which the packet was received
|
||||||
|
* @param port the remote port from which the packet was received
|
||||||
|
*/
|
||||||
|
typedef void (*udp_recv_ip6_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||||
|
ip6_addr_t *addr, u16_t port);
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#define UDP_PCB_RECV_IP6 udp_recv_ip6_fn ip6;
|
||||||
|
#else
|
||||||
|
#define UDP_PCB_RECV_IP6
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
struct udp_pcb {
|
struct udp_pcb {
|
||||||
/* Common members of all PCB types */
|
/* Common members of all PCB types */
|
||||||
@@ -111,7 +132,10 @@ struct udp_pcb {
|
|||||||
#endif /* LWIP_UDPLITE */
|
#endif /* LWIP_UDPLITE */
|
||||||
|
|
||||||
/** receive callback function */
|
/** receive callback function */
|
||||||
udp_recv_fn recv;
|
union {
|
||||||
|
udp_recv_fn ip4;
|
||||||
|
UDP_PCB_RECV_IP6
|
||||||
|
}recv;
|
||||||
/** user-supplied argument for the recv callback */
|
/** user-supplied argument for the recv callback */
|
||||||
void *recv_arg;
|
void *recv_arg;
|
||||||
};
|
};
|
||||||
@@ -156,6 +180,26 @@ void udp_input (struct pbuf *p, struct netif *inp);
|
|||||||
|
|
||||||
#define udp_init() /* Compatibility define, not init needed. */
|
#define udp_init() /* Compatibility define, not init needed. */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
struct udp_pcb * udp_new_ip6(void);
|
||||||
|
#define udp_bind_ip6(pcb, ip6addr, port) \
|
||||||
|
udp_bind(pcb, ip6_2_ip(ip6addr), port)
|
||||||
|
#define udp_connect_ip6(pcb, ip6addr, port) \
|
||||||
|
udp_connect(pcb, ip6_2_ip(ip6addr), port)
|
||||||
|
#define udp_recv_ip6(pcb, recv_ip6_fn, recv_arg) \
|
||||||
|
udp_recv(pcb, (udp_recv_fn)recv_ip6_fn, recv_arg)
|
||||||
|
#define udp_sendto_ip6(pcb, pbuf, ip6addr, port) \
|
||||||
|
udp_sendto(pcb, pbuf, ip6_2_ip(ip6addr), port)
|
||||||
|
#define udp_sendto_if_ip6(pcb, pbuf, ip6addr, port, netif) \
|
||||||
|
udp_sendto_if(pcb, pbuf, ip6_2_ip(ip6addr), port, netif)
|
||||||
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
|
#define udp_sendto_chksum_ip6(pcb, pbuf, ip6addr, port, have_chk, chksum) \
|
||||||
|
udp_sendto_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, have_chk, chksum)
|
||||||
|
#define udp_sendto_if_chksum_ip6(pcb, pbuf, ip6addr, port, netif, have_chk, chksum) \
|
||||||
|
udp_sendto_if_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, netif, have_chk, chksum)
|
||||||
|
#endif /*LWIP_CHECKSUM_ON_COPY */
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
void udp_debug_print(struct udp_hdr *udphdr);
|
void udp_debug_print(struct udp_hdr *udphdr);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ PACK_STRUCT_BEGIN
|
|||||||
* if 'type' in ethernet header is ETHTYPE_VLAN.
|
* if 'type' in ethernet header is ETHTYPE_VLAN.
|
||||||
* See IEEE802.Q */
|
* See IEEE802.Q */
|
||||||
struct eth_vlan_hdr {
|
struct eth_vlan_hdr {
|
||||||
PACK_STRUCT_FIELD(u16_t tpid);
|
|
||||||
PACK_STRUCT_FIELD(u16_t prio_vid);
|
PACK_STRUCT_FIELD(u16_t prio_vid);
|
||||||
|
PACK_STRUCT_FIELD(u16_t tpid);
|
||||||
} PACK_STRUCT_STRUCT;
|
} PACK_STRUCT_STRUCT;
|
||||||
PACK_STRUCT_END
|
PACK_STRUCT_END
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
@@ -134,11 +134,12 @@ PACK_STRUCT_END
|
|||||||
/** 5 seconds period */
|
/** 5 seconds period */
|
||||||
#define ARP_TMR_INTERVAL 5000
|
#define ARP_TMR_INTERVAL 5000
|
||||||
|
|
||||||
#define ETHTYPE_ARP 0x0806
|
#define ETHTYPE_ARP 0x0806U
|
||||||
#define ETHTYPE_IP 0x0800
|
#define ETHTYPE_IP 0x0800U
|
||||||
#define ETHTYPE_VLAN 0x8100
|
#define ETHTYPE_VLAN 0x8100U
|
||||||
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
|
#define ETHTYPE_IPV6 0x86DDU
|
||||||
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
|
#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
|
||||||
|
#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
|
||||||
|
|
||||||
/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
|
/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
|
||||||
* or known to be 32-bit aligned within the protocol header. */
|
* or known to be 32-bit aligned within the protocol header. */
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
#include "lwip/autoip.h"
|
#include "lwip/autoip.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
#include "lwip/ip6.h"
|
||||||
|
|
||||||
#if PPPOE_SUPPORT
|
#if PPPOE_SUPPORT
|
||||||
#include "netif/ppp_oe.h"
|
#include "netif/ppp_oe.h"
|
||||||
@@ -93,6 +94,9 @@ struct etharp_entry {
|
|||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/** Pointer to queue of pending outgoing packets on this ARP entry. */
|
/** Pointer to queue of pending outgoing packets on this ARP entry. */
|
||||||
struct etharp_q_entry *q;
|
struct etharp_q_entry *q;
|
||||||
|
#else /* ARP_QUEUEING */
|
||||||
|
/** Pointer to a single pending outgoing packet on this ARP entry. */
|
||||||
|
struct pbuf *q;
|
||||||
#endif /* ARP_QUEUEING */
|
#endif /* ARP_QUEUEING */
|
||||||
ip_addr_t ipaddr;
|
ip_addr_t ipaddr;
|
||||||
struct eth_addr ethaddr;
|
struct eth_addr ethaddr;
|
||||||
@@ -154,6 +158,11 @@ free_etharp_q(struct etharp_q_entry *q)
|
|||||||
memp_free(MEMP_ARP_QUEUE, r);
|
memp_free(MEMP_ARP_QUEUE, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else /* ARP_QUEUEING */
|
||||||
|
|
||||||
|
/** Compatibility define: free the queued pbuf */
|
||||||
|
#define free_etharp_q(q) pbuf_free(q)
|
||||||
|
|
||||||
#endif /* ARP_QUEUEING */
|
#endif /* ARP_QUEUEING */
|
||||||
|
|
||||||
/** Clean up ARP table entries */
|
/** Clean up ARP table entries */
|
||||||
@@ -162,7 +171,6 @@ free_entry(int i)
|
|||||||
{
|
{
|
||||||
/* remove from SNMP ARP index tree */
|
/* remove from SNMP ARP index tree */
|
||||||
snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
|
snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* and empty packet queue */
|
/* and empty packet queue */
|
||||||
if (arp_table[i].q != NULL) {
|
if (arp_table[i].q != NULL) {
|
||||||
/* remove all queued packets */
|
/* remove all queued packets */
|
||||||
@@ -170,7 +178,6 @@ free_entry(int i)
|
|||||||
free_etharp_q(arp_table[i].q);
|
free_etharp_q(arp_table[i].q);
|
||||||
arp_table[i].q = NULL;
|
arp_table[i].q = NULL;
|
||||||
}
|
}
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
/* recycle entry for re-use */
|
/* recycle entry for re-use */
|
||||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||||
#if ETHARP_SUPPORT_STATIC_ENTRIES
|
#if ETHARP_SUPPORT_STATIC_ENTRIES
|
||||||
@@ -254,12 +261,10 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
|||||||
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
|
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
|
||||||
s8_t empty = ARP_TABLE_SIZE;
|
s8_t empty = ARP_TABLE_SIZE;
|
||||||
u8_t i = 0, age_pending = 0, age_stable = 0;
|
u8_t i = 0, age_pending = 0, age_stable = 0;
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* oldest entry with packets on queue */
|
/* oldest entry with packets on queue */
|
||||||
s8_t old_queue = ARP_TABLE_SIZE;
|
s8_t old_queue = ARP_TABLE_SIZE;
|
||||||
/* its age */
|
/* its age */
|
||||||
u8_t age_queue = 0;
|
u8_t age_queue = 0;
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a) do a search through the cache, remember candidates
|
* a) do a search through the cache, remember candidates
|
||||||
@@ -295,14 +300,12 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
|||||||
/* pending entry? */
|
/* pending entry? */
|
||||||
if (state == ETHARP_STATE_PENDING) {
|
if (state == ETHARP_STATE_PENDING) {
|
||||||
/* pending with queued packets? */
|
/* pending with queued packets? */
|
||||||
#if ARP_QUEUEING
|
|
||||||
if (arp_table[i].q != NULL) {
|
if (arp_table[i].q != NULL) {
|
||||||
if (arp_table[i].ctime >= age_queue) {
|
if (arp_table[i].ctime >= age_queue) {
|
||||||
old_queue = i;
|
old_queue = i;
|
||||||
age_queue = arp_table[i].ctime;
|
age_queue = arp_table[i].ctime;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
/* pending without queued packets? */
|
/* pending without queued packets? */
|
||||||
{
|
{
|
||||||
if (arp_table[i].ctime >= age_pending) {
|
if (arp_table[i].ctime >= age_pending) {
|
||||||
@@ -355,22 +358,18 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
|||||||
/* recycle oldest stable*/
|
/* recycle oldest stable*/
|
||||||
i = old_stable;
|
i = old_stable;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* no queued packets should exist on stable entries */
|
/* no queued packets should exist on stable entries */
|
||||||
LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
|
LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
/* 3) found recyclable pending entry without queued packets? */
|
/* 3) found recyclable pending entry without queued packets? */
|
||||||
} else if (old_pending < ARP_TABLE_SIZE) {
|
} else if (old_pending < ARP_TABLE_SIZE) {
|
||||||
/* recycle oldest pending */
|
/* recycle oldest pending */
|
||||||
i = old_pending;
|
i = old_pending;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* 4) found recyclable pending entry with queued packets? */
|
/* 4) found recyclable pending entry with queued packets? */
|
||||||
} else if (old_queue < ARP_TABLE_SIZE) {
|
} else if (old_queue < ARP_TABLE_SIZE) {
|
||||||
/* recycle oldest pending (queued packets are free in free_entry) */
|
/* recycle oldest pending (queued packets are free in free_entry) */
|
||||||
i = old_queue;
|
i = old_queue;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
/* no empty or recyclable entries found */
|
/* no empty or recyclable entries found */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
|
||||||
@@ -486,8 +485,8 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd
|
|||||||
ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
|
ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
|
||||||
/* reset time stamp */
|
/* reset time stamp */
|
||||||
arp_table[i].ctime = 0;
|
arp_table[i].ctime = 0;
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* this is where we will send out queued packets! */
|
/* this is where we will send out queued packets! */
|
||||||
|
#if ARP_QUEUEING
|
||||||
while (arp_table[i].q != NULL) {
|
while (arp_table[i].q != NULL) {
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
/* remember remainder of queue */
|
/* remember remainder of queue */
|
||||||
@@ -498,12 +497,16 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd
|
|||||||
p = q->p;
|
p = q->p;
|
||||||
/* now queue entry can be freed */
|
/* now queue entry can be freed */
|
||||||
memp_free(MEMP_ARP_QUEUE, q);
|
memp_free(MEMP_ARP_QUEUE, q);
|
||||||
|
#else /* ARP_QUEUEING */
|
||||||
|
if (arp_table[i].q != NULL) {
|
||||||
|
struct pbuf *p = arp_table[i].q;
|
||||||
|
arp_table[i].q = NULL;
|
||||||
|
#endif /* ARP_QUEUEING */
|
||||||
/* send the queued IP packet */
|
/* send the queued IP packet */
|
||||||
etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
|
etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
|
||||||
/* free the queued IP packet */
|
/* free the queued IP packet */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +629,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
|
|||||||
ethhdr = (struct eth_hdr *)p->payload;
|
ethhdr = (struct eth_hdr *)p->payload;
|
||||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||||
#if ETHARP_SUPPORT_VLAN
|
#if ETHARP_SUPPORT_VLAN
|
||||||
if (ethhdr->type == ETHTYPE_VLAN) {
|
if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||||
}
|
}
|
||||||
#endif /* ETHARP_SUPPORT_VLAN */
|
#endif /* ETHARP_SUPPORT_VLAN */
|
||||||
@@ -691,7 +694,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
ethhdr = (struct eth_hdr *)p->payload;
|
ethhdr = (struct eth_hdr *)p->payload;
|
||||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||||
#if ETHARP_SUPPORT_VLAN
|
#if ETHARP_SUPPORT_VLAN
|
||||||
if (ethhdr->type == ETHTYPE_VLAN) {
|
if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||||
hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||||
}
|
}
|
||||||
#endif /* ETHARP_SUPPORT_VLAN */
|
#endif /* ETHARP_SUPPORT_VLAN */
|
||||||
@@ -700,11 +703,10 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
|
if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
|
||||||
(hdr->hwlen != ETHARP_HWADDR_LEN) ||
|
(hdr->hwlen != ETHARP_HWADDR_LEN) ||
|
||||||
(hdr->protolen != sizeof(ip_addr_t)) ||
|
(hdr->protolen != sizeof(ip_addr_t)) ||
|
||||||
(hdr->proto != PP_HTONS(ETHTYPE_IP)) ||
|
(hdr->proto != PP_HTONS(ETHTYPE_IP))) {
|
||||||
(ethhdr->type != PP_HTONS(ETHTYPE_ARP))) {
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||||
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
||||||
hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen, ethhdr->type));
|
hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
|
||||||
ETHARP_STATS_INC(etharp.proterr);
|
ETHARP_STATS_INC(etharp.proterr);
|
||||||
ETHARP_STATS_INC(etharp.drop);
|
ETHARP_STATS_INC(etharp.drop);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -871,14 +873,25 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
|
|||||||
/* outside local network? */
|
/* outside local network? */
|
||||||
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
|
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
|
||||||
!ip_addr_islinklocal(ipaddr)) {
|
!ip_addr_islinklocal(ipaddr)) {
|
||||||
/* interface has default gateway? */
|
#if LWIP_AUTOIP
|
||||||
if (!ip_addr_isany(&netif->gw)) {
|
struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
|
||||||
/* send to hardware address of default gateway IP address */
|
sizeof(struct eth_hdr));
|
||||||
ipaddr = &(netif->gw);
|
/* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
|
||||||
/* no default gateway available */
|
a link-local source address must always be "directly to its destination
|
||||||
} else {
|
on the same physical link. The host MUST NOT send the packet to any
|
||||||
/* no route to destination error (default gateway missing) */
|
router for forwarding". */
|
||||||
return ERR_RTE;
|
if (!ip_addr_islinklocal(&iphdr->src))
|
||||||
|
#endif /* LWIP_AUTOIP */
|
||||||
|
{
|
||||||
|
/* interface has default gateway? */
|
||||||
|
if (!ip_addr_isany(&netif->gw)) {
|
||||||
|
/* send to hardware address of default gateway IP address */
|
||||||
|
ipaddr = &(netif->gw);
|
||||||
|
/* no default gateway available */
|
||||||
|
} else {
|
||||||
|
/* no route to destination error (default gateway missing) */
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
@@ -1004,7 +1017,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
|||||||
result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
|
result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
|
||||||
/* pending entry? (either just created or already pending */
|
/* pending entry? (either just created or already pending */
|
||||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||||
#if ARP_QUEUEING /* queue the given q packet */
|
/* entry is still pending, queue the given packet 'q' */
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
int copy_needed = 0;
|
int copy_needed = 0;
|
||||||
/* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
|
/* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
|
||||||
@@ -1036,6 +1049,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
|||||||
/* packet could be taken over? */
|
/* packet could be taken over? */
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
/* queue packet ... */
|
/* queue packet ... */
|
||||||
|
#if ARP_QUEUEING
|
||||||
struct etharp_q_entry *new_entry;
|
struct etharp_q_entry *new_entry;
|
||||||
/* allocate a new arp queue entry */
|
/* allocate a new arp queue entry */
|
||||||
new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
|
new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
|
||||||
@@ -1060,18 +1074,23 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
|||||||
/* the pool MEMP_ARP_QUEUE is empty */
|
/* the pool MEMP_ARP_QUEUE is empty */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||||
/* { result == ERR_MEM } through initialization */
|
result = ERR_MEM;
|
||||||
}
|
}
|
||||||
|
#else /* ARP_QUEUEING */
|
||||||
|
/* always queue one packet per ARP request only, freeing a previously queued packet */
|
||||||
|
if (arp_table[i].q != NULL) {
|
||||||
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||||
|
pbuf_free(arp_table[i].q);
|
||||||
|
}
|
||||||
|
arp_table[i].q = p;
|
||||||
|
result = ERR_OK;
|
||||||
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||||
|
#endif /* ARP_QUEUEING */
|
||||||
} else {
|
} else {
|
||||||
ETHARP_STATS_INC(etharp.memerr);
|
ETHARP_STATS_INC(etharp.memerr);
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||||
/* { result == ERR_MEM } through initialization */
|
result = ERR_MEM;
|
||||||
}
|
}
|
||||||
#else /* ARP_QUEUEING */
|
|
||||||
/* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
|
|
||||||
/* { result == ERR_MEM } through initialization */
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
|
|
||||||
#endif /* ARP_QUEUEING */
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1199,6 +1218,14 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||||||
{
|
{
|
||||||
struct eth_hdr* ethhdr;
|
struct eth_hdr* ethhdr;
|
||||||
u16_t type;
|
u16_t type;
|
||||||
|
s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
|
||||||
|
|
||||||
|
if (p->len <= SIZEOF_ETH_HDR) {
|
||||||
|
/* a packet with only an ethernet header (or less) is not valid for us */
|
||||||
|
ETHARP_STATS_INC(etharp.proterr);
|
||||||
|
ETHARP_STATS_INC(etharp.drop);
|
||||||
|
goto free_and_return;
|
||||||
|
}
|
||||||
|
|
||||||
/* points to packet payload, which starts with an Ethernet header */
|
/* points to packet payload, which starts with an Ethernet header */
|
||||||
ethhdr = (struct eth_hdr *)p->payload;
|
ethhdr = (struct eth_hdr *)p->payload;
|
||||||
@@ -1214,6 +1241,12 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||||||
#if ETHARP_SUPPORT_VLAN
|
#if ETHARP_SUPPORT_VLAN
|
||||||
if (type == PP_HTONS(ETHTYPE_VLAN)) {
|
if (type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||||
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
|
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
|
||||||
|
if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
|
||||||
|
/* a packet with only an ethernet/vlan header (or less) is not valid for us */
|
||||||
|
ETHARP_STATS_INC(etharp.proterr);
|
||||||
|
ETHARP_STATS_INC(etharp.drop);
|
||||||
|
goto free_and_return;
|
||||||
|
}
|
||||||
#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
|
#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
|
||||||
if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
|
if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
|
||||||
/* silently ignore this packet: not for our VLAN */
|
/* silently ignore this packet: not for our VLAN */
|
||||||
@@ -1222,6 +1255,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||||||
}
|
}
|
||||||
#endif /* ETHARP_VLAN_CHECK */
|
#endif /* ETHARP_VLAN_CHECK */
|
||||||
type = vlan->tpid;
|
type = vlan->tpid;
|
||||||
|
ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
|
||||||
}
|
}
|
||||||
#endif /* ETHARP_SUPPORT_VLAN */
|
#endif /* ETHARP_SUPPORT_VLAN */
|
||||||
|
|
||||||
@@ -1241,7 +1275,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||||||
etharp_ip_input(netif, p);
|
etharp_ip_input(netif, p);
|
||||||
#endif /* ETHARP_TRUST_IP_MAC */
|
#endif /* ETHARP_TRUST_IP_MAC */
|
||||||
/* skip Ethernet header */
|
/* skip Ethernet header */
|
||||||
if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
|
if(pbuf_header(p, -ip_hdr_offset)) {
|
||||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||||
goto free_and_return;
|
goto free_and_return;
|
||||||
} else {
|
} else {
|
||||||
@@ -1268,6 +1302,19 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||||||
break;
|
break;
|
||||||
#endif /* PPPOE_SUPPORT */
|
#endif /* PPPOE_SUPPORT */
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */
|
||||||
|
/* skip Ethernet header */
|
||||||
|
if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
|
||||||
|
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||||
|
goto free_and_return;
|
||||||
|
} else {
|
||||||
|
/* pass to IPv6 layer */
|
||||||
|
ip6_input(p, netif);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ETHARP_STATS_INC(etharp.proterr);
|
ETHARP_STATS_INC(etharp.proterr);
|
||||||
ETHARP_STATS_INC(etharp.drop);
|
ETHARP_STATS_INC(etharp.drop);
|
||||||
|
|||||||
@@ -50,9 +50,9 @@
|
|||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/stats.h"
|
||||||
#include <lwip/stats.h>
|
#include "lwip/snmp.h"
|
||||||
#include <lwip/snmp.h>
|
#include "lwip/ethip6.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
#include "netif/ppp_oe.h"
|
#include "netif/ppp_oe.h"
|
||||||
|
|
||||||
@@ -239,6 +239,7 @@ ethernetif_input(struct netif *netif)
|
|||||||
switch (htons(ethhdr->type)) {
|
switch (htons(ethhdr->type)) {
|
||||||
/* IP or ARP packet? */
|
/* IP or ARP packet? */
|
||||||
case ETHTYPE_IP:
|
case ETHTYPE_IP:
|
||||||
|
case ETHTYPE_IPV6:
|
||||||
case ETHTYPE_ARP:
|
case ETHTYPE_ARP:
|
||||||
#if PPPOE_SUPPORT
|
#if PPPOE_SUPPORT
|
||||||
/* PPPoE packet? */
|
/* PPPoE packet? */
|
||||||
@@ -305,6 +306,9 @@ ethernetif_init(struct netif *netif)
|
|||||||
* from it if you have to do some checks before sending (e.g. if link
|
* from it if you have to do some checks before sending (e.g. if link
|
||||||
* is available...) */
|
* is available...) */
|
||||||
netif->output = etharp_output;
|
netif->output = etharp_output;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
netif->output_ip6 = ethip6_output;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
netif->linkoutput = low_level_output;
|
netif->linkoutput = low_level_output;
|
||||||
|
|
||||||
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ upap_timeout(void *arg)
|
|||||||
u->us_unit, u->us_timeouttime, u->us_clientstate));
|
u->us_unit, u->us_timeouttime, u->us_clientstate));
|
||||||
|
|
||||||
if (u->us_clientstate != UPAPCS_AUTHREQ) {
|
if (u->us_clientstate != UPAPCS_AUTHREQ) {
|
||||||
UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n"));
|
UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,9 @@ static void
|
|||||||
pppRecvWakeup(int pd)
|
pppRecvWakeup(int pd)
|
||||||
{
|
{
|
||||||
PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
|
PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
|
||||||
sio_read_abort(pppControl[pd].fd);
|
if (pppControl[pd].openFlag != 0) {
|
||||||
|
sio_read_abort(pppControl[pd].fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* PPPOS_SUPPORT */
|
#endif /* PPPOS_SUPPORT */
|
||||||
|
|
||||||
@@ -363,7 +365,6 @@ pppLinkTerminated(int pd)
|
|||||||
PPPControl* pc;
|
PPPControl* pc;
|
||||||
pppRecvWakeup(pd);
|
pppRecvWakeup(pd);
|
||||||
pc = &pppControl[pd];
|
pc = &pppControl[pd];
|
||||||
pppDrop(&pc->rx); /* bug fix #17726 */
|
|
||||||
|
|
||||||
PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
|
PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
|
||||||
if (pc->linkStatusCB) {
|
if (pc->linkStatusCB) {
|
||||||
@@ -439,7 +440,7 @@ pppInit(void)
|
|||||||
|
|
||||||
magicInit();
|
magicInit();
|
||||||
|
|
||||||
subnetMask = PP_HTONL(0xffffff00);
|
subnetMask = PP_HTONL(0xffffff00UL);
|
||||||
|
|
||||||
for (i = 0; i < NUM_PPP; i++) {
|
for (i = 0; i < NUM_PPP; i++) {
|
||||||
/* Initialize each protocol to the standard option set. */
|
/* Initialize each protocol to the standard option set. */
|
||||||
@@ -681,20 +682,8 @@ pppClose(int pd)
|
|||||||
void
|
void
|
||||||
pppSigHUP(int pd)
|
pppSigHUP(int pd)
|
||||||
{
|
{
|
||||||
#if PPPOE_SUPPORT
|
PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
|
||||||
PPPControl *pc = &pppControl[pd];
|
pppHup(pd);
|
||||||
if(pc->ethif) {
|
|
||||||
PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
|
|
||||||
pppHup(pd);
|
|
||||||
} else
|
|
||||||
#endif /* PPPOE_SUPPORT */
|
|
||||||
{
|
|
||||||
#if PPPOS_SUPPORT
|
|
||||||
PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
|
|
||||||
pppHup(pd);
|
|
||||||
pppRecvWakeup(pd);
|
|
||||||
#endif /* PPPOS_SUPPORT */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PPPOS_SUPPORT
|
#if PPPOS_SUPPORT
|
||||||
@@ -1704,8 +1693,8 @@ pppInput(void *arg)
|
|||||||
}
|
}
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
protocol = htons(protocol);
|
protocol = htons(protocol);
|
||||||
SMEMCPY(nb->payload, &protocol, sizeof(protocol));
|
|
||||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||||
|
SMEMCPY(nb->payload, &protocol, sizeof(protocol));
|
||||||
lcp_sprotrej(pd, nb->payload, nb->len);
|
lcp_sprotrej(pd, nb->payload, nb->len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1809,6 +1798,7 @@ pppInProc(PPPControlRx *pcrx, u_char *s, int l)
|
|||||||
pppDrop(pcrx);
|
pppDrop(pcrx);
|
||||||
/* Otherwise it's a good packet so pass it on. */
|
/* Otherwise it's a good packet so pass it on. */
|
||||||
} else {
|
} else {
|
||||||
|
struct pbuf *inp;
|
||||||
/* Trim off the checksum. */
|
/* Trim off the checksum. */
|
||||||
if(pcrx->inTail->len >= 2) {
|
if(pcrx->inTail->len >= 2) {
|
||||||
pcrx->inTail->len -= 2;
|
pcrx->inTail->len -= 2;
|
||||||
@@ -1827,18 +1817,20 @@ pppInProc(PPPControlRx *pcrx, u_char *s, int l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatch the packet thereby consuming it. */
|
/* Dispatch the packet thereby consuming it. */
|
||||||
|
inp = pcrx->inHead;
|
||||||
|
/* Packet consumed, release our references. */
|
||||||
|
pcrx->inHead = NULL;
|
||||||
|
pcrx->inTail = NULL;
|
||||||
#if PPP_INPROC_MULTITHREADED
|
#if PPP_INPROC_MULTITHREADED
|
||||||
if(tcpip_callback_with_block(pppInput, pcrx->inHead, 0) != ERR_OK) {
|
if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) {
|
||||||
PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
|
PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
|
||||||
pbuf_free(pcrx->inHead);
|
pbuf_free(inp);
|
||||||
LINK_STATS_INC(link.drop);
|
LINK_STATS_INC(link.drop);
|
||||||
snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
|
snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
|
||||||
}
|
}
|
||||||
#else /* PPP_INPROC_MULTITHREADED */
|
#else /* PPP_INPROC_MULTITHREADED */
|
||||||
pppInput(pcrx->inHead);
|
pppInput(inp);
|
||||||
#endif /* PPP_INPROC_MULTITHREADED */
|
#endif /* PPP_INPROC_MULTITHREADED */
|
||||||
pcrx->inHead = NULL;
|
|
||||||
pcrx->inTail = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for a new packet. */
|
/* Prepare for a new packet. */
|
||||||
@@ -1912,10 +1904,12 @@ pppInProc(PPPControlRx *pcrx, u_char *s, int l)
|
|||||||
case PDDATA: /* Process data byte. */
|
case PDDATA: /* Process data byte. */
|
||||||
/* Make space to receive processed data. */
|
/* Make space to receive processed data. */
|
||||||
if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
|
if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
|
||||||
if(pcrx->inTail) {
|
if (pcrx->inTail != NULL) {
|
||||||
pcrx->inTail->tot_len = pcrx->inTail->len;
|
pcrx->inTail->tot_len = pcrx->inTail->len;
|
||||||
if (pcrx->inTail != pcrx->inHead) {
|
if (pcrx->inTail != pcrx->inHead) {
|
||||||
pbuf_cat(pcrx->inHead, pcrx->inTail);
|
pbuf_cat(pcrx->inHead, pcrx->inTail);
|
||||||
|
/* give up the inTail reference now */
|
||||||
|
pcrx->inTail = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If we haven't started a packet, we need a packet header. */
|
/* If we haven't started a packet, we need a packet header. */
|
||||||
|
|||||||
@@ -49,10 +49,12 @@
|
|||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
#include "lwip/sio.h"
|
#include "lwip/sio.h"
|
||||||
|
#if !NO_SYS
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SLIP_BLOCK 1
|
#define SLIP_BLOCK 1
|
||||||
#define SLIP_DONTBLOCK 0
|
#define SLIP_DONTBLOCK 0
|
||||||
@@ -335,9 +337,11 @@ slipif_init(struct netif *netif)
|
|||||||
*/
|
*/
|
||||||
NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
|
NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
|
||||||
|
|
||||||
|
#if !NO_SYS
|
||||||
/* Create a thread to poll the serial line. */
|
/* Create a thread to poll the serial line. */
|
||||||
sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif,
|
sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif,
|
||||||
SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
|
SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
|
||||||
|
#endif
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ create_arp_response(ip_addr_t *adr)
|
|||||||
|
|
||||||
etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1);
|
etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1);
|
||||||
etharphdr->proto = htons(ETHTYPE_IP);
|
etharphdr->proto = htons(ETHTYPE_IP);
|
||||||
etharphdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t));
|
etharphdr->hwlen = ETHARP_HWADDR_LEN;
|
||||||
|
etharphdr->protolen = sizeof(ip_addr_t);
|
||||||
etharphdr->opcode = htons(ARP_REPLY);
|
etharphdr->opcode = htons(ARP_REPLY);
|
||||||
|
|
||||||
SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip_addr_t));
|
SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip_addr_t));
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t se
|
|||||||
u32_t ackno_offset, u8_t headerflags)
|
u32_t ackno_offset, u8_t headerflags)
|
||||||
{
|
{
|
||||||
return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
|
return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
|
||||||
data, data_len, pcb->rcv_nxt + seqno_offset, pcb->snd_nxt + ackno_offset, headerflags);
|
data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a TCP segment usable for passing to tcp_input */
|
/** Create a TCP segment usable for passing to tcp_input */
|
||||||
@@ -88,7 +88,8 @@ tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
|
|||||||
memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
|
memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest),
|
|
||||||
|
tcphdr->chksum = inet_chksum_pseudo(p, src_ip, dst_ip,
|
||||||
IP_PROTO_TCP, p->tot_len);
|
IP_PROTO_TCP, p->tot_len);
|
||||||
|
|
||||||
pbuf_header(p, sizeof(struct ip_hdr));
|
pbuf_header(p, sizeof(struct ip_hdr));
|
||||||
@@ -190,6 +191,59 @@ test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
|
|||||||
tcp_arg(pcb, counters);
|
tcp_arg(pcb, counters);
|
||||||
tcp_recv(pcb, test_tcp_counters_recv);
|
tcp_recv(pcb, test_tcp_counters_recv);
|
||||||
tcp_err(pcb, test_tcp_counters_err);
|
tcp_err(pcb, test_tcp_counters_err);
|
||||||
|
pcb->snd_wnd = TCP_WND;
|
||||||
}
|
}
|
||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Calls tcp_input() after adjusting current_iphdr_dest */
|
||||||
|
void test_tcp_input(struct pbuf *p, struct netif *inp)
|
||||||
|
{
|
||||||
|
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
|
||||||
|
ip_addr_copy(current_iphdr_dest, iphdr->dest);
|
||||||
|
ip_addr_copy(current_iphdr_src, iphdr->src);
|
||||||
|
current_netif = inp;
|
||||||
|
current_header = iphdr;
|
||||||
|
|
||||||
|
tcp_input(p, inp);
|
||||||
|
|
||||||
|
current_iphdr_dest.addr = 0;
|
||||||
|
current_iphdr_src.addr = 0;
|
||||||
|
current_netif = NULL;
|
||||||
|
current_header = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p,
|
||||||
|
ip_addr_t *ipaddr)
|
||||||
|
{
|
||||||
|
struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state;
|
||||||
|
LWIP_UNUSED_ARG(ipaddr);
|
||||||
|
txcounters->num_tx_calls++;
|
||||||
|
txcounters->num_tx_bytes += p->tot_len;
|
||||||
|
/*if (txcounters->tx_packets == NULL) {
|
||||||
|
txcounters->tx_packets = p;
|
||||||
|
} else {
|
||||||
|
pbuf_cat(txcounters->tx_packets, p);
|
||||||
|
}*/
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters,
|
||||||
|
ip_addr_t *ip_addr, ip_addr_t *netmask)
|
||||||
|
{
|
||||||
|
struct netif *n;
|
||||||
|
memset(netif, 0, sizeof(struct netif));
|
||||||
|
memset(txcounters, 0, sizeof(struct test_tcp_txcounters));
|
||||||
|
netif->output = test_tcp_netif_output;
|
||||||
|
netif->state = txcounters;
|
||||||
|
netif->flags |= NETIF_FLAG_UP;
|
||||||
|
ip_addr_copy(netif->netmask, *netmask);
|
||||||
|
ip_addr_copy(netif->ip_addr, *ip_addr);
|
||||||
|
for (n = netif_list; n != NULL; n = n->next) {
|
||||||
|
if (n == netif) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netif->next = NULL;
|
||||||
|
netif_list = netif;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "../lwip_check.h"
|
#include "../lwip_check.h"
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
/* counters used for test_tcp_counters_* callback functions */
|
/* counters used for test_tcp_counters_* callback functions */
|
||||||
struct test_tcp_counters {
|
struct test_tcp_counters {
|
||||||
@@ -18,6 +19,11 @@ struct test_tcp_counters {
|
|||||||
u32_t expected_data_len;
|
u32_t expected_data_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct test_tcp_txcounters {
|
||||||
|
u32_t num_tx_calls;
|
||||||
|
u32_t num_tx_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
/* Helper functions */
|
/* Helper functions */
|
||||||
void tcp_remove_all(void);
|
void tcp_remove_all(void);
|
||||||
|
|
||||||
@@ -33,4 +39,10 @@ err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err
|
|||||||
|
|
||||||
struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
|
struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
|
||||||
|
|
||||||
|
void test_tcp_input(struct pbuf *p, struct netif *inp);
|
||||||
|
|
||||||
|
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters,
|
||||||
|
ip_addr_t *ip_addr, ip_addr_t *netmask);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ tcp_setup(void)
|
|||||||
static void
|
static void
|
||||||
tcp_teardown(void)
|
tcp_teardown(void)
|
||||||
{
|
{
|
||||||
|
netif_list = NULL;
|
||||||
tcp_remove_all();
|
tcp_remove_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ START_TEST(test_tcp_recv_inseq)
|
|||||||
EXPECT(p != NULL);
|
EXPECT(p != NULL);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p, &netif);
|
test_tcp_input(p, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 1);
|
EXPECT(counters.recv_calls == 1);
|
||||||
@@ -91,6 +92,179 @@ START_TEST(test_tcp_recv_inseq)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
|
||||||
|
* At the end, send more data. */
|
||||||
|
START_TEST(test_tcp_fast_retx_recover)
|
||||||
|
{
|
||||||
|
struct netif netif;
|
||||||
|
struct test_tcp_txcounters txcounters;
|
||||||
|
struct test_tcp_counters counters;
|
||||||
|
struct tcp_pcb* pcb;
|
||||||
|
struct pbuf* p;
|
||||||
|
char data1[] = { 1, 2, 3, 4};
|
||||||
|
char data2[] = { 5, 6, 7, 8};
|
||||||
|
char data3[] = { 9, 10, 11, 12};
|
||||||
|
char data4[] = {13, 14, 15, 16};
|
||||||
|
char data5[] = {17, 18, 19, 20};
|
||||||
|
char data6[] = {21, 22, 23, 24};
|
||||||
|
ip_addr_t remote_ip, local_ip, netmask;
|
||||||
|
u16_t remote_port = 0x100, local_port = 0x101;
|
||||||
|
err_t err;
|
||||||
|
LWIP_UNUSED_ARG(_i);
|
||||||
|
|
||||||
|
/* initialize local vars */
|
||||||
|
IP4_ADDR(&local_ip, 192, 168, 1, 1);
|
||||||
|
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
|
||||||
|
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||||
|
test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
|
||||||
|
memset(&counters, 0, sizeof(counters));
|
||||||
|
|
||||||
|
/* create and initialize the pcb */
|
||||||
|
pcb = test_tcp_new_counters_pcb(&counters);
|
||||||
|
EXPECT_RET(pcb != NULL);
|
||||||
|
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
|
||||||
|
pcb->mss = TCP_MSS;
|
||||||
|
/* disable initial congestion window (we don't send a SYN here...) */
|
||||||
|
pcb->cwnd = pcb->snd_wnd;
|
||||||
|
//tcp_nagle_disable(pcb);
|
||||||
|
|
||||||
|
/* send data1 */
|
||||||
|
err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 1);
|
||||||
|
EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
/* "recv" ACK for data1 */
|
||||||
|
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(pcb->unacked == NULL);
|
||||||
|
/* send data2 */
|
||||||
|
err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 1);
|
||||||
|
EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
/* duplicate ACK for data1 (data2 is lost) */
|
||||||
|
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(pcb->dupacks == 1);
|
||||||
|
/* send data3 */
|
||||||
|
err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* nagle enabled, no tx calls */
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(txcounters.num_tx_bytes == 0);
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
/* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
|
||||||
|
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(pcb->dupacks == 2);
|
||||||
|
/* queue data4, don't send it (unsent-oversize is != 0) */
|
||||||
|
err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
|
||||||
|
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
//EXPECT_RET(txcounters.num_tx_calls == 1);
|
||||||
|
EXPECT_RET(pcb->dupacks == 3);
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
// TODO: check expected data?
|
||||||
|
|
||||||
|
/* send data5, not output yet */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
//err = tcp_output(pcb);
|
||||||
|
//EXPECT_RET(err == ERR_OK);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(txcounters.num_tx_bytes == 0);
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
|
||||||
|
i++;
|
||||||
|
}while(err == ERR_OK);
|
||||||
|
EXPECT_RET(err != ERR_OK);
|
||||||
|
}
|
||||||
|
//err = tcp_output(pcb);
|
||||||
|
//EXPECT_RET(err == ERR_OK);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
EXPECT_RET(txcounters.num_tx_bytes == 0);
|
||||||
|
memset(&txcounters, 0, sizeof(txcounters));
|
||||||
|
|
||||||
|
/* send even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* ...and even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* ...and even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* ...and even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
|
||||||
|
/* send ACKs for data2 and data3 */
|
||||||
|
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||||
|
|
||||||
|
/* ...and even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
/* ...and even more data */
|
||||||
|
err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
err = tcp_output(pcb);
|
||||||
|
EXPECT_RET(err == ERR_OK);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* create expected segment */
|
||||||
|
p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
|
||||||
|
EXPECT_RET(p != NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
/* pass the segment to tcp_input */
|
||||||
|
test_tcp_input(p, &netif);
|
||||||
|
/* check if counters are as expected */
|
||||||
|
EXPECT_RET(counters.close_calls == 0);
|
||||||
|
EXPECT_RET(counters.recv_calls == 1);
|
||||||
|
EXPECT_RET(counters.recved_bytes == data_len);
|
||||||
|
EXPECT_RET(counters.err_calls == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* make sure the pcb is freed */
|
||||||
|
EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
|
||||||
|
tcp_abort(pcb);
|
||||||
|
EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
/** Create the suite including all tests for this module */
|
/** Create the suite including all tests for this module */
|
||||||
Suite *
|
Suite *
|
||||||
@@ -99,6 +273,7 @@ tcp_suite(void)
|
|||||||
TFun tests[] = {
|
TFun tests[] = {
|
||||||
test_tcp_new_abort,
|
test_tcp_new_abort,
|
||||||
test_tcp_recv_inseq,
|
test_tcp_recv_inseq,
|
||||||
|
test_tcp_fast_retx_recover,
|
||||||
};
|
};
|
||||||
return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
|
return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT(p_fin != NULL);
|
EXPECT(p_fin != NULL);
|
||||||
if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
|
if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_8_9, &netif);
|
test_tcp_input(p_8_9, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -192,7 +192,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_4_8, &netif);
|
test_tcp_input(p_4_8, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -206,7 +206,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_4_10, &netif);
|
test_tcp_input(p_4_10, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -220,7 +220,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_2_14, &netif);
|
test_tcp_input(p_2_14, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -232,7 +232,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_fin, &netif);
|
test_tcp_input(p_fin, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -244,7 +244,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(pinseq, &netif);
|
test_tcp_input(pinseq, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 1);
|
EXPECT(counters.close_calls == 1);
|
||||||
EXPECT(counters.recv_calls == 1);
|
EXPECT(counters.recv_calls == 1);
|
||||||
@@ -330,7 +330,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
|
if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
|
||||||
&& (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
|
&& (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_1_2, &netif);
|
test_tcp_input(p_1_2, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -342,7 +342,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_4_8, &netif);
|
test_tcp_input(p_4_8, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -356,7 +356,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_3_11, &netif);
|
test_tcp_input(p_3_11, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -371,7 +371,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_2_12, &netif);
|
test_tcp_input(p_2_12, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -385,7 +385,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(pinseq, &netif);
|
test_tcp_input(pinseq, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 1);
|
EXPECT(counters.recv_calls == 1);
|
||||||
@@ -394,7 +394,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT(pcb->ooseq == NULL);
|
EXPECT(pcb->ooseq == NULL);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_15_1, &netif);
|
test_tcp_input(p_15_1, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 1);
|
EXPECT(counters.recv_calls == 1);
|
||||||
@@ -406,7 +406,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_15_1a, &netif);
|
test_tcp_input(p_15_1a, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 1);
|
EXPECT(counters.recv_calls == 1);
|
||||||
@@ -418,7 +418,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
|||||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
||||||
|
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(pinseqFIN, &netif);
|
test_tcp_input(pinseqFIN, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 1);
|
EXPECT(counters.close_calls == 1);
|
||||||
EXPECT(counters.recv_calls == 2);
|
EXPECT(counters.recv_calls == 2);
|
||||||
@@ -480,7 +480,7 @@ START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
|
|||||||
TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
|
TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
|
||||||
EXPECT(p != NULL);
|
EXPECT(p != NULL);
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p, &netif);
|
test_tcp_input(p, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -504,7 +504,7 @@ START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
|
|||||||
p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
|
p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
|
||||||
EXPECT(p_ovr != NULL);
|
EXPECT(p_ovr != NULL);
|
||||||
/* pass the segment to tcp_input */
|
/* pass the segment to tcp_input */
|
||||||
tcp_input(p_ovr, &netif);
|
test_tcp_input(p_ovr, &netif);
|
||||||
/* check if counters are as expected */
|
/* check if counters are as expected */
|
||||||
EXPECT(counters.close_calls == 0);
|
EXPECT(counters.close_calls == 0);
|
||||||
EXPECT(counters.recv_calls == 0);
|
EXPECT(counters.recv_calls == 0);
|
||||||
@@ -516,7 +516,7 @@ START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
|
|||||||
EXPECT_OOSEQ(datalen == datalen2);
|
EXPECT_OOSEQ(datalen == datalen2);
|
||||||
|
|
||||||
/* now pass inseq */
|
/* now pass inseq */
|
||||||
tcp_input(pinseq, &netif);
|
test_tcp_input(pinseq, &netif);
|
||||||
EXPECT(pcb->ooseq == NULL);
|
EXPECT(pcb->ooseq == NULL);
|
||||||
|
|
||||||
/* make sure the pcb is freed */
|
/* make sure the pcb is freed */
|
||||||
|
|||||||
Reference in New Issue
Block a user