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:
Simon Goldschmidt 2014-04-06 20:32:37 +02:00
parent 40d25adb88
commit be75c483d0
9 changed files with 148 additions and 69 deletions

View File

@ -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

View File

@ -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"));

View File

@ -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);

View File

@ -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);

View File

@ -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? */

View File

@ -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)

View File

@ -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);

View File

@ -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) \

View File

@ -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)