first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address)

This commit is contained in:
goldsimon 2007-11-30 08:55:15 +00:00
parent b714cd5f4b
commit cedd5c21e6
2 changed files with 69 additions and 41 deletions

View File

@ -502,6 +502,12 @@ HISTORY
++ Bug fixes:
2007-11-30 Simon Goldschmidt
* udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple
netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed
to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same
port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address)
2007-11-27 Simon Goldschmidt
* ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by
letting ip_route only use netifs that are up.

View File

@ -61,6 +61,7 @@
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "arch/perf.h"
#include "lwip/dhcp.h"
#include <string.h>
@ -128,50 +129,71 @@ udp_input(struct pbuf *p, struct netif *inp)
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
local_match = 0;
uncon_pcb = NULL;
/* Iterate through the UDP pcb list for a matching pcb.
* 'Perfect match' pcbs (connected to the remote port & ip address) are
* preferred. If no perfect match is found, the first unconnected pcb that
* matches the local port and ip address gets the datagram. */
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(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
#if LWIP_IGMP
ip_addr_ismulticast(&(iphdr->dest)) ||
#endif /* LWIP_IGMP */
ip_addr_isbroadcast(&(iphdr->dest), inp))) {
local_match = 1;
if ((uncon_pcb == NULL) &&
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
/* the first unconnected matching PCB */
uncon_pcb = pcb;
#if LWIP_DHCP
pcb = NULL;
/* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by
the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */
if (dest == DHCP_CLIENT_PORT) {
/* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */
if (src == DHCP_SERVER_PORT) {
if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
/* 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), &(iphdr->src)))) {
pcb = inp->dhcp->pcb;
}
}
}
/* 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), &(iphdr->src)))) {
/* the first fully matching PCB */
break;
} else
#endif /* LWIP_DHCP */
{
local_match = 0;
uncon_pcb = NULL;
/* Iterate through the UDP pcb list for a matching pcb.
* 'Perfect match' pcbs (connected to the remote port & ip address) are
* preferred. If no perfect match is found, the first unconnected pcb that
* matches the local port and ip address gets the datagram. */
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(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
#if LWIP_IGMP
ip_addr_ismulticast(&(iphdr->dest)) ||
#endif /* LWIP_IGMP */
ip_addr_isbroadcast(&(iphdr->dest), inp))) {
local_match = 1;
if ((uncon_pcb == NULL) &&
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
/* the first unconnected matching PCB */
uncon_pcb = pcb;
}
}
/* 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), &(iphdr->src)))) {
/* the first fully matching PCB */
break;
}
}
/* no fully matching pcb found? then look for an unconnected pcb */
if (pcb == NULL) {
pcb = uncon_pcb;
}
}
/* no fully matching pcb found? then look for an unconnected pcb */
if (pcb == NULL) {
pcb = uncon_pcb;
}
/* Check checksum if this is a match or if it was directed at us. */