Compare commits
27 Commits
STABLE-1_4
...
STABLE-1_4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb7d3a159a | ||
|
|
dc6b4e65e0 | ||
|
|
17d4ef4053 | ||
|
|
03be8f88fe | ||
|
|
effcb90fdf | ||
|
|
1bd06bee82 | ||
|
|
92cdc1e33f | ||
|
|
377628216e | ||
|
|
f7627929d5 | ||
|
|
b49cf5e7a2 | ||
|
|
231a6cecb4 | ||
|
|
32f02325f9 | ||
|
|
f418782c2c | ||
|
|
e52730d1fb | ||
|
|
d2679e58a6 | ||
|
|
e3817cd549 | ||
|
|
4ace50a7d7 | ||
|
|
fa092c47c8 | ||
|
|
704d90f693 | ||
|
|
93dc36e091 | ||
|
|
4cc36b2284 | ||
|
|
aaa8d2795e | ||
|
|
229137cad1 | ||
|
|
d73262a0e5 | ||
|
|
cd22a8d851 | ||
|
|
7f7df4ae19 | ||
|
|
3c5723e49d |
79
CHANGELOG
79
CHANGELOG
@@ -13,6 +13,10 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2010-11-21: Simon Goldschmidt
|
||||
* dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
|
||||
(fixes bug #31525).
|
||||
|
||||
2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
|
||||
* ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
|
||||
IP_MULTICAST_LOOP at socket- and raw-API level.
|
||||
@@ -229,6 +233,81 @@ HISTORY
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2011-01-24: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
|
||||
|
||||
2010-12-02: Simon Goldschmidt
|
||||
* err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
|
||||
LWIP_SO_RCVBUF and ioctl/FIONREAD.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
|
||||
least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
|
||||
refusing 'refused_data' again.
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
|
||||
after a successful nonblocking connection.
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
|
||||
must be sent link-local
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
|
||||
LWIP_TIMERS==0
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
|
||||
resemble other stacks.
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
|
||||
no-copy TCP writes will never succeed.
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
|
||||
not match documentation: return ERR_ARG instead of ERR_VAL if not
|
||||
initialized or wrong argument.
|
||||
|
||||
2010-10-20: Simon Goldschmidt
|
||||
* sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
|
||||
|
||||
2010-10-05: Simon Goldschmidt
|
||||
* dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
|
||||
replugging the network cable after an AutoIP address was assigned.
|
||||
|
||||
2010-08-10: Simon Goldschmidt
|
||||
* tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
|
||||
|
||||
2010-08-03: Simon Goldschmidt
|
||||
* udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
|
||||
|
||||
2010-08-01: Simon Goldschmidt (patch by Greg Renda)
|
||||
* ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
|
||||
endian architectures)
|
||||
|
||||
2010-07-28: Simon Goldschmidt
|
||||
* api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
|
||||
disabled.
|
||||
|
||||
2010-07-27: Simon Goldschmidt
|
||||
* tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
|
||||
harm but never did anything
|
||||
|
||||
2010-07-21: Simon Goldschmidt
|
||||
* ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
|
||||
add IP options)
|
||||
|
||||
2010-07-16: Kieran Mansley
|
||||
* msg_in.c: Fixed SNMP ASN constant defines to not use ! operator
|
||||
|
||||
|
||||
@@ -111,11 +111,16 @@ with newer versions.
|
||||
* Added const char* name to mem- and memp-stats for easier debugging.
|
||||
|
||||
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
||||
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
||||
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
||||
|
||||
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
||||
more than one pcb.
|
||||
|
||||
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
|
||||
off any more, if this is set to 0, only one packet (the most recent one) is
|
||||
queued (like demanded by RFC 1122).
|
||||
|
||||
|
||||
++ Major bugfixes/improvements
|
||||
|
||||
* Implemented tcp_shutdown() to only shut down one end of a connection
|
||||
|
||||
@@ -240,6 +240,7 @@ netconn_disconnect(struct netconn *conn)
|
||||
err_t
|
||||
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
@@ -257,6 +258,11 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(conn);
|
||||
LWIP_UNUSED_ARG(backlog);
|
||||
return ERR_ARG;
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -402,7 +408,9 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
||||
}
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_DEC(conn->recv_avail, len);
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
||||
|
||||
@@ -499,6 +507,7 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
||||
void
|
||||
netconn_recved(struct netconn *conn, u32_t length)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
|
||||
(netconn_get_noautorecved(conn))) {
|
||||
struct api_msg msg;
|
||||
@@ -511,6 +520,10 @@ netconn_recved(struct netconn *conn, u32_t length)
|
||||
/* don't care for the return value of do_recv */
|
||||
TCPIP_APIMSG(&msg);
|
||||
}
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(conn);
|
||||
LWIP_UNUSED_ARG(length);
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,7 +120,9 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
netbuf_delete(buf);
|
||||
return 0;
|
||||
} else {
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_INC(conn->recv_avail, len);
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
}
|
||||
@@ -194,7 +196,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
netbuf_delete(buf);
|
||||
return;
|
||||
} else {
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_INC(conn->recv_avail, len);
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
}
|
||||
@@ -248,7 +252,9 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
/* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
|
||||
return ERR_MEM;
|
||||
} else {
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_INC(conn->recv_avail, len);
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
}
|
||||
@@ -614,7 +620,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
|
||||
conn->socket = -1;
|
||||
#endif /* LWIP_SOCKET */
|
||||
conn->callback = callback;
|
||||
conn->recv_avail = 0;
|
||||
#if LWIP_TCP
|
||||
conn->current_msg = NULL;
|
||||
conn->write_offset = 0;
|
||||
@@ -624,6 +629,7 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
|
||||
#endif /* LWIP_SO_RCVTIMEO */
|
||||
#if LWIP_SO_RCVBUF
|
||||
conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
|
||||
conn->recv_avail = 0;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
conn->flags = 0;
|
||||
return conn;
|
||||
@@ -1040,6 +1046,7 @@ do_disconnect(struct api_msg_msg *msg)
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
|
||||
#if LWIP_TCP
|
||||
/**
|
||||
* Set a TCP pcb contained in a netconn into listen mode
|
||||
* Called from netconn_listen.
|
||||
@@ -1049,7 +1056,6 @@ do_disconnect(struct api_msg_msg *msg)
|
||||
void
|
||||
do_listen(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
||||
msg->err = msg->conn->last_err;
|
||||
} else {
|
||||
@@ -1091,9 +1097,9 @@ do_listen(struct api_msg_msg *msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
/**
|
||||
* Send some data on a RAW or UDP pcb contained in a netconn
|
||||
@@ -1147,6 +1153,7 @@ do_send(struct api_msg_msg *msg)
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
|
||||
#if LWIP_TCP
|
||||
/**
|
||||
* Indicate data has been received from a TCP pcb contained in a netconn
|
||||
* Called from netconn_recv
|
||||
@@ -1156,7 +1163,6 @@ do_send(struct api_msg_msg *msg)
|
||||
void
|
||||
do_recv(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
msg->err = ERR_OK;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
@@ -1175,11 +1181,9 @@ do_recv(struct api_msg_msg *msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
|
||||
#if LWIP_TCP
|
||||
/**
|
||||
* See if more data needs to be written from a previous call to netconn_write.
|
||||
* Called initially from do_write. If the first call can't send all data
|
||||
|
||||
@@ -105,8 +105,10 @@ struct lwip_select_cb {
|
||||
struct lwip_setgetsockopt_data {
|
||||
/** socket struct for which to change options */
|
||||
struct lwip_sock *sock;
|
||||
#ifdef LWIP_DEBUG
|
||||
/** socket index for which to change options */
|
||||
int s;
|
||||
#endif /* LWIP_DEBUG */
|
||||
/** level of the option to process */
|
||||
int level;
|
||||
/** name of the option to process */
|
||||
@@ -804,6 +806,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
#if LWIP_TCP
|
||||
return lwip_send(s, data, size, flags);
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(flags);
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG));
|
||||
return -1;
|
||||
#endif /* LWIP_TCP */
|
||||
@@ -852,6 +855,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
if (sock->conn->type == NETCONN_RAW) {
|
||||
err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
|
||||
} else {
|
||||
#if LWIP_UDP
|
||||
#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
|
||||
err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
|
||||
remote_addr, remote_port, 1, chksum);
|
||||
@@ -859,6 +863,9 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
|
||||
remote_addr, remote_port);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
#else /* LWIP_UDP */
|
||||
err = ERR_ARG;
|
||||
#endif /* LWIP_UDP */
|
||||
}
|
||||
UNLOCK_TCPIP_CORE();
|
||||
|
||||
@@ -1181,6 +1188,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
|
||||
select_cb.prev->next = select_cb.next;
|
||||
}
|
||||
/* Increasing this counter tells even_callback that the list has changed. */
|
||||
select_cb_ctr++;
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
sys_sem_free(&select_cb.sem);
|
||||
@@ -1223,6 +1232,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
int s;
|
||||
struct lwip_sock *sock;
|
||||
struct lwip_select_cb *scb;
|
||||
int last_select_cb_ctr;
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
LWIP_UNUSED_ARG(len);
|
||||
@@ -1285,56 +1295,51 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
/* Now decide if anyone is waiting for this socket */
|
||||
/* NOTE: This code is written this way to protect the select link list
|
||||
but to avoid a deadlock situation by releasing select_lock before
|
||||
signalling for the select. This means we need to go through the list
|
||||
multiple times ONLY IF a select was actually waiting. We go through
|
||||
the list the number of waiting select calls + 1. This list is
|
||||
expected to be small. */
|
||||
while (1) {
|
||||
int last_select_cb_ctr;
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
for (scb = select_cb_list; scb; scb = scb->next) {
|
||||
/* @todo: unprotect with each loop and check for changes? */
|
||||
if (scb->sem_signalled == 0) {
|
||||
/* Test this select call for our socket */
|
||||
/* NOTE: This code goes through the select_cb_list list multiple times
|
||||
ONLY IF a select was actually waiting. We go through the list the number
|
||||
of waiting select calls + 1. This list is expected to be small. */
|
||||
|
||||
/* At this point, SYS_ARCH is still protected! */
|
||||
again:
|
||||
for (scb = select_cb_list; scb != NULL; scb = scb->next) {
|
||||
if (scb->sem_signalled == 0) {
|
||||
/* semaphore not signalled yet */
|
||||
int do_signal = 0;
|
||||
/* Test this select call for our socket */
|
||||
if (sock->rcvevent > 0) {
|
||||
if (scb->readset && FD_ISSET(s, scb->readset)) {
|
||||
if (sock->rcvevent > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scb->writeset && FD_ISSET(s, scb->writeset)) {
|
||||
if (sock->sendevent != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scb->exceptset && FD_ISSET(s, scb->exceptset)) {
|
||||
if (sock->errevent != 0) {
|
||||
break;
|
||||
}
|
||||
do_signal = 1;
|
||||
}
|
||||
}
|
||||
/* unlock interrupts with each step */
|
||||
last_select_cb_ctr = select_cb_ctr;
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if (last_select_cb_ctr != select_cb_ctr) {
|
||||
/* someone has changed select_cb_list, restart at the beginning */
|
||||
scb = select_cb_list;
|
||||
if (sock->sendevent != 0) {
|
||||
if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
|
||||
do_signal = 1;
|
||||
}
|
||||
}
|
||||
if (sock->errevent != 0) {
|
||||
if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
|
||||
do_signal = 1;
|
||||
}
|
||||
}
|
||||
if (do_signal) {
|
||||
scb->sem_signalled = 1;
|
||||
/* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
|
||||
lead to the select thread taking itself off the list, invalidagin the semaphore. */
|
||||
sys_sem_signal(&scb->sem);
|
||||
}
|
||||
}
|
||||
if (scb) {
|
||||
scb->sem_signalled = 1;
|
||||
sys_sem_signal(&scb->sem);
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
} else {
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
break;
|
||||
/* unlock interrupts with each step */
|
||||
last_select_cb_ctr = select_cb_ctr;
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
/* this makes sure interrupt protection time is short */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if (last_select_cb_ctr != select_cb_ctr) {
|
||||
/* someone has changed select_cb_list, restart at the beginning */
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1610,6 +1615,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
|
||||
/* Now do the actual option processing */
|
||||
data.sock = sock;
|
||||
#ifdef LWIP_DEBUG
|
||||
data.s = s;
|
||||
#endif /* LWIP_DEBUG */
|
||||
data.level = level;
|
||||
data.optname = optname;
|
||||
data.optval = optval;
|
||||
@@ -1691,8 +1699,8 @@ lwip_getsockopt_internal(void *arg)
|
||||
break;
|
||||
|
||||
case SO_ERROR:
|
||||
/* only overwrite if ERR_OK before */
|
||||
if (sock->err == 0) {
|
||||
/* only overwrite ERR_OK or tempoary errors */
|
||||
if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
|
||||
sock_set_errno(sock, err_to_errno(sock->conn->last_err));
|
||||
}
|
||||
*(int *)optval = sock->err;
|
||||
@@ -2017,6 +2025,9 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
||||
|
||||
/* Now do the actual option processing */
|
||||
data.sock = sock;
|
||||
#ifdef LWIP_DEBUG
|
||||
data.s = s;
|
||||
#endif /* LWIP_DEBUG */
|
||||
data.level = level;
|
||||
data.optname = optname;
|
||||
data.optval = (void*)optval;
|
||||
@@ -2239,15 +2250,18 @@ int
|
||||
lwip_ioctl(int s, long cmd, void *argp)
|
||||
{
|
||||
struct lwip_sock *sock = get_socket(s);
|
||||
u8_t val;
|
||||
#if LWIP_SO_RCVBUF
|
||||
u16_t buflen = 0;
|
||||
s16_t recv_avail;
|
||||
u8_t val;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
|
||||
if (!sock) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
#if LWIP_SO_RCVBUF
|
||||
case FIONREAD:
|
||||
if (!argp) {
|
||||
sock_set_errno(sock, EINVAL);
|
||||
@@ -2275,6 +2289,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
|
||||
case FIONBIO:
|
||||
val = 0;
|
||||
|
||||
@@ -592,6 +592,23 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
|
||||
netif->dhcp = dhcp;
|
||||
}
|
||||
|
||||
/** Removes a struct dhcp from a netif.
|
||||
*
|
||||
* ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
|
||||
* struct dhcp since the memory is passed back to the heap.
|
||||
*
|
||||
* @param netif the netif from which to remove the struct dhcp
|
||||
*/
|
||||
void dhcp_cleanup(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
|
||||
if (netif->dhcp != NULL) {
|
||||
mem_free(netif->dhcp);
|
||||
netif->dhcp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start DHCP negotiation for a network interface.
|
||||
*
|
||||
@@ -762,7 +779,10 @@ dhcp_network_changed(struct netif *netif)
|
||||
default:
|
||||
dhcp->tries = 0;
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
||||
if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
|
||||
autoip_stop(netif);
|
||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
||||
}
|
||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||
dhcp_discover(netif);
|
||||
break;
|
||||
|
||||
@@ -922,6 +922,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
||||
* name is already in the local names table.
|
||||
* - ERR_INPROGRESS enqueue a request to be sent to the DNS server
|
||||
* for resolution if no errors are present.
|
||||
* - ERR_ARG: dns client not initialized or invalid hostname
|
||||
*
|
||||
* @param hostname the hostname that is to be queried
|
||||
* @param addr pointer to a ip_addr_t where to store the address if it is already
|
||||
@@ -941,7 +942,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
|
||||
if ((dns_pcb == NULL) || (addr == NULL) ||
|
||||
(!hostname) || (!hostname[0]) ||
|
||||
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
|
||||
return ERR_VAL;
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
|
||||
@@ -105,6 +105,9 @@
|
||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
|
||||
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
||||
#endif
|
||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
||||
#endif
|
||||
|
||||
@@ -494,12 +494,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
*/
|
||||
ip_addr_t sipaddr, dipaddr;
|
||||
struct eth_addr netifaddr;
|
||||
netifaddr.addr[0] = netif->hwaddr[0];
|
||||
netifaddr.addr[1] = netif->hwaddr[1];
|
||||
netifaddr.addr[2] = netif->hwaddr[2];
|
||||
netifaddr.addr[3] = netif->hwaddr[3];
|
||||
netifaddr.addr[4] = netif->hwaddr[4];
|
||||
netifaddr.addr[5] = netif->hwaddr[5];
|
||||
ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
|
||||
|
||||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
||||
|
||||
@@ -625,7 +625,7 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
|
||||
}
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
for (i = 0; i < optlen_aligned; i += sizeof(u16_t)) {
|
||||
for (i = 0; i < optlen_aligned/2; i++) {
|
||||
chk_sum += ((u16_t*)p->payload)[i];
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
|
||||
@@ -218,8 +218,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
if (p->tot_len != 0) {
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
}
|
||||
/* { first pbuf q points to header pbuf } */
|
||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
} else {
|
||||
|
||||
@@ -43,10 +43,12 @@
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/snmp_asn1.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -408,11 +408,9 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
We do not dump TIME_WAIT pcb's; they can still be matched by incoming
|
||||
packets using both local and remote IP addresses and ports to distinguish.
|
||||
*/
|
||||
#if SO_REUSE
|
||||
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
|
||||
max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
#endif /* SO_REUSE */
|
||||
|
||||
if (port == 0) {
|
||||
@@ -618,7 +616,7 @@ tcp_new_port(void)
|
||||
port = TCP_LOCAL_PORT_RANGE_START;
|
||||
}
|
||||
/* Check all PCB lists. */
|
||||
for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {
|
||||
for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
|
||||
for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
|
||||
if (pcb->local_port == port) {
|
||||
goto again;
|
||||
@@ -679,8 +677,8 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
now that the 5-tuple is unique. */
|
||||
struct tcp_pcb *cpcb;
|
||||
int i;
|
||||
/* Don't check listen PCBs, check bound-, active- and TIME-WAIT PCBs. */
|
||||
for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {
|
||||
/* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */
|
||||
for (i = 2; i < NUM_TCP_PCB_LISTS; i++) {
|
||||
for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
||||
if ((cpcb->local_port == pcb->local_port) &&
|
||||
(cpcb->remote_port == port) &&
|
||||
@@ -740,7 +738,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
void
|
||||
tcp_slowtmr(void)
|
||||
{
|
||||
struct tcp_pcb *pcb, *pcb2, *prev;
|
||||
struct tcp_pcb *pcb, *prev;
|
||||
u16_t eff_wnd;
|
||||
u8_t pcb_remove; /* flag if a PCB should be removed */
|
||||
u8_t pcb_reset; /* flag if a RST should be sent when removing */
|
||||
@@ -896,6 +894,7 @@ tcp_slowtmr(void)
|
||||
|
||||
/* If the PCB should be removed, do it. */
|
||||
if (pcb_remove) {
|
||||
struct tcp_pcb *pcb2;
|
||||
tcp_pcb_purge(pcb);
|
||||
/* Remove PCB from tcp_active_pcbs list. */
|
||||
if (prev != NULL) {
|
||||
@@ -913,9 +912,9 @@ tcp_slowtmr(void)
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
|
||||
pcb2 = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
pcb = pcb2;
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb2);
|
||||
} else {
|
||||
/* get the 'next' element now and work with 'prev' below (in case of abort) */
|
||||
prev = pcb;
|
||||
@@ -937,7 +936,7 @@ tcp_slowtmr(void)
|
||||
|
||||
|
||||
/* Steps through all of the TIME-WAIT PCBs. */
|
||||
prev = NULL;
|
||||
prev = NULL;
|
||||
pcb = tcp_tw_pcbs;
|
||||
while (pcb != NULL) {
|
||||
LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||
@@ -952,6 +951,7 @@ tcp_slowtmr(void)
|
||||
|
||||
/* If the PCB should be removed, do it. */
|
||||
if (pcb_remove) {
|
||||
struct tcp_pcb *pcb2;
|
||||
tcp_pcb_purge(pcb);
|
||||
/* Remove PCB from tcp_tw_pcbs list. */
|
||||
if (prev != NULL) {
|
||||
@@ -962,9 +962,9 @@ tcp_slowtmr(void)
|
||||
LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
|
||||
tcp_tw_pcbs = pcb->next;
|
||||
}
|
||||
pcb2 = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
pcb = pcb2;
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb2);
|
||||
} else {
|
||||
prev = pcb;
|
||||
pcb = pcb->next;
|
||||
@@ -999,7 +999,7 @@ tcp_fasttmr(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* send delayed ACKs */
|
||||
/* send delayed ACKs */
|
||||
if (pcb && (pcb->flags & TF_ACK_DELAY)) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
|
||||
tcp_ack_now(pcb);
|
||||
|
||||
@@ -305,9 +305,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
||||
if (err == ERR_OK) {
|
||||
pcb->refused_data = NULL;
|
||||
} else {
|
||||
} else if ((err == ERR_ABRT) || (tcplen > 0)) {
|
||||
/* if err == ERR_ABRT, 'pcb' is already deallocated */
|
||||
/* drop incoming packets, because pcb is "full" */
|
||||
/* Drop incoming packets because pcb is "full" (only if the incoming
|
||||
segment contains data). */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
@@ -346,6 +347,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
if (recv_data != NULL) {
|
||||
LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
|
||||
if (pcb->flags & TF_RXCLOSED) {
|
||||
/* received data although already closed -> abort (send RST) to
|
||||
notify the remote host that not all data has been processed */
|
||||
|
||||
@@ -773,6 +773,7 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
|
||||
LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
|
||||
@@ -1067,7 +1068,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
|
||||
/* Add any requested options. NB MSS option is only set on SYN
|
||||
packets, so ignore it here */
|
||||
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)(seg->tcphdr + 1) % 4) == 0);
|
||||
LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
|
||||
opts = (u32_t *)(void *)(seg->tcphdr + 1);
|
||||
if (seg->flags & TF_SEG_OPTS_MSS) {
|
||||
TCP_BUILD_MSS_OPTION(*opts);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
|
||||
#if LWIP_TIMERS
|
||||
|
||||
@@ -49,7 +50,6 @@
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
|
||||
@@ -520,8 +520,10 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
if (p->tot_len != 0) {
|
||||
/* chain header q in front of given pbuf p (only if p contains data) */
|
||||
pbuf_chain(q, p);
|
||||
}
|
||||
/* first pbuf q points to header pbuf */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
|
||||
@@ -168,12 +168,11 @@ struct netconn {
|
||||
/** maximum amount of bytes queued in recvmbox
|
||||
not used for TCP: adjust TCP_WND instead! */
|
||||
int recv_bufsize;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/** number of bytes currently in recvmbox to be received,
|
||||
tested against recv_bufsize to limit bytes on recvmbox
|
||||
for UDP and RAW
|
||||
@todo: should only be necessary with LWIP_SO_RCVBUF==1 */
|
||||
for UDP and RAW, used for FIONREAD */
|
||||
s16_t recv_avail;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
||||
u8_t flags;
|
||||
#if LWIP_TCP
|
||||
|
||||
@@ -48,9 +48,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For the netconn API, these values are use as a bitmask! */
|
||||
#define NETCONN_SHUT_RD 1
|
||||
#define NETCONN_SHUT_WR 2
|
||||
#define NETCONN_SHUT_RDWR 3
|
||||
#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
|
||||
|
||||
/* IP addresses and port numbers are expected to be in
|
||||
* the same byte order as in the corresponding pcb.
|
||||
|
||||
@@ -106,6 +106,9 @@ PACK_STRUCT_END
|
||||
#endif
|
||||
|
||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
||||
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
||||
void dhcp_cleanup(struct netif *netif);
|
||||
/** start DHCP configuration */
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
/** enforce early lease renewal (not needed normally)*/
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
|
||||
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** DNS timer period */
|
||||
#define DNS_TMR_INTERVAL 1000
|
||||
|
||||
@@ -111,6 +115,10 @@ int dns_local_removehost(const char *hostname, const ip_addr_t *addr)
|
||||
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
|
||||
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#endif /* __LWIP_DNS_H__ */
|
||||
|
||||
@@ -58,7 +58,7 @@ typedef s8_t err_t;
|
||||
#define ERR_VAL -6 /* Illegal value. */
|
||||
#define ERR_WOULDBLOCK -7 /* Operation would block. */
|
||||
|
||||
#define ERR_IS_FATAL(e) ((e) < ERR_VAL)
|
||||
#define ERR_IS_FATAL(e) ((e) < ERR_WOULDBLOCK)
|
||||
|
||||
#define ERR_ABRT -8 /* Connection aborted. */
|
||||
#define ERR_RST -9 /* Connection reset. */
|
||||
|
||||
@@ -47,7 +47,7 @@ extern "C" {
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
#define LWIP_VERSION_RC 1U
|
||||
#define LWIP_VERSION_RC 2U
|
||||
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||
#define LWIP_RC_RELEASE 255U
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* some rarely used options */
|
||||
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
|
||||
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
|
||||
@@ -111,6 +115,10 @@ int lwip_getaddrinfo(const char *nodename,
|
||||
lwip_getaddrinfo(nodname, servname, hints, res)
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||
|
||||
#endif /* __LWIP_NETDB_H__ */
|
||||
|
||||
@@ -432,11 +432,14 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ARP_QUEUEING==1: Outgoing packets are queued during hardware address
|
||||
* resolution.
|
||||
* ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
|
||||
* resolution. By default, only the most recent packet is queued per IP address.
|
||||
* This is sufficient for most protocols and mainly reduces TCP connection
|
||||
* startup time. Set this to 1 if you know your application sends more than one
|
||||
* packet in a row to an IP address that is not in the ARP cache.
|
||||
*/
|
||||
#ifndef ARP_QUEUEING
|
||||
#define ARP_QUEUEING 1
|
||||
#define ARP_QUEUEING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -954,7 +957,7 @@
|
||||
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
|
||||
*/
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,7 +59,7 @@ struct sockaddr_in {
|
||||
struct sockaddr {
|
||||
u8_t sa_len;
|
||||
u8_t sa_family;
|
||||
u16_t sa_data[14];
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
#ifndef socklen_t
|
||||
@@ -280,9 +280,9 @@ typedef struct ip_mreq {
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RD
|
||||
#define SHUT_RD 1
|
||||
#define SHUT_WR 2
|
||||
#define SHUT_RDWR 3
|
||||
#define SHUT_RD 0
|
||||
#define SHUT_WR 1
|
||||
#define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
/* FD_SET used for lwip_select */
|
||||
|
||||
@@ -93,6 +93,9 @@ struct etharp_entry {
|
||||
#if ARP_QUEUEING
|
||||
/** Pointer to queue of pending outgoing packets on this ARP entry. */
|
||||
struct etharp_q_entry *q;
|
||||
#else /* ARP_QUEUEING */
|
||||
/** Pointer to a single pending outgoing packet on this ARP entry. */
|
||||
struct pbuf *q;
|
||||
#endif /* ARP_QUEUEING */
|
||||
ip_addr_t ipaddr;
|
||||
struct eth_addr ethaddr;
|
||||
@@ -154,6 +157,11 @@ free_etharp_q(struct etharp_q_entry *q)
|
||||
memp_free(MEMP_ARP_QUEUE, r);
|
||||
}
|
||||
}
|
||||
#else /* ARP_QUEUEING */
|
||||
|
||||
/** Compatibility define: free the queued pbuf */
|
||||
#define free_etharp_q(q) pbuf_free(q)
|
||||
|
||||
#endif /* ARP_QUEUEING */
|
||||
|
||||
/** Clean up ARP table entries */
|
||||
@@ -162,7 +170,6 @@ free_entry(int i)
|
||||
{
|
||||
/* remove from SNMP ARP index tree */
|
||||
snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
|
||||
#if ARP_QUEUEING
|
||||
/* and empty packet queue */
|
||||
if (arp_table[i].q != NULL) {
|
||||
/* remove all queued packets */
|
||||
@@ -170,7 +177,6 @@ free_entry(int i)
|
||||
free_etharp_q(arp_table[i].q);
|
||||
arp_table[i].q = NULL;
|
||||
}
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* recycle entry for re-use */
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
#if ETHARP_SUPPORT_STATIC_ENTRIES
|
||||
@@ -254,12 +260,10 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
||||
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
|
||||
s8_t empty = ARP_TABLE_SIZE;
|
||||
u8_t i = 0, age_pending = 0, age_stable = 0;
|
||||
#if ARP_QUEUEING
|
||||
/* oldest entry with packets on queue */
|
||||
s8_t old_queue = ARP_TABLE_SIZE;
|
||||
/* its age */
|
||||
u8_t age_queue = 0;
|
||||
#endif /* ARP_QUEUEING */
|
||||
|
||||
/**
|
||||
* a) do a search through the cache, remember candidates
|
||||
@@ -295,14 +299,12 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
||||
/* pending entry? */
|
||||
if (state == ETHARP_STATE_PENDING) {
|
||||
/* pending with queued packets? */
|
||||
#if ARP_QUEUEING
|
||||
if (arp_table[i].q != NULL) {
|
||||
if (arp_table[i].ctime >= age_queue) {
|
||||
old_queue = i;
|
||||
age_queue = arp_table[i].ctime;
|
||||
}
|
||||
} else
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* pending without queued packets? */
|
||||
{
|
||||
if (arp_table[i].ctime >= age_pending) {
|
||||
@@ -355,22 +357,18 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
|
||||
/* recycle oldest stable*/
|
||||
i = old_stable;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
|
||||
#if ARP_QUEUEING
|
||||
/* no queued packets should exist on stable entries */
|
||||
LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* 3) found recyclable pending entry without queued packets? */
|
||||
} else if (old_pending < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending */
|
||||
i = old_pending;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
|
||||
#if ARP_QUEUEING
|
||||
/* 4) found recyclable pending entry with queued packets? */
|
||||
} else if (old_queue < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending (queued packets are free in free_entry) */
|
||||
i = old_queue;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* no empty or recyclable entries found */
|
||||
} else {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
|
||||
@@ -486,8 +484,8 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd
|
||||
ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
|
||||
/* reset time stamp */
|
||||
arp_table[i].ctime = 0;
|
||||
#if ARP_QUEUEING
|
||||
/* this is where we will send out queued packets! */
|
||||
#if ARP_QUEUEING
|
||||
while (arp_table[i].q != NULL) {
|
||||
struct pbuf *p;
|
||||
/* remember remainder of queue */
|
||||
@@ -498,12 +496,16 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd
|
||||
p = q->p;
|
||||
/* now queue entry can be freed */
|
||||
memp_free(MEMP_ARP_QUEUE, q);
|
||||
#else /* ARP_QUEUEING */
|
||||
if (arp_table[i].q != NULL) {
|
||||
struct pbuf *p = arp_table[i].q;
|
||||
arp_table[i].q = NULL;
|
||||
#endif /* ARP_QUEUEING */
|
||||
/* send the queued IP packet */
|
||||
etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif /* ARP_QUEUEING */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -871,14 +873,25 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
|
||||
/* outside local network? */
|
||||
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
|
||||
!ip_addr_islinklocal(ipaddr)) {
|
||||
/* interface has default gateway? */
|
||||
if (!ip_addr_isany(&netif->gw)) {
|
||||
/* send to hardware address of default gateway IP address */
|
||||
ipaddr = &(netif->gw);
|
||||
/* no default gateway available */
|
||||
} else {
|
||||
/* no route to destination error (default gateway missing) */
|
||||
return ERR_RTE;
|
||||
#if LWIP_AUTOIP
|
||||
struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
|
||||
sizeof(struct eth_hdr));
|
||||
/* 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
|
||||
on the same physical link. The host MUST NOT send the packet to any
|
||||
router for forwarding". */
|
||||
if (!ip_addr_islinklocal(&iphdr->src))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
{
|
||||
/* interface has default gateway? */
|
||||
if (!ip_addr_isany(&netif->gw)) {
|
||||
/* send to hardware address of default gateway IP address */
|
||||
ipaddr = &(netif->gw);
|
||||
/* no default gateway available */
|
||||
} else {
|
||||
/* no route to destination error (default gateway missing) */
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
@@ -1004,7 +1017,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
||||
result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
|
||||
/* pending entry? (either just created or already pending */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
#if ARP_QUEUEING /* queue the given q packet */
|
||||
/* entry is still pending, queue the given packet 'q' */
|
||||
struct pbuf *p;
|
||||
int copy_needed = 0;
|
||||
/* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
|
||||
@@ -1036,6 +1049,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
||||
/* packet could be taken over? */
|
||||
if (p != NULL) {
|
||||
/* queue packet ... */
|
||||
#if ARP_QUEUEING
|
||||
struct etharp_q_entry *new_entry;
|
||||
/* allocate a new arp queue entry */
|
||||
new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
|
||||
@@ -1060,18 +1074,23 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
|
||||
/* the pool MEMP_ARP_QUEUE is empty */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
result = ERR_MEM;
|
||||
}
|
||||
#else /* ARP_QUEUEING */
|
||||
/* always queue one packet per ARP request only, freeing a previously queued packet */
|
||||
if (arp_table[i].q != NULL) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||
pbuf_free(arp_table[i].q);
|
||||
}
|
||||
arp_table[i].q = p;
|
||||
result = ERR_OK;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||
#endif /* ARP_QUEUEING */
|
||||
} else {
|
||||
ETHARP_STATS_INC(etharp.memerr);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
result = ERR_MEM;
|
||||
}
|
||||
#else /* ARP_QUEUEING */
|
||||
/* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
|
||||
#endif /* ARP_QUEUEING */
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1704,8 +1704,8 @@ pppInput(void *arg)
|
||||
}
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
protocol = htons(protocol);
|
||||
SMEMCPY(nb->payload, &protocol, sizeof(protocol));
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
SMEMCPY(nb->payload, &protocol, sizeof(protocol));
|
||||
lcp_sprotrej(pd, nb->payload, nb->len);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user