mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-02-04 21:39:49 +00:00
Fixed bug #41787 DHCP Discovery is invalid when an IP is set to thet netif (send discover, request and decline from 'any').
Addd functions to send udp/ipv4/ipv6 packets with source address 'any' although netif has an address assigned
This commit is contained in:
parent
40d25adb88
commit
be75c483d0
@ -100,6 +100,10 @@ HISTORY
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2014-04-06: Simon Goldschmidt
|
||||
* dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery
|
||||
is invalid when an IP is set to thet netif.
|
||||
|
||||
2014-03-14: Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1
|
||||
|
||||
|
@ -317,7 +317,7 @@ dhcp_select(struct netif *netif)
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* send broadcast to any DHCP server */
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
|
||||
} else {
|
||||
@ -845,7 +845,7 @@ dhcp_decline(struct netif *netif)
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* per section 4.4.4, broadcast DECLINE messages */
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||
} else {
|
||||
@ -895,7 +895,7 @@ dhcp_discover(struct netif *netif)
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
||||
|
@ -655,6 +655,43 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen)
|
||||
{
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
ip_addr_t *src_used = src;
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (ip_addr_isany(src)) {
|
||||
src_used = &netif->ip_addr;
|
||||
}
|
||||
}
|
||||
|
||||
#if IP_OPTIONS_SEND
|
||||
return ip_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif,
|
||||
ip_options, optlen);
|
||||
#else /* IP_OPTIONS_SEND */
|
||||
return ip_output_if_src(p, src_used, dest, ttl, tos, proto, netif);
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as ip_output_if() but 'src' address is not replaced by netif address
|
||||
* when it is 'any'.
|
||||
*/
|
||||
err_t
|
||||
ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
#if IP_OPTIONS_SEND
|
||||
return ip_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as ip_output_if_opt() but 'src' address is not replaced by netif address
|
||||
* when it is 'any'.
|
||||
*/
|
||||
err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen)
|
||||
{
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
struct ip_hdr *iphdr;
|
||||
ip_addr_t dest_addr;
|
||||
@ -741,8 +778,8 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
++ip_id;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_copy(iphdr->src, netif->ip_addr);
|
||||
if (src == NULL) {
|
||||
ip_addr_copy(iphdr->src, ip_addr_any);
|
||||
} else {
|
||||
/* src cannot be NULL here */
|
||||
ip_addr_copy(iphdr->src, *src);
|
||||
|
@ -744,6 +744,29 @@ err_t
|
||||
ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc,
|
||||
u8_t nexth, struct netif *netif)
|
||||
{
|
||||
ip6_addr_t *src_used = src;
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (src != NULL && ip6_addr_isany(src)) {
|
||||
src = ip6_select_source_address(netif, dest);
|
||||
if ((src == NULL) || ip6_addr_isany(src)) {
|
||||
/* No appropriate source address was found for this packet. */
|
||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
|
||||
IP6_STATS_INC(ip6.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as ip6_output_if() but 'src' address is not replaced by netif address
|
||||
* when it is 'any'.
|
||||
*/
|
||||
err_t
|
||||
ip6_output_if_src(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc,
|
||||
u8_t nexth, struct netif *netif)
|
||||
{
|
||||
struct ip6_hdr *ip6hdr;
|
||||
ip6_addr_t dest_addr;
|
||||
@ -777,15 +800,6 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
if (src == NULL) {
|
||||
src = IP6_ADDR_ANY;
|
||||
}
|
||||
else if (ip6_addr_isany(src)) {
|
||||
src = ip6_select_source_address(netif, dest);
|
||||
if ((src == NULL) || ip6_addr_isany(src)) {
|
||||
/* No appropriate source address was found for this packet. */
|
||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
|
||||
IP6_STATS_INC(ip6.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
/* src cannot be NULL here */
|
||||
ip6_addr_copy(ip6hdr->src, *src);
|
||||
|
||||
|
112
src/core/udp.c
112
src/core/udp.c
@ -626,8 +626,65 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t chksum)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */
|
||||
struct udp_hdr *udphdr;
|
||||
ip_addr_t *src_ip;
|
||||
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
#if LWIP_IPV6
|
||||
if (PCB_ISIPV6(pcb)) {
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip)));
|
||||
if (src_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
} else {
|
||||
/* use UDP PCB local IPv6 address as source address, if still valid. */
|
||||
if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) {
|
||||
/* Address isn't valid anymore. */
|
||||
return ERR_RTE;
|
||||
}
|
||||
src_ip = ipX_2_ip(&pcb->local_ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
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(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) {
|
||||
/* local_ip doesn't match, drop the packet */
|
||||
return ERR_VAL;
|
||||
}
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = ipX_2_ip(&(pcb->local_ip));
|
||||
}
|
||||
#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP
|
||||
return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip);
|
||||
#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */
|
||||
return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */
|
||||
}
|
||||
|
||||
/** Same as udp_sendto_if(), but with source address */
|
||||
err_t
|
||||
udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, ip_addr_t *src_ip)
|
||||
{
|
||||
#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP
|
||||
return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip);
|
||||
}
|
||||
|
||||
/** Same as udp_sendto_if_src(), but with checksum */
|
||||
err_t
|
||||
udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t dst_port, struct netif *netif, u8_t have_chksum,
|
||||
u16_t chksum, ip_addr_t *src_ip)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */
|
||||
struct udp_hdr *udphdr;
|
||||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
u8_t ip_proto;
|
||||
@ -704,57 +761,6 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
#if LWIP_IPV6
|
||||
if (PCB_ISIPV6(pcb)) {
|
||||
if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) {
|
||||
src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip)));
|
||||
if (src_ip == NULL) {
|
||||
/* No suitable source address was found. */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
} else {
|
||||
/* use UDP PCB local IPv6 address as source address, if still valid. */
|
||||
if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) {
|
||||
/* Address isn't valid anymore. */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
src_ip = ipX_2_ip(&pcb->local_ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
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(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) {
|
||||
/* local_ip doesn't match, drop the packet */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
q = NULL;
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = ipX_2_ip(&(pcb->local_ip));
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||
|
||||
#if LWIP_UDPLITE
|
||||
@ -840,7 +846,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto));
|
||||
/* output to IP */
|
||||
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
|
||||
err = ipX_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif);
|
||||
err = ipX_output_if_src(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif);
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
/* TODO: must this be increased even if error occured? */
|
||||
|
@ -117,8 +117,9 @@ err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto);
|
||||
err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif);
|
||||
err_t ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint);
|
||||
@ -127,6 +128,9 @@ err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen);
|
||||
err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen);
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
|
||||
#define ip_netif_get_local_ipX(netif) (((netif) != NULL) ? ip_2_ipX(&((netif)->ip_addr)) : NULL)
|
||||
|
@ -169,6 +169,8 @@ err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *
|
||||
u8_t hl, u8_t tc, u8_t nexth);
|
||||
err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
||||
err_t ip6_output_if_src(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint);
|
||||
|
@ -213,6 +213,10 @@ extern struct ip_globals ip_data;
|
||||
((isipv6) ? \
|
||||
ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \
|
||||
ip_output_if(p, (src), (dest), ttl, tos, proto, netif))
|
||||
#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \
|
||||
((isipv6) ? \
|
||||
ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \
|
||||
ip_output_if_src(p, (src), (dest), ttl, tos, proto, netif))
|
||||
#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \
|
||||
((isipv6) ? \
|
||||
ip6_output_hinted(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto, addr_hint) : \
|
||||
@ -231,6 +235,8 @@ extern struct ip_globals ip_data;
|
||||
ip_output(p, src, dest, ttl, tos, proto)
|
||||
#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \
|
||||
ip_output_if(p, src, dest, ttl, tos, proto, netif)
|
||||
#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \
|
||||
ip_output_if_src(p, src, dest, ttl, tos, proto, netif)
|
||||
#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \
|
||||
ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint)
|
||||
#define ipX_route(isipv6, src, dest) \
|
||||
|
@ -156,6 +156,9 @@ void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv,
|
||||
err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
struct netif *netif);
|
||||
err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
struct netif *netif, ip_addr_t *src_ip);
|
||||
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port);
|
||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||
@ -170,6 +173,9 @@ err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif,
|
||||
u8_t have_chksum, u16_t chksum, ip_addr_t *src_ip);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
|
Loading…
x
Reference in New Issue
Block a user