mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-09-29 07:10:54 +00:00
Merge branch 'master' into STABLE-2_0_0
# Conflicts: # src/include/lwip/init.h
This commit is contained in:
commit
1a2a9a4e96
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
|
*.o
|
||||||
|
*.a
|
||||||
/doc/doxygen/output/html
|
/doc/doxygen/output/html
|
||||||
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
|
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/bin/
|
||||||
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
|
/src/apps/snmp/LwipMibCompiler/CCodeGeneration/obj/
|
||||||
@ -11,3 +13,6 @@
|
|||||||
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
|
/src/apps/snmp/LwipMibCompiler/SharpSnmpLib/obj/
|
||||||
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
|
/src/apps/snmp/LwipMibCompiler/LwipMibCompiler.userprefs
|
||||||
/src/apps/snmp/LwipMibCompiler/*.suo
|
/src/apps/snmp/LwipMibCompiler/*.suo
|
||||||
|
/test/fuzz/output
|
||||||
|
/test/fuzz/lwip_fuzz
|
||||||
|
/test/fuzz/.depend
|
||||||
|
68
CHANGELOG
68
CHANGELOG
@ -6,6 +6,74 @@ HISTORY
|
|||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
|
||||||
|
2016-12-31: Simon Goldschmidt
|
||||||
|
* tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error
|
||||||
|
reason when listening fails (bug #49861)
|
||||||
|
|
||||||
|
2016-12-14: Jan Breuer:
|
||||||
|
* opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106)
|
||||||
|
|
||||||
|
2016-12-14: David van Moolenbroek
|
||||||
|
* opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW()
|
||||||
|
|
||||||
|
2016-12-09: Dirk Ziegelmeier
|
||||||
|
* ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
|
|
||||||
|
2016-12-09: Simon Goldschmidt
|
||||||
|
* dns.c: added one-shot multicast DNS queries
|
||||||
|
|
||||||
|
2016-11-24: Ambroz Bizjak, David van Moolenbroek
|
||||||
|
* tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290)
|
||||||
|
|
||||||
|
2016-11-16: Dirk Ziegelmeier
|
||||||
|
* sockets.c: added support for IPv6 mapped IPv4 addresses
|
||||||
|
|
||||||
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2016-12-16: Thomas Mueller
|
||||||
|
* api_lib.c: fixed race condition in return value of netconn_gethostbyname()
|
||||||
|
(and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo())
|
||||||
|
|
||||||
|
2016-12-15: David van Moolenbroek
|
||||||
|
* opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial
|
||||||
|
sequence numbers (see contrib/addons/tcp_isn for an example implementation)
|
||||||
|
|
||||||
|
2016-12-05: Dirk Ziegelmeier
|
||||||
|
* fixed compiling with IPv4 disabled (IPv6 only case)
|
||||||
|
|
||||||
|
2016-11-28: Simon Goldschmidt
|
||||||
|
* api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return
|
||||||
|
ERR_OK without all bytes being written)
|
||||||
|
|
||||||
|
2016-11-28: Ambroz Bizjak
|
||||||
|
* tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK
|
||||||
|
assumed scaled)
|
||||||
|
|
||||||
|
2016-11-25: Simon Goldschmidt
|
||||||
|
* dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options)
|
||||||
|
|
||||||
|
2016-11-23: Dirk Ziegelmeier
|
||||||
|
* udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB
|
||||||
|
(and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY
|
||||||
|
|
||||||
|
2016-11-16: Dirk Ziegelmeier
|
||||||
|
* *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API
|
||||||
|
|
||||||
|
2016-11-14: Joel Cunningham
|
||||||
|
* tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit
|
||||||
|
in window)
|
||||||
|
|
||||||
|
2016-11-16: Roberto Barbieri Carrera
|
||||||
|
* autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address)
|
||||||
|
|
||||||
|
2016-11-11: Dirk Ziegelmeier
|
||||||
|
* sockets.c: fixed bug #49578 (dropping multicast membership does not work
|
||||||
|
with LWIP_SOCKET_OFFSET)
|
||||||
|
|
||||||
|
(STABLE-2.0.0)
|
||||||
|
|
||||||
|
++ New features:
|
||||||
|
|
||||||
2016-07-27: Simon Goldschmidt
|
2016-07-27: Simon Goldschmidt
|
||||||
* opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default
|
* opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default
|
||||||
implementation of timeouts
|
implementation of timeouts
|
||||||
|
@ -8,7 +8,12 @@ with newer versions.
|
|||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
* TODO
|
++ Application changes:
|
||||||
|
|
||||||
|
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
|
||||||
|
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
|
||||||
|
ip_current_netif() to the desired netif for every packet.
|
||||||
|
See bug #49662 for an explanation.
|
||||||
|
|
||||||
(2.0.0)
|
(2.0.0)
|
||||||
|
|
||||||
|
@ -1 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
doxygen lwip.Doxyfile
|
doxygen lwip.Doxyfile
|
||||||
|
@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
|
|||||||
# title of most generated pages and in a few other places.
|
# title of most generated pages and in a few other places.
|
||||||
# The default value is: My Project.
|
# The default value is: My Project.
|
||||||
|
|
||||||
PROJECT_NAME = "lwIP 2.0.0"
|
PROJECT_NAME = "lwIP"
|
||||||
|
|
||||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = "lwIP 2.0.0"
|
PROJECT_NUMBER = "2.0.1"
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
# quick idea about the purpose of the project. Keep the description short.
|
# quick idea about the purpose of the project. Keep the description short.
|
||||||
|
|
||||||
PROJECT_BRIEF = Lightweight IP stack
|
PROJECT_BRIEF = "Lightweight IP stack"
|
||||||
|
|
||||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||||
# in the documentation. The maximum height of the logo should not exceed 55
|
# in the documentation. The maximum height of the logo should not exceed 55
|
||||||
|
@ -103,7 +103,8 @@
|
|||||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
||||||
* context and put them into a queue which is processed from mainloop.\n
|
* context and put them into a queue which is processed from mainloop.\n
|
||||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
* Call sys_check_timeouts() periodically in the mainloop.\n
|
||||||
* Porting: implement all functions in @ref sys_time and @ref sys_prot.\n
|
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
|
||||||
|
* @ref compiler_abstraction.\n
|
||||||
* You can only use @ref callbackstyle_api in this mode.\n
|
* You can only use @ref callbackstyle_api in this mode.\n
|
||||||
* Sample code:\n
|
* Sample code:\n
|
||||||
* @include NO_SYS_SampleCode.c
|
* @include NO_SYS_SampleCode.c
|
||||||
|
162
doc/mqtt_client.txt
Normal file
162
doc/mqtt_client.txt
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
MQTT client for lwIP
|
||||||
|
|
||||||
|
Author: Erik Andersson
|
||||||
|
|
||||||
|
Details of the MQTT protocol can be found at:
|
||||||
|
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
1. Initial steps, reserve memory and make connection to server:
|
||||||
|
|
||||||
|
1.1: Provide storage
|
||||||
|
|
||||||
|
Static allocation:
|
||||||
|
mqtt_client_t static_client;
|
||||||
|
example_do_connect(&static_client);
|
||||||
|
|
||||||
|
Dynamic allocation:
|
||||||
|
mqtt_client_t *client = mqtt_client_new();
|
||||||
|
if(client != NULL) {
|
||||||
|
example_do_connect(&client);
|
||||||
|
}
|
||||||
|
|
||||||
|
1.2: Establish Connection with server
|
||||||
|
|
||||||
|
void example_do_connect(mqtt_client_t *client)
|
||||||
|
{
|
||||||
|
struct mqtt_connect_client_info_t ci;
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
/* Setup an empty client info structure */
|
||||||
|
memset(&ci, 0, sizeof(ci));
|
||||||
|
|
||||||
|
/* Minimal amount of information required is client identifier, so set it here */
|
||||||
|
ci.client_id = "lwip_test";
|
||||||
|
|
||||||
|
/* Initiate client and connect to server, if this fails immediately an error code is returned
|
||||||
|
otherwise mqtt_connection_cb will be called with connection result after attempting
|
||||||
|
to establish a connection with the server.
|
||||||
|
For now MQTT version 3.1.1 is always used */
|
||||||
|
|
||||||
|
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
|
||||||
|
|
||||||
|
/* For now just print the result code if something goes wrong
|
||||||
|
if(err != ERR_OK) {
|
||||||
|
printf("mqtt_connect return %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection to server can also be probed by calling mqtt_client_is_connected(client)
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
2. Implementing the connection status callback
|
||||||
|
|
||||||
|
|
||||||
|
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
if(status == MQTT_CONNECT_ACCEPTED) {
|
||||||
|
printf("mqtt_connection_cb: Successfully connected\n");
|
||||||
|
|
||||||
|
/* Setup callback for incoming publish requests */
|
||||||
|
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
|
||||||
|
|
||||||
|
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
|
||||||
|
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
|
||||||
|
|
||||||
|
if(err != ERR_OK) {
|
||||||
|
printf("mqtt_subscribe return: %d\n", err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
|
||||||
|
|
||||||
|
/* Its more nice to be connected, so try to reconnect */
|
||||||
|
example_do_connect(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_sub_request_cb(void *arg, err_t result)
|
||||||
|
{
|
||||||
|
/* Just print the result code here for simplicity,
|
||||||
|
normal behaviour would be to take some action if subscribe fails like
|
||||||
|
notifying user, retry subscribe or disconnect from server */
|
||||||
|
printf("Subscribe result: %d\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
3. Implementing callbacks for incoming publish and data
|
||||||
|
|
||||||
|
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
|
||||||
|
Example here uses a global variable, better would be to use a member in arg
|
||||||
|
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
|
||||||
|
the topic string and use it in mqtt_incoming_data_cb
|
||||||
|
*/
|
||||||
|
static int inpub_id;
|
||||||
|
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
|
||||||
|
{
|
||||||
|
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
|
||||||
|
|
||||||
|
/* Decode topic string into a user defined reference */
|
||||||
|
if(strcmp(topic, "print_payload") == 0) {
|
||||||
|
inpub_id = 0;
|
||||||
|
} else if(topic[0] == 'A') {
|
||||||
|
/* All topics starting with 'A' might be handled at the same way */
|
||||||
|
inpub_id = 1;
|
||||||
|
} else {
|
||||||
|
/* For all other topics */
|
||||||
|
inpub_id = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
|
||||||
|
{
|
||||||
|
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
|
||||||
|
|
||||||
|
if(flags & MQTT_DATA_FLAG_LAST) {
|
||||||
|
/* Last fragment of payload received (or whole part if payload fits receive buffer
|
||||||
|
See MQTT_VAR_HEADER_BUFFER_LEN) */
|
||||||
|
|
||||||
|
/* Call function or do action depending on reference, in this case inpub_id */
|
||||||
|
if(inpub_id == 0) {
|
||||||
|
/* Don't trust the publisher, check zero termination */
|
||||||
|
if(data[len-1] == 0) {
|
||||||
|
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
|
||||||
|
}
|
||||||
|
} else if(inpub_id == 1) {
|
||||||
|
/* Call an 'A' function... */
|
||||||
|
} else {
|
||||||
|
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Handle fragmented payload, store in buffer, write to file or whatever */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
4. Using outgoing publish
|
||||||
|
|
||||||
|
|
||||||
|
void example_publish(mqtt_client_t *client, void *arg)
|
||||||
|
{
|
||||||
|
const char *pub_payload= "PubSubHubLubJub";
|
||||||
|
err_t err;
|
||||||
|
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
|
||||||
|
u8_t retain = 0; /* No don't retain such crappy payload... */
|
||||||
|
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
|
||||||
|
if(err != ERR_OK) {
|
||||||
|
printf("Publish err: %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when publish is complete either with sucess or failure */
|
||||||
|
static void mqtt_pub_request_cb(void *arg, err_t result)
|
||||||
|
{
|
||||||
|
if(result != ERR_OK) {
|
||||||
|
printf("Publish result: %d\n", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
5. Disconnecting
|
||||||
|
|
||||||
|
Simply call mqtt_disconnect(client)
|
@ -29,7 +29,7 @@ in a mailbox is just a pointer, nothing more.
|
|||||||
|
|
||||||
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
||||||
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
||||||
type "sys_mbox_t". Mutexes are represented ny the type "sys_mutex_t".
|
type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t".
|
||||||
lwIP does not place any restrictions on how these types are represented
|
lwIP does not place any restrictions on how these types are represented
|
||||||
internally.
|
internally.
|
||||||
|
|
||||||
|
@ -167,6 +167,9 @@ NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c
|
|||||||
# TFTPFILES: TFTP server files
|
# TFTPFILES: TFTP server files
|
||||||
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
|
TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c
|
||||||
|
|
||||||
|
# MQTTFILES: MQTT client files
|
||||||
|
MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c
|
||||||
|
|
||||||
# LWIPAPPFILES: All LWIP APPs
|
# LWIPAPPFILES: All LWIP APPs
|
||||||
LWIPAPPFILES=$(SNMPFILES) \
|
LWIPAPPFILES=$(SNMPFILES) \
|
||||||
$(HTTPDFILES) \
|
$(HTTPDFILES) \
|
||||||
@ -174,4 +177,5 @@ LWIPAPPFILES=$(SNMPFILES) \
|
|||||||
$(SNTPFILES) \
|
$(SNTPFILES) \
|
||||||
$(MDNSFILES) \
|
$(MDNSFILES) \
|
||||||
$(NETBIOSNSFILES) \
|
$(NETBIOSNSFILES) \
|
||||||
$(TFTPFILES)
|
$(TFTPFILES) \
|
||||||
|
$(MQTTFILES)
|
||||||
|
@ -254,10 +254,22 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|||||||
|
|
||||||
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
addr = IP4_ADDR_ANY;
|
addr = IP4_ADDR_ANY;
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
|
||||||
|
* and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind
|
||||||
|
*/
|
||||||
|
if ((netconn_get_ipv6only(conn) == 0) &&
|
||||||
|
ip_addr_cmp(addr, IP6_ADDR_ANY)) {
|
||||||
|
addr = IP_ANY_TYPE;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
API_MSG_VAR_ALLOC(msg);
|
||||||
API_MSG_VAR_REF(msg).conn = conn;
|
API_MSG_VAR_REF(msg).conn = conn;
|
||||||
@ -286,10 +298,12 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
|
|||||||
|
|
||||||
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
addr = IP4_ADDR_ANY;
|
addr = IP4_ADDR_ANY;
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
API_MSG_VAR_ALLOC(msg);
|
||||||
API_MSG_VAR_REF(msg).conn = conn;
|
API_MSG_VAR_REF(msg).conn = conn;
|
||||||
@ -376,7 +390,6 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
void *accept_ptr;
|
void *accept_ptr;
|
||||||
struct netconn *newconn;
|
struct netconn *newconn;
|
||||||
err_t err;
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
#if TCP_LISTEN_BACKLOG
|
||||||
API_MSG_VAR_DECLARE(msg);
|
API_MSG_VAR_DECLARE(msg);
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
#endif /* TCP_LISTEN_BACKLOG */
|
||||||
@ -385,11 +398,10 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
|||||||
*new_conn = NULL;
|
*new_conn = NULL;
|
||||||
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||||
|
|
||||||
err = conn->last_err;
|
if (ERR_IS_FATAL(conn->last_err)) {
|
||||||
if (ERR_IS_FATAL(err)) {
|
|
||||||
/* don't recv on fatal errors: this might block the application task
|
/* don't recv on fatal errors: this might block the application task
|
||||||
waiting on acceptmbox forever! */
|
waiting on acceptmbox forever! */
|
||||||
return err;
|
return conn->last_err;
|
||||||
}
|
}
|
||||||
if (!sys_mbox_valid(&conn->acceptmbox)) {
|
if (!sys_mbox_valid(&conn->acceptmbox)) {
|
||||||
return ERR_CLSD;
|
return ERR_CLSD;
|
||||||
@ -465,7 +477,6 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||||||
{
|
{
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
err_t err;
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
API_MSG_VAR_DECLARE(msg);
|
API_MSG_VAR_DECLARE(msg);
|
||||||
#if LWIP_MPU_COMPATIBLE
|
#if LWIP_MPU_COMPATIBLE
|
||||||
@ -489,13 +500,12 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
||||||
|
|
||||||
err = conn->last_err;
|
if (ERR_IS_FATAL(conn->last_err)) {
|
||||||
if (ERR_IS_FATAL(err)) {
|
|
||||||
/* don't recv on fatal errors: this might block the application task
|
/* don't recv on fatal errors: this might block the application task
|
||||||
waiting on recvmbox forever! */
|
waiting on recvmbox forever! */
|
||||||
/* @todo: this does not allow us to fetch data that has been put into recvmbox
|
/* @todo: this does not allow us to fetch data that has been put into recvmbox
|
||||||
before the fatal error occurred - is that a problem? */
|
before the fatal error occurred - is that a problem? */
|
||||||
return err;
|
return conn->last_err;
|
||||||
}
|
}
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
#if (LWIP_UDP || LWIP_RAW)
|
#if (LWIP_UDP || LWIP_RAW)
|
||||||
@ -562,7 +572,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
|||||||
#if (LWIP_UDP || LWIP_RAW)
|
#if (LWIP_UDP || LWIP_RAW)
|
||||||
{
|
{
|
||||||
LWIP_ASSERT("buf != NULL", buf != NULL);
|
LWIP_ASSERT("buf != NULL", buf != NULL);
|
||||||
len = netbuf_len((struct netbuf *)buf);
|
len = netbuf_len((struct netbuf*)buf);
|
||||||
}
|
}
|
||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||||
|
|
||||||
@ -697,6 +707,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
|||||||
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||||
|
|
||||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
|
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
|
||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
API_MSG_VAR_ALLOC(msg);
|
||||||
API_MSG_VAR_REF(msg).conn = conn;
|
API_MSG_VAR_REF(msg).conn = conn;
|
||||||
API_MSG_VAR_REF(msg).msg.b = buf;
|
API_MSG_VAR_REF(msg).msg.b = buf;
|
||||||
@ -734,6 +745,11 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
||||||
|
#if LWIP_SO_SNDTIMEO
|
||||||
|
if (conn->send_timeout != 0) {
|
||||||
|
dontblock = 1;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_SO_SNDTIMEO */
|
||||||
if (dontblock && !bytes_written) {
|
if (dontblock && !bytes_written) {
|
||||||
/* This implies netconn_write() cannot be used for non-blocking send, since
|
/* This implies netconn_write() cannot be used for non-blocking send, since
|
||||||
it has no way to return the number of bytes written. */
|
it has no way to return the number of bytes written. */
|
||||||
@ -761,11 +777,7 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
|||||||
non-blocking version here. */
|
non-blocking version here. */
|
||||||
err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
|
err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
|
||||||
if ((err == ERR_OK) && (bytes_written != NULL)) {
|
if ((err == ERR_OK) && (bytes_written != NULL)) {
|
||||||
if (dontblock
|
if (dontblock) {
|
||||||
#if LWIP_SO_SNDTIMEO
|
|
||||||
|| (conn->send_timeout != 0)
|
|
||||||
#endif /* LWIP_SO_SNDTIMEO */
|
|
||||||
) {
|
|
||||||
/* nonblocking write: maybe the data has been sent partly */
|
/* nonblocking write: maybe the data has been sent partly */
|
||||||
*bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
|
*bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
|
||||||
} else {
|
} else {
|
||||||
@ -869,6 +881,7 @@ netconn_join_leave_group(struct netconn *conn,
|
|||||||
|
|
||||||
API_MSG_VAR_ALLOC(msg);
|
API_MSG_VAR_ALLOC(msg);
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
/* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
|
||||||
if (multiaddr == NULL) {
|
if (multiaddr == NULL) {
|
||||||
multiaddr = IP4_ADDR_ANY;
|
multiaddr = IP4_ADDR_ANY;
|
||||||
@ -876,6 +889,7 @@ netconn_join_leave_group(struct netconn *conn,
|
|||||||
if (netif_addr == NULL) {
|
if (netif_addr == NULL) {
|
||||||
netif_addr = IP4_ADDR_ANY;
|
netif_addr = IP4_ADDR_ANY;
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
API_MSG_VAR_REF(msg).conn = conn;
|
API_MSG_VAR_REF(msg).conn = conn;
|
||||||
API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
|
API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
|
||||||
@ -914,6 +928,7 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
|||||||
sys_sem_t sem;
|
sys_sem_t sem;
|
||||||
#endif /* LWIP_MPU_COMPATIBLE */
|
#endif /* LWIP_MPU_COMPATIBLE */
|
||||||
err_t err;
|
err_t err;
|
||||||
|
err_t cberr;
|
||||||
|
|
||||||
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
|
||||||
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
|
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
|
||||||
@ -946,13 +961,13 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||||
|
|
||||||
err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
|
cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
|
||||||
if (err != ERR_OK) {
|
if (cberr != ERR_OK) {
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
#if !LWIP_NETCONN_SEM_PER_THREAD
|
||||||
sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
|
sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
|
||||||
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
|
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
|
||||||
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
|
API_VAR_FREE(MEMP_DNS_API_MSG, msg);
|
||||||
return err;
|
return cberr;
|
||||||
}
|
}
|
||||||
sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
|
sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
|
||||||
#if !LWIP_NETCONN_SEM_PER_THREAD
|
#if !LWIP_NETCONN_SEM_PER_THREAD
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "lwip/priv/api_msg.h"
|
#include "lwip/priv/api_msg.h"
|
||||||
|
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/raw.h"
|
#include "lwip/raw.h"
|
||||||
@ -544,13 +545,22 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||||||
static void
|
static void
|
||||||
pcb_new(struct api_msg *msg)
|
pcb_new(struct api_msg *msg)
|
||||||
{
|
{
|
||||||
|
enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4;
|
||||||
|
|
||||||
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
|
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
|
||||||
|
|
||||||
|
#if LWIP_IPV6 && LWIP_IPV4
|
||||||
|
/* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */
|
||||||
|
if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) {
|
||||||
|
iptype = IPADDR_TYPE_ANY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Allocate a PCB for this connection */
|
/* Allocate a PCB for this connection */
|
||||||
switch(NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch(NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
#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_ip_type(iptype, msg->msg.n.proto);
|
||||||
if (msg->conn->pcb.raw != NULL) {
|
if (msg->conn->pcb.raw != NULL) {
|
||||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||||
}
|
}
|
||||||
@ -558,7 +568,7 @@ pcb_new(struct api_msg *msg)
|
|||||||
#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_ip_type(iptype);
|
||||||
if (msg->conn->pcb.udp != NULL) {
|
if (msg->conn->pcb.udp != NULL) {
|
||||||
#if LWIP_UDPLITE
|
#if LWIP_UDPLITE
|
||||||
if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
|
if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
|
||||||
@ -574,7 +584,7 @@ pcb_new(struct api_msg *msg)
|
|||||||
#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_ip_type(iptype);
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
setup_tcp(msg->conn);
|
setup_tcp(msg->conn);
|
||||||
}
|
}
|
||||||
@ -588,15 +598,6 @@ pcb_new(struct api_msg *msg)
|
|||||||
if (msg->conn->pcb.ip == NULL) {
|
if (msg->conn->pcb.ip == NULL) {
|
||||||
msg->err = ERR_MEM;
|
msg->err = ERR_MEM;
|
||||||
}
|
}
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
else {
|
|
||||||
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
|
||||||
/* Convert IPv4 PCB manually to an IPv6 PCB */
|
|
||||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
|
|
||||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1113,37 +1114,20 @@ lwip_netconn_do_bind(void *m)
|
|||||||
} else {
|
} else {
|
||||||
msg->err = ERR_VAL;
|
msg->err = ERR_VAL;
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr);
|
|
||||||
|
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
|
||||||
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
|
|
||||||
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
|
|
||||||
*/
|
|
||||||
if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) &&
|
|
||||||
(netconn_get_ipv6only(msg->conn) == 0)) {
|
|
||||||
/* change PCB type to IPADDR_TYPE_ANY */
|
|
||||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
|
|
||||||
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
|
|
||||||
|
|
||||||
/* bind to IPADDR_TYPE_ANY */
|
|
||||||
ipaddr = IP_ANY_TYPE;
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
|
||||||
|
|
||||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
case NETCONN_RAW:
|
case NETCONN_RAW:
|
||||||
msg->err = raw_bind(msg->conn->pcb.raw, ipaddr);
|
msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
#if LWIP_UDP
|
#if LWIP_UDP
|
||||||
case NETCONN_UDP:
|
case NETCONN_UDP:
|
||||||
msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port);
|
msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
case NETCONN_TCP:
|
case NETCONN_TCP:
|
||||||
msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port);
|
msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
|
||||||
break;
|
break;
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
default:
|
default:
|
||||||
@ -1323,6 +1307,13 @@ lwip_netconn_do_listen(void *m)
|
|||||||
/* connection is not closed, cannot listen */
|
/* connection is not closed, cannot listen */
|
||||||
msg->err = ERR_VAL;
|
msg->err = ERR_VAL;
|
||||||
} else {
|
} else {
|
||||||
|
err_t err;
|
||||||
|
u8_t backlog;
|
||||||
|
#if TCP_LISTEN_BACKLOG
|
||||||
|
backlog = msg->msg.lb.backlog;
|
||||||
|
#else /* TCP_LISTEN_BACKLOG */
|
||||||
|
backlog = TCP_DEFAULT_LISTEN_BACKLOG;
|
||||||
|
#endif /* TCP_LISTEN_BACKLOG */
|
||||||
#if LWIP_IPV4 && LWIP_IPV6
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
/* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
|
/* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
|
||||||
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
|
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
|
||||||
@ -1335,15 +1326,11 @@ lwip_netconn_do_listen(void *m)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
#if TCP_LISTEN_BACKLOG
|
lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err);
|
||||||
lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
|
|
||||||
#else /* TCP_LISTEN_BACKLOG */
|
|
||||||
lpcb = tcp_listen(msg->conn->pcb.tcp);
|
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
|
||||||
|
|
||||||
if (lpcb == NULL) {
|
if (lpcb == NULL) {
|
||||||
/* in this case, the old pcb is still allocated */
|
/* in this case, the old pcb is still allocated */
|
||||||
msg->err = ERR_MEM;
|
msg->err = err;
|
||||||
} else {
|
} else {
|
||||||
/* delete the recvmbox and allocate the acceptmbox */
|
/* delete the recvmbox and allocate the acceptmbox */
|
||||||
if (sys_mbox_valid(&msg->conn->recvmbox)) {
|
if (sys_mbox_valid(&msg->conn->recvmbox)) {
|
||||||
@ -1400,7 +1387,7 @@ lwip_netconn_do_send(void *m)
|
|||||||
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 (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(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, &msg->msg.b->addr);
|
||||||
@ -1588,10 +1575,11 @@ err_mem:
|
|||||||
write_finished = 1;
|
write_finished = 1;
|
||||||
conn->current_msg->msg.w.len = 0;
|
conn->current_msg->msg.w.len = 0;
|
||||||
}
|
}
|
||||||
} else if ((err == ERR_MEM) && !dontblock) {
|
} else if (err == ERR_MEM) {
|
||||||
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
|
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called.
|
||||||
we do NOT return to the application thread, since ERR_MEM is
|
For blocking sockets, we do NOT return to the application
|
||||||
only a temporary error! */
|
thread, since ERR_MEM is only a temporary error! Non-blocking
|
||||||
|
will remain non-writable until sent_tcp/poll_tcp is called */
|
||||||
|
|
||||||
/* tcp_write returned ERR_MEM, try tcp_output anyway */
|
/* tcp_write returned ERR_MEM, try tcp_output anyway */
|
||||||
err_t out_err = tcp_output(conn->pcb.tcp);
|
err_t out_err = tcp_output(conn->pcb.tcp);
|
||||||
@ -1602,6 +1590,11 @@ err_mem:
|
|||||||
err = out_err;
|
err = out_err;
|
||||||
write_finished = 1;
|
write_finished = 1;
|
||||||
conn->current_msg->msg.w.len = 0;
|
conn->current_msg->msg.w.len = 0;
|
||||||
|
} else if (dontblock) {
|
||||||
|
/* non-blocking write is done on ERR_MEM */
|
||||||
|
err = ERR_WOULDBLOCK;
|
||||||
|
write_finished = 1;
|
||||||
|
conn->current_msg->msg.w.len = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* On errors != ERR_MEM, we don't try writing any more but return
|
/* On errors != ERR_MEM, we don't try writing any more but return
|
||||||
@ -1710,6 +1703,7 @@ lwip_netconn_do_getaddr(void *m)
|
|||||||
ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
|
ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
|
||||||
msg->conn->pcb.ip->remote_ip);
|
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
|
||||||
|
@ -64,6 +64,15 @@ static const int err_to_errno_table[] = {
|
|||||||
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
|
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
|
||||||
EIO /* ERR_ARG -16 Illegal argument. */
|
EIO /* ERR_ARG -16 Illegal argument. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
err_to_errno(err_t err)
|
||||||
|
{
|
||||||
|
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
|
||||||
|
return EIO;
|
||||||
|
}
|
||||||
|
return err_to_errno_table[-err];
|
||||||
|
}
|
||||||
#endif /* !NO_SYS */
|
#endif /* !NO_SYS */
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
@ -104,14 +113,3 @@ lwip_strerr(err_t err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_DEBUG */
|
#endif /* LWIP_DEBUG */
|
||||||
|
|
||||||
#if !NO_SYS
|
|
||||||
int
|
|
||||||
err_to_errno(err_t err)
|
|
||||||
{
|
|
||||||
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
return err_to_errno_table[-err];
|
|
||||||
}
|
|
||||||
#endif /* !NO_SYS */
|
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
#include "lwip/api.h"
|
#include "lwip/api.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h> /* memset */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h> /* atoi */
|
||||||
|
|
||||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||||
struct gethostbyname_r_helper {
|
struct gethostbyname_r_helper {
|
||||||
@ -382,7 +382,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
|||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
|
struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
|
||||||
/* set up sockaddr */
|
/* set up sockaddr */
|
||||||
inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr));
|
inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr));
|
||||||
sa4->sin_family = AF_INET;
|
sa4->sin_family = AF_INET;
|
||||||
sa4->sin_len = sizeof(struct sockaddr_in);
|
sa4->sin_len = sizeof(struct sockaddr_in);
|
||||||
sa4->sin_port = lwip_htons((u16_t)port_nr);
|
sa4->sin_port = lwip_htons((u16_t)port_nr);
|
||||||
|
@ -82,10 +82,10 @@
|
|||||||
(sin)->sin_len = sizeof(struct sockaddr_in); \
|
(sin)->sin_len = sizeof(struct sockaddr_in); \
|
||||||
(sin)->sin_family = AF_INET; \
|
(sin)->sin_family = AF_INET; \
|
||||||
(sin)->sin_port = lwip_htons((port)); \
|
(sin)->sin_port = lwip_htons((port)); \
|
||||||
inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \
|
inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
|
||||||
memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
|
memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
|
||||||
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
|
#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
|
||||||
inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
|
inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
|
||||||
(port) = lwip_ntohs((sin)->sin_port); }while(0)
|
(port) = lwip_ntohs((sin)->sin_port); }while(0)
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
@ -482,7 +482,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||||||
|
|
||||||
if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
|
if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
|
||||||
sock_set_errno(sock, EWOULDBLOCK);
|
set_errno(EWOULDBLOCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,6 +584,14 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
|||||||
ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
|
ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
|
||||||
|
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||||
|
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&local_addr))) {
|
||||||
|
unmap_ipv6_mapped_ipv4(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
|
||||||
|
IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
err = netconn_bind(sock->conn, &local_addr, local_port);
|
err = netconn_bind(sock->conn, &local_addr, local_port);
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
@ -668,6 +676,14 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
|||||||
ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
|
ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
|
||||||
|
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||||
|
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&remote_addr))) {
|
||||||
|
unmap_ipv6_mapped_ipv4(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
|
||||||
|
IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
err = netconn_connect(sock->conn, &remote_addr, remote_port);
|
err = netconn_connect(sock->conn, &remote_addr, remote_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,7 +771,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
||||||
sock_set_errno(sock, EWOULDBLOCK);
|
set_errno(EWOULDBLOCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,6 +863,15 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
|||||||
port = netbuf_fromport((struct netbuf *)buf);
|
port = netbuf_fromport((struct netbuf *)buf);
|
||||||
fromaddr = netbuf_fromaddr((struct netbuf *)buf);
|
fromaddr = netbuf_fromaddr((struct netbuf *)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */
|
||||||
|
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
|
||||||
|
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
|
||||||
|
IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
|
IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
|
||||||
ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
|
ip_addr_debug_print(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));
|
||||||
@ -1066,6 +1091,14 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
|
|||||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||||
|
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&chain_buf->addr))) {
|
||||||
|
unmap_ipv6_mapped_ipv4(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
|
||||||
|
IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
/* send the data */
|
/* send the data */
|
||||||
err = netconn_send(sock->conn, chain_buf);
|
err = netconn_send(sock->conn, chain_buf);
|
||||||
}
|
}
|
||||||
@ -1107,12 +1140,6 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
#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;
|
||||||
@ -1162,6 +1189,14 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
err = netbuf_ref(&buf, data, short_size);
|
err = netbuf_ref(&buf, data, short_size);
|
||||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||||
|
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&buf.addr))) {
|
||||||
|
unmap_ipv6_mapped_ipv4(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
|
||||||
|
IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
/* send the data */
|
/* send the data */
|
||||||
err = netconn_send(sock->conn, &buf);
|
err = netconn_send(sock->conn, &buf);
|
||||||
}
|
}
|
||||||
@ -1179,9 +1214,7 @@ lwip_socket(int domain, int type, int protocol)
|
|||||||
struct netconn *conn;
|
struct netconn *conn;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#if !LWIP_IPV6
|
|
||||||
LWIP_UNUSED_ARG(domain); /* @todo: check this */
|
LWIP_UNUSED_ARG(domain); /* @todo: check this */
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/* create a netconn */
|
/* create a netconn */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -1244,7 +1277,7 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
|
|||||||
msg.msg_namelen = 0;
|
msg.msg_namelen = 0;
|
||||||
/* Hack: we have to cast via number to cast from 'const' pointer to non-const.
|
/* Hack: we have to cast via number to cast from 'const' pointer to non-const.
|
||||||
Blame the opengroup standard for this inconsistency. */
|
Blame the opengroup standard for this inconsistency. */
|
||||||
msg.msg_iov = (struct iovec *)(size_t)iov;
|
msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov);
|
||||||
msg.msg_iovlen = iovcnt;
|
msg.msg_iovlen = iovcnt;
|
||||||
msg.msg_control = NULL;
|
msg.msg_control = NULL;
|
||||||
msg.msg_controllen = 0;
|
msg.msg_controllen = 0;
|
||||||
@ -1710,12 +1743,21 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the IP address and port */
|
/* get the IP address and port */
|
||||||
/* @todo: this does not work for IPv6, yet */
|
|
||||||
err = netconn_getaddr(sock->conn, &naddr, &port, local);
|
err = netconn_getaddr(sock->conn, &naddr, &port, local);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
sock_set_errno(sock, err_to_errno(err));
|
sock_set_errno(sock, err_to_errno(err));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */
|
||||||
|
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
|
||||||
|
IP_IS_V4_VAL(naddr)) {
|
||||||
|
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
|
||||||
|
IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
|
IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
|
||||||
|
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||||
@ -2001,7 +2043,7 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
|
||||||
return ENOPROTOOPT;
|
return ENOPROTOOPT;
|
||||||
}
|
}
|
||||||
inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
|
inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
|
||||||
s, *(u32_t *)optval));
|
s, *(u32_t *)optval));
|
||||||
break;
|
break;
|
||||||
@ -2029,6 +2071,9 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
/* Special case: all IPPROTO_TCP option take an int */
|
/* Special case: all IPPROTO_TCP option take an int */
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
|
||||||
|
if (sock->conn->pcb.tcp->state == LISTEN) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case TCP_NODELAY:
|
case TCP_NODELAY:
|
||||||
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
|
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
|
||||||
@ -2073,10 +2118,6 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
switch (optname) {
|
switch (optname) {
|
||||||
case IPV6_V6ONLY:
|
case IPV6_V6ONLY:
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
|
||||||
/* @todo: this does not work for datagram sockets, yet */
|
|
||||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
|
||||||
return ENOPROTOOPT;
|
|
||||||
}
|
|
||||||
*(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
|
*(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
|
||||||
s, *(int *)optval));
|
s, *(int *)optval));
|
||||||
@ -2365,7 +2406,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||||||
{
|
{
|
||||||
ip4_addr_t if_addr;
|
ip4_addr_t if_addr;
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
|
||||||
inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval);
|
inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval);
|
||||||
udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
|
udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2389,8 +2430,8 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||||||
ip4_addr_t if_addr;
|
ip4_addr_t if_addr;
|
||||||
ip4_addr_t multi_addr;
|
ip4_addr_t multi_addr;
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
|
||||||
inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
|
inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
|
||||||
inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
|
inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
|
||||||
if (optname == IP_ADD_MEMBERSHIP) {
|
if (optname == IP_ADD_MEMBERSHIP) {
|
||||||
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
|
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
|
||||||
/* cannot track membership (out of memory) */
|
/* cannot track membership (out of memory) */
|
||||||
@ -2422,6 +2463,9 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
/* Special case: all IPPROTO_TCP option take an int */
|
/* Special case: all IPPROTO_TCP option take an int */
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
||||||
|
if (sock->conn->pcb.tcp->state == LISTEN) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case TCP_NODELAY:
|
case TCP_NODELAY:
|
||||||
if (*(const int*)optval) {
|
if (*(const int*)optval) {
|
||||||
@ -2469,7 +2513,6 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
|||||||
case IPPROTO_IPV6:
|
case IPPROTO_IPV6:
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case IPV6_V6ONLY:
|
case IPV6_V6ONLY:
|
||||||
/* @todo: this does not work for datagram sockets, yet */
|
|
||||||
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
|
||||||
if (*(const int*)optval) {
|
if (*(const int*)optval) {
|
||||||
netconn_set_ipv6only(sock->conn, 1);
|
netconn_set_ipv6only(sock->conn, 1);
|
||||||
@ -2770,7 +2813,7 @@ lwip_socket_drop_registered_memberships(int s)
|
|||||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
|
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
|
||||||
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
|
ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
|
||||||
|
|
||||||
netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE);
|
netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,8 +98,8 @@
|
|||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h> /* memset */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h> /* atoi */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
@ -2563,6 +2563,7 @@ httpd_init(void)
|
|||||||
tcp_setprio(pcb, HTTPD_TCP_PRIO);
|
tcp_setprio(pcb, HTTPD_TCP_PRIO);
|
||||||
/* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
|
/* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
|
||||||
err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
|
err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT);
|
||||||
|
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
|
LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
|
||||||
pcb = tcp_listen(pcb);
|
pcb = tcp_listen(pcb);
|
||||||
LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
|
LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
|
||||||
|
@ -294,7 +294,7 @@ lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
|
|||||||
} else {
|
} else {
|
||||||
/* transmit data */
|
/* transmit data */
|
||||||
/* @todo: every x bytes, transmit the settings again */
|
/* @todo: every x bytes, transmit the settings again */
|
||||||
txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
|
txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
|
||||||
txlen_max = TCP_MSS;
|
txlen_max = TCP_MSS;
|
||||||
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
|
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
|
||||||
txlen_max = TCP_MSS - 24;
|
txlen_max = TCP_MSS - 24;
|
||||||
@ -494,10 +494,8 @@ lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
|||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packet_idx += i;
|
|
||||||
#else
|
|
||||||
packet_idx += q->len;
|
|
||||||
#endif
|
#endif
|
||||||
|
packet_idx += q->len;
|
||||||
}
|
}
|
||||||
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
|
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
|
||||||
conn->bytes_transferred += packet_idx;
|
conn->bytes_transferred += packet_idx;
|
||||||
@ -579,7 +577,7 @@ lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||||||
void*
|
void*
|
||||||
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
|
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg)
|
||||||
{
|
{
|
||||||
return lwiperf_start_tcp_server(IP4_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
|
return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT,
|
||||||
report_fn, report_arg);
|
report_fn, report_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
* Author: Erik Ekman <erik@kryo.se>
|
||||||
*
|
|
||||||
* Please coordinate changes and requests with Erik Ekman
|
|
||||||
* <erik.ekman@verisure.com>
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -68,7 +65,6 @@
|
|||||||
#include "lwip/prot/dns.h"
|
#include "lwip/prot/dns.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#if LWIP_MDNS_RESPONDER
|
#if LWIP_MDNS_RESPONDER
|
||||||
|
|
||||||
@ -85,13 +81,13 @@
|
|||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
/* IPv4 multicast group 224.0.0.251 */
|
/* IPv4 multicast group 224.0.0.251 */
|
||||||
static const ip_addr_t v4group = IPADDR4_INIT(PP_HTONL(0xE00000FBUL));
|
static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
#include "lwip/mld6.h"
|
#include "lwip/mld6.h"
|
||||||
/* IPv6 multicast group FF02::FB */
|
/* IPv6 multicast group FF02::FB */
|
||||||
static const ip_addr_t v6group = IPADDR6_INIT(PP_HTONL(0xFF020000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x000000FBUL));
|
static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MDNS_PORT 5353
|
#define MDNS_PORT 5353
|
||||||
@ -573,7 +569,7 @@ mdns_build_dnssd_domain(struct mdns_domain *domain)
|
|||||||
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
||||||
res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1));
|
res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1));
|
||||||
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
||||||
res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
|
res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP]));
|
||||||
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res);
|
||||||
return mdns_add_dotlocal(domain);
|
return mdns_add_dotlocal(domain);
|
||||||
}
|
}
|
||||||
@ -598,7 +594,7 @@ mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *servi
|
|||||||
}
|
}
|
||||||
res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service));
|
res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service));
|
||||||
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
|
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
|
||||||
res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)(sizeof(dnssd_protos[DNSSD_PROTO_UDP])-1));
|
res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto]));
|
||||||
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
|
LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res);
|
||||||
return mdns_add_dotlocal(domain);
|
return mdns_add_dotlocal(domain);
|
||||||
}
|
}
|
||||||
@ -1824,6 +1820,7 @@ mdns_resp_init(void)
|
|||||||
mdns_pcb->ttl = MDNS_TTL;
|
mdns_pcb->ttl = MDNS_TTL;
|
||||||
#endif
|
#endif
|
||||||
res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT);
|
res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT);
|
||||||
|
LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
|
LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
|
||||||
udp_recv(mdns_pcb, mdns_recv, NULL);
|
udp_recv(mdns_pcb, mdns_recv, NULL);
|
||||||
|
|
||||||
@ -2022,7 +2019,7 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service
|
|||||||
err_t
|
err_t
|
||||||
mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
|
mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
|
||||||
{
|
{
|
||||||
LWIP_ASSERT("mdns_resp_add_service: service != NULL", service);
|
LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
|
||||||
|
|
||||||
/* Use a mdns_domain struct to store txt chunks since it is the same encoding */
|
/* Use a mdns_domain struct to store txt chunks since it is the same encoding */
|
||||||
return mdns_domain_add_label(&service->txtdata, txt, txt_len);
|
return mdns_domain_add_label(&service->txtdata, txt, txt_len);
|
||||||
|
1335
src/apps/mqtt/mqtt.c
Normal file
1335
src/apps/mqtt/mqtt.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -581,7 +581,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||||||
snmp_ip4_to_oid(ip, &test_oid[1]);
|
snmp_ip4_to_oid(ip, &test_oid[1]);
|
||||||
|
|
||||||
/* check generated OID: is it a candidate for the next one? */
|
/* check generated OID: is it a candidate for the next one? */
|
||||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i);
|
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), LWIP_PTR_NUMERIC_CAST(void*, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +589,7 @@ ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct
|
|||||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
||||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
||||||
/* fill in object properties */
|
/* fill in object properties */
|
||||||
return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len);
|
return ip_NetToMediaTable_get_cell_value_core(LWIP_PTR_NUMERIC_CAST(u8_t, state.reference), column, value, value_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found */
|
/* not found */
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#if LWIP_SNMP && SNMP_USE_NETCONN
|
#if LWIP_SNMP && SNMP_USE_NETCONN
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "lwip/api.h"
|
#include "lwip/api.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
@ -52,7 +53,7 @@ snmp_netconn_thread(void *arg)
|
|||||||
LWIP_UNUSED_ARG(arg);
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
/* Bind to SNMP port with default IP address */
|
/* Bind to SNMP port with default IP address */
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
conn = netconn_new(NETCONN_UDP_IPV6);
|
conn = netconn_new(NETCONN_UDP_IPV6);
|
||||||
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT);
|
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT);
|
||||||
#else /* LWIP_IPV6 */
|
#else /* LWIP_IPV6 */
|
||||||
|
@ -211,6 +211,7 @@ void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_thread
|
|||||||
err_t err = sys_mutex_new(&instance->sem_usage_mutex);
|
err_t err = sys_mutex_new(&instance->sem_usage_mutex);
|
||||||
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
|
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
|
||||||
err = sys_sem_new(&instance->sem, 0);
|
err = sys_sem_new(&instance->sem, 0);
|
||||||
|
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
|
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
|
||||||
instance->sync_fn = sync_fn;
|
instance->sync_fn = sync_fn;
|
||||||
}
|
}
|
||||||
|
@ -573,6 +573,7 @@ sntp_stop(void)
|
|||||||
{
|
{
|
||||||
if (sntp_pcb != NULL) {
|
if (sntp_pcb != NULL) {
|
||||||
sys_untimeout(sntp_request, NULL);
|
sys_untimeout(sntp_request, NULL);
|
||||||
|
sys_untimeout(sntp_try_next_server, NULL);
|
||||||
udp_remove(sntp_pcb);
|
udp_remove(sntp_pcb);
|
||||||
sntp_pcb = NULL;
|
sntp_pcb = NULL;
|
||||||
}
|
}
|
||||||
@ -688,7 +689,7 @@ sntp_getserver(u8_t idx)
|
|||||||
if (idx < SNTP_MAX_SERVERS) {
|
if (idx < SNTP_MAX_SERVERS) {
|
||||||
return &sntp_servers[idx].addr;
|
return &sntp_servers[idx].addr;
|
||||||
}
|
}
|
||||||
return IP4_ADDR_ANY;
|
return IP_ADDR_ANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SNTP_SERVER_DNS
|
#if SNTP_SERVER_DNS
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
* @ingroup sys_layer
|
* @ingroup sys_layer
|
||||||
* lwIP provides default implementations for non-standard functions.
|
* lwIP provides default implementations for non-standard functions.
|
||||||
* These can be mapped to OS functions to reduce code footprint if desired.
|
* These can be mapped to OS functions to reduce code footprint if desired.
|
||||||
|
* All defines related to this section must not be placed in lwipopts.h,
|
||||||
|
* but in arch/cc.h!
|
||||||
|
* These options cannot be \#defined in lwipopts.h since they are not options
|
||||||
|
* of lwIP itself, but options of the lwIP port to your system.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -101,13 +105,13 @@ char*
|
|||||||
lwip_strnstr(const char* buffer, const char* token, size_t n)
|
lwip_strnstr(const char* buffer, const char* token, size_t n)
|
||||||
{
|
{
|
||||||
const char* p;
|
const char* p;
|
||||||
int tokenlen = (int)strlen(token);
|
size_t tokenlen = strlen(token);
|
||||||
if (tokenlen == 0) {
|
if (tokenlen == 0) {
|
||||||
return (char *)(size_t)buffer;
|
return LWIP_CONST_CAST(char *, buffer);
|
||||||
}
|
}
|
||||||
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
|
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
|
||||||
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
|
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
|
||||||
return (char *)(size_t)p;
|
return LWIP_CONST_CAST(char *, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
127
src/core/dns.c
127
src/core/dns.c
@ -24,6 +24,11 @@
|
|||||||
* the resolver code calls a specified callback function (which
|
* the resolver code calls a specified callback function (which
|
||||||
* must be implemented by the module that uses the resolver).
|
* must be implemented by the module that uses the resolver).
|
||||||
*
|
*
|
||||||
|
* Multicast DNS queries are supported for names ending on ".local".
|
||||||
|
* However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762
|
||||||
|
* chapter 5.1), this is not a fully compliant implementation of continuous
|
||||||
|
* mDNS querying!
|
||||||
|
*
|
||||||
* All functions must be called from TCPIP thread.
|
* All functions must be called from TCPIP thread.
|
||||||
*
|
*
|
||||||
* @see @ref netconn_common for thread-safe access.
|
* @see @ref netconn_common for thread-safe access.
|
||||||
@ -71,6 +76,7 @@
|
|||||||
/** @todo: define good default values (rfc compliance) */
|
/** @todo: define good default values (rfc compliance) */
|
||||||
/** @todo: improve answer parsing, more checkings... */
|
/** @todo: improve answer parsing, more checkings... */
|
||||||
/** @todo: check RFC1035 - 7.3. Processing responses */
|
/** @todo: check RFC1035 - 7.3. Processing responses */
|
||||||
|
/** @todo: one-shot mDNS: dual-stack fallback to another IP version */
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
* Includes
|
* Includes
|
||||||
@ -116,6 +122,13 @@ static u16_t dns_txid;
|
|||||||
#error DNS_MAX_TTL must be a positive 32-bit value
|
#error DNS_MAX_TTL must be a positive 32-bit value
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DNS_TABLE_SIZE > 255
|
||||||
|
#error DNS_TABLE_SIZE must fit into an u8_t
|
||||||
|
#endif
|
||||||
|
#if DNS_MAX_SERVERS > 255
|
||||||
|
#error DNS_MAX_SERVERS must fit into an u8_t
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The number of parallel requests (i.e. calls to dns_gethostbyname
|
/* The number of parallel requests (i.e. calls to dns_gethostbyname
|
||||||
* that cannot be answered from the DNS table.
|
* that cannot be answered from the DNS table.
|
||||||
* This is set to the table size by default.
|
* This is set to the table size by default.
|
||||||
@ -123,6 +136,10 @@ static u16_t dns_txid;
|
|||||||
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
|
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
|
||||||
#ifndef DNS_MAX_REQUESTS
|
#ifndef DNS_MAX_REQUESTS
|
||||||
#define DNS_MAX_REQUESTS DNS_TABLE_SIZE
|
#define DNS_MAX_REQUESTS DNS_TABLE_SIZE
|
||||||
|
#else
|
||||||
|
#if DNS_MAX_REQUESTS > 255
|
||||||
|
#error DNS_MAX_REQUESTS must fit into an u8_t
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
/* In this configuration, both arrays have to have the same size and are used
|
/* In this configuration, both arrays have to have the same size and are used
|
||||||
@ -134,6 +151,10 @@ static u16_t dns_txid;
|
|||||||
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
|
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
|
||||||
#ifndef DNS_MAX_SOURCE_PORTS
|
#ifndef DNS_MAX_SOURCE_PORTS
|
||||||
#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
|
#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
|
||||||
|
#else
|
||||||
|
#if DNS_MAX_SOURCE_PORTS > 255
|
||||||
|
#error DNS_MAX_SOURCE_PORTS must fit into an u8_t
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef DNS_MAX_SOURCE_PORTS
|
#ifdef DNS_MAX_SOURCE_PORTS
|
||||||
@ -160,6 +181,12 @@ static u16_t dns_txid;
|
|||||||
#define LWIP_DNS_SET_ADDRTYPE(x, y)
|
#define LWIP_DNS_SET_ADDRTYPE(x, y)
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
#define LWIP_DNS_ISMDNS_ARG(x) , x
|
||||||
|
#else
|
||||||
|
#define LWIP_DNS_ISMDNS_ARG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
/** DNS query message structure.
|
/** DNS query message structure.
|
||||||
No packing needed: only used locally on the stack. */
|
No packing needed: only used locally on the stack. */
|
||||||
struct dns_query {
|
struct dns_query {
|
||||||
@ -209,6 +236,9 @@ struct dns_table_entry {
|
|||||||
#if LWIP_IPV4 && LWIP_IPV6
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
u8_t reqaddrtype;
|
u8_t reqaddrtype;
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
u8_t is_mdns;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DNS request table entry: used when dns_gehostbyname cannot answer the
|
/** DNS request table entry: used when dns_gehostbyname cannot answer the
|
||||||
@ -272,6 +302,13 @@ static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
|
|||||||
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
|
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
|
||||||
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
|
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the resolver: set up the UDP pcb and configure the default server
|
* Initialize the resolver: set up the UDP pcb and configure the default server
|
||||||
* (if DNS_SERVER_ADDRESS is set).
|
* (if DNS_SERVER_ADDRESS is set).
|
||||||
@ -329,7 +366,7 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
|
|||||||
if (dnsserver != NULL) {
|
if (dnsserver != NULL) {
|
||||||
dns_servers[numdns] = (*dnsserver);
|
dns_servers[numdns] = (*dnsserver);
|
||||||
} else {
|
} else {
|
||||||
dns_servers[numdns] = *IP4_ADDR_ANY;
|
dns_servers[numdns] = *IP_ADDR_ANY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,7 +385,7 @@ dns_getserver(u8_t numdns)
|
|||||||
if (numdns < DNS_MAX_SERVERS) {
|
if (numdns < DNS_MAX_SERVERS) {
|
||||||
return &dns_servers[numdns];
|
return &dns_servers[numdns];
|
||||||
} else {
|
} else {
|
||||||
return IP4_ADDR_ANY;
|
return IP_ADDR_ANY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +702,11 @@ dns_send(u8_t idx)
|
|||||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
|
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
|
||||||
(u16_t)(entry->server_idx), entry->name));
|
(u16_t)(entry->server_idx), entry->name));
|
||||||
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
|
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
|
||||||
if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
|
if (ip_addr_isany_val(dns_servers[entry->server_idx])
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
&& !entry->is_mdns
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
/* DNS server not valid anymore, e.g. PPP netif has been shut down */
|
/* DNS server not valid anymore, e.g. PPP netif has been shut down */
|
||||||
/* call specified callback function if provided */
|
/* call specified callback function if provided */
|
||||||
dns_call_found(idx, NULL);
|
dns_call_found(idx, NULL);
|
||||||
@ -678,6 +719,8 @@ dns_send(u8_t idx)
|
|||||||
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
|
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
|
||||||
SIZEOF_DNS_QUERY), PBUF_RAM);
|
SIZEOF_DNS_QUERY), PBUF_RAM);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
|
const ip_addr_t* dst;
|
||||||
|
u16_t dst_port;
|
||||||
/* fill dns header */
|
/* fill dns header */
|
||||||
memset(&hdr, 0, SIZEOF_DNS_HDR);
|
memset(&hdr, 0, SIZEOF_DNS_HDR);
|
||||||
hdr.id = lwip_htons(entry->txid);
|
hdr.id = lwip_htons(entry->txid);
|
||||||
@ -720,7 +763,30 @@ dns_send(u8_t idx)
|
|||||||
/* send dns packet */
|
/* send dns packet */
|
||||||
LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
|
LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
|
||||||
entry->txid, entry->name, entry->server_idx));
|
entry->txid, entry->name, entry->server_idx));
|
||||||
err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT);
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
if (entry->is_mdns) {
|
||||||
|
dst_port = DNS_MQUERY_PORT;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
|
||||||
|
{
|
||||||
|
dst = &dns_mquery_v6group;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if LWIP_IPV4
|
||||||
|
{
|
||||||
|
dst = &dns_mquery_v4group;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||||
|
{
|
||||||
|
dst_port = DNS_SERVER_PORT;
|
||||||
|
dst = &dns_servers[entry->server_idx];
|
||||||
|
}
|
||||||
|
err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
|
||||||
|
|
||||||
/* free pbuf */
|
/* free pbuf */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@ -923,7 +989,11 @@ dns_check_entry(u8_t i)
|
|||||||
case DNS_STATE_ASKING:
|
case DNS_STATE_ASKING:
|
||||||
if (--entry->tmr == 0) {
|
if (--entry->tmr == 0) {
|
||||||
if (++entry->retries == DNS_MAX_RETRIES) {
|
if (++entry->retries == DNS_MAX_RETRIES) {
|
||||||
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
|
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
&& !entry->is_mdns
|
||||||
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||||
|
) {
|
||||||
/* change of server */
|
/* change of server */
|
||||||
entry->server_idx++;
|
entry->server_idx++;
|
||||||
entry->tmr = 1;
|
entry->tmr = 1;
|
||||||
@ -1060,10 +1130,15 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|||||||
goto memerr; /* ignore this packet */
|
goto memerr; /* ignore this packet */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether response comes from the same network address to which the
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
question was sent. (RFC 5452) */
|
if (!entry->is_mdns)
|
||||||
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||||
goto memerr; /* ignore this packet */
|
{
|
||||||
|
/* Check whether response comes from the same network address to which the
|
||||||
|
question was sent. (RFC 5452) */
|
||||||
|
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
|
||||||
|
goto memerr; /* ignore this packet */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the name in the "question" part match with the name in the entry and
|
/* Check if the name in the "question" part match with the name in the entry and
|
||||||
@ -1195,7 +1270,7 @@ memerr:
|
|||||||
*/
|
*/
|
||||||
static err_t
|
static err_t
|
||||||
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
||||||
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
|
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns))
|
||||||
{
|
{
|
||||||
u8_t i;
|
u8_t i;
|
||||||
u8_t lseq, lseqi;
|
u8_t lseq, lseqi;
|
||||||
@ -1244,8 +1319,9 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|||||||
}
|
}
|
||||||
/* check if this is the oldest completed entry */
|
/* check if this is the oldest completed entry */
|
||||||
if (entry->state == DNS_STATE_DONE) {
|
if (entry->state == DNS_STATE_DONE) {
|
||||||
if ((u8_t)(dns_seqno - entry->seqno) > lseq) {
|
u8_t age = dns_seqno - entry->seqno;
|
||||||
lseq = dns_seqno - entry->seqno;
|
if (age > lseq) {
|
||||||
|
lseq = age;
|
||||||
lseqi = i;
|
lseqi = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1310,6 +1386,10 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|||||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
|
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
entry->is_mdns = is_mdns;
|
||||||
|
#endif
|
||||||
|
|
||||||
dns_seqno++;
|
dns_seqno++;
|
||||||
|
|
||||||
/* force to send query without waiting timer */
|
/* force to send query without waiting timer */
|
||||||
@ -1365,6 +1445,9 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|||||||
void *callback_arg, u8_t dns_addrtype)
|
void *callback_arg, u8_t dns_addrtype)
|
||||||
{
|
{
|
||||||
size_t hostnamelen;
|
size_t hostnamelen;
|
||||||
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
|
u8_t is_mdns;
|
||||||
|
#endif
|
||||||
/* not initialized or no valid server yet, or invalid addr pointer
|
/* not initialized or no valid server yet, or invalid addr pointer
|
||||||
* or invalid hostname or invalid hostname length */
|
* or invalid hostname or invalid hostname length */
|
||||||
if ((addr == NULL) ||
|
if ((addr == NULL) ||
|
||||||
@ -1421,13 +1504,25 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|||||||
LWIP_UNUSED_ARG(dns_addrtype);
|
LWIP_UNUSED_ARG(dns_addrtype);
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
/* prevent calling found callback if no server is set, return error instead */
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
if (ip_addr_isany_val(dns_servers[0])) {
|
if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) {
|
||||||
return ERR_VAL;
|
is_mdns = 1;
|
||||||
|
} else {
|
||||||
|
is_mdns = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_mdns)
|
||||||
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
|
||||||
|
{
|
||||||
|
/* prevent calling found callback if no server is set, return error instead */
|
||||||
|
if (ip_addr_isany_val(dns_servers[0])) {
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* queue query with specified callback */
|
/* queue query with specified callback */
|
||||||
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
|
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)
|
||||||
|
LWIP_DNS_ISMDNS_ARG(is_mdns));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DNS */
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef LWIP_CHKSUM
|
#ifndef LWIP_CHKSUM
|
||||||
|
@ -141,7 +141,7 @@ PACK_STRUCT_END
|
|||||||
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
|
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
|
||||||
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
|
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
|
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
|
||||||
#error "The maximum valid window scale value is 14!"
|
#error "The maximum valid window scale value is 14!"
|
||||||
#endif
|
#endif
|
||||||
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
|
||||||
@ -339,6 +339,11 @@ PACK_STRUCT_END
|
|||||||
void
|
void
|
||||||
lwip_init(void)
|
lwip_init(void)
|
||||||
{
|
{
|
||||||
|
#ifndef LWIP_SKIP_CONST_CHECK
|
||||||
|
int a;
|
||||||
|
LWIP_UNUSED_ARG(a);
|
||||||
|
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||||
|
#endif
|
||||||
#ifndef LWIP_SKIP_PACKING_CHECK
|
#ifndef LWIP_SKIP_PACKING_CHECK
|
||||||
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
|
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,7 +68,6 @@
|
|||||||
#include "lwip/etharp.h"
|
#include "lwip/etharp.h"
|
||||||
#include "lwip/prot/autoip.h"
|
#include "lwip/prot/autoip.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/** Pseudo random macro based on netif informations.
|
/** Pseudo random macro based on netif informations.
|
||||||
@ -95,8 +94,6 @@
|
|||||||
static err_t autoip_arp_announce(struct netif *netif);
|
static err_t autoip_arp_announce(struct netif *netif);
|
||||||
static void autoip_start_probing(struct netif *netif);
|
static void autoip_start_probing(struct netif *netif);
|
||||||
|
|
||||||
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup autoip
|
* @ingroup autoip
|
||||||
* Set a statically allocated struct autoip to work with.
|
* Set a statically allocated struct autoip to work with.
|
||||||
@ -482,7 +479,8 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||||||
* ip.dst == llipaddr && hw.src != own hwaddr
|
* ip.dst == llipaddr && hw.src != own hwaddr
|
||||||
*/
|
*/
|
||||||
if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
|
if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
|
||||||
(ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
|
(ip4_addr_isany_val(sipaddr) &&
|
||||||
|
ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
|
||||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
|
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
|
||||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||||
("autoip_arp_reply(): Probe Conflict detected\n"));
|
("autoip_arp_reply(): Probe Conflict detected\n"));
|
||||||
|
@ -103,26 +103,40 @@
|
|||||||
|
|
||||||
#define REBOOT_TRIES 2
|
#define REBOOT_TRIES 2
|
||||||
|
|
||||||
|
#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
|
||||||
|
#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
|
||||||
|
#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
|
||||||
|
#else
|
||||||
|
#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Option handling: options are parsed in dhcp_parse_reply
|
/** Option handling: options are parsed in dhcp_parse_reply
|
||||||
* and saved in an array where other functions can load them from.
|
* and saved in an array where other functions can load them from.
|
||||||
* This might be moved into the struct dhcp (not necessarily since
|
* This might be moved into the struct dhcp (not necessarily since
|
||||||
* lwIP is single-threaded and the array is only used while in recv
|
* lwIP is single-threaded and the array is only used while in recv
|
||||||
* callback). */
|
* callback). */
|
||||||
#define DHCP_OPTION_IDX_OVERLOAD 0
|
enum dhcp_option_idx {
|
||||||
#define DHCP_OPTION_IDX_MSG_TYPE 1
|
DHCP_OPTION_IDX_OVERLOAD = 0,
|
||||||
#define DHCP_OPTION_IDX_SERVER_ID 2
|
DHCP_OPTION_IDX_MSG_TYPE,
|
||||||
#define DHCP_OPTION_IDX_LEASE_TIME 3
|
DHCP_OPTION_IDX_SERVER_ID,
|
||||||
#define DHCP_OPTION_IDX_T1 4
|
DHCP_OPTION_IDX_LEASE_TIME,
|
||||||
#define DHCP_OPTION_IDX_T2 5
|
DHCP_OPTION_IDX_T1,
|
||||||
#define DHCP_OPTION_IDX_SUBNET_MASK 6
|
DHCP_OPTION_IDX_T2,
|
||||||
#define DHCP_OPTION_IDX_ROUTER 7
|
DHCP_OPTION_IDX_SUBNET_MASK,
|
||||||
#define DHCP_OPTION_IDX_DNS_SERVER 8
|
DHCP_OPTION_IDX_ROUTER,
|
||||||
|
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||||
|
DHCP_OPTION_IDX_DNS_SERVER,
|
||||||
|
DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
|
||||||
|
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||||
#if LWIP_DHCP_GET_NTP_SRV
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
#define DHCP_OPTION_IDX_NTP_SERVER (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
DHCP_OPTION_IDX_NTP_SERVER,
|
||||||
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS)
|
DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
|
||||||
#else /* LWIP_DHCP_GET_NTP_SRV */
|
|
||||||
#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
|
|
||||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
DHCP_OPTION_IDX_MAX
|
||||||
|
};
|
||||||
|
|
||||||
/** Holds the decoded option values, only valid while in dhcp_recv.
|
/** Holds the decoded option values, only valid while in dhcp_recv.
|
||||||
@todo: move this into struct dhcp? */
|
@todo: move this into struct dhcp? */
|
||||||
@ -135,8 +149,10 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
|
|||||||
static u8_t dhcp_discover_request_options[] = {
|
static u8_t dhcp_discover_request_options[] = {
|
||||||
DHCP_OPTION_SUBNET_MASK,
|
DHCP_OPTION_SUBNET_MASK,
|
||||||
DHCP_OPTION_ROUTER,
|
DHCP_OPTION_ROUTER,
|
||||||
DHCP_OPTION_BROADCAST,
|
DHCP_OPTION_BROADCAST
|
||||||
DHCP_OPTION_DNS_SERVER
|
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||||
|
, DHCP_OPTION_DNS_SERVER
|
||||||
|
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||||
#if LWIP_DHCP_GET_NTP_SRV
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
, DHCP_OPTION_NTP
|
, DHCP_OPTION_NTP
|
||||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
@ -193,8 +209,6 @@ static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif);
|
|||||||
/* always add the DHCP options trailer to end and pad */
|
/* always add the DHCP options trailer to end and pad */
|
||||||
static void dhcp_option_trailer(struct dhcp *dhcp);
|
static void dhcp_option_trailer(struct dhcp *dhcp);
|
||||||
|
|
||||||
#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
|
|
||||||
|
|
||||||
/** Ensure DHCP PCB is allocated and bound */
|
/** Ensure DHCP PCB is allocated and bound */
|
||||||
static err_t
|
static err_t
|
||||||
dhcp_inc_pcb_refcount(void)
|
dhcp_inc_pcb_refcount(void)
|
||||||
@ -572,9 +586,9 @@ dhcp_handle_ack(struct netif *netif)
|
|||||||
{
|
{
|
||||||
struct dhcp *dhcp = netif_dhcp_data(netif);
|
struct dhcp *dhcp = netif_dhcp_data(netif);
|
||||||
|
|
||||||
#if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV
|
#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
|
||||||
u8_t n;
|
u8_t n;
|
||||||
#endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */
|
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
|
||||||
#if LWIP_DHCP_GET_NTP_SRV
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
|
ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
|
||||||
#endif
|
#endif
|
||||||
@ -640,14 +654,14 @@ dhcp_handle_ack(struct netif *netif)
|
|||||||
dhcp_set_ntp_servers(n, ntp_server_addrs);
|
dhcp_set_ntp_servers(n, ntp_server_addrs);
|
||||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
|
||||||
#if LWIP_DNS
|
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||||
/* DNS servers */
|
/* DNS servers */
|
||||||
for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
|
for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
|
||||||
ip_addr_t dns_addr;
|
ip_addr_t dns_addr;
|
||||||
ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
|
ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
|
||||||
dns_setserver(n, &dns_addr);
|
dns_setserver(n, &dns_addr);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_DNS */
|
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1517,6 +1531,7 @@ again:
|
|||||||
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
||||||
decode_idx = DHCP_OPTION_IDX_ROUTER;
|
decode_idx = DHCP_OPTION_IDX_ROUTER;
|
||||||
break;
|
break;
|
||||||
|
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
|
||||||
case(DHCP_OPTION_DNS_SERVER):
|
case(DHCP_OPTION_DNS_SERVER):
|
||||||
/* special case: there might be more than one server */
|
/* special case: there might be more than one server */
|
||||||
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
|
LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
|
||||||
@ -1525,6 +1540,7 @@ again:
|
|||||||
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
|
||||||
decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
|
decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
|
||||||
break;
|
break;
|
||||||
|
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
|
||||||
case(DHCP_OPTION_LEASE_TIME):
|
case(DHCP_OPTION_LEASE_TIME):
|
||||||
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
|
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
|
||||||
decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
|
decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
|
||||||
@ -1541,6 +1557,8 @@ again:
|
|||||||
#endif /* LWIP_DHCP_GET_NTP_SRV*/
|
#endif /* LWIP_DHCP_GET_NTP_SRV*/
|
||||||
case(DHCP_OPTION_OVERLOAD):
|
case(DHCP_OPTION_OVERLOAD):
|
||||||
LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
|
LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
|
||||||
|
/* decode overload only in options, not in file/sname: invalid packet */
|
||||||
|
LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
|
||||||
decode_idx = DHCP_OPTION_IDX_OVERLOAD;
|
decode_idx = DHCP_OPTION_IDX_OVERLOAD;
|
||||||
break;
|
break;
|
||||||
case(DHCP_OPTION_MESSAGE_TYPE):
|
case(DHCP_OPTION_MESSAGE_TYPE):
|
||||||
|
@ -840,7 +840,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||||||
if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
|
if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
|
||||||
!ip4_addr_islinklocal(ipaddr)) {
|
!ip4_addr_islinklocal(ipaddr)) {
|
||||||
#if LWIP_AUTOIP
|
#if LWIP_AUTOIP
|
||||||
struct ip_hdr *iphdr = (struct ip_hdr*)(size_t)q->payload;
|
struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload);
|
||||||
/* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
|
/* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
|
||||||
a link-local source address must always be "directly to its destination
|
a link-local source address must always be "directly to its destination
|
||||||
on the same physical link. The host MUST NOT send the packet to any
|
on the same physical link. The host MUST NOT send the packet to any
|
||||||
|
@ -81,7 +81,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
#endif /* LWIP_DEBUG */
|
#endif /* LWIP_DEBUG */
|
||||||
struct icmp_echo_hdr *iecho;
|
struct icmp_echo_hdr *iecho;
|
||||||
const struct ip_hdr *iphdr_in;
|
const struct ip_hdr *iphdr_in;
|
||||||
s16_t hlen;
|
u16_t hlen;
|
||||||
const ip4_addr_t* src;
|
const ip4_addr_t* src;
|
||||||
|
|
||||||
ICMP_STATS_INC(icmp.recv);
|
ICMP_STATS_INC(icmp.recv);
|
||||||
@ -148,7 +148,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
if (pbuf_header(p, (hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) {
|
||||||
/* p is not big enough to contain link headers
|
/* p is not big enough to contain link headers
|
||||||
* allocate a new one and copy p into it
|
* allocate a new one and copy p into it
|
||||||
*/
|
*/
|
||||||
@ -167,7 +167,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* copy the ip header */
|
/* copy the ip header */
|
||||||
MEMCPY(r->payload, iphdr_in, hlen);
|
MEMCPY(r->payload, iphdr_in, hlen);
|
||||||
/* switch r->payload back to icmp header (cannot fail) */
|
/* switch r->payload back to icmp header (cannot fail) */
|
||||||
if (pbuf_header(r, -hlen)) {
|
if (pbuf_header(r, (s16_t)-hlen)) {
|
||||||
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
|
||||||
pbuf_free(r);
|
pbuf_free(r);
|
||||||
goto icmperr;
|
goto icmperr;
|
||||||
@ -194,7 +194,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* We generate an answer by switching the dest and src ip addresses,
|
/* We generate an answer by switching the dest and src ip addresses,
|
||||||
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||||
iecho = (struct icmp_echo_hdr *)p->payload;
|
iecho = (struct icmp_echo_hdr *)p->payload;
|
||||||
if (pbuf_header(p, hlen)) {
|
if (pbuf_header(p, (s16_t)hlen)) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
|
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
|
||||||
} else {
|
} else {
|
||||||
err_t ret;
|
err_t ret;
|
||||||
@ -247,7 +247,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
if (type == ICMP_DUR) {
|
if (type == ICMP_DUR) {
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
||||||
} else if (type == ICMP_TE) {
|
} else if (type == ICMP_TE) {
|
||||||
MIB2_STATS_INC(mib2.icmpindestunreachs);
|
MIB2_STATS_INC(mib2.icmpintimeexcds);
|
||||||
} else if (type == ICMP_PP) {
|
} else if (type == ICMP_PP) {
|
||||||
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
MIB2_STATS_INC(mib2.icmpinparmprobs);
|
||||||
} else if (type == ICMP_SQ) {
|
} else if (type == ICMP_SQ) {
|
||||||
|
@ -244,6 +244,7 @@ struct igmp_group *
|
|||||||
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
||||||
{
|
{
|
||||||
struct igmp_group *group;
|
struct igmp_group *group;
|
||||||
|
struct igmp_group *list_head = netif_igmp_data(ifp);
|
||||||
|
|
||||||
/* Search if the group already exists */
|
/* Search if the group already exists */
|
||||||
group = igmp_lookfor_group(ifp, addr);
|
group = igmp_lookfor_group(ifp, addr);
|
||||||
@ -260,9 +261,21 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
|||||||
group->group_state = IGMP_GROUP_NON_MEMBER;
|
group->group_state = IGMP_GROUP_NON_MEMBER;
|
||||||
group->last_reporter_flag = 0;
|
group->last_reporter_flag = 0;
|
||||||
group->use = 0;
|
group->use = 0;
|
||||||
group->next = netif_igmp_data(ifp);
|
|
||||||
|
|
||||||
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
|
/* Ensure allsystems group is always first in list */
|
||||||
|
if (list_head == NULL) {
|
||||||
|
/* this is the first entry in linked list */
|
||||||
|
LWIP_ASSERT("igmp_lookup_group: first group must be allsystems",
|
||||||
|
(ip4_addr_cmp(addr, &allsystems) != 0));
|
||||||
|
group->next = NULL;
|
||||||
|
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
|
||||||
|
} else {
|
||||||
|
/* append _after_ first entry */
|
||||||
|
LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems",
|
||||||
|
(ip4_addr_cmp(addr, &allsystems) == 0));
|
||||||
|
group->next = list_head->next;
|
||||||
|
list_head->next = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
|
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
|
||||||
@ -282,24 +295,19 @@ static err_t
|
|||||||
igmp_remove_group(struct netif* netif, struct igmp_group *group)
|
igmp_remove_group(struct netif* netif, struct igmp_group *group)
|
||||||
{
|
{
|
||||||
err_t err = ERR_OK;
|
err_t err = ERR_OK;
|
||||||
|
struct igmp_group *tmp_group;
|
||||||
|
|
||||||
/* Is it the first group? */
|
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
|
||||||
if (netif_igmp_data(netif) == group) {
|
for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) {
|
||||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next);
|
if (tmp_group->next == group) {
|
||||||
} else {
|
tmp_group->next = group->next;
|
||||||
/* look for group further down the list */
|
break;
|
||||||
struct igmp_group *tmpGroup;
|
|
||||||
for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
|
||||||
if (tmpGroup->next == group) {
|
|
||||||
tmpGroup->next = group->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Group not found in the global igmp_group_list */
|
|
||||||
if (tmpGroup == NULL) {
|
|
||||||
err = ERR_ARG;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Group not found in the global igmp_group_list */
|
||||||
|
if (tmp_group == NULL) {
|
||||||
|
err = ERR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ ip4_route(const ip4_addr_t *dest)
|
|||||||
/* loopif is disabled, looopback traffic is passed through any netif */
|
/* loopif is disabled, looopback traffic is passed through any netif */
|
||||||
if (ip4_addr_isloopback(dest)) {
|
if (ip4_addr_isloopback(dest)) {
|
||||||
/* don't check for link on loopback traffic */
|
/* don't check for link on loopback traffic */
|
||||||
if (netif_is_up(netif_default)) {
|
if (netif_default != NULL && netif_is_up(netif_default)) {
|
||||||
return netif_default;
|
return netif_default;
|
||||||
}
|
}
|
||||||
/* default netif is not up, just use any netif for loopback traffic */
|
/* default netif is not up, just use any netif for loopback traffic */
|
||||||
@ -518,6 +518,15 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||||||
#endif /* LWIP_AUTOIP */
|
#endif /* LWIP_AUTOIP */
|
||||||
}
|
}
|
||||||
if (first) {
|
if (first) {
|
||||||
|
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
|
||||||
|
/* Packets sent to the loopback address must not be accepted on an
|
||||||
|
* interface that does not have the loopback address assigned to it,
|
||||||
|
* unless a non-loopback interface is used for loopback traffic. */
|
||||||
|
if (ip4_addr_isloopback(ip4_current_dest_addr())) {
|
||||||
|
netif = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
|
||||||
first = 0;
|
first = 0;
|
||||||
netif = netif_list;
|
netif = netif_list;
|
||||||
} else {
|
} else {
|
||||||
@ -589,6 +598,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else
|
} else
|
||||||
#endif /* IP_FORWARD */
|
#endif /* IP_FORWARD */
|
||||||
{
|
{
|
||||||
|
IP_STATS_INC(ip.drop);
|
||||||
MIB2_STATS_INC(mib2.ipinaddrerrors);
|
MIB2_STATS_INC(mib2.ipinaddrerrors);
|
||||||
MIB2_STATS_INC(mib2.ipindiscards);
|
MIB2_STATS_INC(mib2.ipindiscards);
|
||||||
}
|
}
|
||||||
@ -853,7 +863,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||||||
IPH_TTL_SET(iphdr, ttl);
|
IPH_TTL_SET(iphdr, ttl);
|
||||||
IPH_PROTO_SET(iphdr, proto);
|
IPH_PROTO_SET(iphdr, proto);
|
||||||
#if CHECKSUM_GEN_IP_INLINE
|
#if CHECKSUM_GEN_IP_INLINE
|
||||||
chk_sum += LWIP_MAKE_U16(proto, ttl);
|
chk_sum += PP_NTOHS(proto | (ttl << 8));
|
||||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||||
|
|
||||||
/* dest cannot be NULL here */
|
/* dest cannot be NULL here */
|
||||||
@ -866,7 +876,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
|
|||||||
IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
|
IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
|
||||||
IPH_TOS_SET(iphdr, tos);
|
IPH_TOS_SET(iphdr, tos);
|
||||||
#if CHECKSUM_GEN_IP_INLINE
|
#if CHECKSUM_GEN_IP_INLINE
|
||||||
chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
|
chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8));
|
||||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||||
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
||||||
#if CHECKSUM_GEN_IP_INLINE
|
#if CHECKSUM_GEN_IP_INLINE
|
||||||
|
@ -183,10 +183,10 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr)
|
|||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
val = (val * base) + (int)(c - '0');
|
val = (val * base) + (u32_t)(c - '0');
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else if (base == 16 && isxdigit(c)) {
|
} else if (base == 16 && isxdigit(c)) {
|
||||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -310,7 +310,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
|
|||||||
do {
|
do {
|
||||||
rem = *ap % (u8_t)10;
|
rem = *ap % (u8_t)10;
|
||||||
*ap /= (u8_t)10;
|
*ap /= (u8_t)10;
|
||||||
inv[i++] = '0' + rem;
|
inv[i++] = (char)('0' + rem);
|
||||||
} while (*ap);
|
} while (*ap);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
if (len++ >= buflen) {
|
if (len++ >= buflen) {
|
||||||
|
@ -687,6 +687,8 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||||||
struct pbuf *rambuf;
|
struct pbuf *rambuf;
|
||||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
struct pbuf *newpbuf;
|
struct pbuf *newpbuf;
|
||||||
|
u16_t newpbuflen = 0;
|
||||||
|
u16_t left_to_copy;
|
||||||
#endif
|
#endif
|
||||||
struct ip_hdr *original_iphdr;
|
struct ip_hdr *original_iphdr;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
@ -696,10 +698,6 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
|
|||||||
int last;
|
int last;
|
||||||
u16_t poff = IP_HLEN;
|
u16_t poff = IP_HLEN;
|
||||||
u16_t tmp;
|
u16_t tmp;
|
||||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
|
||||||
u16_t newpbuflen = 0;
|
|
||||||
u16_t left_to_copy;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
original_iphdr = (struct ip_hdr *)p->payload;
|
original_iphdr = (struct ip_hdr *)p->payload;
|
||||||
iphdr = original_iphdr;
|
iphdr = original_iphdr;
|
||||||
|
@ -62,7 +62,9 @@
|
|||||||
* For IPv6 multicast, corresponding Ethernet addresses
|
* For IPv6 multicast, corresponding Ethernet addresses
|
||||||
* are selected and the packet is transmitted on the link.
|
* are selected and the packet is transmitted on the link.
|
||||||
*
|
*
|
||||||
* For unicast addresses, ...
|
* For unicast addresses, ask the ND6 module what to do. It will either let us
|
||||||
|
* send the the packet right away, or queue the packet for later itself, unless
|
||||||
|
* an error occurs.
|
||||||
*
|
*
|
||||||
* @todo anycast addresses
|
* @todo anycast addresses
|
||||||
*
|
*
|
||||||
@ -71,14 +73,14 @@
|
|||||||
* @param ip6addr The IP address of the packet destination.
|
* @param ip6addr The IP address of the packet destination.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
* - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue.
|
||||||
* or the return type of either nd6_queue_packet() or ethernet_output().
|
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
||||||
{
|
{
|
||||||
struct eth_addr dest;
|
struct eth_addr dest;
|
||||||
s8_t i;
|
const u8_t *hwaddr;
|
||||||
|
err_t result;
|
||||||
|
|
||||||
/* multicast destination IP address? */
|
/* multicast destination IP address? */
|
||||||
if (ip6_addr_ismulticast(ip6addr)) {
|
if (ip6_addr_ismulticast(ip6addr)) {
|
||||||
@ -91,36 +93,26 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
|||||||
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3];
|
||||||
|
|
||||||
/* Send out. */
|
/* Send out. */
|
||||||
return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have a unicast destination IP address */
|
/* We have a unicast destination IP address */
|
||||||
/* @todo anycast? */
|
/* @todo anycast? */
|
||||||
/* Get next hop record. */
|
|
||||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
/* Ask ND6 what to do with the packet. */
|
||||||
if (i < 0) {
|
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
|
||||||
/* failed to get a next hop neighbor record. */
|
if (result != ERR_OK) {
|
||||||
return ERR_MEM;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that we have a destination record, send or queue the packet. */
|
/* If no hardware address is returned, nd6 has queued the packet for later. */
|
||||||
if (neighbor_cache[i].state == ND6_STALE) {
|
if (hwaddr == NULL) {
|
||||||
/* Switch to delay state. */
|
return ERR_OK;
|
||||||
neighbor_cache[i].state = ND6_DELAY;
|
|
||||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
|
|
||||||
}
|
|
||||||
/* @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 ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should queue packet on this interface. */
|
/* Send out the packet using the returned hardware address. */
|
||||||
return nd6_queue_packet(i, q);
|
SMEMCPY(dest.addr, hwaddr, 6);
|
||||||
|
return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||||
|
@ -94,7 +94,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||||||
if (ip6_addr_islinklocal(dest)) {
|
if (ip6_addr_islinklocal(dest)) {
|
||||||
if (ip6_addr_isany(src)) {
|
if (ip6_addr_isany(src)) {
|
||||||
/* Use default netif, if Up. */
|
/* Use default netif, if Up. */
|
||||||
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
|
if (netif_default == NULL || !netif_is_up(netif_default) ||
|
||||||
|
!netif_is_link_up(netif_default)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return netif_default;
|
return netif_default;
|
||||||
@ -114,7 +115,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* netif not found, use default netif, if up */
|
/* netif not found, use default netif, if up */
|
||||||
if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
|
if (netif_default == NULL || !netif_is_up(netif_default) ||
|
||||||
|
!netif_is_link_up(netif_default)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return netif_default;
|
return netif_default;
|
||||||
@ -142,15 +144,9 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the netif for a suitable router. */
|
/* Get the netif for a suitable router. */
|
||||||
i = nd6_select_router(dest, NULL);
|
netif = nd6_find_route(dest);
|
||||||
if (i >= 0) {
|
if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) {
|
||||||
if (default_router_list[i].neighbor_entry != NULL) {
|
return netif;
|
||||||
if (default_router_list[i].neighbor_entry->netif != NULL) {
|
|
||||||
if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
|
|
||||||
return default_router_list[i].neighbor_entry->netif;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try with the netif that matches the source address. */
|
/* try with the netif that matches the source address. */
|
||||||
@ -172,7 +168,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
|||||||
/* loopif is disabled, loopback traffic is passed through any netif */
|
/* loopif is disabled, loopback traffic is passed through any netif */
|
||||||
if (ip6_addr_isloopback(dest)) {
|
if (ip6_addr_isloopback(dest)) {
|
||||||
/* don't check for link on loopback traffic */
|
/* don't check for link on loopback traffic */
|
||||||
if (netif_is_up(netif_default)) {
|
if (netif_default != NULL && netif_is_up(netif_default)) {
|
||||||
return netif_default;
|
return netif_default;
|
||||||
}
|
}
|
||||||
/* default netif is not up, just use any netif for loopback traffic */
|
/* default netif is not up, just use any netif for loopback traffic */
|
||||||
@ -290,8 +286,9 @@ ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
|
|||||||
{
|
{
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
|
||||||
/* do not forward link-local addresses */
|
/* do not forward link-local or loopback addresses */
|
||||||
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
|
if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
|
||||||
|
ip6_addr_isloopback(ip6_current_dest_addr())) {
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
|
||||||
IP6_STATS_INC(ip6.rterr);
|
IP6_STATS_INC(ip6.rterr);
|
||||||
IP6_STATS_INC(ip6.drop);
|
IP6_STATS_INC(ip6.drop);
|
||||||
@ -509,12 +506,21 @@ ip6_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
|
|
||||||
/* Do not match link-local addresses to other netifs. */
|
|
||||||
netif = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (first) {
|
if (first) {
|
||||||
|
if (ip6_addr_islinklocal(ip6_current_dest_addr())
|
||||||
|
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
|
||||||
|
|| ip6_addr_isloopback(ip6_current_dest_addr())
|
||||||
|
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
|
||||||
|
) {
|
||||||
|
/* Do not match link-local addresses to other netifs. The loopback
|
||||||
|
* address is to be considered link-local and packets to it should be
|
||||||
|
* dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This
|
||||||
|
* requirement cannot be implemented in the case that loopback
|
||||||
|
* traffic is sent across a non-loopback interface, however.
|
||||||
|
*/
|
||||||
|
netif = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
netif = netif_list;
|
netif = netif_list;
|
||||||
} else {
|
} else {
|
||||||
@ -709,7 +715,7 @@ netif_found:
|
|||||||
options_done:
|
options_done:
|
||||||
|
|
||||||
/* p points to IPv6 header again. */
|
/* p points to IPv6 header again. */
|
||||||
pbuf_header_force(p, ip_data.current_ip_header_tot_len);
|
pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len);
|
||||||
|
|
||||||
/* send to upper layers */
|
/* send to upper layers */
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
|
||||||
|
@ -132,8 +132,8 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
|||||||
} else if (isxdigit(*s)) {
|
} else if (isxdigit(*s)) {
|
||||||
/* add current digit */
|
/* add current digit */
|
||||||
current_block_value = (current_block_value << 4) +
|
current_block_value = (current_block_value << 4) +
|
||||||
(isdigit(*s) ? *s - '0' :
|
(isdigit(*s) ? (u32_t)(*s - '0') :
|
||||||
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
|
(u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
|
||||||
} else {
|
} else {
|
||||||
/* unexpected digit, space? CRLF? */
|
/* unexpected digit, space? CRLF? */
|
||||||
break;
|
break;
|
||||||
|
@ -379,6 +379,7 @@ ip6_reass(struct pbuf *p)
|
|||||||
/* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4).
|
/* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4).
|
||||||
This cannot fail since we already checked when receiving this fragment. */
|
This cannot fail since we already checked when receiving this fragment. */
|
||||||
u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
|
u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM);
|
||||||
|
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||||
}
|
}
|
||||||
#else /* IPV6_FRAG_COPYHEADER */
|
#else /* IPV6_FRAG_COPYHEADER */
|
||||||
@ -530,6 +531,7 @@ ip6_reass(struct pbuf *p)
|
|||||||
if (IPV6_FRAG_REQROOM > 0) {
|
if (IPV6_FRAG_REQROOM > 0) {
|
||||||
/* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */
|
/* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */
|
||||||
u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
|
u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM));
|
||||||
|
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -546,6 +548,7 @@ ip6_reass(struct pbuf *p)
|
|||||||
if (IPV6_FRAG_REQROOM > 0) {
|
if (IPV6_FRAG_REQROOM > 0) {
|
||||||
/* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */
|
/* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */
|
||||||
u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
|
u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM));
|
||||||
|
LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0);
|
||||||
}
|
}
|
||||||
iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
|
iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN);
|
||||||
@ -610,6 +613,7 @@ nullreturn:
|
|||||||
|
|
||||||
#if LWIP_IPV6 && LWIP_IPV6_FRAG
|
#if LWIP_IPV6 && LWIP_IPV6_FRAG
|
||||||
|
|
||||||
|
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
/** Allocate a new struct pbuf_custom_ref */
|
/** Allocate a new struct pbuf_custom_ref */
|
||||||
static struct pbuf_custom_ref*
|
static struct pbuf_custom_ref*
|
||||||
ip6_frag_alloc_pbuf_custom_ref(void)
|
ip6_frag_alloc_pbuf_custom_ref(void)
|
||||||
@ -638,6 +642,7 @@ ip6_frag_free_pbuf_custom(struct pbuf *p)
|
|||||||
}
|
}
|
||||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||||
}
|
}
|
||||||
|
#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
||||||
@ -658,7 +663,11 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||||||
struct ip6_hdr *ip6hdr;
|
struct ip6_hdr *ip6hdr;
|
||||||
struct ip6_frag_hdr *frag_hdr;
|
struct ip6_frag_hdr *frag_hdr;
|
||||||
struct pbuf *rambuf;
|
struct pbuf *rambuf;
|
||||||
|
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
struct pbuf *newpbuf;
|
struct pbuf *newpbuf;
|
||||||
|
u16_t newpbuflen = 0;
|
||||||
|
u16_t left_to_copy;
|
||||||
|
#endif
|
||||||
static u32_t identification;
|
static u32_t identification;
|
||||||
u16_t nfb;
|
u16_t nfb;
|
||||||
u16_t left, cop;
|
u16_t left, cop;
|
||||||
@ -666,8 +675,6 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||||||
u16_t fragment_offset = 0;
|
u16_t fragment_offset = 0;
|
||||||
u16_t last;
|
u16_t last;
|
||||||
u16_t poff = IP6_HLEN;
|
u16_t poff = IP6_HLEN;
|
||||||
u16_t newpbuflen = 0;
|
|
||||||
u16_t left_to_copy;
|
|
||||||
|
|
||||||
identification++;
|
identification++;
|
||||||
|
|
||||||
@ -686,6 +693,26 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||||||
/* Fill this fragment */
|
/* Fill this fragment */
|
||||||
cop = last ? left : nfb;
|
cop = last ? left : nfb;
|
||||||
|
|
||||||
|
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||||
|
rambuf = pbuf_alloc(PBUF_IP, cop + 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!",
|
||||||
|
(rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
|
||||||
|
poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff);
|
||||||
|
/* make room for the IP header */
|
||||||
|
if (pbuf_header(rambuf, IP6_HLEN)) {
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
/* fill in the IP header */
|
||||||
|
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);
|
||||||
|
#else
|
||||||
/* When not using a static buffer, create a chain of pbufs.
|
/* 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 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,
|
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
|
||||||
@ -744,6 +771,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
poff = newpbuflen;
|
poff = newpbuflen;
|
||||||
|
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||||
|
|
||||||
/* Set headers */
|
/* Set headers */
|
||||||
frag_hdr->_nexth = original_ip6hdr->_nexth;
|
frag_hdr->_nexth = original_ip6hdr->_nexth;
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include "lwip/nd6.h"
|
#include "lwip/nd6.h"
|
||||||
|
#include "lwip/priv/nd6_priv.h"
|
||||||
#include "lwip/prot/nd6.h"
|
#include "lwip/prot/nd6.h"
|
||||||
#include "lwip/prot/icmp6.h"
|
#include "lwip/prot/icmp6.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
@ -59,6 +60,7 @@
|
|||||||
#include "lwip/mld6.h"
|
#include "lwip/mld6.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -93,10 +95,13 @@ static void nd6_free_neighbor_cache_entry(s8_t i);
|
|||||||
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
|
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
|
||||||
static s8_t nd6_new_destination_cache_entry(void);
|
static s8_t nd6_new_destination_cache_entry(void);
|
||||||
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
|
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||||
|
static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||||
static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
|
static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
|
||||||
static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
|
static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
|
||||||
static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
||||||
static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif);
|
||||||
|
static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||||
|
static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q);
|
||||||
|
|
||||||
#define ND6_SEND_FLAG_MULTICAST_DEST 0x01
|
#define ND6_SEND_FLAG_MULTICAST_DEST 0x01
|
||||||
#define ND6_SEND_FLAG_ALLNODES_DEST 0x02
|
#define ND6_SEND_FLAG_ALLNODES_DEST 0x02
|
||||||
@ -155,25 +160,6 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
* link-layer changed?
|
* link-layer changed?
|
||||||
* part of DAD mechanism? */
|
* part of DAD mechanism? */
|
||||||
|
|
||||||
/* Check that link-layer address option also fits in packet. */
|
|
||||||
if (p->len < (sizeof(struct na_header) + 2)) {
|
|
||||||
/* @todo debug message */
|
|
||||||
pbuf_free(p);
|
|
||||||
ND6_STATS_INC(nd6.lenerr);
|
|
||||||
ND6_STATS_INC(nd6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
|
|
||||||
|
|
||||||
if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
|
|
||||||
/* @todo debug message */
|
|
||||||
pbuf_free(p);
|
|
||||||
ND6_STATS_INC(nd6.lenerr);
|
|
||||||
ND6_STATS_INC(nd6.drop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an aligned copy. */
|
/* Create an aligned copy. */
|
||||||
ip6_addr_set(&target_address, &(na_hdr->target_address));
|
ip6_addr_set(&target_address, &(na_hdr->target_address));
|
||||||
|
|
||||||
@ -185,12 +171,6 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* We are using a duplicate address. */
|
/* We are using a duplicate address. */
|
||||||
netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
|
netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
|
||||||
|
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
/* Leave solicited node multicast group. */
|
|
||||||
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]);
|
|
||||||
mld6_leavegroup_netif(inp, &multicast_address);
|
|
||||||
#endif /* LWIP_IPV6_MLD */
|
|
||||||
|
|
||||||
#if LWIP_IPV6_AUTOCONFIG
|
#if LWIP_IPV6_AUTOCONFIG
|
||||||
/* Check to see if this address was autoconfigured. */
|
/* Check to see if this address was autoconfigured. */
|
||||||
if (!ip6_addr_islinklocal(&target_address)) {
|
if (!ip6_addr_islinklocal(&target_address)) {
|
||||||
@ -209,6 +189,25 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
|
#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
|
||||||
|
|
||||||
|
/* Check that link-layer address option also fits in packet. */
|
||||||
|
if (p->len < (sizeof(struct na_header) + 2)) {
|
||||||
|
/* @todo debug message */
|
||||||
|
pbuf_free(p);
|
||||||
|
ND6_STATS_INC(nd6.lenerr);
|
||||||
|
ND6_STATS_INC(nd6.drop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
|
||||||
|
|
||||||
|
if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
|
||||||
|
/* @todo debug message */
|
||||||
|
pbuf_free(p);
|
||||||
|
ND6_STATS_INC(nd6.lenerr);
|
||||||
|
ND6_STATS_INC(nd6.drop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is an unsolicited NA, most likely there was a LLADDR change. */
|
/* This is an unsolicited NA, most likely there was a LLADDR change. */
|
||||||
i = nd6_find_neighbor_cache_entry(&target_address);
|
i = nd6_find_neighbor_cache_entry(&target_address);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
@ -390,6 +389,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
struct ra_header *ra_hdr;
|
struct ra_header *ra_hdr;
|
||||||
u8_t *buffer; /* Used to copy options. */
|
u8_t *buffer; /* Used to copy options. */
|
||||||
u16_t offset;
|
u16_t offset;
|
||||||
|
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||||
|
/* There can by multiple RDNSS options per RA */
|
||||||
|
u8_t rdnss_server_idx = 0;
|
||||||
|
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
|
||||||
|
|
||||||
/* Check that RA header fits in packet. */
|
/* Check that RA header fits in packet. */
|
||||||
if (p->len < sizeof(struct ra_header)) {
|
if (p->len < sizeof(struct ra_header)) {
|
||||||
@ -534,6 +537,37 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
route_opt = (struct route_option *)buffer;*/
|
route_opt = (struct route_option *)buffer;*/
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||||
|
case ND6_OPTION_TYPE_RDNSS:
|
||||||
|
{
|
||||||
|
u8_t num, n;
|
||||||
|
struct rdnss_option * rdnss_opt;
|
||||||
|
|
||||||
|
rdnss_opt = (struct rdnss_option *)buffer;
|
||||||
|
num = (rdnss_opt->length - 1) / 2;
|
||||||
|
for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
|
||||||
|
ip_addr_t rdnss_address;
|
||||||
|
|
||||||
|
/* Get a memory-aligned copy of the prefix. */
|
||||||
|
ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]);
|
||||||
|
|
||||||
|
if (htonl(rdnss_opt->lifetime) > 0) {
|
||||||
|
/* TODO implement Lifetime > 0 */
|
||||||
|
dns_setserver(rdnss_server_idx++, &rdnss_address);
|
||||||
|
} else {
|
||||||
|
/* TODO implement DNS removal in dns.c */
|
||||||
|
u8_t s;
|
||||||
|
for (s = 0; s < DNS_MAX_SERVERS; s++) {
|
||||||
|
const ip_addr_t *addr = dns_getserver(s);
|
||||||
|
if(ip_addr_cmp(addr, &rdnss_address)) {
|
||||||
|
dns_setserver(s, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
|
||||||
default:
|
default:
|
||||||
/* Unrecognized option, abort. */
|
/* Unrecognized option, abort. */
|
||||||
ND6_STATS_INC(nd6.proterr);
|
ND6_STATS_INC(nd6.proterr);
|
||||||
@ -549,6 +583,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
{
|
{
|
||||||
struct redirect_header *redir_hdr;
|
struct redirect_header *redir_hdr;
|
||||||
struct lladdr_option *lladdr_opt;
|
struct lladdr_option *lladdr_opt;
|
||||||
|
ip6_addr_t tmp;
|
||||||
|
|
||||||
/* Check that Redir header fits in packet. */
|
/* Check that Redir header fits in packet. */
|
||||||
if (p->len < sizeof(struct redirect_header)) {
|
if (p->len < sizeof(struct redirect_header)) {
|
||||||
@ -571,10 +606,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy original destination address to current source address, to have an aligned copy. */
|
/* Copy original destination address to current source address, to have an aligned copy. */
|
||||||
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address));
|
ip6_addr_set(&tmp, &(redir_hdr->destination_address));
|
||||||
|
|
||||||
/* Find dest address in cache */
|
/* Find dest address in cache */
|
||||||
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
|
i = nd6_find_destination_cache_entry(&tmp);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
/* Destination not in cache, drop packet. */
|
/* Destination not in cache, drop packet. */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@ -588,15 +623,15 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
if (lladdr_opt != NULL) {
|
if (lladdr_opt != NULL) {
|
||||||
if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
|
if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
|
||||||
/* Copy target address to current source address, to have an aligned copy. */
|
/* Copy target address to current source address, to have an aligned copy. */
|
||||||
ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address));
|
ip6_addr_set(&tmp, &(redir_hdr->target_address));
|
||||||
|
|
||||||
i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
|
i = nd6_find_neighbor_cache_entry(&tmp);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
i = nd6_new_neighbor_cache_entry();
|
i = nd6_new_neighbor_cache_entry();
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
neighbor_cache[i].netif = inp;
|
neighbor_cache[i].netif = inp;
|
||||||
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
|
MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
|
||||||
ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
|
ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp);
|
||||||
|
|
||||||
/* Receiving a message does not prove reachability: only in one direction.
|
/* Receiving a message does not prove reachability: only in one direction.
|
||||||
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
|
||||||
@ -622,6 +657,7 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
struct icmp6_hdr *icmp6hdr; /* Packet too big message */
|
struct icmp6_hdr *icmp6hdr; /* Packet too big message */
|
||||||
struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
|
struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
|
||||||
u32_t pmtu;
|
u32_t pmtu;
|
||||||
|
ip6_addr_t tmp;
|
||||||
|
|
||||||
/* Check that ICMPv6 header + IPv6 header fit in payload */
|
/* Check that ICMPv6 header + IPv6 header fit in payload */
|
||||||
if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) {
|
if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) {
|
||||||
@ -636,10 +672,10 @@ nd6_input(struct pbuf *p, struct netif *inp)
|
|||||||
ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr));
|
ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr));
|
||||||
|
|
||||||
/* Copy original destination address to current source address, to have an aligned copy. */
|
/* Copy original destination address to current source address, to have an aligned copy. */
|
||||||
ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest));
|
ip6_addr_set(&tmp, &(ip6hdr->dest));
|
||||||
|
|
||||||
/* Look for entry in destination cache. */
|
/* Look for entry in destination cache. */
|
||||||
i = nd6_find_destination_cache_entry(ip6_current_src_addr());
|
i = nd6_find_destination_cache_entry(&tmp);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
/* Destination not in cache, drop packet. */
|
/* Destination not in cache, drop packet. */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@ -829,13 +865,6 @@ nd6_tmr(void)
|
|||||||
netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
|
netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
|
||||||
/* @todo implement preferred and valid lifetimes. */
|
/* @todo implement preferred and valid lifetimes. */
|
||||||
} else if (netif->flags & NETIF_FLAG_UP) {
|
} else if (netif->flags & NETIF_FLAG_UP) {
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) == 0) {
|
|
||||||
/* Join solicited node multicast group. */
|
|
||||||
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]);
|
|
||||||
mld6_joingroup_netif(netif, &multicast_address);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6_MLD */
|
|
||||||
/* Send a NS for this address. */
|
/* Send a NS for this address. */
|
||||||
nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST);
|
nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST);
|
||||||
/* tentative: set next state by increasing by one */
|
/* tentative: set next state by increasing by one */
|
||||||
@ -1293,6 +1322,22 @@ nd6_new_destination_cache_entry(void)
|
|||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the destination cache.
|
||||||
|
*
|
||||||
|
* This operation may be necessary for consistency in the light of changing
|
||||||
|
* local addresses and/or use of the gateway hook.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nd6_clear_destination_cache(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
|
||||||
|
ip6_addr_set_any(&destination_cache[i].destination_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether an address matches an on-link prefix.
|
* Determine whether an address matches an on-link prefix.
|
||||||
*
|
*
|
||||||
@ -1328,7 +1373,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
|
|||||||
* @return the default router entry index, or -1 if no suitable
|
* @return the default router entry index, or -1 if no suitable
|
||||||
* router is found
|
* router is found
|
||||||
*/
|
*/
|
||||||
s8_t
|
static s8_t
|
||||||
nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
|
nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||||
{
|
{
|
||||||
s8_t i;
|
s8_t i;
|
||||||
@ -1380,6 +1425,30 @@ nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a router-announced route to the given destination.
|
||||||
|
*
|
||||||
|
* The caller is responsible for checking whether the returned netif, if any,
|
||||||
|
* is in a suitable state (up, link up) to be used for packet transmission.
|
||||||
|
*
|
||||||
|
* @param ip6addr the destination IPv6 address
|
||||||
|
* @return the netif to use for the destination, or NULL if none found
|
||||||
|
*/
|
||||||
|
struct netif *
|
||||||
|
nd6_find_route(const ip6_addr_t *ip6addr)
|
||||||
|
{
|
||||||
|
s8_t i;
|
||||||
|
|
||||||
|
i = nd6_select_router(ip6addr, NULL);
|
||||||
|
if (i >= 0) {
|
||||||
|
if (default_router_list[i].neighbor_entry != NULL) {
|
||||||
|
return default_router_list[i].neighbor_entry->netif; /* may be NULL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find an entry for a default router.
|
* Find an entry for a default router.
|
||||||
*
|
*
|
||||||
@ -1416,6 +1485,7 @@ static s8_t
|
|||||||
nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
|
nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
|
||||||
{
|
{
|
||||||
s8_t router_index;
|
s8_t router_index;
|
||||||
|
s8_t free_router_index;
|
||||||
s8_t neighbor_index;
|
s8_t neighbor_index;
|
||||||
|
|
||||||
/* Do we have a neighbor entry for this router? */
|
/* Do we have a neighbor entry for this router? */
|
||||||
@ -1439,11 +1509,21 @@ nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
|
|||||||
neighbor_cache[neighbor_index].isrouter = 1;
|
neighbor_cache[neighbor_index].isrouter = 1;
|
||||||
|
|
||||||
/* Look for empty entry. */
|
/* Look for empty entry. */
|
||||||
for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) {
|
free_router_index = LWIP_ND6_NUM_ROUTERS;
|
||||||
if (default_router_list[router_index].neighbor_entry == NULL) {
|
for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) {
|
||||||
default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
|
/* check if router already exists (this is a special case for 2 netifs on the same subnet
|
||||||
|
- e.g. wifi and cable) */
|
||||||
|
if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){
|
||||||
return router_index;
|
return router_index;
|
||||||
}
|
}
|
||||||
|
if (default_router_list[router_index].neighbor_entry == NULL) {
|
||||||
|
/* remember lowest free index to create a new entry */
|
||||||
|
free_router_index = router_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (free_router_index < LWIP_ND6_NUM_ROUTERS) {
|
||||||
|
default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
|
||||||
|
return free_router_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Could not create a router entry. */
|
/* Could not create a router entry. */
|
||||||
@ -1521,9 +1601,12 @@ nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif)
|
|||||||
* suitable next hop was found, ERR_MEM if no cache entry
|
* suitable next hop was found, ERR_MEM if no cache entry
|
||||||
* could be created
|
* could be created
|
||||||
*/
|
*/
|
||||||
s8_t
|
static s8_t
|
||||||
nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
|
nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
|
||||||
{
|
{
|
||||||
|
#ifdef LWIP_HOOK_ND6_GET_GW
|
||||||
|
const ip6_addr_t *next_hop_addr;
|
||||||
|
#endif /* LWIP_HOOK_ND6_GET_GW */
|
||||||
s8_t i;
|
s8_t i;
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
@ -1567,6 +1650,12 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
|
|||||||
/* Destination in local link. */
|
/* Destination in local link. */
|
||||||
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
|
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
|
||||||
ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
|
ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
|
||||||
|
#ifdef LWIP_HOOK_ND6_GET_GW
|
||||||
|
} else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) {
|
||||||
|
/* Next hop for destination provided by hook function. */
|
||||||
|
destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
|
||||||
|
ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr);
|
||||||
|
#endif /* LWIP_HOOK_ND6_GET_GW */
|
||||||
} else {
|
} else {
|
||||||
/* We need to select a router. */
|
/* We need to select a router. */
|
||||||
i = nd6_select_router(ip6addr, netif);
|
i = nd6_select_router(ip6addr, netif);
|
||||||
@ -1634,7 +1723,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
|
|||||||
* @param q packet to be queued
|
* @param q packet to be queued
|
||||||
* @return ERR_OK if succeeded, ERR_MEM if out of memory
|
* @return ERR_OK if succeeded, ERR_MEM if out of memory
|
||||||
*/
|
*/
|
||||||
err_t
|
static err_t
|
||||||
nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
|
nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
|
||||||
{
|
{
|
||||||
err_t result = ERR_MEM;
|
err_t result = ERR_MEM;
|
||||||
@ -1811,6 +1900,61 @@ nd6_send_q(s8_t i)
|
|||||||
#endif /* LWIP_ND6_QUEUEING */
|
#endif /* LWIP_ND6_QUEUEING */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A packet is to be transmitted to a specific IPv6 destination on a specific
|
||||||
|
* interface. Check if we can find the hardware address of the next hop to use
|
||||||
|
* for the packet. If so, give the hardware address to the caller, which should
|
||||||
|
* use it to send the packet right away. Otherwise, enqueue the packet for
|
||||||
|
* later transmission while looking up the hardware address, if possible.
|
||||||
|
*
|
||||||
|
* As such, this function returns one of three different possible results:
|
||||||
|
*
|
||||||
|
* - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now.
|
||||||
|
* - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later.
|
||||||
|
* - not ERR_OK: something went wrong; forward the error upward in the stack.
|
||||||
|
*
|
||||||
|
* @param netif The lwIP network interface on which the IP packet will be sent.
|
||||||
|
* @param q The pbuf(s) containing the IP packet to be sent.
|
||||||
|
* @param ip6addr The destination IPv6 address of the packet.
|
||||||
|
* @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning
|
||||||
|
* the packet has been queued).
|
||||||
|
* @return
|
||||||
|
* - ERR_OK on success, ERR_RTE if no route was found for the packet,
|
||||||
|
* or ERR_MEM if low memory conditions prohibit sending the packet at all.
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp)
|
||||||
|
{
|
||||||
|
s8_t i;
|
||||||
|
|
||||||
|
/* Get next hop record. */
|
||||||
|
i = nd6_get_next_hop_entry(ip6addr, netif);
|
||||||
|
if (i < 0) {
|
||||||
|
/* failed to get a next hop neighbor record. */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 / ND6_TMR_INTERVAL;
|
||||||
|
}
|
||||||
|
/* @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)) {
|
||||||
|
|
||||||
|
/* Tell the caller to send out the packet now. */
|
||||||
|
*hwaddrp = neighbor_cache[i].lladdr;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should queue packet on this interface. */
|
||||||
|
*hwaddrp = NULL;
|
||||||
|
return nd6_queue_packet(i, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Path MTU for a destination.
|
* Get the Path MTU for a destination.
|
||||||
@ -1917,4 +2061,38 @@ nd6_cleanup_netif(struct netif *netif)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
/**
|
||||||
|
* The state of a local IPv6 address entry is about to change. If needed, join
|
||||||
|
* or leave the solicited-node multicast group for the address.
|
||||||
|
*
|
||||||
|
* @param netif The netif that owns the address.
|
||||||
|
* @param addr_idx The index of the address.
|
||||||
|
* @param new_state The new (IP6_ADDR_) state for the address.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state)
|
||||||
|
{
|
||||||
|
u8_t old_state, old_member, new_member;
|
||||||
|
|
||||||
|
old_state = netif_ip6_addr_state(netif, addr_idx);
|
||||||
|
|
||||||
|
/* Determine whether we were, and should be, a member of the solicited-node
|
||||||
|
* multicast group for this address. For tentative addresses, the group is
|
||||||
|
* not joined until the address enters the TENTATIVE_1 (or VALID) state. */
|
||||||
|
old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE);
|
||||||
|
new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE);
|
||||||
|
|
||||||
|
if (old_member != new_member) {
|
||||||
|
ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]);
|
||||||
|
|
||||||
|
if (new_member) {
|
||||||
|
mld6_joingroup_netif(netif, &multicast_address);
|
||||||
|
} else {
|
||||||
|
mld6_leavegroup_netif(netif, &multicast_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
@ -61,9 +61,13 @@
|
|||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
#if MEM_LIBC_MALLOC
|
||||||
|
#include <stdlib.h> /* for malloc()/free() */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MEM_LIBC_MALLOC || MEM_USE_POOLS
|
#if MEM_LIBC_MALLOC || MEM_USE_POOLS
|
||||||
|
|
||||||
/** mem_init is not used when using pools instead of a heap or using
|
/** mem_init is not used when using pools instead of a heap or using
|
||||||
* C library malloc().
|
* C library malloc().
|
||||||
*/
|
*/
|
||||||
@ -162,7 +166,7 @@ void *
|
|||||||
mem_malloc(mem_size_t size)
|
mem_malloc(mem_size_t size)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
struct memp_malloc_helper *element;
|
struct memp_malloc_helper *element = NULL;
|
||||||
memp_t poolnr;
|
memp_t poolnr;
|
||||||
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
#include "netif/ppp/ppp_opts.h"
|
#include "netif/ppp/ppp_opts.h"
|
||||||
#include "lwip/netdb.h"
|
#include "lwip/netdb.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#include "lwip/nd6.h"
|
#include "lwip/priv/nd6_priv.h"
|
||||||
#include "lwip/ip6_frag.h"
|
#include "lwip/ip6_frag.h"
|
||||||
#include "lwip/mld6.h"
|
#include "lwip/mld6.h"
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ memp_overflow_check_all(void)
|
|||||||
for (j = 0; j < memp_pools[i]->num; ++j) {
|
for (j = 0; j < memp_pools[i]->num; ++j) {
|
||||||
memp_overflow_check_element_overflow(p, memp_pools[i]);
|
memp_overflow_check_element_overflow(p, memp_pools[i]);
|
||||||
memp_overflow_check_element_underflow(p, memp_pools[i]);
|
memp_overflow_check_element_underflow(p, memp_pools[i]);
|
||||||
p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
@ -301,15 +301,15 @@ do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int
|
|||||||
SYS_ARCH_PROTECT(old_level);
|
SYS_ARCH_PROTECT(old_level);
|
||||||
|
|
||||||
memp = *desc->tab;
|
memp = *desc->tab;
|
||||||
|
|
||||||
#if MEMP_OVERFLOW_CHECK == 1
|
|
||||||
memp_overflow_check_element_overflow(memp, desc);
|
|
||||||
memp_overflow_check_element_underflow(memp, desc);
|
|
||||||
#endif /* MEMP_OVERFLOW_CHECK */
|
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
#endif /* MEMP_MEM_MALLOC */
|
||||||
|
|
||||||
if (memp != NULL) {
|
if (memp != NULL) {
|
||||||
#if !MEMP_MEM_MALLOC
|
#if !MEMP_MEM_MALLOC
|
||||||
|
#if MEMP_OVERFLOW_CHECK == 1
|
||||||
|
memp_overflow_check_element_overflow(memp, desc);
|
||||||
|
memp_overflow_check_element_underflow(memp, desc);
|
||||||
|
#endif /* MEMP_OVERFLOW_CHECK */
|
||||||
|
|
||||||
*desc->tab = memp->next;
|
*desc->tab = memp->next;
|
||||||
#if MEMP_OVERFLOW_CHECK
|
#if MEMP_OVERFLOW_CHECK
|
||||||
memp->next = NULL;
|
memp->next = NULL;
|
||||||
|
106
src/core/netif.c
106
src/core/netif.c
@ -180,7 +180,7 @@ netif_init(void)
|
|||||||
#endif /* NO_SYS */
|
#endif /* NO_SYS */
|
||||||
|
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL));
|
IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
|
||||||
loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
|
loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
@ -415,7 +415,7 @@ netif_remove(struct netif *netif)
|
|||||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,7 +478,7 @@ netif_find(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = name[2] - '0';
|
num = (u8_t)(name[2] - '0');
|
||||||
|
|
||||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
if (num == netif->num &&
|
if (num == netif->num &&
|
||||||
@ -904,7 +904,6 @@ netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* ad
|
|||||||
void
|
void
|
||||||
netif_poll(struct netif *netif)
|
netif_poll(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct pbuf *in;
|
|
||||||
/* If we have a loopif, SNMP counters are adjusted for it,
|
/* If we have a loopif, SNMP counters are adjusted for it,
|
||||||
* if not they are adjusted for 'netif'. */
|
* if not they are adjusted for 'netif'. */
|
||||||
#if MIB2_STATS
|
#if MIB2_STATS
|
||||||
@ -916,56 +915,52 @@ netif_poll(struct netif *netif)
|
|||||||
#endif /* MIB2_STATS */
|
#endif /* MIB2_STATS */
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
SYS_ARCH_DECL_PROTECT(lev);
|
||||||
|
|
||||||
do {
|
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
SYS_ARCH_PROTECT(lev);
|
||||||
SYS_ARCH_PROTECT(lev);
|
while (netif->loop_first != NULL) {
|
||||||
in = netif->loop_first;
|
struct pbuf *in, *in_end;
|
||||||
if (in != NULL) {
|
|
||||||
struct pbuf *in_end = in;
|
|
||||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||||
u8_t clen = 1;
|
u8_t clen = 1;
|
||||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
|
||||||
while (in_end->len != in_end->tot_len) {
|
|
||||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
|
||||||
in_end = in_end->next;
|
|
||||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
|
||||||
clen++;
|
|
||||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
|
||||||
}
|
|
||||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
|
||||||
/* adjust the number of pbufs on queue */
|
|
||||||
LWIP_ASSERT("netif->loop_cnt_current underflow",
|
|
||||||
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
|
||||||
netif->loop_cnt_current -= clen;
|
|
||||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||||
|
|
||||||
/* 'in_end' now points to the last pbuf from 'in' */
|
in = in_end = netif->loop_first;
|
||||||
if (in_end == netif->loop_last) {
|
while (in_end->len != in_end->tot_len) {
|
||||||
/* this was the last pbuf in the list */
|
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||||
netif->loop_first = netif->loop_last = NULL;
|
in_end = in_end->next;
|
||||||
} else {
|
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||||
/* pop the pbuf off the list */
|
clen++;
|
||||||
netif->loop_first = in_end->next;
|
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||||
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
|
||||||
}
|
|
||||||
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
|
||||||
in_end->next = NULL;
|
|
||||||
}
|
}
|
||||||
|
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||||
|
/* adjust the number of pbufs on queue */
|
||||||
|
LWIP_ASSERT("netif->loop_cnt_current underflow",
|
||||||
|
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
||||||
|
netif->loop_cnt_current -= clen;
|
||||||
|
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||||
|
|
||||||
|
/* 'in_end' now points to the last pbuf from 'in' */
|
||||||
|
if (in_end == netif->loop_last) {
|
||||||
|
/* this was the last pbuf in the list */
|
||||||
|
netif->loop_first = netif->loop_last = NULL;
|
||||||
|
} else {
|
||||||
|
/* pop the pbuf off the list */
|
||||||
|
netif->loop_first = in_end->next;
|
||||||
|
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
||||||
|
}
|
||||||
|
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
||||||
|
in_end->next = NULL;
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
|
|
||||||
if (in != NULL) {
|
LINK_STATS_INC(link.recv);
|
||||||
LINK_STATS_INC(link.recv);
|
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
|
||||||
MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
|
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
|
||||||
MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
|
/* loopback packets are always IP packets! */
|
||||||
/* loopback packets are always IP packets! */
|
if (ip_input(in, netif) != ERR_OK) {
|
||||||
if (ip_input(in, netif) != ERR_OK) {
|
pbuf_free(in);
|
||||||
pbuf_free(in);
|
|
||||||
}
|
|
||||||
/* Don't reference the packet any more! */
|
|
||||||
in = NULL;
|
|
||||||
}
|
}
|
||||||
/* go on while there is a packet on the list */
|
SYS_ARCH_PROTECT(lev);
|
||||||
} while (netif->loop_first != NULL);
|
}
|
||||||
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
@ -1058,7 +1053,7 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1,
|
|||||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
}
|
}
|
||||||
/* @todo: remove/readd mib2 ip6 entries? */
|
/* @todo: remove/readd mib2 ip6 entries? */
|
||||||
@ -1101,6 +1096,13 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
|
|||||||
u8_t new_valid = state & IP6_ADDR_VALID;
|
u8_t new_valid = state & IP6_ADDR_VALID;
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
|
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
|
||||||
|
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
/* Reevaluate solicited-node multicast group membership. */
|
||||||
|
if (netif->flags & NETIF_FLAG_MLD6) {
|
||||||
|
nd6_adjust_mld_membership(netif, addr_idx, state);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
|
||||||
if (old_valid && !new_valid) {
|
if (old_valid && !new_valid) {
|
||||||
/* address about to be removed by setting invalid */
|
/* address about to be removed by setting invalid */
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
@ -1110,7 +1112,7 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
|
|||||||
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
/* @todo: remove mib2 ip6 entries? */
|
/* @todo: remove mib2 ip6 entries? */
|
||||||
}
|
}
|
||||||
@ -1200,10 +1202,10 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
|
|||||||
/* Set address state. */
|
/* Set address state. */
|
||||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||||
/* Will perform duplicate address detection (DAD). */
|
/* Will perform duplicate address detection (DAD). */
|
||||||
netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
|
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
|
||||||
#else
|
#else
|
||||||
/* Consider address valid. */
|
/* Consider address valid. */
|
||||||
netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
|
netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
|
||||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1233,7 +1235,7 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos
|
|||||||
|
|
||||||
/* Find a free slot -- musn't be the first one (reserved for link local) */
|
/* Find a free slot -- musn't be the first one (reserved for link local) */
|
||||||
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
|
if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
|
||||||
ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
|
ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
|
||||||
netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
|
netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
|
||||||
if (chosen_idx != NULL) {
|
if (chosen_idx != NULL) {
|
||||||
|
@ -568,11 +568,11 @@ pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (header_size_increment < 0) {
|
if (header_size_increment < 0) {
|
||||||
increment_magnitude = -header_size_increment;
|
increment_magnitude = (u16_t)-header_size_increment;
|
||||||
/* Check that we aren't going to move off the end of the pbuf */
|
/* Check that we aren't going to move off the end of the pbuf */
|
||||||
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
|
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
|
||||||
} else {
|
} else {
|
||||||
increment_magnitude = header_size_increment;
|
increment_magnitude = (u16_t)header_size_increment;
|
||||||
#if 0
|
#if 0
|
||||||
/* Can't assert these as some callers speculatively call
|
/* Can't assert these as some callers speculatively call
|
||||||
pbuf_header() to see if it's OK. Will return 1 below instead. */
|
pbuf_header() to see if it's OK. Will return 1 below instead. */
|
||||||
@ -1119,7 +1119,8 @@ pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset)
|
|||||||
struct pbuf*
|
struct pbuf*
|
||||||
pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
|
pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
|
||||||
{
|
{
|
||||||
return (struct pbuf*)(size_t)pbuf_skip_const(in, in_offset, out_offset);
|
const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset);
|
||||||
|
return LWIP_CONST_CAST(struct pbuf*, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1227,6 +1228,7 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
err = pbuf_copy(q, p);
|
err = pbuf_copy(q, p);
|
||||||
|
LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
|
||||||
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
|
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return q;
|
return q;
|
||||||
|
@ -209,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
err_t
|
err_t
|
||||||
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
||||||
{
|
{
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
|
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
|
||||||
@ -233,7 +233,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
|||||||
err_t
|
err_t
|
||||||
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
|
||||||
{
|
{
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
|
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
|
||||||
@ -320,7 +320,13 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
netif = ip_route(&pcb->local_ip, ipaddr);
|
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
||||||
|
/* Don't call ip_route() with IP_ANY_TYPE */
|
||||||
|
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
|
||||||
|
} else {
|
||||||
|
netif = ip_route(&pcb->local_ip, ipaddr);
|
||||||
|
}
|
||||||
|
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
|
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
|
||||||
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
|
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
|
||||||
|
@ -36,6 +36,44 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup sys_layer Porting (system abstraction layer)
|
||||||
|
* @ingroup lwip
|
||||||
|
* @verbinclude "sys_arch.txt"
|
||||||
|
*
|
||||||
|
* @defgroup sys_os OS abstraction layer
|
||||||
|
* @ingroup sys_layer
|
||||||
|
* No need to implement functions in this section in NO_SYS mode.
|
||||||
|
*
|
||||||
|
* @defgroup sys_sem Semaphores
|
||||||
|
* @ingroup sys_os
|
||||||
|
*
|
||||||
|
* @defgroup sys_mutex Mutexes
|
||||||
|
* @ingroup sys_os
|
||||||
|
* Mutexes are recommended to correctly handle priority inversion,
|
||||||
|
* especially if you use LWIP_CORE_LOCKING .
|
||||||
|
*
|
||||||
|
* @defgroup sys_mbox Mailboxes
|
||||||
|
* @ingroup sys_os
|
||||||
|
*
|
||||||
|
* @defgroup sys_time Time
|
||||||
|
* @ingroup sys_layer
|
||||||
|
*
|
||||||
|
* @defgroup sys_prot Critical sections
|
||||||
|
* @ingroup sys_layer
|
||||||
|
* Used to protect short regions of code against concurrent access.
|
||||||
|
* - Your system is a bare-metal system (probably with an RTOS)
|
||||||
|
* and interrupts are under your control:
|
||||||
|
* Implement this as LockInterrupts() / UnlockInterrupts()
|
||||||
|
* - Your system uses an RTOS with deferred interrupt handling from a
|
||||||
|
* worker thread: Implement as a global mutex or lock/unlock scheduler
|
||||||
|
* - Your system uses a high-level OS with e.g. POSIX signals:
|
||||||
|
* Implement as a global mutex
|
||||||
|
*
|
||||||
|
* @defgroup sys_misc Misc
|
||||||
|
* @ingroup sys_os
|
||||||
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
@ -551,7 +551,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
/* still need to check for ipaddr == NULL in IPv6 only case */
|
/* still need to check for ipaddr == NULL in IPv6 only case */
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,19 +636,44 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||||||
*
|
*
|
||||||
* @note The original tcp_pcb is freed. This function therefore has to be
|
* @note The original tcp_pcb is freed. This function therefore has to be
|
||||||
* called like this:
|
* called like this:
|
||||||
* tpcb = tcp_listen(tpcb);
|
* tpcb = tcp_listen_with_backlog(tpcb, backlog);
|
||||||
*/
|
*/
|
||||||
struct tcp_pcb *
|
struct tcp_pcb *
|
||||||
tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||||
{
|
{
|
||||||
struct tcp_pcb_listen *lpcb;
|
return tcp_listen_with_backlog_and_err(pcb, backlog, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tcp_raw
|
||||||
|
* Set the state of the connection to be LISTEN, which means that it
|
||||||
|
* is able to accept incoming connections. The protocol control block
|
||||||
|
* is reallocated in order to consume less memory. Setting the
|
||||||
|
* connection to LISTEN is an irreversible process.
|
||||||
|
*
|
||||||
|
* @param pcb the original tcp_pcb
|
||||||
|
* @param backlog the incoming connections queue limit
|
||||||
|
* @param err when NULL is returned, this contains the error reason
|
||||||
|
* @return tcp_pcb used for listening, consumes less memory.
|
||||||
|
*
|
||||||
|
* @note The original tcp_pcb is freed. This function therefore has to be
|
||||||
|
* called like this:
|
||||||
|
* tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err);
|
||||||
|
*/
|
||||||
|
struct tcp_pcb *
|
||||||
|
tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
||||||
|
{
|
||||||
|
struct tcp_pcb_listen *lpcb = NULL;
|
||||||
|
err_t res;
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(backlog);
|
LWIP_UNUSED_ARG(backlog);
|
||||||
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
|
LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done);
|
||||||
|
|
||||||
/* already listening? */
|
/* already listening? */
|
||||||
if (pcb->state == LISTEN) {
|
if (pcb->state == LISTEN) {
|
||||||
return pcb;
|
lpcb = (struct tcp_pcb_listen*)pcb;
|
||||||
|
res = ERR_ALREADY;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
#if SO_REUSE
|
#if SO_REUSE
|
||||||
if (ip_get_option(pcb, SOF_REUSEADDR)) {
|
if (ip_get_option(pcb, SOF_REUSEADDR)) {
|
||||||
@ -659,14 +684,17 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||||||
if ((lpcb->local_port == pcb->local_port) &&
|
if ((lpcb->local_port == pcb->local_port) &&
|
||||||
ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
||||||
/* this address/port is already used */
|
/* this address/port is already used */
|
||||||
return NULL;
|
lpcb = NULL;
|
||||||
|
res = ERR_USE;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
|
lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
|
||||||
if (lpcb == NULL) {
|
if (lpcb == NULL) {
|
||||||
return NULL;
|
res = ERR_MEM;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
lpcb->callback_arg = pcb->callback_arg;
|
lpcb->callback_arg = pcb->callback_arg;
|
||||||
lpcb->local_port = pcb->local_port;
|
lpcb->local_port = pcb->local_port;
|
||||||
@ -691,6 +719,11 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||||||
tcp_backlog_set(lpcb, backlog);
|
tcp_backlog_set(lpcb, backlog);
|
||||||
#endif /* TCP_LISTEN_BACKLOG */
|
#endif /* TCP_LISTEN_BACKLOG */
|
||||||
TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
|
TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
|
||||||
|
res = ERR_OK;
|
||||||
|
done:
|
||||||
|
if (err != NULL) {
|
||||||
|
*err = res;
|
||||||
|
}
|
||||||
return (struct tcp_pcb *)lpcb;
|
return (struct tcp_pcb *)lpcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,7 +859,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
|||||||
u32_t iss;
|
u32_t iss;
|
||||||
u16_t old_local_port;
|
u16_t old_local_port;
|
||||||
|
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,10 +913,11 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
|||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
}
|
}
|
||||||
|
|
||||||
iss = tcp_next_iss();
|
iss = tcp_next_iss(pcb);
|
||||||
pcb->rcv_nxt = 0;
|
pcb->rcv_nxt = 0;
|
||||||
pcb->snd_nxt = iss;
|
pcb->snd_nxt = iss;
|
||||||
pcb->lastack = iss - 1;
|
pcb->lastack = iss - 1;
|
||||||
|
pcb->snd_wl2 = iss - 1;
|
||||||
pcb->snd_lbb = iss - 1;
|
pcb->snd_lbb = iss - 1;
|
||||||
/* Start with a window that does not need scaling. When window scaling is
|
/* Start with a window that does not need scaling. When window scaling is
|
||||||
enabled and used, the window is enlarged when both sides agree on scaling. */
|
enabled and used, the window is enlarged when both sides agree on scaling. */
|
||||||
@ -1491,7 +1525,6 @@ struct tcp_pcb *
|
|||||||
tcp_alloc(u8_t prio)
|
tcp_alloc(u8_t prio)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
u32_t iss;
|
|
||||||
|
|
||||||
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
|
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
|
||||||
if (pcb == NULL) {
|
if (pcb == NULL) {
|
||||||
@ -1554,11 +1587,6 @@ tcp_alloc(u8_t prio)
|
|||||||
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
||||||
pcb->rtime = -1;
|
pcb->rtime = -1;
|
||||||
pcb->cwnd = 1;
|
pcb->cwnd = 1;
|
||||||
iss = tcp_next_iss();
|
|
||||||
pcb->snd_wl2 = iss;
|
|
||||||
pcb->snd_nxt = iss;
|
|
||||||
pcb->lastack = iss;
|
|
||||||
pcb->snd_lbb = iss;
|
|
||||||
pcb->tmr = tcp_ticks;
|
pcb->tmr = tcp_ticks;
|
||||||
pcb->last_timer = tcp_timer_ctr;
|
pcb->last_timer = tcp_timer_ctr;
|
||||||
|
|
||||||
@ -1826,12 +1854,18 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
|||||||
* @return u32_t pseudo random sequence number
|
* @return u32_t pseudo random sequence number
|
||||||
*/
|
*/
|
||||||
u32_t
|
u32_t
|
||||||
tcp_next_iss(void)
|
tcp_next_iss(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
#ifdef LWIP_HOOK_TCP_ISN
|
||||||
|
return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port);
|
||||||
|
#else /* LWIP_HOOK_TCP_ISN */
|
||||||
static u32_t iss = 6510;
|
static u32_t iss = 6510;
|
||||||
|
|
||||||
|
LWIP_UNUSED_ARG(pcb);
|
||||||
|
|
||||||
iss += tcp_ticks; /* XXX */
|
iss += tcp_ticks; /* XXX */
|
||||||
return iss;
|
return iss;
|
||||||
|
#endif /* LWIP_HOOK_TCP_ISN */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
|
@ -358,6 +358,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
((pcb->refused_data != NULL) && (tcplen > 0))) {
|
((pcb->refused_data != NULL) && (tcplen > 0))) {
|
||||||
/* pcb has been aborted or refused data is still refused and the new
|
/* pcb has been aborted or refused data is still refused and the new
|
||||||
segment contains data */
|
segment contains data */
|
||||||
|
if (pcb->rcv_ann_wnd == 0) {
|
||||||
|
/* this is a zero-window probe, we respond to it with current RCV.NXT
|
||||||
|
and drop the data segment */
|
||||||
|
tcp_send_empty_ack(pcb);
|
||||||
|
}
|
||||||
TCP_STATS_INC(tcp.drop);
|
TCP_STATS_INC(tcp.drop);
|
||||||
MIB2_STATS_INC(mib2.tcpinerrs);
|
MIB2_STATS_INC(mib2.tcpinerrs);
|
||||||
goto aborted;
|
goto aborted;
|
||||||
@ -542,6 +547,7 @@ static void
|
|||||||
tcp_listen_input(struct tcp_pcb_listen *pcb)
|
tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *npcb;
|
struct tcp_pcb *npcb;
|
||||||
|
u32_t iss;
|
||||||
err_t rc;
|
err_t rc;
|
||||||
|
|
||||||
if (flags & TCP_RST) {
|
if (flags & TCP_RST) {
|
||||||
@ -589,6 +595,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
npcb->state = SYN_RCVD;
|
npcb->state = SYN_RCVD;
|
||||||
npcb->rcv_nxt = seqno + 1;
|
npcb->rcv_nxt = seqno + 1;
|
||||||
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
|
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
|
||||||
|
iss = tcp_next_iss(npcb);
|
||||||
|
npcb->snd_wl2 = iss;
|
||||||
|
npcb->snd_nxt = iss;
|
||||||
|
npcb->lastack = iss;
|
||||||
|
npcb->snd_lbb = iss;
|
||||||
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
|
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
|
||||||
npcb->callback_arg = pcb->callback_arg;
|
npcb->callback_arg = pcb->callback_arg;
|
||||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||||
@ -602,7 +613,7 @@ 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);
|
||||||
npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd);
|
npcb->snd_wnd = tcphdr->wnd;
|
||||||
npcb->snd_wnd_max = npcb->snd_wnd;
|
npcb->snd_wnd_max = npcb->snd_wnd;
|
||||||
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
|
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
|
||||||
|
|
||||||
@ -751,7 +762,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
pcb->rcv_nxt = seqno + 1;
|
pcb->rcv_nxt = seqno + 1;
|
||||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
||||||
pcb->lastack = ackno;
|
pcb->lastack = ackno;
|
||||||
pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
|
pcb->snd_wnd = tcphdr->wnd;
|
||||||
pcb->snd_wnd_max = pcb->snd_wnd;
|
pcb->snd_wnd_max = pcb->snd_wnd;
|
||||||
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
|
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
|
||||||
pcb->state = ESTABLISHED;
|
pcb->state = ESTABLISHED;
|
||||||
|
@ -377,6 +377,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
u16_t oversize = 0;
|
u16_t oversize = 0;
|
||||||
u16_t oversize_used = 0;
|
u16_t oversize_used = 0;
|
||||||
#endif /* TCP_OVERSIZE */
|
#endif /* TCP_OVERSIZE */
|
||||||
|
u16_t extendlen = 0;
|
||||||
#if TCP_CHECKSUM_ON_COPY
|
#if TCP_CHECKSUM_ON_COPY
|
||||||
u16_t concat_chksum = 0;
|
u16_t concat_chksum = 0;
|
||||||
u8_t concat_chksum_swapped = 0;
|
u8_t concat_chksum_swapped = 0;
|
||||||
@ -480,6 +481,10 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
/*
|
/*
|
||||||
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
|
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
|
||||||
*
|
*
|
||||||
|
* As an exception when NOT copying the data, if the given data buffer
|
||||||
|
* directly follows the last unsent data buffer in memory, extend the last
|
||||||
|
* ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation.
|
||||||
|
*
|
||||||
* We don't extend segments containing SYN/FIN flags or options
|
* We don't extend segments containing SYN/FIN flags or options
|
||||||
* (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
|
* (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
|
||||||
* the end.
|
* the end.
|
||||||
@ -506,12 +511,24 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
#if TCP_CHECKSUM_ON_COPY
|
#if TCP_CHECKSUM_ON_COPY
|
||||||
concat_chksummed += seglen;
|
concat_chksummed += seglen;
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||||
|
queuelen += pbuf_clen(concat_p);
|
||||||
} else {
|
} else {
|
||||||
/* Data is not copied */
|
/* Data is not copied */
|
||||||
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
|
/* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
struct pbuf *p;
|
||||||
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
for (p = last_unsent->p; p->next != NULL; p = p->next);
|
||||||
goto memerr;
|
if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) {
|
||||||
|
LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0);
|
||||||
|
extendlen = seglen;
|
||||||
|
} else {
|
||||||
|
if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
|
||||||
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
|
("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
||||||
|
goto memerr;
|
||||||
|
}
|
||||||
|
/* reference the non-volatile payload data */
|
||||||
|
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
|
||||||
|
queuelen += pbuf_clen(concat_p);
|
||||||
}
|
}
|
||||||
#if TCP_CHECKSUM_ON_COPY
|
#if TCP_CHECKSUM_ON_COPY
|
||||||
/* calculate the checksum of nocopy-data */
|
/* calculate the checksum of nocopy-data */
|
||||||
@ -519,12 +536,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
&concat_chksum, &concat_chksum_swapped);
|
&concat_chksum, &concat_chksum_swapped);
|
||||||
concat_chksummed += seglen;
|
concat_chksummed += seglen;
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||||
/* reference the non-volatile payload data */
|
|
||||||
((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += seglen;
|
pos += seglen;
|
||||||
queuelen += pbuf_clen(concat_p);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if TCP_OVERSIZE
|
#if TCP_OVERSIZE
|
||||||
@ -669,26 +683,40 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
#endif /* TCP_OVERSIZE */
|
#endif /* TCP_OVERSIZE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Phase 2: concat_p can be concatenated onto last_unsent->p
|
* Phase 2: concat_p can be concatenated onto last_unsent->p, unless we
|
||||||
|
* determined that the last ROM pbuf can be extended to include the new data.
|
||||||
*/
|
*/
|
||||||
if (concat_p != NULL) {
|
if (concat_p != NULL) {
|
||||||
LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
|
LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
|
||||||
(last_unsent != NULL));
|
(last_unsent != NULL));
|
||||||
pbuf_cat(last_unsent->p, concat_p);
|
pbuf_cat(last_unsent->p, concat_p);
|
||||||
last_unsent->len += concat_p->tot_len;
|
last_unsent->len += concat_p->tot_len;
|
||||||
#if TCP_CHECKSUM_ON_COPY
|
} else if (extendlen > 0) {
|
||||||
if (concat_chksummed) {
|
struct pbuf *p;
|
||||||
/*if concat checksumm swapped - swap it back */
|
LWIP_ASSERT("tcp_write: extension of reference requires reference",
|
||||||
if (concat_chksum_swapped) {
|
last_unsent != NULL && last_unsent->p != NULL);
|
||||||
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
|
for (p = last_unsent->p; p->next != NULL; p = p->next) {
|
||||||
}
|
p->tot_len += extendlen;
|
||||||
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
|
|
||||||
&last_unsent->chksum_swapped);
|
|
||||||
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
|
|
||||||
}
|
}
|
||||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
p->tot_len += extendlen;
|
||||||
|
p->len += extendlen;
|
||||||
|
last_unsent->len += extendlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TCP_CHECKSUM_ON_COPY
|
||||||
|
if (concat_chksummed) {
|
||||||
|
LWIP_ASSERT("tcp_write: concat checksum needs concatenated data",
|
||||||
|
concat_p != NULL || extendlen > 0);
|
||||||
|
/*if concat checksumm swapped - swap it back */
|
||||||
|
if (concat_chksum_swapped) {
|
||||||
|
concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
|
||||||
|
}
|
||||||
|
tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
|
||||||
|
&last_unsent->chksum_swapped);
|
||||||
|
last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
|
||||||
|
}
|
||||||
|
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
|
* Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
|
||||||
* is harmless
|
* is harmless
|
||||||
@ -1033,6 +1061,24 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
|
lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||||
}
|
}
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
/* Check if we need to start the persistent timer when the next unsent segment
|
||||||
|
* does not fit within the remaining send window and RTO timer is not running (we
|
||||||
|
* have no in-flight data). A traditional approach would fill the remaining window
|
||||||
|
* with part of the unsent segment (which will engage zero-window probing upon
|
||||||
|
* reception of the zero window update from the receiver). This ensures the
|
||||||
|
* subsequent window update is reliably received. With the goal of being lightweight,
|
||||||
|
* we avoid splitting the unsent segment and treat the window as already zero.
|
||||||
|
*/
|
||||||
|
if (seg != NULL &&
|
||||||
|
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
|
||||||
|
wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
|
||||||
|
/* Start the persist timer */
|
||||||
|
if (pcb->persist_backoff == 0) {
|
||||||
|
pcb->persist_cnt = 0;
|
||||||
|
pcb->persist_backoff = 1;
|
||||||
|
}
|
||||||
|
goto output_done;
|
||||||
|
}
|
||||||
/* data available and window allows it to be sent? */
|
/* data available and window allows it to be sent? */
|
||||||
while (seg != NULL &&
|
while (seg != NULL &&
|
||||||
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||||
@ -1112,6 +1158,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
seg = pcb->unsent;
|
seg = pcb->unsent;
|
||||||
}
|
}
|
||||||
|
output_done:
|
||||||
#if TCP_OVERSIZE
|
#if TCP_OVERSIZE
|
||||||
if (pcb->unsent == NULL) {
|
if (pcb->unsent == NULL) {
|
||||||
/* last unsent has been removed, reset unsent_oversize */
|
/* last unsent has been removed, reset unsent_oversize */
|
||||||
|
@ -179,7 +179,7 @@ void sys_timeouts_init(void)
|
|||||||
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
||||||
/* we have to cast via size_t to get rid of const warning
|
/* we have to cast via size_t to get rid of const warning
|
||||||
(this is OK as cyclic_timer() casts back to const* */
|
(this is OK as cyclic_timer() casts back to const* */
|
||||||
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, (void*)(size_t)&lwip_cyclic_timers[i]);
|
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise timestamp for sys_check_timeouts */
|
/* Initialise timestamp for sys_check_timeouts */
|
||||||
|
@ -116,24 +116,6 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return udp_port;
|
return udp_port;
|
||||||
#if 0
|
|
||||||
struct udp_pcb *ipcb = udp_pcbs;
|
|
||||||
while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
|
|
||||||
if (ipcb->local_port == udp_port) {
|
|
||||||
/* port is already used by another udp_pcb */
|
|
||||||
udp_port++;
|
|
||||||
/* restart scanning all udp pcbs */
|
|
||||||
ipcb = udp_pcbs;
|
|
||||||
} else {
|
|
||||||
/* go on with next udp pcb */
|
|
||||||
ipcb = ipcb->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ipcb != NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return udp_port;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Common code to see if the current input packet matches the pcb
|
/** Common code to see if the current input packet matches the pcb
|
||||||
@ -178,15 +160,8 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast)
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
/* Handle IPv4 and IPv6: all, multicast or exact match */
|
/* Handle IPv4 and IPv6: all or exact match */
|
||||||
if (ip_addr_isany(&pcb->local_ip) ||
|
if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
|
||||||
#if LWIP_IPV6_MLD
|
|
||||||
(ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) ||
|
|
||||||
#endif /* LWIP_IPV6_MLD */
|
|
||||||
#if LWIP_IGMP
|
|
||||||
(!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) ||
|
|
||||||
#endif /* LWIP_IGMP */
|
|
||||||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +404,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
destination address was broadcast/multicast. */
|
destination address was broadcast/multicast. */
|
||||||
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
|
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||||
/* move payload pointer back to ip header */
|
/* move payload pointer back to ip header */
|
||||||
pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN);
|
pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN));
|
||||||
icmp_port_unreach(ip_current_is_v6(), p);
|
icmp_port_unreach(ip_current_is_v6(), p);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
||||||
@ -571,7 +546,12 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
|
|||||||
#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */
|
#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */
|
||||||
|
|
||||||
/* find the outgoing network interface for this packet */
|
/* find the outgoing network interface for this packet */
|
||||||
netif = ip_route(&pcb->local_ip, dst_ip_route);
|
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
||||||
|
/* Don't call ip_route() with IP_ANY_TYPE */
|
||||||
|
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route);
|
||||||
|
} else {
|
||||||
|
netif = ip_route(&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) {
|
||||||
@ -662,7 +642,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_i
|
|||||||
* 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 (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {
|
if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {
|
||||||
/* local_ip doesn't match, drop the packet */
|
/* local_ip doesn't match, drop the packet */
|
||||||
return ERR_VAL;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
/* 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 = &pcb->local_ip;
|
||||||
@ -912,7 +892,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
|
|
||||||
/* still need to check for ipaddr == NULL in IPv6 only case */
|
/* still need to check for ipaddr == NULL in IPv6 only case */
|
||||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
|
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,7 @@
|
|||||||
/* Note: Netconn API is always available when sockets are enabled -
|
/* Note: Netconn API is always available when sockets are enabled -
|
||||||
* sockets are implemented on top of them */
|
* sockets are implemented on top of them */
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
#include "lwip/arch.h"
|
||||||
|
|
||||||
#include "lwip/netbuf.h"
|
#include "lwip/netbuf.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
@ -90,6 +89,7 @@ extern "C" {
|
|||||||
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
|
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
|
||||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
|
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
|
||||||
#else /* LWIP_IPV6 */
|
#else /* LWIP_IPV6 */
|
||||||
|
#define NETCONNTYPE_ISIPV6(t) (0)
|
||||||
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
|
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
|
||||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
|
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
* Author: Erik Ekman <erik@kryo.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_HDR_MDNS_H
|
#ifndef LWIP_HDR_MDNS_H
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
* Author: Erik Ekman <erik@kryo.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the lwIP TCP/IP stack.
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
*
|
*
|
||||||
* Author: Erik Ekman <erik.ekman@verisure.com>
|
* Author: Erik Ekman <erik@kryo.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_HDR_MDNS_PRIV_H
|
#ifndef LWIP_HDR_MDNS_PRIV_H
|
||||||
|
243
src/include/lwip/apps/mqtt.h
Normal file
243
src/include/lwip/apps/mqtt.h
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* MQTT client
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Erik Andersson
|
||||||
|
* 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: Erik Andersson
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H
|
||||||
|
#define LWIP_HDR_APPS_MQTT_CLIENT_H
|
||||||
|
|
||||||
|
#include "lwip/apps/mqtt_opts.h"
|
||||||
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct mqtt_client_t mqtt_client_t;
|
||||||
|
|
||||||
|
/** @ingroup mqtt
|
||||||
|
* Default MQTT port */
|
||||||
|
#define MQTT_PORT 1883
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Connection with server */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Client information and connection parameters */
|
||||||
|
struct mqtt_connect_client_info_t {
|
||||||
|
/** Client identifier, must be set by caller */
|
||||||
|
const char *client_id;
|
||||||
|
/** User name and password, set to NULL if not used */
|
||||||
|
const char* client_user;
|
||||||
|
const char* client_pass;
|
||||||
|
/** keep alive time in seconds, 0 to disable keep alive functionality*/
|
||||||
|
u16_t keep_alive;
|
||||||
|
/** will topic, set to NULL if will is not to be used,
|
||||||
|
will_msg, will_qos and will retain are then ignored */
|
||||||
|
const char* will_topic;
|
||||||
|
const char* will_msg;
|
||||||
|
u8_t will_qos;
|
||||||
|
u8_t will_retain;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Connection status codes */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MQTT_CONNECT_ACCEPTED = 0,
|
||||||
|
MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1,
|
||||||
|
MQTT_CONNECT_REFUSED_IDENTIFIER = 2,
|
||||||
|
MQTT_CONNECT_REFUSED_SERVER = 3,
|
||||||
|
MQTT_CONNECT_REFUSED_USERNAME_PASS = 4,
|
||||||
|
MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5,
|
||||||
|
MQTT_CONNECT_DISCONNECTED = 256,
|
||||||
|
MQTT_CONNECT_TIMEOUT = 257
|
||||||
|
} mqtt_connection_status_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Function prototype for mqtt connection status callback. Called when
|
||||||
|
* client has connected to the server after initiating a mqtt connection attempt by
|
||||||
|
* calling mqtt_connect() or when connection is closed by server or an error
|
||||||
|
*
|
||||||
|
* @param client MQTT client itself
|
||||||
|
* @param arg Additional argument to pass to the callback function
|
||||||
|
* @param status Connect result code or disconnection notification @see mqtt_connection_status_t
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Data callback flags */
|
||||||
|
enum {
|
||||||
|
/** Flag set when last fragment of data arrives in data callback */
|
||||||
|
MQTT_DATA_FLAG_LAST = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Function prototype for MQTT incoming publish data callback function. Called when data
|
||||||
|
* arrives to a subscribed topic @see mqtt_subscribe
|
||||||
|
*
|
||||||
|
* @param arg Additional argument to pass to the callback function
|
||||||
|
* @param data User data, pointed object, data may not be referenced after callback return,
|
||||||
|
NULL is passed when all publish data are delivered
|
||||||
|
* @param len Length of publish data fragment
|
||||||
|
* @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Function prototype for MQTT incoming publish function. Called when an incoming publish
|
||||||
|
* arrives to a subscribed topic @see mqtt_subscribe
|
||||||
|
*
|
||||||
|
* @param arg Additional argument to pass to the callback function
|
||||||
|
* @param topic Zero terminated Topic text string, topic may not be referenced after callback return
|
||||||
|
* @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked
|
||||||
|
*/
|
||||||
|
typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup mqtt
|
||||||
|
* Function prototype for mqtt request callback. Called when a subscribe, unsubscribe
|
||||||
|
* or publish request has completed
|
||||||
|
* @param arg Pointer to user data supplied when invoking request
|
||||||
|
* @param err ERR_OK on success
|
||||||
|
* ERR_TIMEOUT if no response was received within timeout,
|
||||||
|
* ERR_ABRT if (un)subscribe was denied
|
||||||
|
*/
|
||||||
|
typedef void (*mqtt_request_cb_t)(void *arg, err_t err);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pending request item, binds application callback to pending server requests
|
||||||
|
*/
|
||||||
|
struct mqtt_request_t
|
||||||
|
{
|
||||||
|
/** Next item in list, NULL means this is the last in chain,
|
||||||
|
next pointing at itself means request is unallocated */
|
||||||
|
struct mqtt_request_t *next;
|
||||||
|
/** Callback to upper layer */
|
||||||
|
mqtt_request_cb_t cb;
|
||||||
|
void *arg;
|
||||||
|
/** MQTT packet identifier */
|
||||||
|
u16_t pkt_id;
|
||||||
|
/** Expire time relative to element before this */
|
||||||
|
u16_t timeout_diff;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Ring buffer */
|
||||||
|
struct mqtt_ringbuf_t {
|
||||||
|
u16_t put;
|
||||||
|
u16_t get;
|
||||||
|
u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** MQTT client */
|
||||||
|
struct mqtt_client_t
|
||||||
|
{
|
||||||
|
/** Timers and timeouts */
|
||||||
|
u16_t cyclic_tick;
|
||||||
|
u16_t keep_alive;
|
||||||
|
u16_t server_watchdog;
|
||||||
|
/** Packet identifier generator*/
|
||||||
|
u16_t pkt_id_seq;
|
||||||
|
/** Packet identifier of pending incoming publish */
|
||||||
|
u16_t inpub_pkt_id;
|
||||||
|
/** Connection state */
|
||||||
|
u8_t conn_state;
|
||||||
|
struct tcp_pcb *conn;
|
||||||
|
/** Connection callback */
|
||||||
|
void *connect_arg;
|
||||||
|
mqtt_connection_cb_t connect_cb;
|
||||||
|
/** Pending requests to server */
|
||||||
|
struct mqtt_request_t *pend_req_queue;
|
||||||
|
struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT];
|
||||||
|
void *inpub_arg;
|
||||||
|
/** Incoming data callback */
|
||||||
|
mqtt_incoming_data_cb_t data_cb;
|
||||||
|
mqtt_incoming_publish_cb_t pub_cb;
|
||||||
|
/** Input */
|
||||||
|
u32_t msg_idx;
|
||||||
|
u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN];
|
||||||
|
/** Output ring-buffer */
|
||||||
|
struct mqtt_ringbuf_t output;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Connect to server */
|
||||||
|
err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg,
|
||||||
|
const struct mqtt_connect_client_info_t *client_info);
|
||||||
|
|
||||||
|
/** Disconnect from server */
|
||||||
|
void mqtt_disconnect(mqtt_client_t *client);
|
||||||
|
|
||||||
|
/** Create new client */
|
||||||
|
mqtt_client_t *mqtt_client_new(void);
|
||||||
|
|
||||||
|
/** Check connection status */
|
||||||
|
u8_t mqtt_client_is_connected(mqtt_client_t *client);
|
||||||
|
|
||||||
|
/** Set callback to call for incoming publish */
|
||||||
|
void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t,
|
||||||
|
mqtt_incoming_data_cb_t data_cb, void *arg);
|
||||||
|
|
||||||
|
/** Common function for subscribe and unsubscribe */
|
||||||
|
err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub);
|
||||||
|
|
||||||
|
/** @ingroup mqtt
|
||||||
|
*Subscribe to topic */
|
||||||
|
#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1)
|
||||||
|
/** @ingroup mqtt
|
||||||
|
* Unsubscribe to topic */
|
||||||
|
#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0)
|
||||||
|
|
||||||
|
|
||||||
|
/** Publish data to topic */
|
||||||
|
err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
|
||||||
|
mqtt_request_cb_t cb, void *arg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */
|
103
src/include/lwip/apps/mqtt_opts.h
Normal file
103
src/include/lwip/apps/mqtt_opts.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* MQTT client options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Erik Andersson
|
||||||
|
* 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: Erik Andersson
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_HDR_APPS_MQTT_OPTS_H
|
||||||
|
#define LWIP_HDR_APPS_MQTT_OPTS_H
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup mqtt_opts Options
|
||||||
|
* @ingroup mqtt
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_OUTPUT_RINGBUF_SIZE
|
||||||
|
#define MQTT_OUTPUT_RINGBUF_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8
|
||||||
|
* If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_VAR_HEADER_BUFFER_LEN
|
||||||
|
#define MQTT_VAR_HEADER_BUFFER_LEN 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of pending subscribe, unsubscribe and publish requests to server .
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_REQ_MAX_IN_FLIGHT
|
||||||
|
#define MQTT_REQ_MAX_IN_FLIGHT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seconds between each cyclic timer call.
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_CYCLIC_TIMER_INTERVAL
|
||||||
|
#define MQTT_CYCLIC_TIMER_INTERVAL 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish, subscribe and unsubscribe request timeout in seconds.
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_REQ_TIMEOUT
|
||||||
|
#define MQTT_REQ_TIMEOUT 30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seconds for MQTT connect response timeout after sending connect request
|
||||||
|
*/
|
||||||
|
#ifndef MQTT_CONNECT_TIMOUT
|
||||||
|
#define MQTT_CONNECT_TIMOUT 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */
|
@ -47,12 +47,67 @@
|
|||||||
|
|
||||||
#include "arch/cc.h"
|
#include "arch/cc.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup compiler_abstraction Compiler/platform abstraction
|
||||||
|
* @ingroup sys_layer
|
||||||
|
* All defines related to this section must not be placed in lwipopts.h,
|
||||||
|
* but in arch/cc.h!
|
||||||
|
* These options cannot be \#defined in lwipopts.h since they are not options
|
||||||
|
* of lwIP itself, but options of the lwIP port to your system.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Define the byte order of the system.
|
||||||
|
* Needed for conversion of network data to host byte order.
|
||||||
|
* Allowed values: LITTLE_ENDIAN and BIG_ENDIAN
|
||||||
|
*/
|
||||||
|
#ifndef BYTE_ORDER
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Define random number generator function of your system */
|
||||||
|
#ifndef LWIP_RAND
|
||||||
|
#define LWIP_RAND() ((u32_t)rand())
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Platform specific diagnostic output.\n
|
||||||
|
* Note the default implementation pulls in printf, which may
|
||||||
|
* in turn pull in a lot of standard libary code. In resource-constrained
|
||||||
|
* systems, this should be defined to something less resource-consuming.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_PLATFORM_DIAG
|
||||||
|
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Platform specific assertion handling.\n
|
||||||
|
* Note the default implementation pulls in printf, fflush and abort, which may
|
||||||
|
* in turn pull in a lot of standard libary code. In resource-constrained
|
||||||
|
* systems, this should be defined to something less resource-consuming.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_PLATFORM_ASSERT
|
||||||
|
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
|
||||||
|
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Define this to 1 in arch/cc.h of your port if you do not want to
|
||||||
|
* include stddef.h header to get size_t. You need to typedef size_t
|
||||||
|
* by yourself in this case.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_NO_STDDEF_H
|
||||||
|
#define LWIP_NO_STDDEF_H 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !LWIP_NO_STDDEF_H
|
||||||
|
#include <stddef.h> /* for size_t */
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
||||||
* the stdint.h header. This cannot be \#defined in lwipopts.h since
|
* the stdint.h header. You need to typedef the generic types listed in
|
||||||
* this is not an option of lwIP itself, but an option of the lwIP port
|
* lwip/arch.h yourself in this case (u8_t, u16_t...).
|
||||||
* to your system.
|
|
||||||
* Additionally, this header is meant to be \#included in lwipopts.h
|
|
||||||
* (you may need to declare function prototypes in there).
|
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_NO_STDINT_H
|
#ifndef LWIP_NO_STDINT_H
|
||||||
#define LWIP_NO_STDINT_H 0
|
#define LWIP_NO_STDINT_H 0
|
||||||
@ -71,11 +126,8 @@ typedef uintptr_t mem_ptr_t;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
|
||||||
* the inttypes.h header. This cannot be \#defined in lwipopts.h since
|
* the inttypes.h header. You need to define the format strings listed in
|
||||||
* this is not an option of lwIP itself, but an option of the lwIP port
|
* lwip/arch.h yourself in this case (X8_F, U16_F...).
|
||||||
* to your system.
|
|
||||||
* Additionally, this header is meant to be \#included in lwipopts.h
|
|
||||||
* (you may need to declare function prototypes in there).
|
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_NO_INTTYPES_H
|
#ifndef LWIP_NO_INTTYPES_H
|
||||||
#define LWIP_NO_INTTYPES_H 0
|
#define LWIP_NO_INTTYPES_H 0
|
||||||
@ -110,14 +162,31 @@ typedef uintptr_t mem_ptr_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
|
||||||
|
#ifndef LWIP_CONST_CAST
|
||||||
|
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Get rid of alignment cast warnings (GCC -Wcast-align) */
|
||||||
|
#ifndef LWIP_ALIGNMENT_CAST
|
||||||
|
#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Get rid of warnings related to pointer-to-numeric and vice-versa casts,
|
||||||
|
* e.g. "conversion from 'u8_t' to 'void *' of greater size"
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_PTR_NUMERIC_CAST
|
||||||
|
#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Allocates a memory buffer of specified size that is of sufficient size to align
|
/** Allocates a memory buffer of specified size that is of sufficient size to align
|
||||||
* its start address using LWIP_MEM_ALIGN.
|
* its start address using LWIP_MEM_ALIGN.
|
||||||
* You can declare your own version here e.g. to enforce alignment without adding
|
* You can declare your own version here e.g. to enforce alignment without adding
|
||||||
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
|
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
|
||||||
* requirements.
|
* requirements.\n
|
||||||
* e.g. if you use gcc and need 32 bit alignment:
|
* e.g. if you use gcc and need 32 bit alignment:\n
|
||||||
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] __attribute__((aligned(4)))
|
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
|
||||||
* or more portable:
|
* or more portable:\n
|
||||||
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
|
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
|
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
|
||||||
@ -151,39 +220,84 @@ typedef uintptr_t mem_ptr_t;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Packed structs support.
|
||||||
|
* Placed BEFORE declaration of a packed struct.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_BEGIN
|
#ifndef PACK_STRUCT_BEGIN
|
||||||
#define PACK_STRUCT_BEGIN
|
#define PACK_STRUCT_BEGIN
|
||||||
#endif /* PACK_STRUCT_BEGIN */
|
#endif /* PACK_STRUCT_BEGIN */
|
||||||
|
|
||||||
|
/** Packed structs support.
|
||||||
|
* Placed AFTER declaration of a packed struct.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_END
|
#ifndef PACK_STRUCT_END
|
||||||
#define PACK_STRUCT_END
|
#define PACK_STRUCT_END
|
||||||
#endif /* PACK_STRUCT_END */
|
#endif /* PACK_STRUCT_END */
|
||||||
|
|
||||||
|
/** Packed structs support.
|
||||||
|
* Placed between end of declaration of a packed struct and trailing semicolon.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_STRUCT
|
#ifndef PACK_STRUCT_STRUCT
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define PACK_STRUCT_STRUCT __attribute__((packed))
|
||||||
|
#else
|
||||||
#define PACK_STRUCT_STRUCT
|
#define PACK_STRUCT_STRUCT
|
||||||
|
#endif
|
||||||
#endif /* PACK_STRUCT_STRUCT */
|
#endif /* PACK_STRUCT_STRUCT */
|
||||||
|
|
||||||
|
/** Packed structs support.
|
||||||
|
* Wraps u32_t and u16_t members.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_FIELD
|
#ifndef PACK_STRUCT_FIELD
|
||||||
#define PACK_STRUCT_FIELD(x) x
|
#define PACK_STRUCT_FIELD(x) x
|
||||||
#endif /* PACK_STRUCT_FIELD */
|
#endif /* PACK_STRUCT_FIELD */
|
||||||
|
|
||||||
/* Used for struct fields of u8_t,
|
/** Packed structs support.
|
||||||
* where some compilers warn that packing is not necessary */
|
* Wraps u8_t members, where some compilers warn that packing is not necessary.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_FLD_8
|
#ifndef PACK_STRUCT_FLD_8
|
||||||
#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x)
|
#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x)
|
||||||
#endif /* PACK_STRUCT_FLD_8 */
|
#endif /* PACK_STRUCT_FLD_8 */
|
||||||
|
|
||||||
/* Used for struct fields of that are packed structs themself,
|
/** Packed structs support.
|
||||||
* where some compilers warn that packing is not necessary */
|
* Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
#ifndef PACK_STRUCT_FLD_S
|
#ifndef PACK_STRUCT_FLD_S
|
||||||
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
|
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
|
||||||
#endif /* PACK_STRUCT_FLD_S */
|
#endif /* PACK_STRUCT_FLD_S */
|
||||||
|
|
||||||
|
/** Packed structs support using \#include files before and after struct to be packed.\n
|
||||||
|
* The file included BEFORE the struct is "arch/bpstruct.h".\n
|
||||||
|
* The file included AFTER the struct is "arch/epstruct.h".\n
|
||||||
|
* This can be used to implement struct packing on MS Visual C compilers, see
|
||||||
|
* the Win32 port in the lwIP contrib repository for reference.
|
||||||
|
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
|
||||||
|
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN__
|
||||||
|
#define PACK_STRUCT_USE_INCLUDES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */
|
||||||
#ifndef LWIP_UNUSED_ARG
|
#ifndef LWIP_UNUSED_ARG
|
||||||
#define LWIP_UNUSED_ARG(x) (void)x
|
#define LWIP_UNUSED_ARG(x) (void)x
|
||||||
#endif /* LWIP_UNUSED_ARG */
|
#endif /* LWIP_UNUSED_ARG */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,8 @@ u8_t autoip_supplied_address(const struct netif *netif);
|
|||||||
/* for lwIP internal use by ip4.c */
|
/* for lwIP internal use by ip4.c */
|
||||||
u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr);
|
u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr);
|
||||||
|
|
||||||
|
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,24 +40,45 @@
|
|||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
/** lower two bits indicate debug level
|
/**
|
||||||
* - 0 all
|
* @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values
|
||||||
* - 1 warning
|
* @ingroup lwip_opts_debugmsg
|
||||||
* - 2 serious
|
* @{
|
||||||
* - 3 severe
|
|
||||||
*/
|
*/
|
||||||
#define LWIP_DBG_LEVEL_ALL 0x00
|
|
||||||
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */
|
|
||||||
#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
|
|
||||||
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
|
|
||||||
#define LWIP_DBG_LEVEL_SEVERE 0x03
|
|
||||||
#define LWIP_DBG_MASK_LEVEL 0x03
|
|
||||||
|
|
||||||
|
/** @name Debug level (LWIP_DBG_MIN_LEVEL)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** Debug level: ALL messages*/
|
||||||
|
#define LWIP_DBG_LEVEL_ALL 0x00
|
||||||
|
/** Debug level: Warnings. bad checksums, dropped packets, ... */
|
||||||
|
#define LWIP_DBG_LEVEL_WARNING 0x01
|
||||||
|
/** Debug level: Serious. memory allocation failures, ... */
|
||||||
|
#define LWIP_DBG_LEVEL_SERIOUS 0x02
|
||||||
|
/** Debug level: Severe */
|
||||||
|
#define LWIP_DBG_LEVEL_SEVERE 0x03
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LWIP_DBG_MASK_LEVEL 0x03
|
||||||
|
/* compatibility define only */
|
||||||
|
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL
|
||||||
|
|
||||||
|
/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
/** flag for LWIP_DEBUGF to enable that debug message */
|
/** flag for LWIP_DEBUGF to enable that debug message */
|
||||||
#define LWIP_DBG_ON 0x80U
|
#define LWIP_DBG_ON 0x80U
|
||||||
/** flag for LWIP_DEBUGF to disable that debug message */
|
/** flag for LWIP_DEBUGF to disable that debug message */
|
||||||
#define LWIP_DBG_OFF 0x00U
|
#define LWIP_DBG_OFF 0x00U
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @name Debug message types (LWIP_DBG_TYPES_ON)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
|
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
|
||||||
#define LWIP_DBG_TRACE 0x40U
|
#define LWIP_DBG_TRACE 0x40U
|
||||||
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
|
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
|
||||||
@ -66,11 +87,31 @@
|
|||||||
#define LWIP_DBG_FRESH 0x10U
|
#define LWIP_DBG_FRESH 0x10U
|
||||||
/** flag for LWIP_DEBUGF to halt after printing this debug message */
|
/** flag for LWIP_DEBUGF to halt after printing this debug message */
|
||||||
#define LWIP_DBG_HALT 0x08U
|
#define LWIP_DBG_HALT 0x08U
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LWIP_NOASSERT: Disable LWIP_ASSERT checks.
|
* @}
|
||||||
* -- To disable assertions define LWIP_NOASSERT in arch/cc.h.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lwip_assertions Assertion handling
|
||||||
|
* @ingroup lwip_opts_debug
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* LWIP_NOASSERT: Disable LWIP_ASSERT checks:
|
||||||
|
* To disable assertions define LWIP_NOASSERT in arch/cc.h.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN__
|
||||||
|
#define LWIP_NOASSERT
|
||||||
|
#undef LWIP_NOASSERT
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef LWIP_NOASSERT
|
#ifndef LWIP_NOASSERT
|
||||||
#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \
|
#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \
|
||||||
LWIP_PLATFORM_ASSERT(message); }} while(0)
|
LWIP_PLATFORM_ASSERT(message); }} while(0)
|
||||||
@ -81,7 +122,6 @@
|
|||||||
#define LWIP_ASSERT(message, assertion)
|
#define LWIP_ASSERT(message, assertion)
|
||||||
#endif /* LWIP_NOASSERT */
|
#endif /* LWIP_NOASSERT */
|
||||||
|
|
||||||
/** if "expression" isn't true, then print "message" and execute "handler" expression */
|
|
||||||
#ifndef LWIP_ERROR
|
#ifndef LWIP_ERROR
|
||||||
#ifndef LWIP_NOASSERT
|
#ifndef LWIP_NOASSERT
|
||||||
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
|
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
|
||||||
@ -91,17 +131,23 @@
|
|||||||
#define LWIP_PLATFORM_ERROR(message)
|
#define LWIP_PLATFORM_ERROR(message)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* if "expression" isn't true, then print "message" and execute "handler" expression */
|
||||||
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
|
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
|
||||||
LWIP_PLATFORM_ERROR(message); handler;}} while(0)
|
LWIP_PLATFORM_ERROR(message); handler;}} while(0)
|
||||||
#endif /* LWIP_ERROR */
|
#endif /* LWIP_ERROR */
|
||||||
|
|
||||||
|
/** Enable debug message printing, but only if debug message type is enabled
|
||||||
|
* AND is of correct type AND is at least LWIP_DBG_LEVEL.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN__
|
||||||
|
#define LWIP_DEBUG
|
||||||
|
#undef LWIP_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
#ifndef LWIP_PLATFORM_DIAG
|
#ifndef LWIP_PLATFORM_DIAG
|
||||||
#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h"
|
#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h"
|
||||||
#endif
|
#endif
|
||||||
/** print debug message only if debug message type is enabled...
|
|
||||||
* AND is of correct type AND is at least LWIP_DBG_LEVEL
|
|
||||||
*/
|
|
||||||
#define LWIP_DEBUGF(debug, message) do { \
|
#define LWIP_DEBUGF(debug, message) do { \
|
||||||
if ( \
|
if ( \
|
||||||
((debug) & LWIP_DBG_ON) && \
|
((debug) & LWIP_DBG_ON) && \
|
||||||
@ -119,4 +165,3 @@
|
|||||||
#endif /* LWIP_DEBUG */
|
#endif /* LWIP_DEBUG */
|
||||||
|
|
||||||
#endif /* LWIP_HDR_DEBUG_H */
|
#endif /* LWIP_HDR_DEBUG_H */
|
||||||
|
|
||||||
|
@ -57,6 +57,12 @@ extern "C" {
|
|||||||
/* Get the number of entries in an array ('x' must NOT be a pointer!) */
|
/* Get the number of entries in an array ('x' must NOT be a pointer!) */
|
||||||
#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
|
#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
/** Create u32_t value from bytes */
|
||||||
|
#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \
|
||||||
|
((u32_t)((b) & 0xff) << 16) | \
|
||||||
|
((u32_t)((c) & 0xff) << 8) | \
|
||||||
|
(u32_t)((d) & 0xff))
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
@ -65,13 +71,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Endianess-optimized shifting of two u8_t to create one u16_t */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
#define LWIP_MAKE_U16(a, b) ((a << 8) | b)
|
|
||||||
#else
|
|
||||||
#define LWIP_MAKE_U16(a, b) ((b << 8) | a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
#define lwip_htons(x) (x)
|
#define lwip_htons(x) (x)
|
||||||
#define lwip_ntohs(x) (x)
|
#define lwip_ntohs(x) (x)
|
||||||
@ -103,11 +102,11 @@ u32_t lwip_htonl(u32_t x);
|
|||||||
/* These macros should be calculated by the preprocessor and are used
|
/* These macros should be calculated by the preprocessor and are used
|
||||||
with compile-time constants only (so that there is no little-endian
|
with compile-time constants only (so that there is no little-endian
|
||||||
overhead at runtime). */
|
overhead at runtime). */
|
||||||
#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
|
#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
|
||||||
#define PP_NTOHS(x) PP_HTONS(x)
|
#define PP_NTOHS(x) PP_HTONS(x)
|
||||||
#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
|
#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \
|
||||||
(((x) & 0xff00) << 8) | \
|
(((x) & 0x0000ff00UL) << 8) | \
|
||||||
(((x) & 0xff0000UL) >> 8) | \
|
(((x) & 0x00ff0000UL) >> 8) | \
|
||||||
(((x) & 0xff000000UL) >> 24))
|
(((x) & 0xff000000UL) >> 24))
|
||||||
#define PP_NTOHL(x) PP_HTONL(x)
|
#define PP_NTOHL(x) PP_HTONL(x)
|
||||||
|
|
||||||
|
@ -132,6 +132,8 @@ void dhcp_fine_tmr(void);
|
|||||||
extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
|
extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
|
||||||
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
|
||||||
|
#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -61,7 +61,7 @@ extern "C" {
|
|||||||
#ifndef LWIP_DNS_ADDRTYPE_DEFAULT
|
#ifndef LWIP_DNS_ADDRTYPE_DEFAULT
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6
|
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6
|
||||||
#endif
|
#endif
|
||||||
#elif defined(LWIP_IPV4)
|
#elif LWIP_IPV4
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4
|
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4
|
||||||
#else
|
#else
|
||||||
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6
|
#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6
|
||||||
@ -84,6 +84,13 @@ struct local_hostlist_entry {
|
|||||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||||
#endif /* DNS_LOCAL_HOSTLIST */
|
#endif /* DNS_LOCAL_HOSTLIST */
|
||||||
|
|
||||||
|
#if LWIP_IPV4
|
||||||
|
extern const ip_addr_t dns_mquery_v4group;
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
#if LWIP_IPV6
|
||||||
|
extern const ip_addr_t dns_mquery_v6group;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
/** Callback which is invoked when a hostname is found.
|
/** Callback which is invoked when a hostname is found.
|
||||||
* A function of this type must be implemented by the application using the DNS resolver.
|
* A function of this type must be implemented by the application using the DNS resolver.
|
||||||
* @param name pointer to the name that was looked up.
|
* @param name pointer to the name that was looked up.
|
||||||
|
@ -45,100 +45,100 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef LWIP_PROVIDE_ERRNO
|
#ifdef LWIP_PROVIDE_ERRNO
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
#define ENOENT 2 /* No such file or directory */
|
#define ENOENT 2 /* No such file or directory */
|
||||||
#define ESRCH 3 /* No such process */
|
#define ESRCH 3 /* No such process */
|
||||||
#define EINTR 4 /* Interrupted system call */
|
#define EINTR 4 /* Interrupted system call */
|
||||||
#define EIO 5 /* I/O error */
|
#define EIO 5 /* I/O error */
|
||||||
#define ENXIO 6 /* No such device or address */
|
#define ENXIO 6 /* No such device or address */
|
||||||
#define E2BIG 7 /* Arg list too long */
|
#define E2BIG 7 /* Arg list too long */
|
||||||
#define ENOEXEC 8 /* Exec format error */
|
#define ENOEXEC 8 /* Exec format error */
|
||||||
#define EBADF 9 /* Bad file number */
|
#define EBADF 9 /* Bad file number */
|
||||||
#define ECHILD 10 /* No child processes */
|
#define ECHILD 10 /* No child processes */
|
||||||
#define EAGAIN 11 /* Try again */
|
#define EAGAIN 11 /* Try again */
|
||||||
#define ENOMEM 12 /* Out of memory */
|
#define ENOMEM 12 /* Out of memory */
|
||||||
#define EACCES 13 /* Permission denied */
|
#define EACCES 13 /* Permission denied */
|
||||||
#define EFAULT 14 /* Bad address */
|
#define EFAULT 14 /* Bad address */
|
||||||
#define ENOTBLK 15 /* Block device required */
|
#define ENOTBLK 15 /* Block device required */
|
||||||
#define EBUSY 16 /* Device or resource busy */
|
#define EBUSY 16 /* Device or resource busy */
|
||||||
#define EEXIST 17 /* File exists */
|
#define EEXIST 17 /* File exists */
|
||||||
#define EXDEV 18 /* Cross-device link */
|
#define EXDEV 18 /* Cross-device link */
|
||||||
#define ENODEV 19 /* No such device */
|
#define ENODEV 19 /* No such device */
|
||||||
#define ENOTDIR 20 /* Not a directory */
|
#define ENOTDIR 20 /* Not a directory */
|
||||||
#define EISDIR 21 /* Is a directory */
|
#define EISDIR 21 /* Is a directory */
|
||||||
#define EINVAL 22 /* Invalid argument */
|
#define EINVAL 22 /* Invalid argument */
|
||||||
#define ENFILE 23 /* File table overflow */
|
#define ENFILE 23 /* File table overflow */
|
||||||
#define EMFILE 24 /* Too many open files */
|
#define EMFILE 24 /* Too many open files */
|
||||||
#define ENOTTY 25 /* Not a typewriter */
|
#define ENOTTY 25 /* Not a typewriter */
|
||||||
#define ETXTBSY 26 /* Text file busy */
|
#define ETXTBSY 26 /* Text file busy */
|
||||||
#define EFBIG 27 /* File too large */
|
#define EFBIG 27 /* File too large */
|
||||||
#define ENOSPC 28 /* No space left on device */
|
#define ENOSPC 28 /* No space left on device */
|
||||||
#define ESPIPE 29 /* Illegal seek */
|
#define ESPIPE 29 /* Illegal seek */
|
||||||
#define EROFS 30 /* Read-only file system */
|
#define EROFS 30 /* Read-only file system */
|
||||||
#define EMLINK 31 /* Too many links */
|
#define EMLINK 31 /* Too many links */
|
||||||
#define EPIPE 32 /* Broken pipe */
|
#define EPIPE 32 /* Broken pipe */
|
||||||
#define EDOM 33 /* Math argument out of domain of func */
|
#define EDOM 33 /* Math argument out of domain of func */
|
||||||
#define ERANGE 34 /* Math result not representable */
|
#define ERANGE 34 /* Math result not representable */
|
||||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||||
#define ENAMETOOLONG 36 /* File name too long */
|
#define ENAMETOOLONG 36 /* File name too long */
|
||||||
#define ENOLCK 37 /* No record locks available */
|
#define ENOLCK 37 /* No record locks available */
|
||||||
#define ENOSYS 38 /* Function not implemented */
|
#define ENOSYS 38 /* Function not implemented */
|
||||||
#define ENOTEMPTY 39 /* Directory not empty */
|
#define ENOTEMPTY 39 /* Directory not empty */
|
||||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||||
#define ENOMSG 42 /* No message of desired type */
|
#define ENOMSG 42 /* No message of desired type */
|
||||||
#define EIDRM 43 /* Identifier removed */
|
#define EIDRM 43 /* Identifier removed */
|
||||||
#define ECHRNG 44 /* Channel number out of range */
|
#define ECHRNG 44 /* Channel number out of range */
|
||||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||||
#define EL3HLT 46 /* Level 3 halted */
|
#define EL3HLT 46 /* Level 3 halted */
|
||||||
#define EL3RST 47 /* Level 3 reset */
|
#define EL3RST 47 /* Level 3 reset */
|
||||||
#define ELNRNG 48 /* Link number out of range */
|
#define ELNRNG 48 /* Link number out of range */
|
||||||
#define EUNATCH 49 /* Protocol driver not attached */
|
#define EUNATCH 49 /* Protocol driver not attached */
|
||||||
#define ENOCSI 50 /* No CSI structure available */
|
#define ENOCSI 50 /* No CSI structure available */
|
||||||
#define EL2HLT 51 /* Level 2 halted */
|
#define EL2HLT 51 /* Level 2 halted */
|
||||||
#define EBADE 52 /* Invalid exchange */
|
#define EBADE 52 /* Invalid exchange */
|
||||||
#define EBADR 53 /* Invalid request descriptor */
|
#define EBADR 53 /* Invalid request descriptor */
|
||||||
#define EXFULL 54 /* Exchange full */
|
#define EXFULL 54 /* Exchange full */
|
||||||
#define ENOANO 55 /* No anode */
|
#define ENOANO 55 /* No anode */
|
||||||
#define EBADRQC 56 /* Invalid request code */
|
#define EBADRQC 56 /* Invalid request code */
|
||||||
#define EBADSLT 57 /* Invalid slot */
|
#define EBADSLT 57 /* Invalid slot */
|
||||||
|
|
||||||
#define EDEADLOCK EDEADLK
|
#define EDEADLOCK EDEADLK
|
||||||
|
|
||||||
#define EBFONT 59 /* Bad font file format */
|
#define EBFONT 59 /* Bad font file format */
|
||||||
#define ENOSTR 60 /* Device not a stream */
|
#define ENOSTR 60 /* Device not a stream */
|
||||||
#define ENODATA 61 /* No data available */
|
#define ENODATA 61 /* No data available */
|
||||||
#define ETIME 62 /* Timer expired */
|
#define ETIME 62 /* Timer expired */
|
||||||
#define ENOSR 63 /* Out of streams resources */
|
#define ENOSR 63 /* Out of streams resources */
|
||||||
#define ENONET 64 /* Machine is not on the network */
|
#define ENONET 64 /* Machine is not on the network */
|
||||||
#define ENOPKG 65 /* Package not installed */
|
#define ENOPKG 65 /* Package not installed */
|
||||||
#define EREMOTE 66 /* Object is remote */
|
#define EREMOTE 66 /* Object is remote */
|
||||||
#define ENOLINK 67 /* Link has been severed */
|
#define ENOLINK 67 /* Link has been severed */
|
||||||
#define EADV 68 /* Advertise error */
|
#define EADV 68 /* Advertise error */
|
||||||
#define ESRMNT 69 /* Srmount error */
|
#define ESRMNT 69 /* Srmount error */
|
||||||
#define ECOMM 70 /* Communication error on send */
|
#define ECOMM 70 /* Communication error on send */
|
||||||
#define EPROTO 71 /* Protocol error */
|
#define EPROTO 71 /* Protocol error */
|
||||||
#define EMULTIHOP 72 /* Multihop attempted */
|
#define EMULTIHOP 72 /* Multihop attempted */
|
||||||
#define EDOTDOT 73 /* RFS specific error */
|
#define EDOTDOT 73 /* RFS specific error */
|
||||||
#define EBADMSG 74 /* Not a data message */
|
#define EBADMSG 74 /* Not a data message */
|
||||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||||
#define EBADFD 77 /* File descriptor in bad state */
|
#define EBADFD 77 /* File descriptor in bad state */
|
||||||
#define EREMCHG 78 /* Remote address changed */
|
#define EREMCHG 78 /* Remote address changed */
|
||||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||||
#define EILSEQ 84 /* Illegal byte sequence */
|
#define EILSEQ 84 /* Illegal byte sequence */
|
||||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||||
#define ESTRPIPE 86 /* Streams pipe error */
|
#define ESTRPIPE 86 /* Streams pipe error */
|
||||||
#define EUSERS 87 /* Too many users */
|
#define EUSERS 87 /* Too many users */
|
||||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||||
#define EDESTADDRREQ 89 /* Destination address required */
|
#define EDESTADDRREQ 89 /* Destination address required */
|
||||||
#define EMSGSIZE 90 /* Message too long */
|
#define EMSGSIZE 90 /* Message too long */
|
||||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||||
|
@ -45,99 +45,12 @@
|
|||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/ip6_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
#include "lwip/prot/icmp6.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** ICMP type */
|
|
||||||
enum icmp6_type {
|
|
||||||
/** Destination unreachable */
|
|
||||||
ICMP6_TYPE_DUR = 1,
|
|
||||||
/** Packet too big */
|
|
||||||
ICMP6_TYPE_PTB = 2,
|
|
||||||
/** Time exceeded */
|
|
||||||
ICMP6_TYPE_TE = 3,
|
|
||||||
/** Parameter problem */
|
|
||||||
ICMP6_TYPE_PP = 4,
|
|
||||||
/** Private experimentation */
|
|
||||||
ICMP6_TYPE_PE1 = 100,
|
|
||||||
/** Private experimentation */
|
|
||||||
ICMP6_TYPE_PE2 = 101,
|
|
||||||
/** Reserved for expansion of error messages */
|
|
||||||
ICMP6_TYPE_RSV_ERR = 127,
|
|
||||||
|
|
||||||
/** Echo request */
|
|
||||||
ICMP6_TYPE_EREQ = 128,
|
|
||||||
/** Echo reply */
|
|
||||||
ICMP6_TYPE_EREP = 129,
|
|
||||||
/** Multicast listener query */
|
|
||||||
ICMP6_TYPE_MLQ = 130,
|
|
||||||
/** Multicast listener report */
|
|
||||||
ICMP6_TYPE_MLR = 131,
|
|
||||||
/** Multicast listener done */
|
|
||||||
ICMP6_TYPE_MLD = 132,
|
|
||||||
/** Router solicitation */
|
|
||||||
ICMP6_TYPE_RS = 133,
|
|
||||||
/** Router advertisement */
|
|
||||||
ICMP6_TYPE_RA = 134,
|
|
||||||
/** Neighbor solicitation */
|
|
||||||
ICMP6_TYPE_NS = 135,
|
|
||||||
/** Neighbor advertisement */
|
|
||||||
ICMP6_TYPE_NA = 136,
|
|
||||||
/** Redirect */
|
|
||||||
ICMP6_TYPE_RD = 137,
|
|
||||||
/** Multicast router advertisement */
|
|
||||||
ICMP6_TYPE_MRA = 151,
|
|
||||||
/** Multicast router solicitation */
|
|
||||||
ICMP6_TYPE_MRS = 152,
|
|
||||||
/** Multicast router termination */
|
|
||||||
ICMP6_TYPE_MRT = 153,
|
|
||||||
/** Private experimentation */
|
|
||||||
ICMP6_TYPE_PE3 = 200,
|
|
||||||
/** Private experimentation */
|
|
||||||
ICMP6_TYPE_PE4 = 201,
|
|
||||||
/** Reserved for expansion of informational messages */
|
|
||||||
ICMP6_TYPE_RSV_INF = 255
|
|
||||||
};
|
|
||||||
|
|
||||||
/** ICMP destination unreachable codes */
|
|
||||||
enum icmp6_dur_code {
|
|
||||||
/** No route to destination */
|
|
||||||
ICMP6_DUR_NO_ROUTE = 0,
|
|
||||||
/** Communication with destination administratively prohibited */
|
|
||||||
ICMP6_DUR_PROHIBITED = 1,
|
|
||||||
/** Beyond scope of source address */
|
|
||||||
ICMP6_DUR_SCOPE = 2,
|
|
||||||
/** Address unreachable */
|
|
||||||
ICMP6_DUR_ADDRESS = 3,
|
|
||||||
/** Port unreachable */
|
|
||||||
ICMP6_DUR_PORT = 4,
|
|
||||||
/** Source address failed ingress/egress policy */
|
|
||||||
ICMP6_DUR_POLICY = 5,
|
|
||||||
/** Reject route to destination */
|
|
||||||
ICMP6_DUR_REJECT_ROUTE = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
/** ICMP time exceeded codes */
|
|
||||||
enum icmp6_te_code {
|
|
||||||
/** Hop limit exceeded in transit */
|
|
||||||
ICMP6_TE_HL = 0,
|
|
||||||
/** Fragment reassembly time exceeded */
|
|
||||||
ICMP6_TE_FRAG = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/** ICMP parameter code */
|
|
||||||
enum icmp6_pp_code {
|
|
||||||
/** Erroneous header field encountered */
|
|
||||||
ICMP6_PP_FIELD = 0,
|
|
||||||
/** Unrecognized next header type encountered */
|
|
||||||
ICMP6_PP_HEADER = 1,
|
|
||||||
/** Unrecognized IPv6 option encountered */
|
|
||||||
ICMP6_PP_OPTION = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LWIP_ICMP6 && LWIP_IPV6 /* 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 */
|
||||||
|
|
||||||
void icmp6_input(struct pbuf *p, struct netif *inp);
|
void icmp6_input(struct pbuf *p, struct netif *inp);
|
||||||
|
@ -132,10 +132,10 @@ extern const struct in6_addr in6addr_any;
|
|||||||
|
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
|
|
||||||
#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
|
#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
|
||||||
#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
|
#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
|
||||||
/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */
|
/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */
|
||||||
#define inet_addr_to_ipaddr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr))
|
#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr))
|
||||||
|
|
||||||
/* directly map this to the lwip internal functions */
|
/* directly map this to the lwip internal functions */
|
||||||
#define inet_addr(cp) ipaddr_addr(cp)
|
#define inet_addr(cp) ipaddr_addr(cp)
|
||||||
|
@ -54,11 +54,11 @@ extern "C" {
|
|||||||
/** x.X.x: Minor version of the stack */
|
/** x.X.x: Minor version of the stack */
|
||||||
#define LWIP_VERSION_MINOR 0
|
#define LWIP_VERSION_MINOR 0
|
||||||
/** x.x.X: Revision of the stack */
|
/** x.x.X: Revision of the stack */
|
||||||
#define LWIP_VERSION_REVISION 0
|
#define LWIP_VERSION_REVISION 1
|
||||||
/** 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 (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||||
#define LWIP_VERSION_RC LWIP_RC_RELEASE
|
#define LWIP_VERSION_RC LWIP_RC_DEVELOPMENT
|
||||||
|
|
||||||
/** 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 255
|
#define LWIP_RC_RELEASE 255
|
||||||
|
@ -52,24 +52,9 @@ struct ip4_addr {
|
|||||||
u32_t addr;
|
u32_t addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** This is the packed version of ip4_addr_t,
|
|
||||||
used in network headers that are itself packed */
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip4_addr_packed {
|
|
||||||
PACK_STRUCT_FIELD(u32_t addr);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** ip4_addr_t uses a struct for convenience only, so that the same defines can
|
/** ip4_addr_t uses a struct for convenience only, so that the same defines can
|
||||||
* operate both on ip4_addr_t as well as on ip4_addr_p_t. */
|
* operate both on ip4_addr_t as well as on ip4_addr_p_t. */
|
||||||
typedef struct ip4_addr ip4_addr_t;
|
typedef struct ip4_addr ip4_addr_t;
|
||||||
typedef struct ip4_addr_packed ip4_addr_p_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ipaddr2 is used in the definition of the ARP packet format in
|
* struct ipaddr2 is used in the definition of the ARP packet format in
|
||||||
@ -131,23 +116,8 @@ struct netif;
|
|||||||
|
|
||||||
#define IP_LOOPBACKNET 127 /* official! */
|
#define IP_LOOPBACKNET 127 /* official! */
|
||||||
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
/** Set an IP address given by the four byte-parts */
|
/** Set an IP address given by the four byte-parts */
|
||||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d))
|
||||||
(ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
|
|
||||||
((u32_t)((b) & 0xff) << 16) | \
|
|
||||||
((u32_t)((c) & 0xff) << 8) | \
|
|
||||||
(u32_t)((d) & 0xff)
|
|
||||||
#else
|
|
||||||
/** Set an IP address given by the four byte-parts.
|
|
||||||
Little-endian version that prevents the use of lwip_htonl. */
|
|
||||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
|
||||||
(ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
|
|
||||||
((u32_t)((c) & 0xff) << 16) | \
|
|
||||||
((u32_t)((b) & 0xff) << 8) | \
|
|
||||||
(u32_t)((a) & 0xff)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** MEMCPY-like copying of IP addresses where addresses are known to be
|
/** MEMCPY-like copying of IP addresses where addresses are known to be
|
||||||
* 16-bit-aligned if the port is correctly configured (so a port could define
|
* 16-bit-aligned if the port is correctly configured (so a port could define
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#define LWIP_HDR_IP6_ADDR_H
|
#define LWIP_HDR_IP6_ADDR_H
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
#include "def.h"
|
||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
@ -58,41 +59,12 @@ struct ip6_addr {
|
|||||||
u32_t addr[4];
|
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
|
|
||||||
|
|
||||||
/** IPv6 address */
|
/** IPv6 address */
|
||||||
typedef struct ip6_addr ip6_addr_t;
|
typedef struct ip6_addr ip6_addr_t;
|
||||||
typedef struct ip6_addr_packed ip6_addr_p_t;
|
|
||||||
|
|
||||||
|
/** Set an IPv6 partial address given by byte-parts */
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
/** Set an IPv6 partial address given by byte-parts. */
|
|
||||||
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
|
#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \
|
||||||
(ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \
|
(ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d))
|
||||||
((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 lwip_htonl). */
|
|
||||||
#define IP6_ADDR_PART(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
|
|
||||||
|
|
||||||
/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order
|
/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order
|
||||||
(use PP_HTONL() for constants) */
|
(use PP_HTONL() for constants) */
|
||||||
|
@ -66,7 +66,7 @@ enum lwip_ip_addr_type {
|
|||||||
* A union struct for both IP version's addresses.
|
* A union struct for both IP version's addresses.
|
||||||
* ATTENTION: watch out for its size when adding IPv6 address scope!
|
* ATTENTION: watch out for its size when adding IPv6 address scope!
|
||||||
*/
|
*/
|
||||||
typedef struct _ip_addr {
|
typedef struct ip_addr {
|
||||||
union {
|
union {
|
||||||
ip6_addr_t ip6;
|
ip6_addr_t ip6;
|
||||||
ip4_addr_t ip4;
|
ip4_addr_t ip4;
|
||||||
@ -79,8 +79,12 @@ extern const ip_addr_t ip_addr_any_type;
|
|||||||
|
|
||||||
/** @ingroup ip4addr */
|
/** @ingroup ip4addr */
|
||||||
#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 }
|
#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 }
|
||||||
|
/** @ingroup ip4addr */
|
||||||
|
#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d)))
|
||||||
/** @ingroup ip6addr */
|
/** @ingroup ip6addr */
|
||||||
#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 }
|
#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 }
|
||||||
|
/** @ingroup ip6addr */
|
||||||
|
#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 }
|
||||||
|
|
||||||
/** @ingroup ipaddr */
|
/** @ingroup ipaddr */
|
||||||
#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY)
|
#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY)
|
||||||
@ -118,6 +122,8 @@ extern const ip_addr_t ip_addr_any_type;
|
|||||||
/** @ingroup ip6addr */
|
/** @ingroup ip6addr */
|
||||||
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \
|
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \
|
||||||
IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0)
|
IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0)
|
||||||
|
/** @ingroup ip6addr */
|
||||||
|
#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3))
|
||||||
|
|
||||||
/** @ingroup ipaddr */
|
/** @ingroup ipaddr */
|
||||||
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
||||||
@ -215,6 +221,19 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
|
|||||||
/** @ingroup ipaddr */
|
/** @ingroup ipaddr */
|
||||||
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
|
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
|
||||||
|
|
||||||
|
/** @ingroup ipaddr */
|
||||||
|
#define ip4_2_ipv6_mapped_ipv4(ip6addr, ip4addr) do { \
|
||||||
|
(ip6addr)->addr[3] = (ip4addr)->addr; \
|
||||||
|
(ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \
|
||||||
|
(ip6addr)->addr[1] = 0; \
|
||||||
|
(ip6addr)->addr[0] = 0; } while(0);
|
||||||
|
|
||||||
|
/** @ingroup ipaddr */
|
||||||
|
#define unmap_ipv6_mapped_ipv4(ip4addr, ip6addr) \
|
||||||
|
(ip4addr)->addr = (ip6addr)->addr[3];
|
||||||
|
|
||||||
|
#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY)
|
||||||
|
|
||||||
#else /* LWIP_IPV4 && LWIP_IPV6 */
|
#else /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1
|
#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1
|
||||||
@ -224,6 +243,7 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
|
|||||||
|
|
||||||
typedef ip4_addr_t ip_addr_t;
|
typedef ip4_addr_t ip_addr_t;
|
||||||
#define IPADDR4_INIT(u32val) { u32val }
|
#define IPADDR4_INIT(u32val) { u32val }
|
||||||
|
#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d)))
|
||||||
#define IP_IS_V4_VAL(ipaddr) 1
|
#define IP_IS_V4_VAL(ipaddr) 1
|
||||||
#define IP_IS_V6_VAL(ipaddr) 0
|
#define IP_IS_V6_VAL(ipaddr) 0
|
||||||
#define IP_IS_V4(ipaddr) 1
|
#define IP_IS_V4(ipaddr) 1
|
||||||
@ -263,10 +283,13 @@ typedef ip4_addr_t ip_addr_t;
|
|||||||
|
|
||||||
#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX
|
#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX
|
||||||
|
|
||||||
|
#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY)
|
||||||
|
|
||||||
#else /* LWIP_IPV4 */
|
#else /* LWIP_IPV4 */
|
||||||
|
|
||||||
typedef ip6_addr_t ip_addr_t;
|
typedef ip6_addr_t ip_addr_t;
|
||||||
#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } }
|
#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } }
|
||||||
|
#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } }
|
||||||
#define IP_IS_V4_VAL(ipaddr) 0
|
#define IP_IS_V4_VAL(ipaddr) 0
|
||||||
#define IP_IS_V6_VAL(ipaddr) 1
|
#define IP_IS_V6_VAL(ipaddr) 1
|
||||||
#define IP_IS_V4(ipaddr) 0
|
#define IP_IS_V4(ipaddr) 0
|
||||||
@ -277,6 +300,7 @@ typedef ip6_addr_t ip_addr_t;
|
|||||||
#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6
|
#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6
|
||||||
#define ip_2_ip6(ipaddr) (ipaddr)
|
#define ip_2_ip6(ipaddr) (ipaddr)
|
||||||
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3)
|
#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3)
|
||||||
|
#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3))
|
||||||
|
|
||||||
#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src)
|
#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src)
|
||||||
#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src)
|
#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src)
|
||||||
@ -304,6 +328,8 @@ typedef ip6_addr_t ip_addr_t;
|
|||||||
|
|
||||||
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
|
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
|
||||||
|
|
||||||
|
#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY)
|
||||||
|
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 */
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
@ -314,7 +340,13 @@ extern const ip_addr_t ip_addr_broadcast;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup ip4addr
|
* @ingroup ip4addr
|
||||||
* Provided for compatibility. Use IP4_ADDR_ANY for better readability.
|
* Can be used as a fixed/const ip_addr_t
|
||||||
|
* for the IP wildcard.
|
||||||
|
* Defined to @ref IP4_ADDR_ANY when IPv4 is enabled.
|
||||||
|
* Defined to @ref IP6_ADDR_ANY in IPv6 only systems.
|
||||||
|
* Use this if you can handle IPv4 _AND_ IPv6 addresses.
|
||||||
|
* Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP
|
||||||
|
* type matters.
|
||||||
*/
|
*/
|
||||||
#define IP_ADDR_ANY IP4_ADDR_ANY
|
#define IP_ADDR_ANY IP4_ADDR_ANY
|
||||||
/**
|
/**
|
||||||
@ -355,7 +387,7 @@ extern const ip_addr_t ip6_addr_any;
|
|||||||
#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any))
|
#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any))
|
||||||
|
|
||||||
#if !LWIP_IPV4
|
#if !LWIP_IPV4
|
||||||
/** Just a little upgrade-helper for IPv6-only configurations: */
|
/** IPv6-only configurations */
|
||||||
#define IP_ADDR_ANY IP6_ADDR_ANY
|
#define IP_ADDR_ANY IP6_ADDR_ANY
|
||||||
#endif /* !LWIP_IPV4 */
|
#endif /* !LWIP_IPV4 */
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ extern "C" {
|
|||||||
|
|
||||||
#if MEM_LIBC_MALLOC
|
#if MEM_LIBC_MALLOC
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
#include "lwip/arch.h"
|
||||||
|
|
||||||
typedef size_t mem_size_t;
|
typedef size_t mem_size_t;
|
||||||
#define MEM_SIZE_F SZT_F
|
#define MEM_SIZE_F SZT_F
|
||||||
|
|
||||||
|
@ -48,107 +48,32 @@
|
|||||||
|
|
||||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.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/ip6_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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;
|
|
||||||
#else /* LWIP_ND6_QUEUEING */
|
|
||||||
/** Pointer to a single pending outgoing packet on this entry. */
|
|
||||||
struct pbuf *q;
|
|
||||||
#endif /* LWIP_ND6_QUEUEING */
|
|
||||||
u8_t state;
|
|
||||||
u8_t isrouter;
|
|
||||||
union {
|
|
||||||
u32_t reachable_time; /* in ms since value may originate from network packet */
|
|
||||||
u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */
|
|
||||||
u32_t probes_sent;
|
|
||||||
u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */
|
|
||||||
} counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nd6_destination_cache_entry {
|
|
||||||
ip6_addr_t destination_addr;
|
|
||||||
ip6_addr_t next_hop_addr;
|
|
||||||
u16_t pmtu;
|
|
||||||
u32_t age;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nd6_prefix_list_entry {
|
|
||||||
ip6_addr_t prefix;
|
|
||||||
struct netif *netif;
|
|
||||||
u32_t invalidation_timer; /* in ms since value may originate from network packet */
|
|
||||||
#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; /* in ms since value may originate from network packet */
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/** 1 second period */
|
/** 1 second period */
|
||||||
#define ND6_TMR_INTERVAL 1000
|
#define ND6_TMR_INTERVAL 1000
|
||||||
|
|
||||||
/* Router tables. */
|
struct pbuf;
|
||||||
/* @todo make these static? and entries accessible through API? */
|
struct netif;
|
||||||
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;
|
|
||||||
|
|
||||||
void nd6_tmr(void);
|
void nd6_tmr(void);
|
||||||
void nd6_input(struct pbuf *p, struct netif *inp);
|
void nd6_input(struct pbuf *p, struct netif *inp);
|
||||||
s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
|
void nd6_clear_destination_cache(void);
|
||||||
s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
|
struct netif *nd6_find_route(const ip6_addr_t *ip6addr);
|
||||||
|
err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp);
|
||||||
u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif);
|
u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif);
|
||||||
err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *p);
|
|
||||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||||
void nd6_reachability_hint(const ip6_addr_t *ip6addr);
|
void nd6_reachability_hint(const ip6_addr_t *ip6addr);
|
||||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||||
void nd6_cleanup_netif(struct netif *netif);
|
void nd6_cleanup_netif(struct netif *netif);
|
||||||
|
#if LWIP_IPV6_MLD
|
||||||
|
void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state);
|
||||||
|
#endif /* LWIP_IPV6_MLD */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,7 @@
|
|||||||
|
|
||||||
#if LWIP_DNS && LWIP_SOCKET
|
#if LWIP_DNS && LWIP_SOCKET
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
#include "lwip/arch.h"
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
|
|
||||||
|
@ -93,13 +93,17 @@ err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
|||||||
netifapi_errt_fn errtfunc);
|
netifapi_errt_fn errtfunc);
|
||||||
|
|
||||||
/** @ingroup netifapi_netif */
|
/** @ingroup netifapi_netif */
|
||||||
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
|
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
|
||||||
/** @ingroup netifapi_netif */
|
/** @ingroup netifapi_netif */
|
||||||
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
|
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
|
||||||
/** @ingroup netifapi_netif */
|
/** @ingroup netifapi_netif */
|
||||||
#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL)
|
#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL)
|
||||||
/** @ingroup netifapi_netif */
|
/** @ingroup netifapi_netif */
|
||||||
#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL)
|
#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL)
|
||||||
|
/** @ingroup netifapi_netif */
|
||||||
|
#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL)
|
||||||
|
/** @ingroup netifapi_netif */
|
||||||
|
#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup netifapi_dhcp4 DHCPv4
|
* @defgroup netifapi_dhcp4 DHCPv4
|
||||||
|
@ -882,6 +882,15 @@
|
|||||||
#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__
|
#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__
|
||||||
#define LWIP_DHCP_MAX_NTP_SERVERS 1
|
#define LWIP_DHCP_MAX_NTP_SERVERS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select.
|
||||||
|
* DHCP servers received in the response are passed to DNS via @ref dns_setserver()
|
||||||
|
* (up to the maximum limit defined here).
|
||||||
|
*/
|
||||||
|
#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__
|
||||||
|
#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -1057,6 +1066,12 @@
|
|||||||
#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__
|
#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__
|
||||||
#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0
|
#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0
|
||||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||||
|
|
||||||
|
/** Set this to 1 to enable querying ".local" names via mDNS
|
||||||
|
* using a One-Shot Multicast DNS Query */
|
||||||
|
#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__
|
||||||
|
#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -1128,7 +1143,10 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TCP_WND: The size of a TCP window. This must be at least
|
* TCP_WND: The size of a TCP window. This must be at least
|
||||||
* (2 * TCP_MSS) for things to work well
|
* (2 * TCP_MSS) for things to work well.
|
||||||
|
* ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size
|
||||||
|
* with scaling applied. Maximum window value in the TCP header
|
||||||
|
* will be TCP_WND >> TCP_RCV_SCALE
|
||||||
*/
|
*/
|
||||||
#if !defined TCP_WND || defined __DOXYGEN__
|
#if !defined TCP_WND || defined __DOXYGEN__
|
||||||
#define TCP_WND (4 * TCP_MSS)
|
#define TCP_WND (4 * TCP_MSS)
|
||||||
@ -1345,7 +1363,7 @@
|
|||||||
* for an additional encapsulation header before ethernet headers (e.g. 802.11)
|
* for an additional encapsulation header before ethernet headers (e.g. 802.11)
|
||||||
*/
|
*/
|
||||||
#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__
|
#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__
|
||||||
#define PBUF_LINK_ENCAPSULATION_HLEN 0
|
#define PBUF_LINK_ENCAPSULATION_HLEN 0u
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2161,7 +2179,7 @@
|
|||||||
/**
|
/**
|
||||||
* LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
|
* LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ || defined __DOXYGEN__
|
#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__
|
||||||
#define LWIP_IPV6_REASS (LWIP_IPV6)
|
#define LWIP_IPV6_REASS (LWIP_IPV6)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2227,13 +2245,18 @@
|
|||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol.
|
* LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol.
|
||||||
|
* If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must
|
||||||
|
* indiscriminately pass all inbound IPv6 multicast traffic to lwIP.
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__
|
#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__
|
||||||
#define LWIP_IPV6_MLD (LWIP_IPV6)
|
#define LWIP_IPV6_MLD (LWIP_IPV6)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined.
|
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined.
|
||||||
|
* There must be enough groups so that each netif can join the solicited-node
|
||||||
|
* multicast group for each of its local addresses, plus one for MDNS if
|
||||||
|
* applicable, plus any number of groups to be joined on UDP sockets.
|
||||||
*/
|
*/
|
||||||
#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__
|
#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__
|
||||||
#define MEMP_NUM_MLD6_GROUP 4
|
#define MEMP_NUM_MLD6_GROUP 4
|
||||||
@ -2339,7 +2362,7 @@
|
|||||||
* LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation
|
* LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation
|
||||||
* message is sent, during neighbor reachability detection.
|
* message is sent, during neighbor reachability detection.
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__s
|
#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__
|
||||||
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000
|
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2356,9 +2379,18 @@
|
|||||||
* with reachability hints for connected destinations. This helps avoid sending
|
* with reachability hints for connected destinations. This helps avoid sending
|
||||||
* unicast neighbor solicitation messages.
|
* unicast neighbor solicitation messages.
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ || defined __DOXYGEN__
|
#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__
|
||||||
#define LWIP_ND6_TCP_REACHABILITY_HINTS 1
|
#define LWIP_ND6_TCP_REACHABILITY_HINTS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive
|
||||||
|
* DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS
|
||||||
|
* servers to the DNS module.
|
||||||
|
*/
|
||||||
|
#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__
|
||||||
|
#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -2383,6 +2415,29 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_HOOK_TCP_ISN:
|
||||||
|
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP
|
||||||
|
* connection. The default lwIP ISN generation algorithm is very basic and may
|
||||||
|
* allow for TCP spoofing attacks. This hook provides the means to implement
|
||||||
|
* the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn),
|
||||||
|
* or any other desired algorithm as a replacement.
|
||||||
|
* Called from tcp_connect() and tcp_listen_input() when an ISN is needed for
|
||||||
|
* a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n
|
||||||
|
* Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port);
|
||||||
|
* - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n
|
||||||
|
* Arguments:
|
||||||
|
* - local_ip: pointer to the local IP address of the connection
|
||||||
|
* - local_port: local port number of the connection (host-byte order)
|
||||||
|
* - remote_ip: pointer to the remote IP address of the connection
|
||||||
|
* - remote_port: remote port number of the connection (host-byte order)\n
|
||||||
|
* Return value:
|
||||||
|
* - the 32-bit Initial Sequence Number to use for the new TCP connection.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN__
|
||||||
|
#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
|
* LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
|
||||||
* - called from ip_input() (IPv4)
|
* - called from ip_input() (IPv4)
|
||||||
@ -2424,7 +2479,7 @@
|
|||||||
* - dest: the destination IPv4 address
|
* - dest: the destination IPv4 address
|
||||||
* Returns the IPv4 address of the gateway to handle the specified destination
|
* Returns the IPv4 address of the gateway to handle the specified destination
|
||||||
* IPv4 address. If NULL is returned, the netif's default gateway is used.
|
* IPv4 address. If NULL is returned, the netif's default gateway is used.
|
||||||
* The returned address MUST be reachable on the specified netif!
|
* The returned address MUST be directly reachable on the specified netif!
|
||||||
* This function is meant to implement advanced IPv4 routing together with
|
* This function is meant to implement advanced IPv4 routing together with
|
||||||
* LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is
|
* LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is
|
||||||
* not part of lwIP but can e.g. be hidden in the netif's state argument.
|
* not part of lwIP but can e.g. be hidden in the netif's state argument.
|
||||||
@ -2460,6 +2515,22 @@
|
|||||||
#define LWIP_HOOK_IP6_ROUTE(src, dest)
|
#define LWIP_HOOK_IP6_ROUTE(src, dest)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_HOOK_ND6_GET_GW(netif, dest):
|
||||||
|
* - called from nd6_get_next_hop_entry() (IPv6)
|
||||||
|
* - netif: the netif used for sending
|
||||||
|
* - dest: the destination IPv6 address
|
||||||
|
* Returns the IPv6 address of the next hop to handle the specified destination
|
||||||
|
* IPv6 address. If NULL is returned, a NDP-discovered router is used instead.
|
||||||
|
* The returned address MUST be directly reachable on the specified netif!
|
||||||
|
* This function is meant to implement advanced IPv6 routing together with
|
||||||
|
* LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is
|
||||||
|
* not part of lwIP but can e.g. be hidden in the netif's state argument.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN__
|
||||||
|
#define LWIP_HOOK_ND6_GET_GW(netif, dest)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr):
|
* LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr):
|
||||||
* - called from ethernet_input() if VLAN support is enabled
|
* - called from ethernet_input() if VLAN support is enabled
|
||||||
@ -2523,7 +2594,7 @@
|
|||||||
---------------------------------------
|
---------------------------------------
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @defgroup lwip_opts_debugmsg Debugging
|
* @defgroup lwip_opts_debugmsg Debug messages
|
||||||
* @ingroup lwip_opts_debug
|
* @ingroup lwip_opts_debug
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
@ -2531,14 +2602,16 @@
|
|||||||
* LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is
|
* LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is
|
||||||
* compared against this value. If it is smaller, then debugging
|
* compared against this value. If it is smaller, then debugging
|
||||||
* messages are written.
|
* messages are written.
|
||||||
|
* @see debugging_levels
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ || defined __DOXYGEN__
|
#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__
|
||||||
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
|
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable
|
* LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable
|
||||||
* debug messages of certain types.
|
* debug messages of certain types.
|
||||||
|
* @see debugging_levels
|
||||||
*/
|
*/
|
||||||
#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__
|
#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__
|
||||||
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
|
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
|
||||||
|
@ -43,8 +43,7 @@
|
|||||||
/* Note: Netconn API is always available when sockets are enabled -
|
/* Note: Netconn API is always available when sockets are enabled -
|
||||||
* sockets are implemented on top of them */
|
* sockets are implemented on top of them */
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
#include "lwip/arch.h"
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
144
src/include/lwip/priv/nd6_priv.h
Normal file
144
src/include/lwip/priv/nd6_priv.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
* @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_HDR_ND6_PRIV_H
|
||||||
|
#define LWIP_HDR_ND6_PRIV_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_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
#else /* LWIP_ND6_QUEUEING */
|
||||||
|
/** Pointer to a single pending outgoing packet on this entry. */
|
||||||
|
struct pbuf *q;
|
||||||
|
#endif /* LWIP_ND6_QUEUEING */
|
||||||
|
u8_t state;
|
||||||
|
u8_t isrouter;
|
||||||
|
union {
|
||||||
|
u32_t reachable_time; /* in ms since value may originate from network packet */
|
||||||
|
u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */
|
||||||
|
u32_t probes_sent;
|
||||||
|
u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */
|
||||||
|
} counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nd6_destination_cache_entry {
|
||||||
|
ip6_addr_t destination_addr;
|
||||||
|
ip6_addr_t next_hop_addr;
|
||||||
|
u16_t pmtu;
|
||||||
|
u32_t age;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nd6_prefix_list_entry {
|
||||||
|
ip6_addr_t prefix;
|
||||||
|
struct netif *netif;
|
||||||
|
u32_t invalidation_timer; /* in ms since value may originate from network packet */
|
||||||
|
#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; /* in ms since value may originate from network packet */
|
||||||
|
u8_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nd6_neighbor_cache_entry_state {
|
||||||
|
ND6_NO_ENTRY = 0,
|
||||||
|
ND6_INCOMPLETE,
|
||||||
|
ND6_REACHABLE,
|
||||||
|
ND6_STALE,
|
||||||
|
ND6_DELAY,
|
||||||
|
ND6_PROBE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#endif /* LWIP_HDR_ND6_PRIV_H */
|
@ -34,8 +34,8 @@
|
|||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_HDR_TCP_IMPL_H
|
#ifndef LWIP_HDR_TCP_PRIV_H
|
||||||
#define LWIP_HDR_TCP_IMPL_H
|
#define LWIP_HDR_TCP_PRIV_H
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ void tcp_rst(u32_t seqno, u32_t ackno,
|
|||||||
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
|
||||||
u16_t local_port, u16_t remote_port);
|
u16_t local_port, u16_t remote_port);
|
||||||
|
|
||||||
u32_t tcp_next_iss(void);
|
u32_t tcp_next_iss(struct tcp_pcb *pcb);
|
||||||
|
|
||||||
err_t tcp_keepalive(struct tcp_pcb *pcb);
|
err_t tcp_keepalive(struct tcp_pcb *pcb);
|
||||||
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
|
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||||
@ -501,4 +501,4 @@ void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_a
|
|||||||
|
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
|
||||||
#endif /* LWIP_HDR_TCP_H */
|
#endif /* LWIP_HDR_TCP_PRIV_H */
|
||||||
|
@ -115,6 +115,24 @@ PACK_STRUCT_END
|
|||||||
#endif
|
#endif
|
||||||
#define SIZEOF_DNS_HDR 12
|
#define SIZEOF_DNS_HDR 12
|
||||||
|
|
||||||
|
|
||||||
|
/* Multicast DNS definitions */
|
||||||
|
|
||||||
|
/** UDP port for multicast DNS queries */
|
||||||
|
#ifndef DNS_MQUERY_PORT
|
||||||
|
#define DNS_MQUERY_PORT 5353
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IPv4 group for multicast DNS queries: 224.0.0.251 */
|
||||||
|
#ifndef DNS_MQUERY_IPV4_GROUP_INIT
|
||||||
|
#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IPv6 group for multicast DNS queries: FF02::FB */
|
||||||
|
#ifndef DNS_MQUERY_IPV6_GROUP_INIT
|
||||||
|
#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,93 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** ICMP type */
|
||||||
|
enum icmp6_type {
|
||||||
|
/** Destination unreachable */
|
||||||
|
ICMP6_TYPE_DUR = 1,
|
||||||
|
/** Packet too big */
|
||||||
|
ICMP6_TYPE_PTB = 2,
|
||||||
|
/** Time exceeded */
|
||||||
|
ICMP6_TYPE_TE = 3,
|
||||||
|
/** Parameter problem */
|
||||||
|
ICMP6_TYPE_PP = 4,
|
||||||
|
/** Private experimentation */
|
||||||
|
ICMP6_TYPE_PE1 = 100,
|
||||||
|
/** Private experimentation */
|
||||||
|
ICMP6_TYPE_PE2 = 101,
|
||||||
|
/** Reserved for expansion of error messages */
|
||||||
|
ICMP6_TYPE_RSV_ERR = 127,
|
||||||
|
|
||||||
|
/** Echo request */
|
||||||
|
ICMP6_TYPE_EREQ = 128,
|
||||||
|
/** Echo reply */
|
||||||
|
ICMP6_TYPE_EREP = 129,
|
||||||
|
/** Multicast listener query */
|
||||||
|
ICMP6_TYPE_MLQ = 130,
|
||||||
|
/** Multicast listener report */
|
||||||
|
ICMP6_TYPE_MLR = 131,
|
||||||
|
/** Multicast listener done */
|
||||||
|
ICMP6_TYPE_MLD = 132,
|
||||||
|
/** Router solicitation */
|
||||||
|
ICMP6_TYPE_RS = 133,
|
||||||
|
/** Router advertisement */
|
||||||
|
ICMP6_TYPE_RA = 134,
|
||||||
|
/** Neighbor solicitation */
|
||||||
|
ICMP6_TYPE_NS = 135,
|
||||||
|
/** Neighbor advertisement */
|
||||||
|
ICMP6_TYPE_NA = 136,
|
||||||
|
/** Redirect */
|
||||||
|
ICMP6_TYPE_RD = 137,
|
||||||
|
/** Multicast router advertisement */
|
||||||
|
ICMP6_TYPE_MRA = 151,
|
||||||
|
/** Multicast router solicitation */
|
||||||
|
ICMP6_TYPE_MRS = 152,
|
||||||
|
/** Multicast router termination */
|
||||||
|
ICMP6_TYPE_MRT = 153,
|
||||||
|
/** Private experimentation */
|
||||||
|
ICMP6_TYPE_PE3 = 200,
|
||||||
|
/** Private experimentation */
|
||||||
|
ICMP6_TYPE_PE4 = 201,
|
||||||
|
/** Reserved for expansion of informational messages */
|
||||||
|
ICMP6_TYPE_RSV_INF = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ICMP destination unreachable codes */
|
||||||
|
enum icmp6_dur_code {
|
||||||
|
/** No route to destination */
|
||||||
|
ICMP6_DUR_NO_ROUTE = 0,
|
||||||
|
/** Communication with destination administratively prohibited */
|
||||||
|
ICMP6_DUR_PROHIBITED = 1,
|
||||||
|
/** Beyond scope of source address */
|
||||||
|
ICMP6_DUR_SCOPE = 2,
|
||||||
|
/** Address unreachable */
|
||||||
|
ICMP6_DUR_ADDRESS = 3,
|
||||||
|
/** Port unreachable */
|
||||||
|
ICMP6_DUR_PORT = 4,
|
||||||
|
/** Source address failed ingress/egress policy */
|
||||||
|
ICMP6_DUR_POLICY = 5,
|
||||||
|
/** Reject route to destination */
|
||||||
|
ICMP6_DUR_REJECT_ROUTE = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ICMP time exceeded codes */
|
||||||
|
enum icmp6_te_code {
|
||||||
|
/** Hop limit exceeded in transit */
|
||||||
|
ICMP6_TE_HL = 0,
|
||||||
|
/** Fragment reassembly time exceeded */
|
||||||
|
ICMP6_TE_FRAG = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ICMP parameter code */
|
||||||
|
enum icmp6_pp_code {
|
||||||
|
/** Erroneous header field encountered */
|
||||||
|
ICMP6_PP_FIELD = 0,
|
||||||
|
/** Unrecognized next header type encountered */
|
||||||
|
ICMP6_PP_HEADER = 1,
|
||||||
|
/** Unrecognized IPv6 option encountered */
|
||||||
|
ICMP6_PP_OPTION = 2
|
||||||
|
};
|
||||||
|
|
||||||
/** This is the standard ICMP6 header. */
|
/** This is the standard ICMP6 header. */
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
# include "arch/bpstruct.h"
|
# include "arch/bpstruct.h"
|
||||||
|
@ -44,6 +44,22 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** This is the packed version of ip4_addr_t,
|
||||||
|
used in network headers that are itself packed */
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip4_addr_packed {
|
||||||
|
PACK_STRUCT_FIELD(u32_t addr);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct ip4_addr_packed ip4_addr_p_t;
|
||||||
|
|
||||||
/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */
|
/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */
|
||||||
#define IP_HLEN 20
|
#define IP_HLEN 20
|
||||||
|
|
||||||
|
@ -44,6 +44,21 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
typedef struct ip6_addr_packed ip6_addr_p_t;
|
||||||
|
|
||||||
#define IP6_HLEN 40
|
#define IP6_HLEN 40
|
||||||
|
|
||||||
#define IP6_NEXTH_HOPBYHOP 0
|
#define IP6_NEXTH_HOPBYHOP 0
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#define LWIP_HDR_PROT_MLD6_H
|
#define LWIP_HDR_PROT_MLD6_H
|
||||||
|
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/prot/ip6.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
#include "lwip/ip6_addr.h"
|
#include "lwip/ip6_addr.h"
|
||||||
|
#include "lwip/prot/ip6.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -246,6 +247,29 @@ PACK_STRUCT_END
|
|||||||
# include "arch/epstruct.h"
|
# include "arch/epstruct.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Recursive DNS Server Option. */
|
||||||
|
#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||||
|
#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS
|
||||||
|
#else
|
||||||
|
#define LWIP_RDNSS_OPTION_MAX_SERVERS 1
|
||||||
|
#endif
|
||||||
|
#define ND6_OPTION_TYPE_RDNSS (25)
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct rdnss_option {
|
||||||
|
PACK_STRUCT_FLD_8(u8_t type);
|
||||||
|
PACK_STRUCT_FLD_8(u8_t length);
|
||||||
|
PACK_STRUCT_FIELD(u16_t reserved);
|
||||||
|
PACK_STRUCT_FIELD(u32_t lifetime);
|
||||||
|
PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,7 +85,7 @@ PACK_STRUCT_END
|
|||||||
|
|
||||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr))
|
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags))
|
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags))
|
||||||
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | (flags))
|
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags)))
|
||||||
|
|
||||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags))
|
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags))
|
||||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags))
|
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags))
|
||||||
|
@ -43,8 +43,6 @@
|
|||||||
|
|
||||||
#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include <stddef.h> /* for size_t */
|
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
@ -34,44 +34,6 @@
|
|||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup sys_layer System abstraction layer
|
|
||||||
* @ingroup infrastructure
|
|
||||||
* @verbinclude "sys_arch.txt"
|
|
||||||
*
|
|
||||||
* @defgroup sys_os OS abstraction layer
|
|
||||||
* @ingroup sys_layer
|
|
||||||
* No need to implement functions in this section in NO_SYS mode.
|
|
||||||
*
|
|
||||||
* @defgroup sys_sem Semaphores
|
|
||||||
* @ingroup sys_os
|
|
||||||
*
|
|
||||||
* @defgroup sys_mutex Mutexes
|
|
||||||
* @ingroup sys_os
|
|
||||||
* Mutexes are recommended to correctly handle priority inversion,
|
|
||||||
* especially if you use LWIP_CORE_LOCKING .
|
|
||||||
*
|
|
||||||
* @defgroup sys_mbox Mailboxes
|
|
||||||
* @ingroup sys_os
|
|
||||||
*
|
|
||||||
* @defgroup sys_time Time
|
|
||||||
* @ingroup sys_layer
|
|
||||||
*
|
|
||||||
* @defgroup sys_prot Critical sections
|
|
||||||
* @ingroup sys_layer
|
|
||||||
* Used to protect short regions of code against concurrent access.
|
|
||||||
* - Your system is a bare-metal system (probably with an RTOS)
|
|
||||||
* and interrupts are under your control:
|
|
||||||
* Implement this as LockInterrupts() / UnlockInterrupts()
|
|
||||||
* - Your system uses an RTOS with deferred interrupt handling from a
|
|
||||||
* worker thread: Implement as a global mutex or lock/unlock scheduler
|
|
||||||
* - Your system uses a high-level OS with e.g. POSIX signals:
|
|
||||||
* Implement as a global mutex
|
|
||||||
*
|
|
||||||
* @defgroup sys_misc Misc
|
|
||||||
* @ingroup sys_os
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LWIP_HDR_SYS_H
|
#ifndef LWIP_HDR_SYS_H
|
||||||
#define LWIP_HDR_SYS_H
|
#define LWIP_HDR_SYS_H
|
||||||
|
|
||||||
|
@ -387,6 +387,7 @@ err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
|
|||||||
err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
|
err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
|
||||||
u16_t port, tcp_connected_fn connected);
|
u16_t port, tcp_connected_fn connected);
|
||||||
|
|
||||||
|
struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err);
|
||||||
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||||
/** @ingroup tcp_raw */
|
/** @ingroup tcp_raw */
|
||||||
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||||
|
@ -616,7 +616,8 @@ lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
|
|||||||
err_t
|
err_t
|
||||||
lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
||||||
{
|
{
|
||||||
s8_t i;
|
err_t result;
|
||||||
|
const u8_t *hwaddr;
|
||||||
struct ieee_802154_addr src, dest;
|
struct ieee_802154_addr src, dest;
|
||||||
#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
|
#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
|
||||||
ip6_addr_t ip6_src;
|
ip6_addr_t ip6_src;
|
||||||
@ -663,35 +664,23 @@ lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
|
#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
|
||||||
|
|
||||||
|
/* Ask ND6 what to do with the packet. */
|
||||||
/* Get next hop record. */
|
result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
|
||||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
if (result != ERR_OK) {
|
||||||
if (i < 0) {
|
|
||||||
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
|
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
|
||||||
/* failed to get a next hop neighbor record. */
|
return result;
|
||||||
return ERR_MEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that we have a destination record, send or queue the packet. */
|
/* If no hardware address is returned, nd6 has queued the packet for later. */
|
||||||
if (neighbor_cache[i].state == ND6_STALE) {
|
if (hwaddr == NULL) {
|
||||||
/* Switch to delay state. */
|
return ERR_OK;
|
||||||
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. */
|
|
||||||
dest.addr_len = netif->hwaddr_len;
|
|
||||||
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, netif->hwaddr_len);
|
|
||||||
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
|
||||||
return lowpan6_frag(netif, q, &src, &dest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should queue packet on this interface. */
|
/* Send out the packet using the returned hardware address. */
|
||||||
return nd6_queue_packet(i, q);
|
dest.addr_len = netif->hwaddr_len;
|
||||||
|
SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len);
|
||||||
|
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
||||||
|
return lowpan6_frag(netif, q, &src, &dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pbuf *
|
static struct pbuf *
|
||||||
|
@ -1145,12 +1145,12 @@ int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
|
|||||||
nsa = dns_getserver(0);
|
nsa = dns_getserver(0);
|
||||||
ip_addr_set_ip4_u32(&nsb, ns1);
|
ip_addr_set_ip4_u32(&nsb, ns1);
|
||||||
if (ip_addr_cmp(nsa, &nsb)) {
|
if (ip_addr_cmp(nsa, &nsb)) {
|
||||||
dns_setserver(0, IP4_ADDR_ANY);
|
dns_setserver(0, IP_ADDR_ANY);
|
||||||
}
|
}
|
||||||
nsa = dns_getserver(1);
|
nsa = dns_getserver(1);
|
||||||
ip_addr_set_ip4_u32(&nsb, ns2);
|
ip_addr_set_ip4_u32(&nsb, ns2);
|
||||||
if (ip_addr_cmp(nsa, &nsb)) {
|
if (ip_addr_cmp(nsa, &nsb)) {
|
||||||
dns_setserver(1, IP4_ADDR_ANY);
|
dns_setserver(1, IP_ADDR_ANY);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,7 @@ pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m)
|
|||||||
msg->msg.msg.l2tpcreate.secret_len,
|
msg->msg.msg.l2tpcreate.secret_len,
|
||||||
#else /* PPPOL2TP_AUTH_SUPPORT */
|
#else /* PPPOL2TP_AUTH_SUPPORT */
|
||||||
NULL,
|
NULL,
|
||||||
|
0,
|
||||||
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
#endif /* PPPOL2TP_AUTH_SUPPORT */
|
||||||
msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb);
|
msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@ -239,6 +240,10 @@ pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipad
|
|||||||
ppp_pcb* result;
|
ppp_pcb* result;
|
||||||
PPPAPI_VAR_DECLARE(msg);
|
PPPAPI_VAR_DECLARE(msg);
|
||||||
PPPAPI_VAR_ALLOC_RETURN_NULL(msg);
|
PPPAPI_VAR_ALLOC_RETURN_NULL(msg);
|
||||||
|
#if !PPPOL2TP_AUTH_SUPPORT
|
||||||
|
LWIP_UNUSED_ARG(secret);
|
||||||
|
LWIP_UNUSED_ARG(secret_len);
|
||||||
|
#endif /* !PPPOL2TP_AUTH_SUPPORT */
|
||||||
|
|
||||||
PPPAPI_VAR_REF(msg).msg.ppp = NULL;
|
PPPAPI_VAR_REF(msg).msg.ppp = NULL;
|
||||||
PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif;
|
PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif;
|
||||||
|
@ -113,6 +113,10 @@ ppp_pcb *pppol2tp_create(struct netif *pppif,
|
|||||||
ppp_pcb *ppp;
|
ppp_pcb *ppp;
|
||||||
pppol2tp_pcb *l2tp;
|
pppol2tp_pcb *l2tp;
|
||||||
struct udp_pcb *udp;
|
struct udp_pcb *udp;
|
||||||
|
#if !PPPOL2TP_AUTH_SUPPORT
|
||||||
|
LWIP_UNUSED_ARG(secret);
|
||||||
|
LWIP_UNUSED_ARG(secret_len);
|
||||||
|
#endif /* !PPPOL2TP_AUTH_SUPPORT */
|
||||||
|
|
||||||
if (ipaddr == NULL) {
|
if (ipaddr == NULL) {
|
||||||
goto ipaddr_check_failed;
|
goto ipaddr_check_failed;
|
||||||
@ -303,7 +307,7 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
|
|||||||
udp_bind(l2tp->udp, IP6_ADDR_ANY, 0);
|
udp_bind(l2tp->udp, IP6_ADDR_ANY, 0);
|
||||||
} else
|
} else
|
||||||
#endif /* LWIP_IPV6 */
|
#endif /* LWIP_IPV6 */
|
||||||
udp_bind(l2tp->udp, IP4_ADDR_ANY, 0);
|
udp_bind(l2tp->udp, IP_ADDR_ANY, 0);
|
||||||
|
|
||||||
#if PPPOL2TP_AUTH_SUPPORT
|
#if PPPOL2TP_AUTH_SUPPORT
|
||||||
/* Generate random vector */
|
/* Generate random vector */
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
|
#include "lwip/arch.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
@ -471,18 +471,20 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l)
|
|||||||
u8_t escaped;
|
u8_t escaped;
|
||||||
PPPOS_DECL_PROTECT(lev);
|
PPPOS_DECL_PROTECT(lev);
|
||||||
|
|
||||||
PPPOS_PROTECT(lev);
|
|
||||||
if (!pppos->open) {
|
|
||||||
PPPOS_UNPROTECT(lev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PPPOS_UNPROTECT(lev);
|
|
||||||
|
|
||||||
PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
|
PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
|
||||||
while (l-- > 0) {
|
while (l-- > 0) {
|
||||||
cur_char = *s++;
|
cur_char = *s++;
|
||||||
|
|
||||||
PPPOS_PROTECT(lev);
|
PPPOS_PROTECT(lev);
|
||||||
|
/* ppp_input can disconnect the interface, we need to abort to prevent a memory
|
||||||
|
* leak if there are remaining bytes because pppos_connect and pppos_listen
|
||||||
|
* functions expect input buffer to be free. Furthermore there are no real
|
||||||
|
* reason to continue reading bytes if we are disconnected.
|
||||||
|
*/
|
||||||
|
if (!pppos->open) {
|
||||||
|
PPPOS_UNPROTECT(lev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
escaped = ESCAPE_P(pppos->in_accm, cur_char);
|
escaped = ESCAPE_P(pppos->in_accm, cur_char);
|
||||||
PPPOS_UNPROTECT(lev);
|
PPPOS_UNPROTECT(lev);
|
||||||
/* Handle special characters. */
|
/* Handle special characters. */
|
||||||
|
@ -247,11 +247,13 @@ int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) {
|
|||||||
val = va_arg(args, unsigned int);
|
val = va_arg(args, unsigned int);
|
||||||
base = 16;
|
base = 16;
|
||||||
break;
|
break;
|
||||||
|
#if 0 /* unused (and wrong on LLP64 systems) */
|
||||||
case 'p':
|
case 'p':
|
||||||
val = (unsigned long) va_arg(args, void *);
|
val = (unsigned long) va_arg(args, void *);
|
||||||
base = 16;
|
base = 16;
|
||||||
neg = 2;
|
neg = 2;
|
||||||
break;
|
break;
|
||||||
|
#endif /* unused (and wrong on LLP64 systems) */
|
||||||
case 's':
|
case 's':
|
||||||
str = va_arg(args, char *);
|
str = va_arg(args, char *);
|
||||||
break;
|
break;
|
||||||
|
53
test/fuzz/Makefile
Normal file
53
test/fuzz/Makefile
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
# 3. The name of the author may not be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
# OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# This file is part of the lwIP TCP/IP stack.
|
||||||
|
#
|
||||||
|
# Author: Adam Dunkels <adam@sics.se>
|
||||||
|
#
|
||||||
|
|
||||||
|
all compile: lwip_fuzz
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
CC=afl-gcc
|
||||||
|
LDFLAGS=-lm
|
||||||
|
CFLAGS=-O0
|
||||||
|
|
||||||
|
CONTRIBDIR=../../../lwip-contrib
|
||||||
|
include $(CONTRIBDIR)/ports/unix/Common.mk
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(LWIPLIBCOMMON) lwip_fuzz *.s .depend* *.core core
|
||||||
|
|
||||||
|
depend dep: .depend
|
||||||
|
|
||||||
|
include .depend
|
||||||
|
|
||||||
|
.depend: fuzz.c $(LWIPFILES) $(APPFILES)
|
||||||
|
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
|
||||||
|
|
||||||
|
lwip_fuzz: .depend $(LWIPLIBCOMMON) fuzz.o
|
||||||
|
$(CC) $(CFLAGS) -o lwip_fuzz fuzz.o $(LWIPLIBCOMMON) $(LDFLAGS)
|
34
test/fuzz/README
Normal file
34
test/fuzz/README
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
Fuzzing the lwIP stack (afl-fuzz requires linux/unix or similar)
|
||||||
|
|
||||||
|
This directory contains a small app that reads Ethernet frames from stdin and
|
||||||
|
processes them. It is used together with the 'american fuzzy lop' tool (found
|
||||||
|
at http://lcamtuf.coredump.cx/afl/) and the sample inputs to test how
|
||||||
|
unexpected inputs are handled. The afl tool will read the known inputs, and
|
||||||
|
try to modify them to exercise as many code paths as possible, by instrumenting
|
||||||
|
the code and keeping track of which code is executed.
|
||||||
|
|
||||||
|
Just running make will produce the test program.
|
||||||
|
|
||||||
|
Then run afl with:
|
||||||
|
|
||||||
|
afl-fuzz -i inputs/<INPUT> -o output ./lwip_fuzz
|
||||||
|
|
||||||
|
and it should start working. It will probably complain about CPU scheduler,
|
||||||
|
set AFL_SKIP_CPUFREQ=1 to ignore it.
|
||||||
|
If it complains about invalid "/proc/sys/kernel/core_pattern" setting, try
|
||||||
|
executing "sudo bash -c 'echo core > /proc/sys/kernel/core_pattern'".
|
||||||
|
|
||||||
|
The input is split into different subdirectories since they test different
|
||||||
|
parts of the code, and since you want to run one instance of afl-fuzz on each
|
||||||
|
core.
|
||||||
|
|
||||||
|
When afl finds a crash or a hang, the input that caused it will be placed in
|
||||||
|
the output directory. If you have hexdump and text2pcap tools installed,
|
||||||
|
running output_to_pcap.sh <outputdir> will create pcap files for each input
|
||||||
|
file to simplify viewing in wireshark.
|
||||||
|
|
||||||
|
The lwipopts.h file needs to have checksum checking off, otherwise almost every
|
||||||
|
packet will be discarded because of that. The other options can be tuned to
|
||||||
|
expose different parts of the code.
|
||||||
|
|
0
test/fuzz/config.h
Normal file
0
test/fuzz/config.h
Normal file
136
test/fuzz/fuzz.c
Normal file
136
test/fuzz/fuzz.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the lwIP TCP/IP stack.
|
||||||
|
*
|
||||||
|
* Author: Erik Ekman <erik@kryo.se>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwip/init.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
#include "netif/etharp.h"
|
||||||
|
#if LWIP_IPV6
|
||||||
|
#include "lwip/ethip6.h"
|
||||||
|
#include "lwip/nd6.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* no-op send function */
|
||||||
|
static err_t lwip_tx_func(struct netif *netif, struct pbuf *p)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(netif);
|
||||||
|
LWIP_UNUSED_ARG(p);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t testif_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
netif->name[0] = 'f';
|
||||||
|
netif->name[1] = 'z';
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = lwip_tx_func;
|
||||||
|
netif->mtu = 1500;
|
||||||
|
netif->hwaddr_len = 6;
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||||
|
|
||||||
|
netif->hwaddr[0] = 0x00;
|
||||||
|
netif->hwaddr[1] = 0x23;
|
||||||
|
netif->hwaddr[2] = 0xC1;
|
||||||
|
netif->hwaddr[3] = 0xDE;
|
||||||
|
netif->hwaddr[4] = 0xD0;
|
||||||
|
netif->hwaddr[5] = 0x0D;
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
netif->output_ip6 = ethip6_output;
|
||||||
|
netif->ip6_autoconfig_enabled = 1;
|
||||||
|
netif_create_ip6_linklocal_address(netif, 1);
|
||||||
|
netif->flags |= NETIF_FLAG_MLD6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void input_pkt(struct netif *netif, const u8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
struct pbuf *p, *q;
|
||||||
|
err_t err;
|
||||||
|
|
||||||
|
LWIP_ASSERT("pkt too big", len <= 0xFFFF);
|
||||||
|
p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL);
|
||||||
|
LWIP_ASSERT("alloc failed", p);
|
||||||
|
for(q = p; q != NULL; q = q->next) {
|
||||||
|
MEMCPY(q->payload, data, q->len);
|
||||||
|
data += q->len;
|
||||||
|
}
|
||||||
|
err = netif->input(p, netif);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
struct netif net_test;
|
||||||
|
ip4_addr_t addr;
|
||||||
|
ip4_addr_t netmask;
|
||||||
|
ip4_addr_t gw;
|
||||||
|
u8_t pktbuf[2000];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
lwip_init();
|
||||||
|
|
||||||
|
IP4_ADDR(&addr, 172, 30, 115, 84);
|
||||||
|
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||||
|
IP4_ADDR(&gw, 172, 30, 115, 1);
|
||||||
|
|
||||||
|
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
|
||||||
|
netif_set_up(&net_test);
|
||||||
|
|
||||||
|
#if LWIP_IPV6
|
||||||
|
nd6_tmr(); /* tick nd to join multicast groups */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(argc > 1) {
|
||||||
|
FILE* f;
|
||||||
|
const char* filename;
|
||||||
|
printf("reading input from file... ");
|
||||||
|
fflush(stdout);
|
||||||
|
filename = argv[1];
|
||||||
|
LWIP_ASSERT("invalid filename", filename != NULL);
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
LWIP_ASSERT("open failed", f != NULL);
|
||||||
|
len = fread(pktbuf, 1, sizeof(pktbuf), f);
|
||||||
|
fclose(f);
|
||||||
|
printf("testing file: \"%s\"...\r\n", filename);
|
||||||
|
} else {
|
||||||
|
len = fread(pktbuf, 1, sizeof(pktbuf), stdin);
|
||||||
|
}
|
||||||
|
input_pkt(&net_test, pktbuf, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
test/fuzz/inputs/arp/arp_req.bin
Normal file
BIN
test/fuzz/inputs/arp/arp_req.bin
Normal file
Binary file not shown.
BIN
test/fuzz/inputs/icmp/icmp_ping.bin
Normal file
BIN
test/fuzz/inputs/icmp/icmp_ping.bin
Normal file
Binary file not shown.
BIN
test/fuzz/inputs/ipv6/neighbor_solicitation.bin
Normal file
BIN
test/fuzz/inputs/ipv6/neighbor_solicitation.bin
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user