mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-02 12:34:38 +08:00
... and finally, we got a first working version of a dual-stack lwIP runnin IPv4 and IPv6 in parallel - big thanks to Ivan Delamer! (this is work in progress, so please beware, test a lot and report problems!)
This commit is contained in:
parent
f3c1686a40
commit
4bfbe7ebeb
@ -6,6 +6,10 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt)
|
||||
* nearly the whole stack: Finally, we got decent IPv6 support, big thanks to
|
||||
Ivan! (this is work in progress: we're just post release anyway :-)
|
||||
|
||||
2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage)
|
||||
* tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static
|
||||
memory message
|
||||
|
@ -372,7 +372,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
|
||||
#if LWIP_TCP
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
|
||||
/* Let the stack know that we have taken the data. */
|
||||
/* TODO: Speedup: Don't block and wait for the answer here
|
||||
@ -434,7 +434,7 @@ err_t
|
||||
netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
|
||||
{
|
||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
|
||||
netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
|
||||
NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
|
||||
|
||||
return netconn_recv_data(conn, (void **)new_buf);
|
||||
}
|
||||
@ -461,7 +461,7 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
||||
LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
||||
|
||||
#if LWIP_TCP
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||
struct pbuf *p = NULL;
|
||||
/* This is not a listening netconn, since recvmbox is set */
|
||||
|
||||
@ -481,7 +481,11 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->port = 0;
|
||||
ip_addr_set_any(&buf->addr);
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_set_any(&buf->addr.ip6);
|
||||
#else /* LWIP_IPV6 */
|
||||
ip_addr_set_any(&buf->addr.ip4);
|
||||
#endif /* LWIP_IPV6 */
|
||||
*new_buf = buf;
|
||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
||||
return ERR_OK;
|
||||
@ -508,7 +512,7 @@ void
|
||||
netconn_recved(struct netconn *conn, u32_t length)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
|
||||
if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) &&
|
||||
(netconn_get_noautorecved(conn))) {
|
||||
struct api_msg msg;
|
||||
/* Let the stack know that we have taken the data. */
|
||||
@ -540,7 +544,15 @@ err_t
|
||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
if (buf != NULL) {
|
||||
ip_addr_set(&buf->addr, addr);
|
||||
#if LWIP_IPV6
|
||||
if (conn->pcb.ip->isipv6) {
|
||||
ip6_addr_set(&buf->addr.ip6, (ip6_addr_t *)addr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&buf->addr.ip4, addr);
|
||||
}
|
||||
buf->port = port;
|
||||
return netconn_send(conn, buf);
|
||||
}
|
||||
@ -591,7 +603,7 @@ netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apifl
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
|
||||
LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
|
||||
if (size == 0) {
|
||||
return ERR_OK;
|
||||
}
|
||||
@ -664,7 +676,7 @@ netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
|
||||
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
/**
|
||||
* Join multicast groups for UDP netconns.
|
||||
*
|
||||
@ -696,7 +708,7 @@ netconn_join_leave_group(struct netconn *conn,
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
|
||||
#if LWIP_DNS
|
||||
/**
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -112,7 +113,15 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
|
||||
buf->p = q;
|
||||
buf->ptr = q;
|
||||
ip_addr_copy(buf->addr, *ip_current_src_addr());
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_copy(buf->addr.ip6, *ip6_current_src_addr());
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_copy(buf->addr.ip4, *ip_current_src_addr());
|
||||
}
|
||||
buf->port = pcb->protocol;
|
||||
|
||||
len = q->tot_len;
|
||||
@ -175,9 +184,30 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
} else {
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
ip_addr_set(&buf->addr, addr);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
ip6_addr_set(&buf->addr.ip6, (ip6_addr_t *)addr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&buf->addr.ip4, addr);
|
||||
}
|
||||
buf->port = port;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
||||
const struct udp_hdr* udphdr = (void*)(((char*)ip6_current_header()) +
|
||||
ip6_current_header_tot_len());
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
buf->flags = NETBUF_FLAG_DESTADDR;
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
ip6_addr_set(&buf->toaddr.ip6, ip6_current_dest_addr());
|
||||
buf->toport_chksum = udphdr->dest;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
const struct ip_hdr* iphdr = ip_current_header();
|
||||
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
||||
@ -185,7 +215,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
buf->flags = NETBUF_FLAG_DESTADDR;
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
ip_addr_set(&buf->toaddr, ip_current_dest_addr());
|
||||
ip_addr_set(&buf->toaddr.ip4, ip_current_dest_addr());
|
||||
buf->toport_chksum = udphdr->dest;
|
||||
}
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
@ -487,7 +517,15 @@ pcb_new(struct api_msg_msg *msg)
|
||||
switch(NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||
msg->conn->pcb.raw = raw_new_ip6(msg->msg.n.proto);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
|
||||
}
|
||||
if(msg->conn->pcb.raw == NULL) {
|
||||
msg->err = ERR_MEM;
|
||||
break;
|
||||
@ -497,17 +535,25 @@ pcb_new(struct api_msg_msg *msg)
|
||||
#endif /* LWIP_RAW */
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||
msg->conn->pcb.udp = udp_new_ip6();
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
}
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
#if LWIP_UDPLITE
|
||||
if (msg->conn->type==NETCONN_UDPLITE) {
|
||||
if (NETCONNTYPE_ISUDPLITE((msg->conn->type)) {
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
}
|
||||
#endif /* LWIP_UDPLITE */
|
||||
if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
|
||||
if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) {
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
}
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
@ -515,7 +561,15 @@ pcb_new(struct api_msg_msg *msg)
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||
msg->conn->pcb.tcp = tcp_new_ip6();
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
}
|
||||
if(msg->conn->pcb.tcp == NULL) {
|
||||
msg->err = ERR_MEM;
|
||||
break;
|
||||
@ -680,7 +734,7 @@ netconn_drain(struct netconn *conn)
|
||||
if (sys_mbox_valid(&conn->recvmbox)) {
|
||||
while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
|
||||
#if LWIP_TCP
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
|
||||
if(mem != NULL) {
|
||||
p = (struct pbuf*)mem;
|
||||
/* pcb might be set to NULL already by err_tcp() */
|
||||
@ -738,7 +792,7 @@ do_close_internal(struct netconn *conn)
|
||||
u8_t shut, shut_rx, shut_tx, close;
|
||||
|
||||
LWIP_ASSERT("invalid conn", (conn != NULL));
|
||||
LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
|
||||
LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP));
|
||||
LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
|
||||
LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
|
||||
LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
|
||||
@ -824,7 +878,7 @@ do_delconn(struct api_msg_msg *msg)
|
||||
(msg->conn->state != NETCONN_LISTEN) &&
|
||||
(msg->conn->state != NETCONN_CONNECT)) {
|
||||
/* this only happens for TCP netconns */
|
||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
|
||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP);
|
||||
msg->err = ERR_INPROGRESS;
|
||||
} else {
|
||||
LWIP_ASSERT("blocking connect in progress",
|
||||
@ -942,7 +996,7 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
if (conn->current_msg != NULL) {
|
||||
conn->current_msg->err = err;
|
||||
}
|
||||
if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
|
||||
if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) {
|
||||
setup_tcp(conn);
|
||||
}
|
||||
was_blocking = !IN_NONBLOCKING_CONNECT(conn);
|
||||
@ -1056,7 +1110,7 @@ do_listen(struct api_msg_msg *msg)
|
||||
} else {
|
||||
msg->err = ERR_CONN;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||
if (msg->conn->state == NETCONN_NONE) {
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
|
||||
@ -1113,29 +1167,62 @@ do_send(struct api_msg_msg *msg)
|
||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
||||
#if LWIP_IPV6
|
||||
if (msg->conn->pcb.ip->isipv6) {
|
||||
if (ip6_addr_isany(&msg->msg.b->addr.ip6)) {
|
||||
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
||||
} else {
|
||||
msg->err = raw_sendto_ip6(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr.ip6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&msg->msg.b->addr.ip4)) {
|
||||
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
||||
} 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.ip4);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDP:
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
||||
#if LWIP_IPV6
|
||||
if (msg->conn->pcb.ip->isipv6) {
|
||||
if (ip6_addr_isany(&msg->msg.b->addr.ip6)) {
|
||||
msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||
} else {
|
||||
msg->err = udp_sendto_chksum_ip6(msg->conn->pcb.udp, msg->msg.b->p,
|
||||
&msg->msg.b->addr.ip6, msg->msg.b->port,
|
||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&msg->msg.b->addr.ip4)) {
|
||||
msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||
} else {
|
||||
msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
|
||||
&msg->msg.b->addr, msg->msg.b->port,
|
||||
&msg->msg.b->addr.ip4, msg->msg.b->port,
|
||||
msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
|
||||
}
|
||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
||||
if (ip_addr_isany(&msg->msg.b->addr)) {
|
||||
#if LWIP_IPV6
|
||||
if (msg->conn->pcb.ip->isipv6) {
|
||||
if (ip6_addr_isany(&msg->msg.b->addr.ip6)) {
|
||||
msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
|
||||
} else {
|
||||
msg->err = udp_sendto_ip6(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr.ip6, msg->msg.b->port);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&msg->msg.b->addr.ip4)) {
|
||||
msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
|
||||
} else {
|
||||
msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
|
||||
msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr.ip4, msg->msg.b->port);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
break;
|
||||
@ -1160,7 +1247,7 @@ do_recv(struct api_msg_msg *msg)
|
||||
{
|
||||
msg->err = ERR_OK;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
tcp_accepted(msg->conn->pcb.tcp);
|
||||
@ -1315,7 +1402,7 @@ do_write(struct api_msg_msg *msg)
|
||||
if (ERR_IS_FATAL(msg->conn->last_err)) {
|
||||
msg->err = msg->conn->last_err;
|
||||
} else {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||
#if LWIP_TCP
|
||||
if (msg->conn->state != NETCONN_NONE) {
|
||||
/* netconn is connecting, closing or in blocking write */
|
||||
@ -1368,8 +1455,20 @@ void
|
||||
do_getaddr(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.ip != NULL) {
|
||||
*(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip :
|
||||
msg->conn->pcb.ip->remote_ip);
|
||||
#if LWIP_IPV6
|
||||
if (msg->conn->pcb.ip->isipv6) {
|
||||
if (msg->msg.ad.local) {
|
||||
ip6_addr_set((ip6_addr_t *)msg->msg.ad.ipaddr, &(msg->conn->pcb.ip->local_ip.ip6));
|
||||
} else {
|
||||
ip6_addr_set((ip6_addr_t *)msg->msg.ad.ipaddr, &(msg->conn->pcb.ip->remote_ip.ip6));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
*(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip.ip4 :
|
||||
msg->conn->pcb.ip->remote_ip.ip4);
|
||||
}
|
||||
|
||||
msg->err = ERR_OK;
|
||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
@ -1424,9 +1523,9 @@ do_close(struct api_msg_msg *msg)
|
||||
/* @todo: abort running write/connect? */
|
||||
if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
|
||||
/* this only happens for TCP netconns */
|
||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
|
||||
LWIP_ASSERT("msg->conn->type == NETCONN_TCP", NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP);
|
||||
msg->err = ERR_INPROGRESS;
|
||||
} else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
|
||||
} else if ((msg->conn->pcb.tcp != NULL) && (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)) {
|
||||
if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
|
||||
/* LISTEN doesn't support half shutdown */
|
||||
msg->err = ERR_CONN;
|
||||
@ -1451,7 +1550,7 @@ do_close(struct api_msg_msg *msg)
|
||||
sys_sem_signal(&msg->conn->op_completed);
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
/**
|
||||
* Join multicast groups for UDP netconns.
|
||||
* Called from netconn_join_leave_group
|
||||
@ -1467,10 +1566,24 @@ do_join_leave_group(struct api_msg_msg *msg)
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
|
||||
#if LWIP_UDP
|
||||
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
||||
msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
||||
} else {
|
||||
msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
if (msg->conn->pcb.udp->isipv6) {
|
||||
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
||||
msg->err = mld6_joingroup((ip6_addr_t *)msg->msg.jl.netif_addr, (ip6_addr_t *)msg->msg.jl.multiaddr);
|
||||
} else {
|
||||
msg->err = mld6_leavegroup((ip6_addr_t *)msg->msg.jl.netif_addr, (ip6_addr_t *)msg->msg.jl.multiaddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
{
|
||||
#if LWIP_IGMP
|
||||
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
|
||||
msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
||||
} else {
|
||||
msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
}
|
||||
#endif /* LWIP_UDP */
|
||||
#if (LWIP_TCP || LWIP_RAW)
|
||||
@ -1484,7 +1597,7 @@ do_join_leave_group(struct api_msg_msg *msg)
|
||||
}
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
|
||||
#if LWIP_DNS
|
||||
/**
|
||||
|
@ -61,7 +61,11 @@ netbuf *netbuf_new(void)
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
ip_addr_set_any(&buf->addr);
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_set_any(&buf->addr.ip6);
|
||||
#else /* LWIP_IPV6 */
|
||||
ip_addr_set_any(&buf->addr.ip4);
|
||||
#endif /* LWIP_IPV6 */
|
||||
buf->port = 0;
|
||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
@ -69,7 +73,11 @@ netbuf *netbuf_new(void)
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
buf->toport_chksum = 0;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
ip_addr_set_any(&buf->toaddr);
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_set_any(&buf->toaddr.ip6);
|
||||
#else /* LWIP_IPV6 */
|
||||
ip_addr_set_any(&buf->toaddr.ip4);
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||
return buf;
|
||||
|
@ -58,6 +58,16 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Check that the family member of a struct sockaddr matches the socket's IP version */
|
||||
#if LWIP_IPV6
|
||||
#define SOCK_ADDR_MATCH(name, sock) \
|
||||
((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
|
||||
(((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
|
||||
#else /* LWIP_IPV6 */
|
||||
#define SOCK_ADDR_MATCH(name, sock) (((name)->sa_family) == AF_INET)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
||||
#define NUM_SOCKETS MEMP_NUM_NETCONN
|
||||
|
||||
/** Contains all internal pointers and states used for a socket */
|
||||
@ -259,7 +269,7 @@ alloc_socket(struct netconn *newconn, int accepted)
|
||||
sockets[i].rcvevent = 0;
|
||||
/* TCP sendbuf is empty, but the socket is not yet writable until connected
|
||||
* (unless it has been created by accept()). */
|
||||
sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
|
||||
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
|
||||
sockets[i].errevent = 0;
|
||||
sockets[i].err = 0;
|
||||
sockets[i].select_waiting = 0;
|
||||
@ -313,10 +323,19 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
struct lwip_sock *sock, *nsock;
|
||||
struct netconn *newconn;
|
||||
ip_addr_t naddr;
|
||||
union {
|
||||
ip_addr_t ip4;
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t ip6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
} naddr;
|
||||
u16_t port;
|
||||
int newsock;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr tempaddr;
|
||||
struct sockaddr_in * sin;
|
||||
#if LWIP_IPV6
|
||||
struct sockaddr_in6 * sin6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
err_t err;
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
@ -344,7 +363,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
netconn_set_noautorecved(newconn, 1);
|
||||
|
||||
/* get the IP address and port of the remote host */
|
||||
err = netconn_peer(newconn, &naddr, &port);
|
||||
err = netconn_peer(newconn, &naddr.ip4, &port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
|
||||
netconn_delete(newconn);
|
||||
@ -357,16 +376,34 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
*/
|
||||
if (NULL != addr) {
|
||||
LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
|
||||
memset(&tempaddr, 0, sizeof(tempaddr));
|
||||
|
||||
if (*addrlen > sizeof(sin))
|
||||
*addrlen = sizeof(sin);
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(newconn->type)) {
|
||||
sin6 = (struct sockaddr_in6 *)&tempaddr;
|
||||
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(port);
|
||||
sin6->sin6_flowinfo = 0;
|
||||
inet6_addr_from_ip6addr(&sin6->sin6_addr, &naddr.ip6);
|
||||
|
||||
MEMCPY(addr, &sin, *addrlen);
|
||||
if (*addrlen > sin6->sin6_len)
|
||||
*addrlen = sin6->sin6_len;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
sin = (struct sockaddr_in *)&tempaddr;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = htons(port);
|
||||
inet_addr_from_ipaddr(&sin->sin_addr, &naddr.ip4);
|
||||
|
||||
if (*addrlen > sin->sin_len)
|
||||
*addrlen = sin->sin_len;
|
||||
}
|
||||
|
||||
MEMCPY(addr, &tempaddr, *addrlen);
|
||||
}
|
||||
|
||||
newsock = alloc_socket(newconn, 1);
|
||||
@ -390,7 +427,15 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(newconn->type)) {
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, &naddr.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr.ip4);
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
|
||||
|
||||
sock_set_errno(sock, 0);
|
||||
@ -401,10 +446,18 @@ int
|
||||
lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
struct lwip_sock *sock;
|
||||
ip_addr_t local_addr;
|
||||
union {
|
||||
ip_addr_t ip4;
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t ip6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
} local_addr;
|
||||
u16_t local_port;
|
||||
err_t err;
|
||||
const struct sockaddr_in *name_in;
|
||||
#if LWIP_IPV6
|
||||
const struct sockaddr_in6 *name_in6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
@ -413,18 +466,33 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
|
||||
/* check size, familiy and alignment of 'name' */
|
||||
LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
||||
((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
|
||||
SOCK_ADDR_MATCH(name, sock) &&
|
||||
((((mem_ptr_t)name) % 4) == 0)),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
name_in = (const struct sockaddr_in *)(void*)name;
|
||||
|
||||
inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
|
||||
local_port = name_in->sin_port;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
|
||||
#if LWIP_IPV6
|
||||
if ((name->sa_family) == AF_INET6) {
|
||||
name_in6 = (const struct sockaddr_in6 *)(void*)name;
|
||||
|
||||
inet6_addr_to_ip6addr(&local_addr.ip6, &name_in6->sin6_addr);
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, &local_addr.ip6);
|
||||
|
||||
local_port = name_in6->sin6_port;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
name_in = (const struct sockaddr_in *)(void*)name;
|
||||
|
||||
inet_addr_to_ipaddr(&local_addr.ip4, &name_in->sin_addr);
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr.ip4);
|
||||
|
||||
local_port = name_in->sin_port;
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
|
||||
|
||||
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
|
||||
err = netconn_bind(sock->conn, &local_addr.ip4, ntohs(local_port));
|
||||
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
|
||||
@ -451,7 +519,7 @@ lwip_close(int s)
|
||||
}
|
||||
|
||||
if(sock->conn != NULL) {
|
||||
is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
|
||||
is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
|
||||
} else {
|
||||
LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
|
||||
}
|
||||
@ -468,7 +536,6 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
struct lwip_sock *sock;
|
||||
err_t err;
|
||||
const struct sockaddr_in *name_in;
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
@ -477,17 +544,38 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
|
||||
/* check size, familiy and alignment of 'name' */
|
||||
LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
||||
((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
|
||||
SOCK_ADDR_MATCH(name, sock) &&
|
||||
((((mem_ptr_t)name) % 4) == 0)),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
name_in = (const struct sockaddr_in *)(void*)name;
|
||||
|
||||
if (name_in->sin_family == AF_UNSPEC) {
|
||||
if (name->sa_family == AF_UNSPEC) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
|
||||
err = netconn_disconnect(sock->conn);
|
||||
} else {
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
else if (name->sa_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *name_in6;
|
||||
ip6_addr_t remote_addr;
|
||||
u16_t remote_port;
|
||||
|
||||
name_in6 = (const struct sockaddr_in6 *)(void*)name;
|
||||
|
||||
inet6_addr_to_ip6addr(&remote_addr, &name_in6->sin6_addr);
|
||||
remote_port = name_in6->sin6_port;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
|
||||
|
||||
err = netconn_connect(sock->conn, (ip_addr_t *)&remote_addr, ntohs(remote_port));
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
else {
|
||||
const struct sockaddr_in *name_in;
|
||||
ip_addr_t remote_addr;
|
||||
u16_t remote_port;
|
||||
|
||||
name_in = (const struct sockaddr_in *)(void*)name;
|
||||
|
||||
inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
|
||||
remote_port = name_in->sin_port;
|
||||
|
||||
@ -554,7 +642,6 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
struct pbuf *p;
|
||||
u16_t buflen, copylen;
|
||||
int off = 0;
|
||||
ip_addr_t *addr;
|
||||
u16_t port;
|
||||
u8_t done = 0;
|
||||
err_t err;
|
||||
@ -588,7 +675,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
|
||||
/* No data was left from the previous operation, so we try to get
|
||||
some from the network. */
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
|
||||
} else {
|
||||
err = netconn_recv(sock->conn, (struct netbuf **)&buf);
|
||||
@ -618,7 +705,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
sock->lastdata = buf;
|
||||
}
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
p = (struct pbuf *)buf;
|
||||
} else {
|
||||
p = ((struct netbuf *)buf)->p;
|
||||
@ -641,7 +728,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
|
||||
off += copylen;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
|
||||
len -= copylen;
|
||||
if ( (len <= 0) ||
|
||||
@ -656,47 +743,69 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
|
||||
/* Check to see from where the data was.*/
|
||||
if (done) {
|
||||
ip_addr_t fromaddr;
|
||||
if (from && fromlen) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = &fromaddr;
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr((struct netbuf *)buf);
|
||||
port = netbuf_fromport((struct netbuf *)buf);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
inet_addr_from_ipaddr(&sin.sin_addr, addr);
|
||||
|
||||
if (*fromlen > sizeof(sin)) {
|
||||
*fromlen = sizeof(sin);
|
||||
}
|
||||
|
||||
MEMCPY(from, &sin, *fromlen);
|
||||
|
||||
#if !SOCKETS_DEBUG
|
||||
if (from && fromlen)
|
||||
#endif /* !SOCKETS_DEBUG */
|
||||
{
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
||||
} else {
|
||||
#if SOCKETS_DEBUG
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = &fromaddr;
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr((struct netbuf *)buf);
|
||||
port = netbuf_fromport((struct netbuf *)buf);
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn))) {
|
||||
ip6_addr_t *fromaddr6;
|
||||
ip6_addr_t tmpaddr6;
|
||||
struct sockaddr_in6 sin6;
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
/* @todo: implement netconn_getaddr() for IPv6 addresses */
|
||||
ip6_addr_set_any(&tmpaddr6);
|
||||
fromaddr6 = &tmpaddr6;
|
||||
port = 0;
|
||||
} else {
|
||||
fromaddr6 = netbuf_fromaddr_ip6((struct netbuf *)buf);
|
||||
port = netbuf_fromport((struct netbuf *)buf);
|
||||
}
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = htons(port);
|
||||
inet6_addr_from_ip6addr(&sin6.sin6_addr, fromaddr6);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||
if (from && fromlen) {
|
||||
if (*fromlen > sizeof(sin6)) {
|
||||
*fromlen = sizeof(sin6);
|
||||
}
|
||||
MEMCPY(from, &sin6, *fromlen);
|
||||
}
|
||||
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, fromaddr6);
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_t *fromaddr4;
|
||||
ip_addr_t tmpaddr4;
|
||||
struct sockaddr_in sin;
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
fromaddr4 = &tmpaddr4;
|
||||
netconn_getaddr(sock->conn, fromaddr4, &port, 0);
|
||||
} else {
|
||||
fromaddr4 = netbuf_fromaddr((struct netbuf *)buf);
|
||||
port = netbuf_fromport((struct netbuf *)buf);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
inet_addr_from_ipaddr(&sin.sin_addr, fromaddr4);
|
||||
|
||||
if (from && fromlen) {
|
||||
if (*fromlen > sizeof(sin)) {
|
||||
*fromlen = sizeof(sin);
|
||||
}
|
||||
MEMCPY(from, &sin, *fromlen);
|
||||
}
|
||||
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &fromaddr4);
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
|
||||
#endif /* SOCKETS_DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
@ -705,7 +814,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
/* If this is a TCP socket, check if there is data left in the
|
||||
buffer. If so, it should be saved in the sock structure for next
|
||||
time around. */
|
||||
if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
|
||||
if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
|
||||
sock->lastdata = buf;
|
||||
sock->lastoffset += copylen;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
|
||||
@ -713,7 +822,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
sock->lastdata = NULL;
|
||||
sock->lastoffset = 0;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
|
||||
pbuf_free((struct pbuf *)buf);
|
||||
} else {
|
||||
netbuf_delete((struct netbuf *)buf);
|
||||
@ -757,7 +866,7 @@ lwip_send(int s, const void *data, size_t size, int flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock->conn->type != NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
return lwip_sendto(s, data, size, flags, NULL, 0);
|
||||
#else /* (LWIP_UDP || LWIP_RAW) */
|
||||
@ -791,7 +900,6 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
struct lwip_sock *sock;
|
||||
err_t err;
|
||||
u16_t short_size;
|
||||
const struct sockaddr_in *to_in;
|
||||
u16_t remote_port;
|
||||
#if !LWIP_TCPIP_CORE_LOCKING
|
||||
struct netbuf buf;
|
||||
@ -802,7 +910,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock->conn->type == NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_TCP) {
|
||||
#if LWIP_TCP
|
||||
return lwip_send(s, data, size, flags);
|
||||
#else /* LWIP_TCP */
|
||||
@ -817,22 +925,25 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
short_size = (u16_t)size;
|
||||
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
|
||||
((tolen == sizeof(struct sockaddr_in)) &&
|
||||
((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
|
||||
SOCK_ADDR_MATCH(to, sock) &&
|
||||
((((mem_ptr_t)to) % 4) == 0))),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
to_in = (const struct sockaddr_in *)(void*)to;
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
|
||||
{
|
||||
struct pbuf* p;
|
||||
ip_addr_t *remote_addr;
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t *remote_addr6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
|
||||
if (p != NULL) {
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
u16_t chksum = 0;
|
||||
if (sock->conn->type != NETCONN_RAW) {
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_RAW) {
|
||||
chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
@ -843,20 +954,39 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
p->payload = (void*)data;
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
if (to_in != NULL) {
|
||||
inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
|
||||
remote_port = ntohs(to_in->sin_port);
|
||||
if (to != NULL) {
|
||||
#if LWIP_IPV6
|
||||
if (to->sa_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *to_in6;
|
||||
to_in6 = (const struct sockaddr_in6 *)(void*)to;
|
||||
inet6_addr_to_ip6addr_p(remote_addr6, &to_in6->sin6_addr);
|
||||
remote_addr = (ip_addr_t *)remote_addr6;
|
||||
remote_port = ntohs(to_in6->sin6_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
const struct sockaddr_in *to_in;
|
||||
to_in = (const struct sockaddr_in *)(void*)to;
|
||||
inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
|
||||
remote_port = ntohs(to_in->sin_port);
|
||||
}
|
||||
} else {
|
||||
remote_addr = &sock->conn->pcb.raw->remote_ip;
|
||||
if (sock->conn->type == NETCONN_RAW) {
|
||||
remote_port = 0;
|
||||
} else {
|
||||
remote_port = sock->conn->pcb.udp->remote_port;
|
||||
remote_addr = IP_ADDR_ANY;
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(sock->conn->type)) {
|
||||
remote_addr6 = IP6_ADDR_ANY;
|
||||
remote_addr = (ip_addr_t *)remote_addr6;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
remote_addr = IP_ADDR_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
if (sock->conn->type == NETCONN_RAW) {
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_RAW) {
|
||||
err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
|
||||
} else {
|
||||
#if LWIP_UDP
|
||||
@ -885,18 +1015,48 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
buf.flags = 0;
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
if (to) {
|
||||
inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
|
||||
remote_port = ntohs(to_in->sin_port);
|
||||
#if LWIP_IPV6
|
||||
if ((to->sa_family) == AF_INET6) {
|
||||
const struct sockaddr_in6 *to_in6;
|
||||
to_in6 = (const struct sockaddr_in6 *)(void*)to;
|
||||
inet6_addr_to_ip6addr(&buf.addr.ip6, &to_in6->sin6_addr);
|
||||
remote_port = ntohs(to_in6->sin6_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
const struct sockaddr_in *to_in;
|
||||
to_in = (const struct sockaddr_in *)(void*)to;
|
||||
inet_addr_to_ipaddr(&buf.addr.ip4, &to_in->sin_addr);
|
||||
remote_port = ntohs(to_in->sin_port);
|
||||
}
|
||||
netbuf_fromport(&buf) = remote_port;
|
||||
} else {
|
||||
remote_port = 0;
|
||||
ip_addr_set_any(&buf.addr);
|
||||
remote_port = 0;
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(sock->conn->type)) {
|
||||
ip6_addr_set_any(&buf.addr.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set_any(&buf.addr.ip4);
|
||||
}
|
||||
netbuf_fromport(&buf) = 0;
|
||||
}
|
||||
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
|
||||
s, data, short_size, flags));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(sock->conn->type)) {
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, &buf.addr.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr.ip4);
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
||||
|
||||
/* make the buffer point to the data that should be sent */
|
||||
@ -906,7 +1066,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
err = ERR_MEM;
|
||||
} else {
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (sock->conn->type != NETCONN_RAW) {
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_RAW) {
|
||||
u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
|
||||
netbuf_set_chksum(&buf, chksum);
|
||||
err = ERR_OK;
|
||||
@ -937,23 +1097,41 @@ lwip_socket(int domain, int type, int protocol)
|
||||
struct netconn *conn;
|
||||
int i;
|
||||
|
||||
#if !LWIP_IPV6
|
||||
LWIP_UNUSED_ARG(domain);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* create a netconn */
|
||||
switch (type) {
|
||||
case SOCK_RAW:
|
||||
#if LWIP_IPV6
|
||||
conn = netconn_new_with_proto_and_callback((domain == AF_INET) ? NETCONN_RAW : NETCONN_RAW_IPV6,
|
||||
(u8_t)protocol, event_callback);
|
||||
#else /* LWIP_IPV6 */
|
||||
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
|
||||
#endif /* LWIP_IPV6 */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
|
||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
#if LWIP_IPV6
|
||||
conn = netconn_new_with_callback((domain == AF_INET) ?
|
||||
((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP) :
|
||||
((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE_IPV6 : NETCONN_UDP_IPV6) ,
|
||||
event_callback);
|
||||
#else /* LWIP_IPV6 */
|
||||
conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
|
||||
NETCONN_UDPLITE : NETCONN_UDP, event_callback);
|
||||
#endif /* LWIP_IPV6 */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
|
||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||
break;
|
||||
case SOCK_STREAM:
|
||||
#if LWIP_IPV6
|
||||
conn = netconn_new_with_callback((domain == AF_INET) ? NETCONN_TCP : NETCONN_TCP_IPV6, event_callback);
|
||||
#else /* LWIP_IPV6 */
|
||||
conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
|
||||
#endif /* LWIP_IPV6 */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
|
||||
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
|
||||
if (conn != NULL) {
|
||||
@ -1365,7 +1543,7 @@ lwip_shutdown(int s, int how)
|
||||
}
|
||||
|
||||
if (sock->conn != NULL) {
|
||||
if (netconn_type(sock->conn) != NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||
sock_set_errno(sock, EOPNOTSUPP);
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
@ -1395,33 +1573,63 @@ static int
|
||||
lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
||||
{
|
||||
struct lwip_sock *sock;
|
||||
struct sockaddr_in sin;
|
||||
ip_addr_t naddr;
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
#if LWIP_IPV6
|
||||
if (NETCONNTYPE_ISIPV6(sock->conn->type)) {
|
||||
struct sockaddr_in6 sin6;
|
||||
ip6_addr_t naddr6;
|
||||
|
||||
/* get the IP address and port */
|
||||
netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
|
||||
/* get the IP address and port */
|
||||
netconn_getaddr(sock->conn, (ip_addr_t *)&naddr6, &sin6.sin6_port, local);
|
||||
|
||||
sin.sin_port = htons(sin.sin_port);
|
||||
inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||
ip6_addr_debug_print(SOCKETS_DEBUG, &naddr6);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin6.sin6_port));
|
||||
|
||||
if (*namelen > sizeof(sin)) {
|
||||
*namelen = sizeof(sin);
|
||||
sin6.sin6_port = htons(sin6.sin6_port);
|
||||
inet6_addr_from_ip6addr(&sin6.sin6_addr, &naddr6);
|
||||
|
||||
if (*namelen > sizeof(sin6)) {
|
||||
*namelen = sizeof(sin6);
|
||||
}
|
||||
|
||||
MEMCPY(name, &sin6, *namelen);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
ip_addr_t naddr;
|
||||
|
||||
MEMCPY(name, &sin, *namelen);
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
|
||||
/* get the IP address and port */
|
||||
netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
|
||||
|
||||
sin.sin_port = htons(sin.sin_port);
|
||||
inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
|
||||
|
||||
if (*namelen > sizeof(sin)) {
|
||||
*namelen = sizeof(sin);
|
||||
}
|
||||
|
||||
MEMCPY(name, &sin, *namelen);
|
||||
}
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
}
|
||||
@ -1495,7 +1703,12 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = EINVAL;
|
||||
}
|
||||
#if LWIP_UDP
|
||||
if ((sock->conn->type != NETCONN_UDP) ||
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
((sock->conn->type != NETCONN_UDP) && (sock->conn->type != NETCONN_UDP_IPV6)) ||
|
||||
#else /* LWIP_IPV6 */
|
||||
(sock->conn->type != NETCONN_UDP) ||
|
||||
#endif /* LWIP_IPV6 */
|
||||
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
||||
/* this flag is only available for UDP, not for UDP lite */
|
||||
err = EAFNOSUPPORT;
|
||||
@ -1559,7 +1772,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
}
|
||||
|
||||
/* If this is no TCP socket, ignore any options. */
|
||||
if (sock->conn->type != NETCONN_TCP)
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP)
|
||||
return 0;
|
||||
|
||||
switch (optname) {
|
||||
@ -1588,7 +1801,11 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
}
|
||||
|
||||
/* If this is no UDP lite socket, ignore any options. */
|
||||
#if LWIP_IPV6
|
||||
if ((sock->conn->type != NETCONN_UDPLITE) && (sock->conn->type != NETCONN_UDPLITE_IPV6)) {
|
||||
#else /* LWIP_IPV6 */
|
||||
if (sock->conn->type != NETCONN_UDPLITE) {
|
||||
#endif /* LWIP_IPV6 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1892,7 +2109,12 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
||||
err = EINVAL;
|
||||
}
|
||||
#if LWIP_UDP
|
||||
if ((sock->conn->type != NETCONN_UDP) ||
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
((sock->conn->type != NETCONN_UDP) && (sock->conn->type != NETCONN_UDP_IPV6)) ||
|
||||
#else /* LWIP_IPV6 */
|
||||
(sock->conn->type != NETCONN_UDP) ||
|
||||
#endif /* LWIP_IPV6 */
|
||||
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
|
||||
/* this flag is only available for UDP, not for UDP lite */
|
||||
err = EAFNOSUPPORT;
|
||||
@ -1969,7 +2191,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
||||
}
|
||||
|
||||
/* If this is no TCP socket, ignore any options. */
|
||||
if (sock->conn->type != NETCONN_TCP)
|
||||
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP)
|
||||
return 0;
|
||||
|
||||
switch (optname) {
|
||||
@ -1998,7 +2220,11 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
|
||||
}
|
||||
|
||||
/* If this is no UDP lite socket, ignore any options. */
|
||||
#if LWIP_IPV6
|
||||
if ((sock->conn->type != NETCONN_UDPLITE) && (sock->conn->type != NETCONN_UDPLITE_IPV6))
|
||||
#else /* LWIP_IPV6 */
|
||||
if (sock->conn->type != NETCONN_UDPLITE)
|
||||
#endif /* LWIP_IPV6 */
|
||||
return 0;
|
||||
|
||||
switch (optname) {
|
||||
@ -2281,7 +2507,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
||||
/* Check if there is data left from the last recv operation. /maq 041215 */
|
||||
if (sock->lastdata) {
|
||||
struct pbuf *p = (struct pbuf *)sock->lastdata;
|
||||
if (netconn_type(sock->conn) != NETCONN_TCP) {
|
||||
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
|
||||
p = ((struct netbuf *)p)->p;
|
||||
}
|
||||
buflen = p->tot_len;
|
||||
|
@ -56,6 +56,9 @@
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
/* Compile-time sanity checks for configuration errors.
|
||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||
@ -299,6 +302,13 @@ lwip_init(void)
|
||||
#if LWIP_DNS
|
||||
dns_init();
|
||||
#endif /* LWIP_DNS */
|
||||
#if LWIP_IPV6
|
||||
ip6_init();
|
||||
nd6_init();
|
||||
#if LWIP_IPV6_MLD
|
||||
mld6_init();
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_TIMERS
|
||||
sys_timeouts_init();
|
||||
|
@ -70,7 +70,7 @@ static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
||||
* Currently only processes icmp echo requests and sends
|
||||
* out the echo response.
|
||||
*
|
||||
* @param p the icmp echo request packet, p->payload pointing to the ip header
|
||||
* @param p the icmp echo request packet, p->payload pointing to the icmp header
|
||||
* @param inp the netif on which this packet was received
|
||||
*/
|
||||
void
|
||||
@ -87,10 +87,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
snmp_inc_icmpinmsgs();
|
||||
|
||||
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
iphdr = (struct ip_hdr *)ip_current_header();
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||
if (p->len < sizeof(u16_t)*2) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||
goto lenerr;
|
||||
}
|
||||
@ -110,13 +109,13 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
int accepted = 1;
|
||||
#if !LWIP_MULTICAST_PING
|
||||
/* multicast destination address? */
|
||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
if (ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_MULTICAST_PING */
|
||||
#if !LWIP_BROADCAST_PING
|
||||
/* broadcast destination address? */
|
||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
||||
if (ip_addr_isbroadcast(ip_current_dest_addr(), inp)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_BROADCAST_PING */
|
||||
|
@ -382,14 +382,13 @@ igmp_remove_group(struct igmp_group *group)
|
||||
/**
|
||||
* Called from ip_input() if a new IGMP packet is received.
|
||||
*
|
||||
* @param p received igmp packet, p->payload pointing to the ip header
|
||||
* @param p received igmp packet, p->payload pointing to the igmp header
|
||||
* @param inp network interface on which the packet was received
|
||||
* @param dest destination ip address of the igmp packet
|
||||
*/
|
||||
void
|
||||
igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
||||
{
|
||||
struct ip_hdr * iphdr;
|
||||
struct igmp_msg* igmp;
|
||||
struct igmp_group* group;
|
||||
struct igmp_group* groupref;
|
||||
@ -397,8 +396,7 @@ igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
||||
IGMP_STATS_INC(igmp.recv);
|
||||
|
||||
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
|
||||
if (p->len < IGMP_MINLEN) {
|
||||
pbuf_free(p);
|
||||
IGMP_STATS_INC(igmp.lenerr);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
|
||||
@ -406,9 +404,9 @@ igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->src));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->dest));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
|
||||
|
||||
/* Now calculate and check the checksum */
|
||||
|
@ -60,6 +60,7 @@
|
||||
# ifndef LWIP_CHKSUM_ALGORITHM
|
||||
# define LWIP_CHKSUM_ALGORITHM 2
|
||||
# endif
|
||||
u16_t lwip_standard_chksum(void *dataptr, int len);
|
||||
#endif
|
||||
/* If none set: */
|
||||
#ifndef LWIP_CHKSUM_ALGORITHM
|
||||
@ -77,7 +78,7 @@
|
||||
* @note accumulator size limits summable length to 64k
|
||||
* @note host endianess is irrelevant (p3 RFC1071)
|
||||
*/
|
||||
static u16_t
|
||||
u16_t
|
||||
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
@ -131,7 +132,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = (u8_t *)dataptr;
|
||||
@ -187,7 +188,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = (u8_t *)dataptr;
|
||||
|
@ -496,23 +496,27 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
case IP_PROTO_UDPLITE:
|
||||
#endif /* LWIP_UDPLITE */
|
||||
snmp_inc_ipindelivers();
|
||||
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||
udp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case IP_PROTO_TCP:
|
||||
snmp_inc_ipindelivers();
|
||||
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||
tcp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_ICMP
|
||||
case IP_PROTO_ICMP:
|
||||
snmp_inc_ipindelivers();
|
||||
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||
icmp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_ICMP */
|
||||
#if LWIP_IGMP
|
||||
case IP_PROTO_IGMP:
|
||||
pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */
|
||||
igmp_input(p, inp, ¤t_iphdr_dest);
|
||||
break;
|
||||
#endif /* LWIP_IGMP */
|
||||
|
@ -1,5 +1,11 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 version of ICMP, as per RFC 4443.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,154 +32,272 @@
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
/* Some ICMP messages should be passed to the transport protocols. This
|
||||
is not implemented. */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/mld6.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef LWIP_ICMP6_DATASIZE
|
||||
#define LWIP_ICMP6_DATASIZE 8
|
||||
#endif
|
||||
#if LWIP_ICMP6_DATASIZE == 0
|
||||
#define LWIP_ICMP6_DATASIZE 8
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
static void icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data);
|
||||
|
||||
|
||||
/**
|
||||
* Process an input ICMPv6 message. Called by ip6_input.
|
||||
*
|
||||
* Will generate a reply for echo requests. Other messages are forwarded
|
||||
* to nd6_input, or mld6_input.
|
||||
*
|
||||
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
||||
* @param inp the netif on which this packet was received
|
||||
*/
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
icmp6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
u8_t type;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
struct icmp6_hdr *icmp6hdr;
|
||||
struct pbuf * r;
|
||||
ip6_addr_t * reply_src;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
ICMP6_STATS_INC(icmp6.recv);
|
||||
|
||||
/* TODO: check length before accessing payload! */
|
||||
/* Check that ICMPv6 header fits in payload */
|
||||
if (p->len < sizeof(struct icmp6_hdr)) {
|
||||
/* drop short packets */
|
||||
pbuf_free(p);
|
||||
ICMP6_STATS_INC(icmp6.lenerr);
|
||||
ICMP6_STATS_INC(icmp6.drop);
|
||||
return;
|
||||
}
|
||||
|
||||
type = ((u8_t *)p->payload)[0];
|
||||
icmp6hdr = (struct icmp6_hdr *)p->payload;
|
||||
|
||||
switch (type) {
|
||||
case ICMP6_ECHO:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
#if LWIP_ICMP6_CHECKSUM_CHECK
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_ICMP6, p->tot_len) != 0) {
|
||||
/* Checksum failed */
|
||||
pbuf_free(p);
|
||||
ICMP6_STATS_INC(icmp6.chkerr);
|
||||
ICMP6_STATS_INC(icmp6.drop);
|
||||
return;
|
||||
}
|
||||
#endif /* LWIP_ICMP6_CHECKSUM_CHECK */
|
||||
|
||||
switch (icmp6hdr->type) {
|
||||
case ICMP6_TYPE_NA: /* Neighbor advertisement */
|
||||
case ICMP6_TYPE_NS: /* Neighbor solicitation */
|
||||
case ICMP6_TYPE_RA: /* Router advertisement */
|
||||
case ICMP6_TYPE_RD: /* Redirect */
|
||||
case ICMP6_TYPE_PTB: /* Packet too big */
|
||||
nd6_input(p, inp);
|
||||
return;
|
||||
break;
|
||||
case ICMP6_TYPE_RS:
|
||||
#if LWIP_IPV6_FORWARD
|
||||
/* TODO implement router functionality */
|
||||
#endif
|
||||
break;
|
||||
#if LWIP_IPV6_MLD
|
||||
case ICMP6_TYPE_MLQ:
|
||||
case ICMP6_TYPE_MLR:
|
||||
case ICMP6_TYPE_MLD:
|
||||
mld6_input(p, inp);
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
case ICMP6_TYPE_EREQ:
|
||||
#if !LWIP_MULTICAST_PING
|
||||
/* multicast destination address? */
|
||||
if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
|
||||
/* drop */
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
ICMP6_STATS_INC(icmp6.drop);
|
||||
return;
|
||||
}
|
||||
iecho = p->payload;
|
||||
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
|
||||
if (inet_chksum_pbuf(p) != 0) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||
ICMP_STATS_INC(icmp.chkerr);
|
||||
/* return;*/
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
|
||||
ip_addr_set(&tmpaddr, &(iphdr->src));
|
||||
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
||||
iecho->type = ICMP6_ER;
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP6_ECHO << 8);
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
#endif /* LWIP_MULTICAST_PING */
|
||||
|
||||
/* Allocate reply. */
|
||||
r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM);
|
||||
if (r == NULL) {
|
||||
/* drop */
|
||||
pbuf_free(p);
|
||||
ICMP6_STATS_INC(icmp6.memerr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy echo request. */
|
||||
if (pbuf_copy(r, p) != ERR_OK) {
|
||||
/* drop */
|
||||
pbuf_free(p);
|
||||
pbuf_free(r);
|
||||
ICMP6_STATS_INC(icmp6.err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine reply source IPv6 address. */
|
||||
reply_src = ip6_select_source_address(inp, ip6_current_src_addr());
|
||||
if (reply_src == NULL) {
|
||||
/* drop */
|
||||
pbuf_free(p);
|
||||
pbuf_free(r);
|
||||
ICMP6_STATS_INC(icmp6.rterr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set fields in reply. */
|
||||
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
|
||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
|
||||
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
|
||||
reply_src, ip6_current_src_addr(),
|
||||
IP6_NEXTH_ICMP6, r->tot_len);
|
||||
|
||||
/* Send reply. */
|
||||
ICMP6_STATS_INC(icmp6.xmit);
|
||||
ip6_output_if(r, reply_src, ip6_current_src_addr(),
|
||||
LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp);
|
||||
pbuf_free(r);
|
||||
|
||||
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
|
||||
ICMP_STATS_INC(icmp.proterr);
|
||||
ICMP_STATS_INC(icmp.drop);
|
||||
ICMP6_STATS_INC(icmp6.proterr);
|
||||
ICMP6_STATS_INC(icmp6.drop);
|
||||
break;
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send an icmpv6 'destination unreachable' packet.
|
||||
*
|
||||
* @param p the input packet for which the 'unreachable' should be sent,
|
||||
* p->payload pointing to the IPv6 header
|
||||
* @param c ICMPv6 code for the unreachable type
|
||||
*/
|
||||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_dur_hdr *idur;
|
||||
|
||||
/* @todo: can this be PBUF_LINK instead of PBUF_IP? */
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (8 + IP_HLEN + 8)));
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
idur->type = (u8_t)ICMP6_DUR;
|
||||
idur->icode = (u8_t)t;
|
||||
|
||||
SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
idur->chksum = 0;
|
||||
idur->chksum = inet_chksum(idur, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
|
||||
ip_output(q, NULL,
|
||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
icmp6_send_response(p, ICMP6_TYPE_DUR, c, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an icmpv6 'packet too big' packet.
|
||||
*
|
||||
* @param p the input packet for which the 'packet too big' should be sent,
|
||||
* p->payload pointing to the IPv6 header
|
||||
* @param mtu the maximum mtu that we can accept
|
||||
*/
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
icmp6_packet_too_big(struct pbuf *p, u32_t mtu)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_PTB, 0, mtu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an icmpv6 'time exceeded' packet.
|
||||
*
|
||||
* @param p the input packet for which the 'unreachable' should be sent,
|
||||
* p->payload pointing to the IPv6 header
|
||||
* @param c ICMPv6 code for the time exceeded type
|
||||
*/
|
||||
void
|
||||
icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_TE, c, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an icmpv6 'parameter problem' packet.
|
||||
*
|
||||
* @param p the input packet for which the 'param problem' should be sent,
|
||||
* p->payload pointing to the IP header
|
||||
* @param c ICMPv6 code for the param problem type
|
||||
* @param pointer the pointer to the byte where the parameter is found
|
||||
*/
|
||||
void
|
||||
icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer)
|
||||
{
|
||||
icmp6_send_response(p, ICMP6_TYPE_PP, c, pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ICMPv6 packet in response to an incoming packet.
|
||||
*
|
||||
* @param p the input packet for which the response should be sent,
|
||||
* p->payload pointing to the IPv6 header
|
||||
* @param type Type of the ICMPv6 header
|
||||
* @param code Code of the ICMPv6 header
|
||||
* @param data Additional 32-bit parameter in the ICMPv6 header
|
||||
*/
|
||||
static void
|
||||
icmp6_send_response(struct pbuf *p, u8_t type, u8_t code, u32_t data)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_te_hdr *tehdr;
|
||||
struct icmp6_hdr *icmp6hdr;
|
||||
ip6_addr_t * reply_src;
|
||||
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
|
||||
|
||||
/* @todo: can this be PBUF_LINK instead of PBUF_IP? */
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
/* ICMPv6 header + IPv6 header + data */
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
|
||||
PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
||||
ICMP6_STATS_INC(icmp6.memerr);
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (8 + IP_HLEN + 8)));
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp 6message",
|
||||
(q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
tehdr = q->payload;
|
||||
tehdr->type = (u8_t)ICMP6_TE;
|
||||
tehdr->icode = (u8_t)t;
|
||||
icmp6hdr = (struct icmp6_hdr *)q->payload;
|
||||
icmp6hdr->type = type;
|
||||
icmp6hdr->code = code;
|
||||
icmp6hdr->data = data;
|
||||
|
||||
/* copy fields from original packet */
|
||||
SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
|
||||
IP6_HLEN + LWIP_ICMP6_DATASIZE);
|
||||
|
||||
/* Select an address to use as source. */
|
||||
reply_src = ip6_select_source_address(current_netif, ip6_current_src_addr());
|
||||
if (reply_src == NULL) {
|
||||
/* drop */
|
||||
pbuf_free(q);
|
||||
ICMP6_STATS_INC(icmp6.rterr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* calculate checksum */
|
||||
tehdr->chksum = 0;
|
||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
ip_output(q, NULL,
|
||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
||||
icmp6hdr->chksum = 0;
|
||||
icmp6hdr->chksum = ip6_chksum_pseudo(q, reply_src, ip6_current_src_addr(),
|
||||
IP6_NEXTH_ICMP6, q->tot_len);
|
||||
|
||||
ICMP6_STATS_INC(icmp6.xmit);
|
||||
ip6_output(q, reply_src, ip6_current_src_addr(), LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#endif /* LWIP_ICMP */
|
||||
|
||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||
|
@ -1,12 +1,11 @@
|
||||
/**
|
||||
* @file
|
||||
* Functions common to all TCP/IPv6 modules, such as the Internet checksum and the
|
||||
* byte order functions.
|
||||
*
|
||||
* INET v6 addresses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -33,131 +32,20 @@
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet6.h"
|
||||
|
||||
/* chksum:
|
||||
*
|
||||
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
|
||||
* This function is used by the other checksum functions.
|
||||
*
|
||||
* For now, this is not optimized. Must be optimized for the particular processor
|
||||
* arcitecture on which it is to run. Preferebly coded in assembler.
|
||||
*/
|
||||
/** @see ip6_addr.c for implementation of functions. */
|
||||
|
||||
static u32_t
|
||||
chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u16_t *sdataptr = dataptr;
|
||||
u32_t acc;
|
||||
|
||||
|
||||
for(acc = 0; len > 1; len -= 2) {
|
||||
acc += *sdataptr++;
|
||||
}
|
||||
|
||||
/* add up any odd byte */
|
||||
if (len == 1) {
|
||||
acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
||||
}
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u32_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped, i;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
acc += ((u16_t *)src->addr)[i] & 0xffff;
|
||||
acc += ((u16_t *)dest->addr)[i] & 0xffff;
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
}
|
||||
acc += (u16_t)htons((u16_t)proto);
|
||||
acc += ((u16_t *)&proto_len)[0] & 0xffff;
|
||||
acc += ((u16_t *)&proto_len)[1] & 0xffff;
|
||||
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
|
||||
* and ICMP.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc, sum;
|
||||
|
||||
acc = chksum(dataptr, len);
|
||||
sum = (acc & 0xffff) + (acc >> 16);
|
||||
sum += (sum >> 16);
|
||||
return ~(sum & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
1105
src/core/ipv6/ip6.c
1105
src/core/ipv6/ip6.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,11 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 addresses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,47 +32,210 @@
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
* Functions for handling IPv6 addresses.
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
u8_t
|
||||
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||
struct ip_addr *mask)
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
/* used by IP6_ADDR_ANY in ip6_addr.h */
|
||||
const ip6_addr_t ip6_addr_any = { { 0ul, 0ul, 0ul, 0ul } };
|
||||
|
||||
#ifndef isprint
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an IPv6 address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
*
|
||||
* @param cp IPv6 address in ascii represenation (e.g. "FF01::1")
|
||||
* @param addr pointer to which to save the ip address in network order
|
||||
* @return 1 if cp could be converted to addr, 0 on failure
|
||||
*/
|
||||
int
|
||||
ip6addr_aton(const char *cp, ip6_addr_t *addr)
|
||||
{
|
||||
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
||||
(addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) &&
|
||||
(addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) &&
|
||||
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
|
||||
|
||||
u32_t addr_index, zero_blocks, current_block_index, current_block_value;
|
||||
const char * s;
|
||||
|
||||
/* Count the number of colons, to count the number of blocks in a "::" sequence
|
||||
zero_blocks may be 1 even if there are no :: sequences */
|
||||
zero_blocks = 8;
|
||||
for (s = cp; *s != 0; s++) {
|
||||
if (*s == ':')
|
||||
zero_blocks--;
|
||||
else if (!isxdigit(*s))
|
||||
break;
|
||||
}
|
||||
|
||||
/* parse each block */
|
||||
addr_index = 0;
|
||||
current_block_index = 0;
|
||||
current_block_value = 0;
|
||||
for (s = cp; *s != 0; s++) {
|
||||
if (*s == ':') {
|
||||
if (current_block_index & 0x1) {
|
||||
addr->addr[addr_index++] |= current_block_value;
|
||||
}
|
||||
else {
|
||||
addr->addr[addr_index] = current_block_value << 16;
|
||||
}
|
||||
current_block_index++;
|
||||
current_block_value = 0;
|
||||
if (current_block_index > 7) {
|
||||
/* address too long! */
|
||||
return 0;
|
||||
} if (s[1] == ':') {
|
||||
s++;
|
||||
/* "::" found, set zeros */
|
||||
while (zero_blocks-- > 0) {
|
||||
if (current_block_index & 0x1) {
|
||||
addr_index++;
|
||||
}
|
||||
else {
|
||||
addr->addr[addr_index] = 0;
|
||||
}
|
||||
current_block_index++;
|
||||
}
|
||||
}
|
||||
} else if (isxdigit(*s)) {
|
||||
/* add current digit */
|
||||
current_block_value = (current_block_value << 4) +
|
||||
(isdigit(*s) ? *s - '0' :
|
||||
10 + (islower(*s) ? *s - 'a' : *s - 'A'));
|
||||
} else {
|
||||
/* unexpected digit, space? CRLF? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_block_index & 0x1) {
|
||||
addr->addr[addr_index++] |= current_block_value;
|
||||
}
|
||||
else {
|
||||
addr->addr[addr_index] = current_block_value << 16;
|
||||
}
|
||||
|
||||
/* convert to network byte order. */
|
||||
for (addr_index = 0; addr_index < 4; addr_index++) {
|
||||
addr->addr[addr_index] = htonl(addr->addr[addr_index]);
|
||||
}
|
||||
|
||||
if (current_block_index != 7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
u8_t
|
||||
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
||||
/**
|
||||
* Convert numeric IPv6 address into ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*
|
||||
* @param addr ip6 address in network order to convert
|
||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||
* represenation of addr
|
||||
*/
|
||||
char *
|
||||
ip6addr_ntoa(const ip6_addr_t *addr)
|
||||
{
|
||||
return(addr1->addr[0] == addr2->addr[0] &&
|
||||
addr1->addr[1] == addr2->addr[1] &&
|
||||
addr1->addr[2] == addr2->addr[2] &&
|
||||
addr1->addr[3] == addr2->addr[3]);
|
||||
static char str[40];
|
||||
return ip6addr_ntoa_r(addr, str, 40);
|
||||
}
|
||||
|
||||
void
|
||||
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
|
||||
/**
|
||||
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
||||
*
|
||||
* @param addr ip6 address in network order to convert
|
||||
* @param buf target buffer where the string is stored
|
||||
* @param buflen length of buf
|
||||
* @return either pointer to buf which now holds the ASCII
|
||||
* representation of addr or NULL if buf was too small
|
||||
*/
|
||||
char *
|
||||
ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
|
||||
{
|
||||
SMEMCPY(dest, src, sizeof(struct ip_addr));
|
||||
/* dest->addr[0] = src->addr[0];
|
||||
dest->addr[1] = src->addr[1];
|
||||
dest->addr[2] = src->addr[2];
|
||||
dest->addr[3] = src->addr[3];*/
|
||||
}
|
||||
u32_t current_block_index, current_block_value;
|
||||
s32_t zero_flag, i;
|
||||
|
||||
u8_t
|
||||
ip_addr_isany(struct ip_addr *addr)
|
||||
{
|
||||
if (addr == NULL) return 1;
|
||||
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
|
||||
i = 0;
|
||||
zero_flag = 0; /* used to indicate a zero chain for "::' */
|
||||
|
||||
for (current_block_index = 0; current_block_index < 8; current_block_index++) {
|
||||
/* get the current 16-bit block */
|
||||
current_block_value = htonl(addr->addr[current_block_index >> 1]);
|
||||
if ((current_block_index & 0x1) == 0) {
|
||||
current_block_value = current_block_value >> 16;
|
||||
}
|
||||
current_block_value &= 0xffff;
|
||||
|
||||
if (current_block_value == 0) {
|
||||
/* generate empty block "::" */
|
||||
if (!zero_flag) {
|
||||
if (current_block_index > 0) {
|
||||
zero_flag = 1;
|
||||
buf[i++] = ':';
|
||||
if (i >= buflen) return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (current_block_index > 0) {
|
||||
buf[i++] = ':';
|
||||
if (i >= buflen) return NULL;
|
||||
}
|
||||
|
||||
if ((current_block_value & 0xf000) == 0) {
|
||||
zero_flag = 1;
|
||||
}
|
||||
else {
|
||||
buf[i++] = xchar(((current_block_value & 0xf000) >> 12));
|
||||
if (i >= buflen) return NULL;
|
||||
}
|
||||
|
||||
if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
|
||||
/* do nothing */
|
||||
}
|
||||
else {
|
||||
buf[i++] = xchar(((current_block_value & 0xf00) >> 8));
|
||||
if (i >= buflen) return NULL;
|
||||
}
|
||||
|
||||
if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
|
||||
/* do nothing */
|
||||
}
|
||||
else {
|
||||
buf[i++] = xchar(((current_block_value & 0xf0) >> 4));
|
||||
if (i >= buflen) return NULL;
|
||||
}
|
||||
|
||||
buf[i++] = xchar((current_block_value & 0xf));
|
||||
if (i >= buflen) return NULL;
|
||||
|
||||
zero_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
buf[i] = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
@ -58,6 +58,9 @@
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "netif/ppp_oe.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/ip6_frag.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
117
src/core/netif.c
117
src/core/netif.c
@ -40,6 +40,7 @@
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/snmp.h"
|
||||
@ -59,6 +60,12 @@
|
||||
#if LWIP_DHCP
|
||||
#include "lwip/dhcp.h"
|
||||
#endif /* LWIP_DHCP */
|
||||
#if LWIP_IPV6_DHCP6
|
||||
#include "lwip/dhcp6.h"
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
#if LWIP_IPV6_MLD
|
||||
#include "lwip/mld6.h"
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
|
||||
@ -138,6 +145,9 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
|
||||
{
|
||||
static u8_t netifnum = 0;
|
||||
#if LWIP_IPV6
|
||||
u32_t i;
|
||||
#endif
|
||||
|
||||
LWIP_ASSERT("No init function given", init != NULL);
|
||||
|
||||
@ -145,6 +155,12 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_set_zero(&netif->ip_addr);
|
||||
ip_addr_set_zero(&netif->netmask);
|
||||
ip_addr_set_zero(&netif->gw);
|
||||
#if LWIP_IPV6
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
ip6_addr_set_zero(&netif->ip6_addr[i]);
|
||||
netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
netif->flags = 0;
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
@ -154,6 +170,17 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
/* netif not under AutoIP control by default */
|
||||
netif->autoip = NULL;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/* IPv6 address autoconfiguration not enabled by default */
|
||||
netif->ip6_autoconfig_enabled = 0;
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
|
||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||
#if LWIP_IPV6_DHCP6
|
||||
/* netif not under DHCPv6 control by default */
|
||||
netif->dhcp6 = NULL;
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
netif->status_callback = NULL;
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
@ -163,6 +190,9 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
#if LWIP_IGMP
|
||||
netif->igmp_mac_filter = NULL;
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
netif->mld_mac_filter = NULL;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
#if ENABLE_LOOPBACK
|
||||
netif->loop_first = NULL;
|
||||
netif->loop_last = NULL;
|
||||
@ -245,6 +275,10 @@ netif_remove(struct netif *netif)
|
||||
igmp_stop(netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
/* stop MLD processing */
|
||||
mld6_stop(netif);
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
if (netif_is_up(netif)) {
|
||||
/* set netif down before removing (call callback function) */
|
||||
netif_set_down(netif);
|
||||
@ -331,10 +365,10 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
|
||||
if (ip_addr_cmp(&(pcb->local_ip.ip4), &(netif->ip_addr))
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||
&& !ip_addr_islinklocal(&(pcb->local_ip))
|
||||
&& !ip_addr_islinklocal(&(pcb->local_ip.ip4))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
) {
|
||||
/* this connection must be aborted */
|
||||
@ -348,11 +382,11 @@ netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
}
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if ((!(ip_addr_isany(&(lpcb->local_ip)))) &&
|
||||
(ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {
|
||||
if ((!(ip_addr_isany(&(lpcb->local_ip.ip4)))) &&
|
||||
(ip_addr_cmp(&(lpcb->local_ip.ip4), &(netif->ip_addr)))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_set(&(lpcb->local_ip), ipaddr);
|
||||
ip_addr_set(&(lpcb->local_ip.ip4), ipaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -471,6 +505,16 @@ void netif_set_up(struct netif *netif)
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
/* send mld memberships */
|
||||
mld6_report_groups( netif);
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
/* Send Router Solicitation messages. */
|
||||
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
|
||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -541,6 +585,10 @@ void netif_set_link_up(struct netif *netif )
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
/* send mld memberships */
|
||||
mld6_report_groups( netif);
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
}
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
@ -750,3 +798,62 @@ netif_poll_all(void)
|
||||
}
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_IPV6
|
||||
s8_t
|
||||
netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr)
|
||||
{
|
||||
s8_t i;
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit)
|
||||
{
|
||||
u8_t i, addr_index;
|
||||
|
||||
/* Link-local prefix. */
|
||||
netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul);
|
||||
netif->ip6_addr[0].addr[1] = 0;
|
||||
|
||||
/* Generate interface ID. */
|
||||
if (from_mac_48bit) {
|
||||
/* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
|
||||
netif->ip6_addr[0].addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
|
||||
((u32_t)(netif->hwaddr[1]) << 16) |
|
||||
((u32_t)(netif->hwaddr[2]) << 8) |
|
||||
(0xff));
|
||||
netif->ip6_addr[0].addr[3] = htonl((0xfeul << 24) |
|
||||
((u32_t)(netif->hwaddr[3]) << 16) |
|
||||
((u32_t)(netif->hwaddr[4]) << 8) |
|
||||
(netif->hwaddr[5]));
|
||||
}
|
||||
else {
|
||||
/* Use hwaddr directly as interface ID. */
|
||||
netif->ip6_addr[0].addr[2] = 0;
|
||||
netif->ip6_addr[0].addr[3] = 0;
|
||||
|
||||
addr_index = 3;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i == 4) {
|
||||
addr_index--;
|
||||
}
|
||||
netif->ip6_addr[0].addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set address state. */
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||
/* Will perform duplicate address detection (DAD). */
|
||||
netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
|
||||
#else
|
||||
/* Consider address valid. */
|
||||
netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
195
src/core/raw.c
195
src/core/raw.c
@ -49,6 +49,8 @@
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -79,11 +81,24 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
struct ip_hdr *iphdr;
|
||||
s16_t proto;
|
||||
u8_t eaten = 0;
|
||||
#if LWIP_IPV6
|
||||
struct ip6_hdr *ip6hdr;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
proto = IPH_PROTO(iphdr);
|
||||
#if LWIP_IPV6
|
||||
if (IPH_V(iphdr) == 6) {
|
||||
ip6hdr = (struct ip6_hdr *)p->payload;
|
||||
proto = IP6H_NEXTH(ip6hdr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
proto = IPH_PROTO(iphdr);
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
pcb = raw_pcbs;
|
||||
@ -91,17 +106,38 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if ((pcb->protocol == proto) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) {
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_addr_isany(&pcb->local_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&pcb->local_ip.ip4) ||
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr()))))) {
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
/* broadcast filter? */
|
||||
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp))
|
||||
if (((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp))
|
||||
#if LWIP_IPV6
|
||||
&& !pcb->isipv6
|
||||
#endif /* LWIP_IPV6 */
|
||||
)
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
{
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
if (pcb->recv.ip4 != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
eaten = pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr());
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||
}
|
||||
if (eaten != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
@ -141,7 +177,15 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
err_t
|
||||
raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip.ip4, ipaddr);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@ -161,7 +205,15 @@ raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
err_t
|
||||
raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip.ip4, ipaddr);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@ -183,7 +235,7 @@ void
|
||||
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv.ip4 = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
|
||||
@ -209,6 +261,33 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||
|
||||
#if LWIP_IPV6
|
||||
/* TODO lots of v4 and v6 code duplication, optimize! Or will compiler optimize? */
|
||||
if (pcb->isipv6) {
|
||||
/* not enough space to add an IPv6 header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP6_HLEN)) {
|
||||
/* allocate header in new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
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);
|
||||
/* { 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 {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
if(pbuf_header(q, -IP6_HLEN)) {
|
||||
LWIP_ASSERT("Can't restore header we just removed!", 0);
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
/* allocate header in new pbuf */
|
||||
@ -233,6 +312,19 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if ((netif = ip6_route(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to IPv6 destionation\n"));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
||||
@ -244,29 +336,62 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
}
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
#if LWIP_IPV6
|
||||
if (!netif->isipv6) {
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* broadcast filter? */
|
||||
if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
return ERR_VAL;
|
||||
#if LWIP_IPV6
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&pcb->local_ip.ip6)) {
|
||||
/* select an IPv6 address from the netif as source address */
|
||||
src_ip = (ip_addr_t *)ip6_select_source_address(netif, (ip6_addr_t *)ipaddr);
|
||||
if (src_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
} else {
|
||||
/* use RAW PCB local IPv6 address as source address */
|
||||
src_ip = (ip_addr_t *)&(pcb->local_ip.ip6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* use RAW PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
src_ip = &(pcb->local_ip.ip4);
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t *)src_ip, (ip6_addr_t *)ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
@ -289,7 +414,13 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
err_t
|
||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
return raw_sendto(pcb, p, &pcb->remote_ip);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* TODO is this necessary, or ar ip4 and ip6 pointers the same (think union)? */
|
||||
return raw_sendto(pcb, p, (ip_addr_t *)&pcb->remote_ip.ip6);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
return raw_sendto(pcb, p, &pcb->remote_ip.ip4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,4 +482,28 @@ raw_new(u8_t proto)
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Create a RAW PCB for IPv6.
|
||||
*
|
||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @param proto the protocol number (next header) of the IPv6 packet payload
|
||||
* (e.g. IP6_NEXTH_ICMP6)
|
||||
*
|
||||
* @see raw_remove()
|
||||
*/
|
||||
struct raw_pcb *
|
||||
raw_new_ip6(u8_t proto)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
pcb = raw_new(proto);
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* LWIP_RAW */
|
||||
|
240
src/core/tcp.c
240
src/core/tcp.c
@ -52,6 +52,9 @@
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/nd6.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -147,8 +150,17 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
||||
|
||||
/* don't call tcp_abort here: we must not deallocate the pcb since
|
||||
that might not be expected when calling tcp_close */
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
|
||||
tcp_pcb_purge(pcb);
|
||||
|
||||
@ -318,8 +330,8 @@ void
|
||||
tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
{
|
||||
u32_t seqno, ackno;
|
||||
u16_t remote_port, local_port;
|
||||
ip_addr_t remote_ip, local_ip;
|
||||
/*u16_t remote_port, local_port;
|
||||
ip_addr_t remote_ip, local_ip; */
|
||||
#if LWIP_CALLBACK_API
|
||||
tcp_err_fn errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
@ -337,10 +349,10 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
} else {
|
||||
seqno = pcb->snd_nxt;
|
||||
ackno = pcb->rcv_nxt;
|
||||
ip_addr_copy(local_ip, pcb->local_ip);
|
||||
ip_addr_copy(remote_ip, pcb->remote_ip);
|
||||
/*ip_addr_copy(local_ip, pcb->local_ip.ip4);
|
||||
ip_addr_copy(remote_ip, pcb->remote_ip.ip4);
|
||||
local_port = pcb->local_port;
|
||||
remote_port = pcb->remote_port;
|
||||
remote_port = pcb->remote_port;*/
|
||||
#if LWIP_CALLBACK_API
|
||||
errf = pcb->errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
@ -357,12 +369,20 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
tcp_segs_free(pcb->ooseq);
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
||||
if (reset) {
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(seqno, ackno, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(seqno, ackno, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,18 +452,40 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
((cpcb->so_options & SOF_REUSEADDR) == 0))
|
||||
#endif /* SO_REUSE */
|
||||
{
|
||||
if (ip_addr_isany(&(cpcb->local_ip)) ||
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
!pcb->isipv6 &&
|
||||
!cpcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&(cpcb->local_ip.ip4)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
||||
ip_addr_cmp(&(cpcb->local_ip.ip4), ipaddr))) {
|
||||
return ERR_USE;
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6 &&
|
||||
cpcb->isipv6 &&
|
||||
(ip6_addr_isany(&(cpcb->local_ip.ip6)) ||
|
||||
ip6_addr_isany((ip6_addr_t *)ipaddr) ||
|
||||
ip6_addr_cmp(&(cpcb->local_ip.ip6), (ip6_addr_t *)ipaddr))) {
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (!ip6_addr_isany((ip6_addr_t *)ipaddr)) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (!ip_addr_isany(ipaddr)) {
|
||||
pcb->local_ip = *ipaddr;
|
||||
pcb->local_ip.ip4 = *ipaddr;
|
||||
}
|
||||
pcb->local_port = port;
|
||||
TCP_REG(&tcp_bound_pcbs, pcb);
|
||||
@ -498,7 +540,15 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
this port is only used once for every local IP. */
|
||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if (lpcb->local_port == pcb->local_port) {
|
||||
if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
||||
if ((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
lpcb->isipv6 &&
|
||||
ip6_addr_cmp(&lpcb->local_ip.ip6, &pcb->local_ip.ip6)) ||
|
||||
(!pcb->isipv6 &&
|
||||
!lpcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&lpcb->local_ip.ip4, &pcb->local_ip.ip4))) {
|
||||
/* this address/port is already used */
|
||||
return NULL;
|
||||
}
|
||||
@ -518,7 +568,16 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
||||
lpcb->so_options |= SOF_ACCEPTCONN;
|
||||
lpcb->ttl = pcb->ttl;
|
||||
lpcb->tos = pcb->tos;
|
||||
ip_addr_copy(lpcb->local_ip, pcb->local_ip);
|
||||
#if LWIP_IPV6
|
||||
lpcb->isipv6 = pcb->isipv6;
|
||||
if (lpcb->isipv6) {
|
||||
ip6_addr_copy(lpcb->local_ip.ip6, pcb->local_ip.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_copy(lpcb->local_ip.ip4, pcb->local_ip.ip4);
|
||||
}
|
||||
if (pcb->local_port != 0) {
|
||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||
}
|
||||
@ -657,23 +716,55 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
||||
if (ipaddr != NULL) {
|
||||
pcb->remote_ip = *ipaddr;
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->remote_ip.ip4 = *ipaddr;
|
||||
}
|
||||
} else {
|
||||
return ERR_VAL;
|
||||
}
|
||||
pcb->remote_port = port;
|
||||
|
||||
/* check if we have a route to the remote host */
|
||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&(pcb->local_ip.ip6))) {
|
||||
/* no local IPv6 address set, yet. */
|
||||
ip6_addr_t * local_addr6;
|
||||
struct netif *netif = ip6_route(&(pcb->remote_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
if (netif == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no route
|
||||
since that will fail. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* Select and IPv6 address from the netif. */
|
||||
local_addr6 = ip6_select_source_address(netif, &(pcb->remote_ip.ip6));
|
||||
if (local_addr6 == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no suitable
|
||||
source address. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
ip6_addr_set(&pcb->local_ip.ip6, local_addr6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&(pcb->local_ip.ip4))) {
|
||||
/* no local IP address set, yet. */
|
||||
struct netif *netif = ip_route(&(pcb->remote_ip));
|
||||
struct netif *netif = ip_route(&(pcb->remote_ip.ip4));
|
||||
if (netif == NULL) {
|
||||
/* Don't even try to send a SYN packet if we have no route
|
||||
since that will fail. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* Use the netif's IP address as local address. */
|
||||
ip_addr_copy(pcb->local_ip, netif->ip_addr);
|
||||
ip_addr_copy(pcb->local_ip.ip4, netif->ip_addr);
|
||||
}
|
||||
|
||||
old_local_port = pcb->local_port;
|
||||
@ -691,8 +782,18 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
||||
if ((cpcb->local_port == pcb->local_port) &&
|
||||
(cpcb->remote_port == port) &&
|
||||
ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
|
||||
ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
|
||||
#if LWIP_IPV6
|
||||
((cpcb->isipv6 &&
|
||||
pcb->isipv6 &&
|
||||
ip6_addr_cmp(&cpcb->local_ip.ip6, &pcb->local_ip.ip6) &&
|
||||
ip6_addr_cmp(&cpcb->remote_ip.ip6, (ip6_addr_t *)ipaddr)) ||
|
||||
(!cpcb->isipv6 &&
|
||||
!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&cpcb->local_ip.ip4, &pcb->local_ip.ip4) &&
|
||||
ip_addr_cmp(&cpcb->remote_ip.ip4, ipaddr)))) {
|
||||
/* linux returns EISCONN here, but ERR_USE should be OK for us */
|
||||
return ERR_USE;
|
||||
}
|
||||
@ -713,7 +814,15 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
||||
The send MSS is updated when an MSS option is received. */
|
||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
pcb->mss = tcp_eff_send_mss_ip6(pcb->mss, &pcb->local_ip.ip6, &pcb->remote_ip.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->remote_ip.ip4);
|
||||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
pcb->cwnd = 1;
|
||||
pcb->ssthresh = pcb->mss * 10;
|
||||
@ -852,9 +961,13 @@ tcp_slowtmr(void)
|
||||
(pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
{
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
|
||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
++pcb_remove;
|
||||
++pcb_reset;
|
||||
@ -919,8 +1032,17 @@ tcp_slowtmr(void)
|
||||
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
|
||||
if (pcb_reset) {
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcp_rst_ip6(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
}
|
||||
|
||||
pcb2 = pcb;
|
||||
@ -1266,6 +1388,27 @@ tcp_new(void)
|
||||
return tcp_alloc(TCP_PRIO_NORMAL);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Creates a new TCP-over-IPv6 protocol control block but doesn't
|
||||
* place it on any of the TCP PCB lists.
|
||||
* The pcb is not put on any list until binding using tcp_bind().
|
||||
*
|
||||
* @return a new tcp_pcb that initially is in state CLOSED
|
||||
*/
|
||||
struct tcp_pcb *
|
||||
tcp_new_ip6(void)
|
||||
{
|
||||
struct tcp_pcb * pcb;
|
||||
pcb = tcp_alloc(TCP_PRIO_NORMAL);
|
||||
/* could allocate TCP PCB? */
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Used to specify the argument that should be passed callback
|
||||
* functions.
|
||||
@ -1376,8 +1519,18 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
tcp_listen_pcbs.listen_pcbs != NULL);
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
(ip_addr_isany(&lpcb->local_ip) ||
|
||||
ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
|
||||
#if LWIP_IPV6
|
||||
((lpcb->isipv6 &&
|
||||
pcb->isipv6 &&
|
||||
(ip6_addr_isany(&lpcb->local_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, &lpcb->local_ip.ip6))) ||
|
||||
(!lpcb->isipv6 &&
|
||||
!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&lpcb->local_ip.ip4) ||
|
||||
ip_addr_cmp(&pcb->local_ip.ip4, &lpcb->local_ip.ip4))))) {
|
||||
/* port and address of the listen pcb match the timed-out pcb */
|
||||
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
||||
lpcb->accepts_pending > 0);
|
||||
@ -1492,6 +1645,35 @@ tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
|
||||
}
|
||||
return sendmss;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Calculates the effective send mss that can be used for a specific IPv6
|
||||
* address by using ip6_route to determine the netif used to send to the
|
||||
* address and calculating the minimum of TCP_MSS and that netif's mtu (if set).
|
||||
*/
|
||||
u16_t
|
||||
tcp_eff_send_mss_ip6(u16_t sendmss, ip6_addr_t *src, ip6_addr_t *dest)
|
||||
{
|
||||
u16_t mss_s;
|
||||
struct netif *outif;
|
||||
s16_t mtu;
|
||||
|
||||
/* First look in destination cache, to see if there is a PAth MTU. */
|
||||
outif = ip6_route(src, dest);
|
||||
mtu = nd6_get_destination_mtu(dest, outif);
|
||||
|
||||
if (mtu != 0) {
|
||||
mss_s = mtu - IP6_HLEN - TCP_HLEN;
|
||||
/* RFC 1122, chap 4.2.2.6:
|
||||
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
||||
* We correct for TCP options in tcp_write().
|
||||
*/
|
||||
sendmss = LWIP_MIN(sendmss, mss_s);
|
||||
}
|
||||
return sendmss;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
const char*
|
||||
|
@ -55,13 +55,18 @@
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
#include "lwip/nd6.h"
|
||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||
|
||||
/* These variables are global to all functions involved in the input
|
||||
processing of TCP segments. They are set by the tcp_input()
|
||||
function. */
|
||||
static struct tcp_seg inseg;
|
||||
static struct tcp_hdr *tcphdr;
|
||||
static struct ip_hdr *iphdr;
|
||||
static u32_t seqno, ackno;
|
||||
static u8_t flags;
|
||||
static u16_t tcplen;
|
||||
@ -85,7 +90,7 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
|
||||
* the TCP finite state machine. This function is called by the IP layer (in
|
||||
* ip_input()).
|
||||
*
|
||||
* @param p received TCP segment to process (p->payload pointing to the IP header)
|
||||
* @param p received TCP segment to process (p->payload pointing to the TCP header)
|
||||
* @param inp network interface on which this segment was received
|
||||
*/
|
||||
void
|
||||
@ -105,15 +110,14 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_STATS_INC(tcp.recv);
|
||||
snmp_inc_tcpinsegs();
|
||||
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
|
||||
#if TCP_INPUT_DEBUG
|
||||
tcp_debug_print(tcphdr);
|
||||
#endif
|
||||
|
||||
/* remove header from payload */
|
||||
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
|
||||
/* Check that TCP header fits in payload */
|
||||
if (p->len < sizeof(struct tcp_hdr)) {
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||
TCP_STATS_INC(tcp.lenerr);
|
||||
@ -124,8 +128,14 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
/* Don't even process incoming broadcasts/multicasts. */
|
||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) ||
|
||||
ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
if ((
|
||||
#if LWIP_IPV6
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_ismulticast(ip6_current_dest_addr())) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isbroadcast(ip_current_dest_addr(), inp) ||
|
||||
ip_addr_ismulticast(ip_current_dest_addr())))) {
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
@ -134,6 +144,25 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
#if CHECKSUM_CHECK_TCP
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_TCP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||
ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_TCP, p->tot_len)));
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print(tcphdr);
|
||||
#endif /* TCP_DEBUG */
|
||||
TCP_STATS_INC(tcp.chkerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* Verify TCP checksum. */
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_TCP, p->tot_len) != 0) {
|
||||
@ -149,7 +178,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* CHECKSUM_CHECK_TCP */
|
||||
|
||||
/* Move the payload pointer in the pbuf so that it points to the
|
||||
TCP data instead of the TCP header. */
|
||||
@ -184,9 +213,18 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_cmp(&(pcb->remote_ip.ip6), ip6_current_src_addr()) &&
|
||||
ip6_addr_cmp(&(pcb->local_ip.ip6), ip6_current_dest_addr())) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr()) &&
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr())))) {
|
||||
|
||||
/* Move this PCB to the front of the list so that subsequent
|
||||
lookups will be faster (we exploit locality in TCP segment
|
||||
@ -209,9 +247,18 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
((
|
||||
#if LWIP_IPV6
|
||||
pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
ip6_addr_cmp(&(pcb->remote_ip.ip6), ip6_current_src_addr()) &&
|
||||
ip6_addr_cmp(&(pcb->local_ip.ip6), ip6_current_dest_addr())) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr()) &&
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr())))) {
|
||||
/* We don't really care enough to move this PCB to the front
|
||||
of the list since we are not very likely to receive that
|
||||
many segments for connections in TIME-WAIT. */
|
||||
@ -228,19 +275,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if (lpcb->local_port == tcphdr->dest) {
|
||||
#if SO_REUSE
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip_addr_isany(&(lpcb->local_ip))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
#if LWIP_IPV6
|
||||
if (lpcb->isipv6 &&
|
||||
(ip6_current_header() != NULL)) {
|
||||
if (ip6_addr_cmp(&(lpcb->local_ip.ip6), ip6_current_dest_addr())) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip6_addr_isany(&(lpcb->local_ip.ip6))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
}
|
||||
}
|
||||
else if (!lpcb->isipv6 &&
|
||||
(ip_current_header() != NULL))
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
if (ip_addr_cmp(&(lpcb->local_ip.ip4), ip_current_dest_addr())) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip_addr_isany(&(lpcb->local_ip.ip4))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
}
|
||||
}
|
||||
#else /* SO_REUSE */
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) ||
|
||||
ip_addr_isany(&(lpcb->local_ip))) {
|
||||
/* found a match */
|
||||
break;
|
||||
#if LWIP_IPV6
|
||||
if (lpcb->isipv6 &&
|
||||
(ip6_current_header() != NULL)) {
|
||||
if (ip6_addr_cmp(&(lpcb->local_ip.ip6), ip6_current_dest_addr()) ||
|
||||
ip6_addr_isany(&(lpcb->local_ip.ip6))) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!lpcb->isipv6 &&
|
||||
(ip_current_header() != NULL))
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
if (ip_addr_cmp(&(lpcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
ip_addr_isany(&(lpcb->local_ip.ip4))) {
|
||||
/* found a match */
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
}
|
||||
@ -415,9 +493,19 @@ aborted:
|
||||
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
tcp_rst(ackno, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen,
|
||||
ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
@ -450,9 +538,19 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
/* For incoming segments with the ACK flag set, respond with a
|
||||
RST. */
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
||||
tcp_rst(ackno + 1, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno + 1, seqno + tcplen,
|
||||
ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno + 1, seqno + tcplen,
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
} else if (flags & TCP_SYN) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
@ -474,9 +572,19 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
pcb->accepts_pending++;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
/* Set up the new PCB. */
|
||||
ip_addr_copy(npcb->local_ip, current_iphdr_dest);
|
||||
#if LWIP_IPV6
|
||||
npcb->isipv6 = pcb->isipv6;
|
||||
if (npcb->isipv6) {
|
||||
ip6_addr_copy(npcb->local_ip.ip6, *ip6_current_dest_addr());
|
||||
ip6_addr_copy(npcb->remote_ip.ip6, *ip6_current_src_addr());
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_copy(npcb->local_ip.ip4, *ip_current_dest_addr());
|
||||
ip_addr_copy(npcb->remote_ip.ip4, *ip_current_src_addr());
|
||||
}
|
||||
npcb->local_port = pcb->local_port;
|
||||
ip_addr_copy(npcb->remote_ip, current_iphdr_src);
|
||||
npcb->remote_port = tcphdr->src;
|
||||
npcb->state = SYN_RCVD;
|
||||
npcb->rcv_nxt = seqno + 1;
|
||||
@ -497,7 +605,15 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
/* Parse any options in the SYN. */
|
||||
tcp_parseopt(npcb);
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
|
||||
#if LWIP_IPV6
|
||||
if (npcb->isipv6) {
|
||||
npcb->mss = tcp_eff_send_mss_ip6(npcb->mss, &(npcb->local_ip.ip6), &(npcb->remote_ip.ip6));
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip.ip4));
|
||||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
snmp_inc_tcppassiveopens();
|
||||
@ -539,8 +655,17 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
||||
should be sent in reply */
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||
/* If the SYN is in the window it is an error, send a reset */
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
} else if (flags & TCP_FIN) {
|
||||
@ -637,7 +762,15 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->state = ESTABLISHED;
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
pcb->mss = tcp_eff_send_mss_ip6(pcb->mss, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip.ip4));
|
||||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
/* Set ssthresh again after changing pcb->mss (already set in tcp_connect
|
||||
@ -673,8 +806,17 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
/* received ACK? possibly a half-open connection */
|
||||
else if (flags & TCP_ACK) {
|
||||
/* send a RST to bring the other side in a non-synchronized state. */
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SYN_RCVD:
|
||||
@ -716,8 +858,17 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
}
|
||||
} else {
|
||||
/* incorrect ACK number, send RST */
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
tcp_rst_ip6(ackno, seqno + tcplen, ip6_current_dest_addr(), ip6_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
}
|
||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||
/* Looks like another copy of the SYN - retransmit our SYN-ACK */
|
||||
@ -1019,6 +1170,13 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
pcb->rtime = 0;
|
||||
|
||||
pcb->polltmr = 0;
|
||||
|
||||
#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
if (pcb->isipv6) {
|
||||
/* Inform neighbor reachability of forward progress. */
|
||||
nd6_reachability_hint(ip6_current_src_addr());
|
||||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
|
||||
} else {
|
||||
/* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
|
||||
pcb->acked = 0;
|
||||
@ -1336,6 +1494,13 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
/* Acknowledge the segment(s). */
|
||||
tcp_ack(pcb);
|
||||
|
||||
#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
if (pcb->isipv6) {
|
||||
/* Inform neighbor reachability of forward progress. */
|
||||
nd6_reachability_hint(ip6_current_src_addr());
|
||||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
|
||||
|
||||
} else {
|
||||
/* We get here if the incoming segment is out-of-sequence. */
|
||||
tcp_send_empty_ack(pcb);
|
||||
|
@ -52,6 +52,9 @@
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -865,17 +868,34 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* Chksum is mandatory over IPv6 */
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip6_output_hinted(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip6_output(p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
ip_output_hinted(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
ip_output(p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
@ -1086,12 +1106,30 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
|
||||
/* If we don't have a local IP address, we get one by
|
||||
calling ip_route(). */
|
||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
||||
netif = ip_route(&(pcb->remote_ip));
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&(pcb->local_ip.ip6))) {
|
||||
ip6_addr_t * local_addr6;
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), &(pcb->remote_ip.ip6));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
/* Select and IPv6 address from the netif. */
|
||||
local_addr6 = ip6_select_source_address(netif, &(pcb->remote_ip.ip6));
|
||||
if (local_addr6 == NULL) {
|
||||
return;
|
||||
}
|
||||
ip6_addr_set(&pcb->local_ip.ip6, local_addr6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&(pcb->local_ip.ip4))) {
|
||||
netif = ip_route(&(pcb->remote_ip.ip4));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
ip_addr_copy(pcb->local_ip, netif->ip_addr);
|
||||
ip_addr_copy(pcb->local_ip.ip4, netif->ip_addr);
|
||||
}
|
||||
|
||||
if (pcb->rttest == 0) {
|
||||
@ -1112,14 +1150,24 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
seg->p->payload = seg->tcphdr;
|
||||
|
||||
seg->tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
{
|
||||
u32_t acc;
|
||||
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
|
||||
u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
u16_t chksum_slow;
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
chksum_slow = ip6_chksum_pseudo(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
}
|
||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||
if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
|
||||
LWIP_ASSERT("data included but not checksummed",
|
||||
@ -1127,9 +1175,19 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
}
|
||||
|
||||
/* rebuild TCP header checksum (TCP header changes for retransmissions!) */
|
||||
acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
acc = ip6_chksum_pseudo_partial(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
|
||||
}
|
||||
/* add payload checksum */
|
||||
if (seg->chksum_swapped) {
|
||||
seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
|
||||
@ -1147,20 +1205,46 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
|
||||
}
|
||||
#else /* TCP_CHECKSUM_ON_COPY */
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
/* Chksum is mandatory in IPv6 */
|
||||
seg->tcphdr->chksum = ip6_chksum_pseudo(seg->p, &(pcb->local_ip.ip6),
|
||||
&(pcb->remote_ip.ip6),
|
||||
IP6_NEXTH_TCP, seg->p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip.ip4),
|
||||
&(pcb->remote_ip.ip4),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
#endif /* CHECKSUM_GEN_TCP */
|
||||
}
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
ip6_output_hinted(seg->p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
ip6_output(seg->p, &(pcb->local_ip.ip6), &(pcb->remote_ip.ip6), pcb->ttl, pcb->tos,
|
||||
IP6_NEXTH_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(seg->p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(seg->p, &(pcb->local_ip.ip4), &(pcb->remote_ip.ip4), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1220,6 +1304,65 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Send a TCP RESET packet (empty segment with RST flag set) over IPv6,
|
||||
* either to abort a connection or to show that there is no matching local
|
||||
* connection for a received segment.
|
||||
*
|
||||
* Called by tcp_abort() (to abort a local connection), tcp_input() (if no
|
||||
* matching local pcb was found), tcp_listen_input() (if incoming segment
|
||||
* has ACK flag set) and tcp_process() (received segment in the wrong state)
|
||||
*
|
||||
* Since a RST segment is in most cases not sent for an active connection,
|
||||
* tcp_rst() has a number of arguments that are taken from a tcp_pcb for
|
||||
* most other segment output functions.
|
||||
*
|
||||
* @param seqno the sequence number to use for the outgoing segment
|
||||
* @param ackno the acknowledge number to use for the outgoing segment
|
||||
* @param local_ip6 the local IPv6 address to send the segment from
|
||||
* @param remote_ip6 the remote IPv6 address to send the segment to
|
||||
* @param local_port the local TCP port to send the segment from
|
||||
* @param remote_port the remote TCP port to send the segment to
|
||||
*/
|
||||
void
|
||||
tcp_rst_ip6(u32_t seqno, u32_t ackno,
|
||||
ip6_addr_t *local_ip6, ip6_addr_t *remote_ip6,
|
||||
u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
|
||||
(p->len >= sizeof(struct tcp_hdr)));
|
||||
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
tcphdr->src = htons(local_port);
|
||||
tcphdr->dest = htons(remote_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
|
||||
tcphdr->wnd = PP_HTONS(TCP_WND);
|
||||
tcphdr->chksum = 0;
|
||||
tcphdr->urgp = 0;
|
||||
|
||||
/* chksum us mandatory over IPv6. */
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, local_ip6, remote_ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
snmp_inc_tcpoutrsts();
|
||||
/* Send output with hardcoded HL since we have no access to the pcb */
|
||||
ip6_output(p, local_ip6, remote_ip6, TCP_TTL, 0, IP6_NEXTH_TCP);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/**
|
||||
* Requeue all unacked segments for retransmission
|
||||
*
|
||||
@ -1351,9 +1494,13 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
|
||||
tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
|
||||
@ -1366,19 +1513,41 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
}
|
||||
tcphdr = (struct tcp_hdr *)p->payload;
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
}
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
ip6_output_hinted(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
ip6_output(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
@ -1404,11 +1573,13 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
u16_t len;
|
||||
u8_t is_fin;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
|
||||
U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(TCP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("tcp_zero_window_probe: tcp_ticks %"U32_F
|
||||
@ -1445,19 +1616,41 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
tcphdr->chksum = ip6_chksum_pseudo(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6,
|
||||
IP6_NEXTH_TCP, p->tot_len);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
}
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
ip6_output_hinted(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
ip6_output(p, &pcb->local_ip.ip6, &pcb->remote_ip.ip6, pcb->ttl, 0, IP6_NEXTH_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip.ip4, &pcb->remote_ip.ip4, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
|
@ -56,7 +56,9 @@
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/ip6_frag.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
/** The one and only timeout list */
|
||||
static struct sys_timeo *next_timeout;
|
||||
@ -217,6 +219,54 @@ dns_timer(void *arg)
|
||||
}
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Timer callback function that calls nd6_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
nd6_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n"));
|
||||
nd6_tmr();
|
||||
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6_REASS
|
||||
/**
|
||||
* Timer callback function that calls ip6_reass_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
ip6_reass_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n"));
|
||||
ip6_reass_tmr();
|
||||
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_IPV6_REASS */
|
||||
|
||||
#if LWIP_IPV6_MLD
|
||||
/**
|
||||
* Timer callback function that calls mld6_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
mld6_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n"));
|
||||
mld6_tmr();
|
||||
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/** Initialize this module */
|
||||
void sys_timeouts_init(void)
|
||||
{
|
||||
@ -239,6 +289,15 @@ void sys_timeouts_init(void)
|
||||
#if LWIP_DNS
|
||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
#endif /* LWIP_DNS */
|
||||
#if LWIP_IPV6
|
||||
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
|
||||
#if LWIP_IPV6_REASS
|
||||
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
|
||||
#endif /* LWIP_IPV6_REASS */
|
||||
#if LWIP_IPV6_MLD
|
||||
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if NO_SYS
|
||||
/* Initialise timestamp for sys_check_timeouts */
|
||||
|
583
src/core/udp.c
583
src/core/udp.c
@ -55,8 +55,12 @@
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "arch/perf.h"
|
||||
@ -76,7 +80,7 @@ struct udp_pcb *udp_pcbs;
|
||||
* recv function. If no pcb is found or the datagram is incorrect, the
|
||||
* pbuf is freed.
|
||||
*
|
||||
* @param p pbuf to be demultiplexed to a UDP PCB.
|
||||
* @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header)
|
||||
* @param inp network interface on which the datagram was received.
|
||||
*
|
||||
*/
|
||||
@ -86,7 +90,6 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
struct udp_hdr *udphdr;
|
||||
struct udp_pcb *pcb, *prev;
|
||||
struct udp_pcb *uncon_pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t src, dest;
|
||||
u8_t local_match;
|
||||
u8_t broadcast;
|
||||
@ -95,11 +98,8 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
UDP_STATS_INC(udp.recv);
|
||||
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
|
||||
/* Check minimum length (IP header + UDP header)
|
||||
* and move payload pointer to UDP header */
|
||||
if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
|
||||
/* Check minimum length (UDP header) */
|
||||
if (p->len < UDP_HLEN) {
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||
@ -113,7 +113,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
udphdr = (struct udp_hdr *)p->payload;
|
||||
|
||||
/* is broadcast packet ? */
|
||||
broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp);
|
||||
#if LWIP_IPV6
|
||||
broadcast = (ip_current_header() != NULL) && ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||
#else /* LWIP_IPV6 */
|
||||
broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||
|
||||
@ -124,13 +128,19 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
udp_debug_print(udphdr);
|
||||
|
||||
/* print the UDP source and destination */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
|
||||
ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
|
||||
ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
|
||||
if (ip_current_header() != NULL) {
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr());
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, ip6_current_dest_addr());
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest)));
|
||||
if (ip_current_header() != NULL) {
|
||||
ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr());
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, ip6_current_src_addr());
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src)));
|
||||
|
||||
#if LWIP_DHCP
|
||||
pcb = NULL;
|
||||
@ -143,8 +153,12 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* accept the packe if
|
||||
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
|
||||
- inp->dhcp->pcb->remote == ANY or iphdr->src */
|
||||
if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) {
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
!pcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
((ip_addr_isany(&inp->dhcp->pcb->remote_ip.ip4) ||
|
||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip.ip4), ip_current_src_addr())))) {
|
||||
pcb = inp->dhcp->pcb;
|
||||
}
|
||||
}
|
||||
@ -162,25 +176,44 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
local_match = 0;
|
||||
/* print the PCB local and remote address */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb ("));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, &pcb->local_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG, &pcb->remote_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port));
|
||||
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) ||
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
(ip6_addr_isany(&pcb->local_ip.ip6) ||
|
||||
#if LWIP_IPV6_MLD
|
||||
ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
ip6_addr_cmp(&pcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((!broadcast && ip_addr_isany(&pcb->local_ip.ip4)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
||||
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
|
||||
(broadcast && (pcb->so_options & SOF_BROADCAST)))))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast))) {
|
||||
(broadcast))))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
@ -192,8 +225,18 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* compare PCB remote addr+port to UDP source addr+port */
|
||||
if ((local_match != 0) &&
|
||||
(pcb->remote_port == src) &&
|
||||
(ip_addr_isany(&pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) {
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
(ip6_current_header() != NULL) &&
|
||||
(ip6_addr_isany(&pcb->remote_ip.ip6) ||
|
||||
ip6_addr_cmp(&pcb->remote_ip.ip6, ip6_current_src_addr()))) ||
|
||||
(!pcb->isipv6 &&
|
||||
(ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((ip_addr_isany(&pcb->remote_ip.ip4) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip.ip4), ip_current_src_addr())))))) {
|
||||
/* the first fully matching PCB */
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of udp_pcbs so that is
|
||||
@ -215,10 +258,26 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
/* Check checksum if this is a match or if it was directed at us. */
|
||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) {
|
||||
if ((pcb != NULL) ||
|
||||
#if LWIP_IPV6
|
||||
((ip6_current_header() != NULL) &&
|
||||
netif_matches_ip6_addr(inp, ip6_current_dest_addr())) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
(
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr()))) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||
#if LWIP_UDPLITE
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
||||
if (
|
||||
#if LWIP_IPV6
|
||||
((ip6_current_header() != NULL) &&
|
||||
(IP6H_NEXTH(ip6_current_header()) == IP_PROTO_UDPLITE)) ||
|
||||
((ip_current_header() != NULL) &&
|
||||
#else /* LWIP_IPV6 */
|
||||
(
|
||||
#endif /* LWIP_IPV6 */
|
||||
(IPH_PROTO(iphdr) == IP_PROTO_UDPLITE))) {
|
||||
/* Do the UDP Lite checksum */
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
u16_t chklen = ntohs(udphdr->len);
|
||||
@ -237,7 +296,22 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest,
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo_partial(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (inet_chksum_pseudo_partial(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
@ -253,6 +327,21 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
if (ip6_chksum_pseudo(p, ip6_current_src_addr(), ip6_current_dest_addr(),
|
||||
IP6_NEXTH_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
@ -277,32 +366,53 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
if (pcb != NULL) {
|
||||
snmp_inc_udpindatagrams();
|
||||
#if SO_REUSE && SO_REUSE_RXTOALL
|
||||
if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) &&
|
||||
if ((broadcast ||
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_ismulticast(ip_current_dest_addr())) &&
|
||||
((pcb->so_options & SOF_REUSEADDR) != 0)) {
|
||||
/* pass broadcast- or multicast packets to all multicast pcbs
|
||||
if SOF_REUSEADDR is set on the first match */
|
||||
struct udp_pcb *mpcb;
|
||||
u8_t p_header_changed = 0;
|
||||
s16_t hdrs_len;
|
||||
#if LWIP_IPV6
|
||||
if (ip6_current_header() != NULL) {
|
||||
hdrs_len = (s16_t)(ip6_current_header_tot_len() + UDP_HLEN);
|
||||
} else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
hdrs_len = (s16_t)((IPH_HL(ip_current_header()) * 4) + UDP_HLEN);
|
||||
}
|
||||
for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
|
||||
if (mpcb != pcb) {
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((mpcb->local_port == dest) &&
|
||||
((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
|
||||
ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) ||
|
||||
#if LWIP_IPV6
|
||||
((mpcb->isipv6 &&
|
||||
(ip6_addr_ismulticast(ip6_current_dest_addr()) ||
|
||||
ip6_addr_cmp(&mpcb->local_ip.ip6, ip6_current_dest_addr()))) ||
|
||||
(!mpcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
((!broadcast && ip_addr_isany(&mpcb->local_ip.ip4)) ||
|
||||
ip_addr_cmp(&(mpcb->local_ip.ip4), ip_current_dest_addr()) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
||||
ip_addr_ismulticast(ip_current_dest_addr()) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
(broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
|
||||
(broadcast && (mpcb->so_options & SOF_BROADCAST)))))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast))) {
|
||||
(broadcast))))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
/* pass a copy of the packet to all local matches */
|
||||
if (mpcb->recv != NULL) {
|
||||
if (mpcb->recv.ip4 != NULL) {
|
||||
struct pbuf *q;
|
||||
/* for that, move payload to IP header again */
|
||||
if (p_header_changed == 0) {
|
||||
pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
pbuf_header(p, hdrs_len);
|
||||
p_header_changed = 1;
|
||||
}
|
||||
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||
@ -310,8 +420,16 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
err_t err = pbuf_copy(q, p);
|
||||
if (err == ERR_OK) {
|
||||
/* move payload to UDP data */
|
||||
pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
|
||||
pbuf_header(q, -hdrs_len);
|
||||
#if LWIP_IPV6
|
||||
if (mpcb->isipv6) {
|
||||
mpcb->recv.ip6(mpcb->recv_arg, mpcb, q, ip6_current_src_addr(), src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
mpcb->recv.ip4(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -320,14 +438,22 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
if (p_header_changed) {
|
||||
/* and move payload to UDP data again */
|
||||
pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
pbuf_header(p, -hdrs_len);
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE && SO_REUSE_RXTOALL */
|
||||
/* callback */
|
||||
if (pcb->recv != NULL) {
|
||||
if (pcb->recv.ip4 != NULL) {
|
||||
/* now the recv function is responsible for freeing p */
|
||||
pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr(), src);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
|
||||
}
|
||||
} else {
|
||||
/* no recv function registered? then we have to free the pbuf! */
|
||||
pbuf_free(p);
|
||||
@ -336,17 +462,33 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
} else {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
|
||||
|
||||
#if LWIP_ICMP
|
||||
#if LWIP_ICMP || LWIP_ICMP6
|
||||
/* No match was found, send ICMP destination port unreachable unless
|
||||
destination address was broadcast/multicast. */
|
||||
if (!broadcast &&
|
||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
|
||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
!ip6_addr_ismulticast(ip6_current_dest_addr()) &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
!ip_addr_ismulticast(ip_current_dest_addr())) {
|
||||
#if LWIP_IPV6 && LWIP_ICMP6
|
||||
if (ip6_current_header() != NULL) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, ip6_current_header_tot_len() + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == ip6_current_header()", (p->payload == ip6_current_header()));
|
||||
icmp6_dest_unreach(p, ICMP6_DUR_PORT);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 && LWIP_ICMP6 */
|
||||
{
|
||||
#if LWIP_ICMP
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, (IPH_HL(ip_current_header()) * 4) + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == ip_current_header()", (p->payload == ip_current_header()));
|
||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
||||
#endif /* LWIP_ICMP */
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_ICMP || LWIP_ICMP6 */
|
||||
UDP_STATS_INC(udp.proterr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpnoports();
|
||||
@ -381,7 +523,7 @@ err_t
|
||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
|
||||
return udp_sendto(pcb, p, &pcb->remote_ip.ip4, pcb->remote_port);
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
@ -392,7 +534,7 @@ udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
|
||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip.ip4, pcb->remote_port,
|
||||
have_chksum, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
@ -433,16 +575,35 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||
|
||||
/* find the outgoing network interface for this packet */
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_ismulticast((ip6_addr_t *)dst_ip)) {
|
||||
/* For multicast, find a netif based on source address. */
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), &(pcb->local_ip.ip6));
|
||||
}
|
||||
else {
|
||||
netif = ip6_route(&(pcb->local_ip.ip6), (ip6_addr_t *)dst_ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if LWIP_IGMP
|
||||
netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
|
||||
netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
|
||||
#else
|
||||
netif = ip_route(dst_ip);
|
||||
netif = ip_route(dst_ip);
|
||||
#endif /* LWIP_IGMP */
|
||||
}
|
||||
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, (ip6_addr_t *)dst_ip);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("\n"));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
@ -494,7 +655,11 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) &&
|
||||
#if LWIP_IPV6
|
||||
!pcb->isipv6 &&
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
return ERR_VAL;
|
||||
@ -504,7 +669,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
err = udp_bind(pcb, &pcb->local_ip.ip4, pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
|
||||
return err;
|
||||
@ -544,20 +709,60 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
|
||||
/* Multicast Loop? */
|
||||
#if LWIP_IGMP
|
||||
if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
|
||||
if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) &&
|
||||
#if LWIP_IPV6
|
||||
(
|
||||
#if LWIP_IPV6_MLD
|
||||
(pcb->isipv6 &&
|
||||
ip6_addr_ismulticast((ip6_addr_t*)dst_ip)) ||
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
(!pcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
ip_addr_ismulticast(dst_ip)))) {
|
||||
q->flags |= PBUF_FLAG_MCASTLOOP;
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
if (ip6_addr_isany(&pcb->local_ip.ip6)) {
|
||||
src_ip =(ip_addr_t *)ip6_select_source_address(netif, (ip6_addr_t *)dst_ip);
|
||||
if (src_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
} else {
|
||||
/* use UDP PCB local IPv6 address as source address, if still valid. */
|
||||
if (netif_matches_ip6_addr(netif, &(pcb->local_ip.ip6)) < 0) {
|
||||
/* Address isn't valid anymore. */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
src_ip = (ip_addr_t *)&(pcb->local_ip.ip6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* check if UDP PCB local IP address is correct
|
||||
* this could be an old address if netif->ip_addr has changed */
|
||||
if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
||||
if (!ip_addr_cmp(&(pcb->local_ip.ip4), &(netif->ip_addr))) {
|
||||
/* local_ip doesn't match, drop the packet */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
@ -568,7 +773,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
return ERR_VAL;
|
||||
}
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
src_ip = &(pcb->local_ip.ip4);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||
@ -595,31 +800,64 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
udphdr->len = htons(chklen_hdr);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
||||
IP_PROTO_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
#if LWIP_IPV6
|
||||
/* Checksum is mandatory for IPv6. */
|
||||
if (pcb->isipv6) {
|
||||
udphdr->chksum = ip6_chksum_pseudo_partial(q, (ip6_addr_t *)src_ip, (ip6_addr_t *)dst_ip,
|
||||
IP6_NEXTH_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
||||
IP_PROTO_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
}
|
||||
/* output to IP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, pcb->ttl, pcb->tos, IP6_NEXTH_UDPLITE, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
@ -629,20 +867,21 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||
udphdr->len = htons(q->tot_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
#if LWIP_IPV6
|
||||
/* Checksum is mandatory over IPv6. */
|
||||
if (pcb->isipv6) {
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
||||
udpchksum = ip6_chksum_pseudo_partial(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, IP6_NEXTH_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
udpchksum = ip6_chksum_pseudo(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, IP6_NEXTH_UDP, q->tot_len);
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
@ -651,14 +890,48 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udpchksum == 0x0000) {
|
||||
udpchksum = 0xffff;
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* output to IP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
err = ip6_output_if(q, (ip6_addr_t*)src_ip, (ip6_addr_t*)dst_ip, pcb->ttl, pcb->tos, IP6_NEXTH_UDP, netif);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
}
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
@ -704,7 +977,11 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
u8_t rebind;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
|
||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
|
||||
|
||||
rebind = 0;
|
||||
@ -730,9 +1007,20 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
#endif /* SO_REUSE */
|
||||
if ((ipcb->local_port == port) &&
|
||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||
(ip_addr_isany(&(ipcb->local_ip)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||
#if LWIP_IPV6
|
||||
((pcb->isipv6 &&
|
||||
ipcb->isipv6 &&
|
||||
(ip6_addr_isany(&(ipcb->local_ip.ip6)) ||
|
||||
ip6_addr_isany((ip6_addr_t *)ipaddr) ||
|
||||
ip6_addr_cmp(&(ipcb->local_ip.ip6), (ip6_addr_t *)ipaddr))) ||
|
||||
(!pcb->isipv6 &&
|
||||
!ipcb->isipv6 &&
|
||||
#else /* LWIP_IPV6 */
|
||||
((
|
||||
#endif /* LWIP_IPV6 */
|
||||
(ip_addr_isany(&(ipcb->local_ip.ip4)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(ipcb->local_ip.ip4), ipaddr))))) {
|
||||
/* other PCB already binds to this local IP and port */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||
@ -741,7 +1029,15 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->local_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip.ip4, ipaddr);
|
||||
}
|
||||
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
@ -778,11 +1074,13 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
||||
pcb->local_port));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
/**
|
||||
@ -808,39 +1106,54 @@ udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if (pcb->local_port == 0) {
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip.ip4, pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set(&pcb->remote_ip.ip6, (ip6_addr_t *)ipaddr);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip.ip4, ipaddr);
|
||||
}
|
||||
pcb->remote_port = port;
|
||||
pcb->flags |= UDP_FLAGS_CONNECTED;
|
||||
/** TODO: this functionality belongs in upper layers */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
|
||||
struct netif *netif;
|
||||
#if LWIP_IPV6
|
||||
if (!pcb->isipv6)
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||
if (ip_addr_isany(&pcb->local_ip.ip4) && !ip_addr_isany(&pcb->remote_ip.ip4)) {
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
if ((netif = ip_route(&(pcb->remote_ip.ip4))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.ip4.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||
is used to route output packets to the remote address. However, we
|
||||
might want to accept incoming packets on any interface! */
|
||||
pcb->local_ip.ip4 = netif->ip_addr;
|
||||
} else if (ip_addr_isany(&pcb->remote_ip.ip4)) {
|
||||
pcb->local_ip.ip4.addr = 0;
|
||||
}
|
||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||
is used to route output packets to the remote address. However, we
|
||||
might want to accept incoming packets on any interface! */
|
||||
pcb->local_ip = netif->ip_addr;
|
||||
} else if (ip_addr_isany(&pcb->remote_ip)) {
|
||||
pcb->local_ip.addr = 0;
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
||||
pcb->local_port));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to "));
|
||||
if (!pcb->isipv6) {
|
||||
ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->remote_ip.ip4);
|
||||
} else {
|
||||
ip6_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->remote_ip.ip6);
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
@ -864,7 +1177,15 @@ void
|
||||
udp_disconnect(struct udp_pcb *pcb)
|
||||
{
|
||||
/* reset remote address association */
|
||||
ip_addr_set_any(&pcb->remote_ip);
|
||||
#if LWIP_IPV6
|
||||
if (pcb->isipv6) {
|
||||
ip6_addr_set_any(&pcb->remote_ip.ip6);
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
{
|
||||
ip_addr_set_any(&pcb->remote_ip.ip4);
|
||||
}
|
||||
pcb->remote_port = 0;
|
||||
/* mark PCB as unconnected */
|
||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||
@ -883,7 +1204,7 @@ void
|
||||
udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv.ip4 = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
|
||||
@ -943,6 +1264,28 @@ udp_new(void)
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Create a UDP PCB for IPv6.
|
||||
*
|
||||
* @return The UDP PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @see udp_remove()
|
||||
*/
|
||||
struct udp_pcb *
|
||||
udp_new_ip6(void)
|
||||
{
|
||||
struct udp_pcb *pcb;
|
||||
pcb = udp_new();
|
||||
/* could allocate UDP PCB? */
|
||||
if (pcb != NULL) {
|
||||
pcb->isipv6 = 1;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if UDP_DEBUG
|
||||
/**
|
||||
* Print UDP header information for debug purposes.
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
@ -69,14 +70,29 @@ extern "C" {
|
||||
#define IP_PCB_ADDRHINT
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define IP_PCB_ISIPV6 u8_t isipv6;
|
||||
#define IP_PCB_IP6 ip6_addr_t ip6;
|
||||
#else
|
||||
#define IP_PCB_ISIPV6
|
||||
#define IP_PCB_IP6
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* This is the common part of all PCB types. It needs to be at the
|
||||
beginning of a PCB type definition. It is located here so that
|
||||
changes to this common part are made in one location instead of
|
||||
having to change all PCB structs. */
|
||||
#define IP_PCB \
|
||||
IP_PCB_ISIPV6 \
|
||||
/* ip addresses in network byte order */ \
|
||||
ip_addr_t local_ip; \
|
||||
ip_addr_t remote_ip; \
|
||||
union { \
|
||||
ip_addr_t ip4; \
|
||||
IP_PCB_IP6 \
|
||||
} local_ip; \
|
||||
union { \
|
||||
ip_addr_t ip4; \
|
||||
IP_PCB_IP6 \
|
||||
} remote_ip; \
|
||||
/* Socket options */ \
|
||||
u8_t so_options; \
|
||||
/* Type Of Service */ \
|
||||
|
@ -70,12 +70,15 @@ struct pbuf * ip_reass(struct pbuf *p);
|
||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
||||
* that points into the original pbuf. */
|
||||
#ifndef __LWIP_PBUF_CUSTOM_REF__
|
||||
#define __LWIP_PBUF_CUSTOM_REF__
|
||||
struct pbuf_custom_ref {
|
||||
/** 'base class' */
|
||||
struct pbuf_custom pc;
|
||||
/** pointer to the original pbuf that is referenced */
|
||||
struct pbuf *original;
|
||||
};
|
||||
#endif /* __LWIP_PBUF_CUSTOM_REF__ */
|
||||
#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
|
||||
|
@ -76,20 +76,35 @@ extern "C" {
|
||||
|
||||
|
||||
/* Helpers to process several netconn_types by the same code */
|
||||
#define NETCONNTYPE_GROUP(t) (t&0xF0)
|
||||
#define NETCONNTYPE_DATAGRAM(t) (t&0xE0)
|
||||
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
|
||||
#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0)
|
||||
#define NETCONNTYPE_ISIPV6(t) ((t)&0x08)
|
||||
#define NETCONNTYPE_ISUDPLITE(t)(((t)&0xF7) == NETCONN_UDPLITE)
|
||||
#define NETCONNTYPE_ISUDPNOCHKSUM(t)(((t)&0xF7) == NETCONN_UDPNOCHKSUM)
|
||||
|
||||
/** Protocol family and type of the netconn */
|
||||
enum netconn_type {
|
||||
NETCONN_INVALID = 0,
|
||||
/* NETCONN_TCP Group */
|
||||
NETCONN_TCP = 0x10,
|
||||
#if LWIP_IPV6
|
||||
NETCONN_TCP_IPV6 = 0x18,
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* NETCONN_UDP Group */
|
||||
NETCONN_UDP = 0x20,
|
||||
NETCONN_UDPLITE = 0x21,
|
||||
NETCONN_UDPNOCHKSUM= 0x22,
|
||||
#if LWIP_IPV6
|
||||
NETCONN_UDP_IPV6 = 0x28,
|
||||
NETCONN_UDPLITE_IPV6 = 0x29,
|
||||
NETCONN_UDPNOCHKSUM_IPV6= 0x2a,
|
||||
#endif /* LWIP_IPV6 */
|
||||
/* NETCONN_RAW Group */
|
||||
NETCONN_RAW = 0x40
|
||||
#if LWIP_IPV6
|
||||
,
|
||||
NETCONN_RAW_IPV6 = 0x48
|
||||
#endif /* LWIP_IPV6 */
|
||||
};
|
||||
|
||||
/** Current state of the netconn. Non-TCP netconns are always
|
||||
@ -111,13 +126,13 @@ enum netconn_evt {
|
||||
NETCONN_EVT_ERROR
|
||||
};
|
||||
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
/** Used for netconn_join_leave_group() */
|
||||
enum netconn_igmp {
|
||||
NETCONN_JOIN,
|
||||
NETCONN_LEAVE
|
||||
};
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
|
||||
/* forward-declare some structs to avoid to include their headers */
|
||||
struct ip_pcb;
|
||||
@ -235,13 +250,25 @@ err_t netconn_write(struct netconn *conn, const void *dataptr, size_t size,
|
||||
err_t netconn_close(struct netconn *conn);
|
||||
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
|
||||
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
|
||||
ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
#if LWIP_DNS
|
||||
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
||||
#endif /* LWIP_DNS */
|
||||
#if LWIP_IPV6
|
||||
#define netconn_bind_ip6(conn, ip6addr, port) \
|
||||
netconn_bind(conn, (ip_addr_t*) ip6addr, port)
|
||||
#define netconn_connect_ip6(conn, ip6addr, port) \
|
||||
netconn_connect(conn, (ip_addr_t*) ip6addr, port)
|
||||
#define netconn_sendto_ip6(conn, buf, ip6addr, port) \
|
||||
netconn_sendto(conn, buf, (ip_addr_t*) ip6addr, port)
|
||||
#if LWIP_IPV6_MLD
|
||||
#define netconn_join_leave_group_ip6(conn, multiaddr, srcaddr, join_or_leave) \
|
||||
netconn_join_leave_group(conn, (ip_addr_t*)multiaddr, (ip_addr_t*)srcaddr, join_or_leave)
|
||||
#endif /* LWIP_IPV6_MLD*/
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#define netconn_err(conn) ((conn)->last_err)
|
||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
||||
|
@ -98,14 +98,14 @@ struct api_msg_msg {
|
||||
struct {
|
||||
u8_t shut;
|
||||
} sd;
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
/** used for do_join_leave_group */
|
||||
struct {
|
||||
ip_addr_t *multiaddr;
|
||||
ip_addr_t *netif_addr;
|
||||
enum netconn_igmp join_or_leave;
|
||||
} jl;
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
struct {
|
||||
u8_t backlog;
|
||||
@ -154,9 +154,9 @@ void do_write ( struct api_msg_msg *msg);
|
||||
void do_getaddr ( struct api_msg_msg *msg);
|
||||
void do_close ( struct api_msg_msg *msg);
|
||||
void do_shutdown ( struct api_msg_msg *msg);
|
||||
#if LWIP_IGMP
|
||||
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
void do_join_leave_group( struct api_msg_msg *msg);
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
|
||||
|
||||
#if LWIP_DNS
|
||||
void do_gethostbyname(void *arg);
|
||||
|
@ -47,7 +47,7 @@ LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg),
|
||||
#if IP_REASSEMBLY
|
||||
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
|
||||
#endif /* IP_REASSEMBLY */
|
||||
#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || LWIP_IPv6_FRAG
|
||||
LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
|
||||
#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
@ -91,6 +91,19 @@ LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE,
|
||||
LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
|
||||
#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
|
||||
|
||||
#if LWIP_IPV6 && LWIP_ND6_QUEUEING
|
||||
LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE")
|
||||
#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV6_REASS
|
||||
LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA")
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP")
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
|
||||
/*
|
||||
* A list of pools of pbuf's used by LWIP.
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -45,9 +46,18 @@ extern "C" {
|
||||
/** This netbuf includes a checksum */
|
||||
#define NETBUF_FLAG_CHKSUM 0x02
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define NETBUF_IP6 ip6_addr_t ip6;
|
||||
#else
|
||||
#define NETBUF_IP6
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
ip_addr_t addr;
|
||||
union {
|
||||
ip_addr_t ip4;
|
||||
NETBUF_IP6
|
||||
} addr;
|
||||
u16_t port;
|
||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
@ -55,7 +65,10 @@ struct netbuf {
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
u16_t toport_chksum;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
ip_addr_t toaddr;
|
||||
union {
|
||||
ip_addr_t ip4;
|
||||
NETBUF_IP6
|
||||
} toaddr;
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||
};
|
||||
@ -81,12 +94,12 @@ void netbuf_first (struct netbuf *buf);
|
||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||
#define netbuf_fromaddr(buf) (&((buf)->addr))
|
||||
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr)
|
||||
#define netbuf_fromaddr(buf) (&((buf)->addr.ip4))
|
||||
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr.ip4), fromaddr)
|
||||
#define netbuf_fromport(buf) ((buf)->port)
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
#define netbuf_destaddr(buf) (&((buf)->toaddr))
|
||||
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr)
|
||||
#define netbuf_destaddr(buf) (&((buf)->toaddr.ip4))
|
||||
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->toaddr.ip4), destaddr)
|
||||
#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
@ -94,6 +107,13 @@ void netbuf_first (struct netbuf *buf);
|
||||
(buf)->toport_chksum = chksum; } while(0)
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define netbuf_fromaddr_ip6(buf) (&((buf)->addr.ip6))
|
||||
#define netbuf_set_fromaddr_ip6(buf, fromaddr) ip6_addr_set((&(buf)->addr.ip6), fromaddr)
|
||||
#define netbuf_destaddr_ip6(buf) (&((buf)->toaddr.ip6))
|
||||
#define netbuf_set_destaddr_ip6(buf, destaddr) ip6_addr_set((&(buf)->toaddr.ip6), destaddr)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
@ -48,6 +49,9 @@ struct dhcp;
|
||||
#if LWIP_AUTOIP
|
||||
struct autoip;
|
||||
#endif
|
||||
#if LWIP_IPV6_DHCP6
|
||||
#include "lwip/dhcp6.h"
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -117,6 +121,18 @@ typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
|
||||
*/
|
||||
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
|
||||
ip_addr_t *ipaddr);
|
||||
#if LWIP_IPV6
|
||||
/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet
|
||||
* shall be sent. For ethernet netif, set this to 'nd_output' and set
|
||||
* 'linkoutput'.
|
||||
*
|
||||
* @param netif The netif which shall send a packet
|
||||
* @param p The packet to send (p->payload points to IP header)
|
||||
* @param ipaddr The IPv6 address to which the packet shall be sent
|
||||
*/
|
||||
typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p,
|
||||
ip6_addr_t *ipaddr);
|
||||
#endif /* LWIP_IPV6 */
|
||||
/** Function prototype for netif->linkoutput functions. Only used for ethernet
|
||||
* netifs. This function is called by ARP when a packet shall be sent.
|
||||
*
|
||||
@ -129,6 +145,11 @@ typedef void (*netif_status_callback_fn)(struct netif *netif);
|
||||
/** Function prototype for netif igmp_mac_filter functions */
|
||||
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
|
||||
ip_addr_t *group, u8_t action);
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
/** Function prototype for netif mld_mac_filter functions */
|
||||
typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif,
|
||||
ip6_addr_t *group, u8_t action);
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
/** Generic data structure used for all lwIP network interfaces.
|
||||
* The following fields should be filled in by the initialization
|
||||
@ -142,6 +163,13 @@ struct netif {
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gw;
|
||||
|
||||
#if LWIP_IPV6
|
||||
/** Array of IPv6 addresses for this netif. */
|
||||
ip6_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
|
||||
/** The state of each IPv6 address (Tentative, Preferred, etc).
|
||||
* @see ip6_addr.h */
|
||||
u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
|
||||
#endif /* LWIP_IPV6 */
|
||||
/** This function is called by the network device driver
|
||||
* to pass a packet up the TCP/IP stack. */
|
||||
netif_input_fn input;
|
||||
@ -153,6 +181,12 @@ struct netif {
|
||||
* to send a packet on the interface. This function outputs
|
||||
* the pbuf as-is on the link medium. */
|
||||
netif_linkoutput_fn linkoutput;
|
||||
#if LWIP_IPV6
|
||||
/** This function is called by the IPv6 module when it wants
|
||||
* to send a packet on the interface. This function typically
|
||||
* first resolves the hardware address, then sends the packet. */
|
||||
netif_output_ip6_fn output_ip6;
|
||||
#endif /* LWIP_IPV6 */
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
/** This function is called when the netif state is set to up or down
|
||||
*/
|
||||
@ -174,6 +208,18 @@ struct netif {
|
||||
/** the AutoIP client state information for this netif */
|
||||
struct autoip *autoip;
|
||||
#endif
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
/** is this netif enabled for IPv6 autoconfiguration */
|
||||
u8_t ip6_autoconfig_enabled;
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
/** Number of Router Solicitation messages that remain to be sent. */
|
||||
u8_t rs_count;
|
||||
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
|
||||
#if LWIP_IPV6_DHCP6
|
||||
/** the DHCPv6 client state information for this netif */
|
||||
struct dhcp6 *dhcp6;
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* the hostname for this netif, NULL is a valid value */
|
||||
char* hostname;
|
||||
@ -208,10 +254,15 @@ struct netif {
|
||||
u32_t ifoutdiscards;
|
||||
#endif /* LWIP_SNMP */
|
||||
#if LWIP_IGMP
|
||||
/** This function could be called to add or delete a entry in the multicast
|
||||
/** This function could be called to add or delete an entry in the multicast
|
||||
filter table of the ethernet MAC.*/
|
||||
netif_igmp_mac_filter_fn igmp_mac_filter;
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
||||
/** This function could be called to add or delete an entry in the IPv6 multicast
|
||||
filter table of the ethernet MAC. */
|
||||
netif_mld_mac_filter_fn mld_mac_filter;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
u8_t *addr_hint;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
@ -308,6 +359,15 @@ void netif_poll_all(void);
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define netif_ip6_addr(netif, i) (&(netif->ip6_addr[(i)]))
|
||||
#define netif_ip6_addr_state(netif, i) (netif->ip6_addr_state[(i)])
|
||||
#define netif_ip6_addr_set_state(netif, i, state) (netif->ip6_addr_state[(i)] = (state))
|
||||
s8_t netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr);
|
||||
void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1544,6 +1544,41 @@
|
||||
#define SYS_STATS (NO_SYS == 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP6_STATS==1: Enable IPv6 stats.
|
||||
*/
|
||||
#ifndef IP6_STATS
|
||||
#define IP6_STATS (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ICMP6_STATS==1: Enable ICMP for IPv6 stats.
|
||||
*/
|
||||
#ifndef ICMP6_STATS
|
||||
#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats.
|
||||
*/
|
||||
#ifndef IP6_FRAG_STATS
|
||||
#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MLD6_STATS==1: Enable MLD for IPv6 stats.
|
||||
*/
|
||||
#ifndef MLD6_STATS
|
||||
#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ND6_STATS==1: Enable Neighbor discovery for IPv6 stats.
|
||||
*/
|
||||
#ifndef ND6_STATS
|
||||
#define ND6_STATS (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define LINK_STATS 0
|
||||
@ -1557,6 +1592,11 @@
|
||||
#define MEMP_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
#define IP6_STATS 0
|
||||
#define ICMP6_STATS 0
|
||||
#define IP6_FRAG_STATS 0
|
||||
#define MLD6_STATS 0
|
||||
#define ND6_STATS 0
|
||||
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
@ -1779,6 +1819,231 @@
|
||||
#define LWIP_CHECKSUM_ON_COPY 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- IPv6 options ---------------
|
||||
---------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_IPV6==1: Enable IPv6
|
||||
*/
|
||||
#ifndef LWIP_IPV6
|
||||
#define LWIP_IPV6 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_NUM_ADDRESSES
|
||||
#define LWIP_IPV6_NUM_ADDRESSES 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs
|
||||
*/
|
||||
#ifndef LWIP_IPV6_FORWARD
|
||||
#define LWIP_IPV6_FORWARD 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC)
|
||||
*/
|
||||
#ifndef LWIP_ICMP6
|
||||
#define LWIP_ICMP6 (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
|
||||
* ICMPv6 error messages.
|
||||
*/
|
||||
#ifndef LWIP_ICMP6_DATASIZE
|
||||
#define LWIP_ICMP6_DATASIZE 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ICMP6_HL: default hop limit for ICMPv6 messages
|
||||
*/
|
||||
#ifndef LWIP_ICMP6_HL
|
||||
#define LWIP_ICMP6_HL 255
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ICMP6_CHECKSUM_CHECK==1: verify checksum on ICMPv6 packets
|
||||
*/
|
||||
#ifndef LWIP_ICMP6_CHECKSUM_CHECK
|
||||
#define LWIP_ICMP6_CHECKSUM_CHECK 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_MLD
|
||||
#define LWIP_IPV6_MLD (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined.
|
||||
*/
|
||||
#ifndef MEMP_NUM_MLD6_GROUP
|
||||
#define MEMP_NUM_MLD6_GROUP 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_FRAG
|
||||
#define LWIP_IPV6_FRAG 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
|
||||
*/
|
||||
#ifndef LWIP_IPV6_REASS
|
||||
#define LWIP_IPV6_REASS (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address
|
||||
* is being resolved.
|
||||
*/
|
||||
#ifndef LWIP_ND6_QUEUEING
|
||||
#define LWIP_ND6_QUEUEING (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution.
|
||||
*/
|
||||
#ifndef MEMP_NUM_ND6_QUEUE
|
||||
#define MEMP_NUM_ND6_QUEUE 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache
|
||||
*/
|
||||
#ifndef LWIP_ND6_NUM_NEIGHBORS
|
||||
#define LWIP_ND6_NUM_NEIGHBORS 10
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache
|
||||
*/
|
||||
#ifndef LWIP_ND6_NUM_DESTINATIONS
|
||||
#define LWIP_ND6_NUM_DESTINATIONS 10
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache
|
||||
*/
|
||||
#ifndef LWIP_ND6_NUM_PREFIXES
|
||||
#define LWIP_ND6_NUM_PREFIXES 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache
|
||||
*/
|
||||
#ifndef LWIP_ND6_NUM_ROUTERS
|
||||
#define LWIP_ND6_NUM_ROUTERS 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send
|
||||
* (neighbor solicit and router solicit)
|
||||
*/
|
||||
#ifndef LWIP_ND6_MAX_MULTICAST_SOLICIT
|
||||
#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages
|
||||
* to send during neighbor reachability detection.
|
||||
*/
|
||||
#ifndef LWIP_ND6_MAX_UNICAST_SOLICIT
|
||||
#define LWIP_ND6_MAX_UNICAST_SOLICIT 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Unused: See ND RFC (time in milliseconds).
|
||||
*/
|
||||
#ifndef LWIP_ND6_MAX_ANYCAST_DELAY_TIME
|
||||
#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Unused: See ND RFC
|
||||
*/
|
||||
#ifndef LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT
|
||||
#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds).
|
||||
* May be updated by router advertisement messages.
|
||||
*/
|
||||
#ifndef LWIP_ND6_REACHABLE_TIME
|
||||
#define LWIP_ND6_REACHABLE_TIME 30000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages
|
||||
*/
|
||||
#ifndef LWIP_ND6_RETRANS_TIMER
|
||||
#define LWIP_ND6_RETRANS_TIMER 1000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation
|
||||
* message is sent, during neighbor reachability detection.
|
||||
*/
|
||||
#ifndef LWIP_ND6_DELAY_FIRST_PROBE_TIME
|
||||
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update
|
||||
* Reachable time and retransmission timers, and netif MTU.
|
||||
*/
|
||||
#ifndef LWIP_ND6_ALLOW_RA_UPDATES
|
||||
#define LWIP_ND6_ALLOW_RA_UPDATES 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during
|
||||
* network startup.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_SEND_ROUTER_SOLICIT
|
||||
#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery
|
||||
* with reachability hints for connected destinations. This helps avoid sending
|
||||
* unicast neighbor solicitation messages.
|
||||
*/
|
||||
#ifndef LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
#define LWIP_ND6_TCP_REACHABILITY_HINTS 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_AUTOCONFIG
|
||||
#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_DUP_DETECT_ATTEMPTS
|
||||
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_DHCP6
|
||||
#define LWIP_IPV6_DHCP6 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- Debugging options ----------
|
||||
@ -2040,4 +2305,11 @@
|
||||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP6_DEBUG: Enable debugging for IPv6.
|
||||
*/
|
||||
#ifndef IP6_DEBUG
|
||||
#define IP6_DEBUG LWIP_DBG_ON
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_OPT_H__ */
|
||||
|
@ -45,7 +45,11 @@ extern "C" {
|
||||
#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
|
||||
|
||||
#define PBUF_TRANSPORT_HLEN 20
|
||||
#if LWIP_IPV6
|
||||
#define PBUF_IP_HLEN 40
|
||||
#else
|
||||
#define PBUF_IP_HLEN 20
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
PBUF_TRANSPORT,
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -60,6 +61,27 @@ struct raw_pcb;
|
||||
typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *addr);
|
||||
|
||||
#if LWIP_IPV6
|
||||
/** Function prototype for raw pcb IPv6 receive callback functions.
|
||||
* @param arg user supplied argument (raw_pcb.recv_arg)
|
||||
* @param pcb the raw_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IPv6 address from which the packet was received
|
||||
* @return 1 if the packet was 'eaten' (aka. deleted),
|
||||
* 0 if the packet lives on
|
||||
* If returning 1, the callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*/
|
||||
typedef u8_t (*raw_recv_ip6_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
ip6_addr_t *addr);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define RAW_PCB_RECV_IP6 raw_recv_ip6_fn ip6;
|
||||
#else
|
||||
#define RAW_PCB_RECV_IP6
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
struct raw_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
@ -69,7 +91,10 @@ struct raw_pcb {
|
||||
u8_t protocol;
|
||||
|
||||
/** receive callback function */
|
||||
raw_recv_fn recv;
|
||||
union {
|
||||
raw_recv_fn ip4;
|
||||
RAW_PCB_RECV_IP6
|
||||
} recv;
|
||||
/* user-supplied argument for the recv callback */
|
||||
void *recv_arg;
|
||||
};
|
||||
@ -85,6 +110,14 @@ void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *re
|
||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr);
|
||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||
|
||||
#if LWIP_IPV6
|
||||
struct raw_pcb * raw_new_ip6 (u8_t proto);
|
||||
#define raw_bind_ip6(pcb, ip6addr) raw_bind(pcb, (ip_addr_t *)ip6addr)
|
||||
#define raw_connect_ip6(pcb, ip6addr) raw_connect(pcb, (ip_addr_t *)ip6addr)
|
||||
#define raw_recv_ip6(pcb, recv_ip6_fn, recv_arg) raw_recv(pcb, (raw_recv_fn)recv_ip6_fn, recv_arg)
|
||||
#define raw_sendto_ip6(pcb, pbuf, ip6addr) raw_sendto(pcb, pbuf, (ip_addr_t *)ip6addr)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/* The following functions are the lower layer interface to RAW. */
|
||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||
#define raw_init() /* Compatibility define, not init needed. */
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet6.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -56,10 +57,24 @@ struct sockaddr_in {
|
||||
char sin_zero[8];
|
||||
};
|
||||
|
||||
#if LWIP_IPV6
|
||||
struct sockaddr_in6 {
|
||||
u8_t sin6_len; /* length of this structure */
|
||||
u8_t sin6_family; /* AF_INET6 */
|
||||
u16_t sin6_port; /* Transport layer port # */
|
||||
u32_t sin6_flowinfo; /* IPv6 flow information */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
};
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
struct sockaddr {
|
||||
u8_t sa_len;
|
||||
u8_t sa_family;
|
||||
char sa_data[14];
|
||||
#if LWIP_IPV6
|
||||
u8_t sa_data[22];
|
||||
#else /* LWIP_IPV6 */
|
||||
u8_t sa_data[14];
|
||||
#endif /* LWIP_IPV6 */
|
||||
};
|
||||
|
||||
#ifndef socklen_t
|
||||
@ -118,7 +133,13 @@ struct linger {
|
||||
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_INET 2
|
||||
#if LWIP_IPV6
|
||||
#define AF_INET6 10
|
||||
#else /* LWIP_IPV6 */
|
||||
#define AF_INET6 AF_UNSPEC
|
||||
#endif /* LWIP_IPV6 */
|
||||
#define PF_INET AF_INET
|
||||
#define PF_INET6 AF_INET6
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
|
||||
#define IPPROTO_IP 0
|
||||
|
@ -144,6 +144,21 @@ struct stats_ {
|
||||
#if SYS_STATS
|
||||
struct stats_sys sys;
|
||||
#endif
|
||||
#if IP6_STATS
|
||||
struct stats_proto ip6;
|
||||
#endif
|
||||
#if ICMP6_STATS
|
||||
struct stats_proto icmp6;
|
||||
#endif
|
||||
#if IP6_FRAG_STATS
|
||||
struct stats_proto ip6_frag;
|
||||
#endif
|
||||
#if MLD6_STATS
|
||||
struct stats_igmp mld6;
|
||||
#endif
|
||||
#if ND6_STATS
|
||||
struct stats_proto nd6;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct stats_ lwip_stats;
|
||||
@ -268,6 +283,46 @@ void stats_init(void);
|
||||
#define SYS_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if IP6_STATS
|
||||
#define IP6_STATS_INC(x) STATS_INC(x)
|
||||
#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6")
|
||||
#else
|
||||
#define IP6_STATS_INC(x)
|
||||
#define IP6_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if ICMP6_STATS
|
||||
#define ICMP6_STATS_INC(x) STATS_INC(x)
|
||||
#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6")
|
||||
#else
|
||||
#define ICMP6_STATS_INC(x)
|
||||
#define ICMP6_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if IP6_FRAG_STATS
|
||||
#define IP6_FRAG_STATS_INC(x) STATS_INC(x)
|
||||
#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG")
|
||||
#else
|
||||
#define IP6_FRAG_STATS_INC(x)
|
||||
#define IP6_FRAG_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if MLD6_STATS
|
||||
#define MLD6_STATS_INC(x) STATS_INC(x)
|
||||
#define MLD6_STATS_DISPLAY() stats_display_proto(&lwip_stats.mld6, "MLDv1")
|
||||
#else
|
||||
#define MLD6_STATS_INC(x)
|
||||
#define MLD6_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if ND6_STATS
|
||||
#define ND6_STATS_INC(x) STATS_INC(x)
|
||||
#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND")
|
||||
#else
|
||||
#define ND6_STATS_INC(x)
|
||||
#define ND6_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -367,6 +369,14 @@ err_t tcp_output (struct tcp_pcb *pcb);
|
||||
|
||||
const char* tcp_debug_state_str(enum tcp_state s);
|
||||
|
||||
#if LWIP_IPV6
|
||||
struct tcp_pcb * tcp_new_ip6 (void);
|
||||
#define tcp_bind_ip6(pcb, ip6addr, port) \
|
||||
tcp_bind(pcb, (ip_addr_t *)ip6addr, port)
|
||||
#define tcp_connect_ip6(pcb, ip6addr, port, connected) \
|
||||
udp_connect(pcb, (ip_addr_t *)ip6addr, port, connected)
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -429,6 +431,11 @@ void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
||||
ip_addr_t *local_ip, ip_addr_t *remote_ip,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
#if LWIP_IPV6
|
||||
void tcp_rst_ip6(u32_t seqno, u32_t ackno,
|
||||
ip6_addr_t *local_ip6, ip6_addr_t *remote_ip6,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
u32_t tcp_next_iss(void);
|
||||
|
||||
@ -437,6 +444,9 @@ void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr);
|
||||
#if LWIP_IPV6
|
||||
u16_t tcp_eff_send_mss_ip6(u16_t sendmss, ip6_addr_t *src, ip6_addr_t *dest);
|
||||
#endif /* LWIP_IPV6 */
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -87,6 +88,26 @@ struct udp_pcb;
|
||||
typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *addr, u16_t port);
|
||||
|
||||
#if LWIP_IPV6
|
||||
/** Function prototype for udp pcb IPv6 receive callback functions
|
||||
* The callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*
|
||||
* @param arg user supplied argument (udp_pcb.recv_arg)
|
||||
* @param pcb the udp_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IPv6 address from which the packet was received
|
||||
* @param port the remote port from which the packet was received
|
||||
*/
|
||||
typedef void (*udp_recv_ip6_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip6_addr_t *addr, u16_t port);
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define UDP_PCB_RECV_IP6 udp_recv_ip6_fn ip6;
|
||||
#else
|
||||
#define UDP_PCB_RECV_IP6
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
struct udp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
@ -111,7 +132,10 @@ struct udp_pcb {
|
||||
#endif /* LWIP_UDPLITE */
|
||||
|
||||
/** receive callback function */
|
||||
udp_recv_fn recv;
|
||||
union {
|
||||
udp_recv_fn ip4;
|
||||
UDP_PCB_RECV_IP6
|
||||
}recv;
|
||||
/** user-supplied argument for the recv callback */
|
||||
void *recv_arg;
|
||||
};
|
||||
@ -156,6 +180,26 @@ void udp_input (struct pbuf *p, struct netif *inp);
|
||||
|
||||
#define udp_init() /* Compatibility define, not init needed. */
|
||||
|
||||
#if LWIP_IPV6
|
||||
struct udp_pcb * udp_new_ip6(void);
|
||||
#define udp_bind_ip6(pcb, ip6addr, port) \
|
||||
udp_bind(pcb, (ip_addr_t *)ip6addr, port)
|
||||
#define udp_connect_ip6(pcb, ip6addr, port) \
|
||||
udp_connect(pcb, (ip_addr_t *)ip6addr, port)
|
||||
#define udp_recv_ip6(pcb, recv_ip6_fn, recv_arg) \
|
||||
udp_recv(pcb, (udp_recv_fn)recv_ip6_fn, recv_arg)
|
||||
#define udp_sendto_ip6(pcb, pbuf, ip6addr, port) \
|
||||
udp_sendto(pcb, pbuf, (ip_addr_t *)ip6addr, port)
|
||||
#define udp_sendto_if_ip6(pcb, pbuf, ip6addr, port, netif) \
|
||||
udp_sendto_if(pcb, pbuf, (ip_addr_t *)ip6addr, port, netif)
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
#define udp_sendto_chksum_ip6(pcb, pbuf, ip6addr, port, have_chk, chksum) \
|
||||
udp_sendto_chksum(pcb, pbuf, (ip_addr_t *)ip6addr, port, have_chk, chksum)
|
||||
#define udp_sendto_if_chksum_ip6(pcb, pbuf, ip6addr, port, netif, have_chk, chksum) \
|
||||
udp_sendto_if_chksum(pcb, pbuf, (ip_addr_t *)ip6addr, port, netif, have_chk, chksum)
|
||||
#endif /*LWIP_CHECKSUM_ON_COPY */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if UDP_DEBUG
|
||||
void udp_debug_print(struct udp_hdr *udphdr);
|
||||
#else
|
||||
|
@ -137,6 +137,7 @@ PACK_STRUCT_END
|
||||
#define ETHTYPE_ARP 0x0806U
|
||||
#define ETHTYPE_IP 0x0800U
|
||||
#define ETHTYPE_VLAN 0x8100U
|
||||
#define ETHTYPE_IPV6 0x86DDU
|
||||
#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
|
||||
#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ip6.h"
|
||||
|
||||
#if PPPOE_SUPPORT
|
||||
#include "netif/ppp_oe.h"
|
||||
@ -1301,6 +1302,19 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
||||
break;
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
|
||||
#if LWIP_IPV6
|
||||
case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */
|
||||
/* skip Ethernet header */
|
||||
if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
|
||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||
goto free_and_return;
|
||||
} else {
|
||||
/* pass to IPv6 layer */
|
||||
ip6_input(p, netif);
|
||||
}
|
||||
break;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
default:
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
|
@ -51,8 +51,9 @@
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/snmp.h>
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "netif/ppp_oe.h"
|
||||
|
||||
@ -239,6 +240,7 @@ ethernetif_input(struct netif *netif)
|
||||
switch (htons(ethhdr->type)) {
|
||||
/* IP or ARP packet? */
|
||||
case ETHTYPE_IP:
|
||||
case ETHTYPE_IPV6:
|
||||
case ETHTYPE_ARP:
|
||||
#if PPPOE_SUPPORT
|
||||
/* PPPoE packet? */
|
||||
@ -305,6 +307,9 @@ ethernetif_init(struct netif *netif)
|
||||
* from it if you have to do some checks before sending (e.g. if link
|
||||
* is available...) */
|
||||
netif->output = etharp_output;
|
||||
#if LWIP_IPV6
|
||||
netif->output_ip6 = ethip6_output;
|
||||
#endif /* LWIP_IPV6 */
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user