Michael Brown
2016-Jul-04 08:35 UTC
[syslinux] [PATCH] core/lwip: Avoid immediate reuse of UDP port numbers
The UDP binding logic will reuse local port numbers immediately. This causes problems for TFTP, which assumes a very low probability of a source port number being reused. The consequence is that lpxelinux.0 may end up downloading an incorrect file (e.g. attempting to download pxelinux.cfg/default but actually receiving a copy of ldlinux.c32, due to the port number having been reused). Fix by allocating local UDP port numbers in the same way as local TCP port numbers. Signed-off-by: Michael Brown <mcb30 at ipxe.org> --- core/lwip/src/core/udp.c | 57 ++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/core/lwip/src/core/udp.c b/core/lwip/src/core/udp.c index 4596ba2..68e7f48 100644 --- a/core/lwip/src/core/udp.c +++ b/core/lwip/src/core/udp.c @@ -679,6 +679,37 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, } /** + * A nastly hack featuring 'goto' statements that allocates a + * new UDP local port. Based on equivalent code in tcp_new_port() + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + struct udp_pcb *pcb; +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#endif + static u16_t port = UDP_LOCAL_PORT_RANGE_START; + + again: + if (port++ >= UDP_LOCAL_PORT_RANGE_END) { + port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check PCB list. */ + for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == port) { + goto again; + } + } + return port; +} + +/** * Bind an UDP PCB. * * @param pcb UDP PCB to be bound with a local address ipaddr and port. @@ -745,31 +776,9 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) /* no port specified? */ if (port == 0) { -#ifndef UDP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define UDP_LOCAL_PORT_RANGE_START 0xc000 -#define UDP_LOCAL_PORT_RANGE_END 0xffff -#endif - port = UDP_LOCAL_PORT_RANGE_START; - ipcb = udp_pcbs; - while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) { - if (ipcb->local_port == port) { - /* port is already used by another udp_pcb */ - port++; - /* restart scanning all udp pcbs */ - ipcb = udp_pcbs; - } else { - /* go on with next udp pcb */ - ipcb = ipcb->next; - } - } - if (ipcb != NULL) { - /* no more ports available in local range */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); - return ERR_USE; - } + port = udp_new_port(); } + pcb->local_port = port; snmp_insert_udpidx_tree(pcb); /* pcb not active yet? */ -- 2.3.8
Michael Brown
2016-Jul-04 10:34 UTC
[syslinux] [PATCH] core/lwip: Avoid immediate reuse of UDP port numbers
On 04/07/16 09:35, Michael Brown wrote:> The UDP binding logic will reuse local port numbers immediately. This > causes problems for TFTP, which assumes a very low probability of a > source port number being reused. The consequence is that lpxelinux.0 > may end up downloading an incorrect file (e.g. attempting to download > pxelinux.cfg/default but actually receiving a copy of ldlinux.c32, due > to the port number having been reused). > > Fix by allocating local UDP port numbers in the same way as local TCP > port numbers.An equivalent patch for this already exists in upstream lwIP. Michael
Gene Cumm
2016-Jul-05 10:43 UTC
[syslinux] [PATCH] core/lwip: Avoid immediate reuse of UDP port numbers
On Mon, Jul 4, 2016 at 6:34 AM, Michael Brown via Syslinux <syslinux at zytor.com> wrote:> On 04/07/16 09:35, Michael Brown wrote: >> >> The UDP binding logic will reuse local port numbers immediately. This >> causes problems for TFTP, which assumes a very low probability of a >> source port number being reused. The consequence is that lpxelinux.0 >> may end up downloading an incorrect file (e.g. attempting to download >> pxelinux.cfg/default but actually receiving a copy of ldlinux.c32, due >> to the port number having been reused). >> >> Fix by allocating local UDP port numbers in the same way as local TCP >> port numbers. > > > An equivalent patch for this already exists in upstream lwIP.I've marked both for review. Thanks. These seem very relevant to some of the reported issues. -- -Gene