fixed a possible endless loop in tcp_new_port() if the number of active PCBs exceeds the number of available ports;
++ New features:
+ 2011-09-11: Simon Goldschmidt
+ * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize
+ initial local TCP/UDP ports (so that different port ranges are used after
+ a reboot; bug #33818; this one added tcp_init/udp_init functions again)
+
2011-09-03: Simon Goldschmidt
* dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302)
#include <string.h>
+#ifndef TCP_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 TCP_LOCAL_PORT_RANGE_START 0xc000
+#define TCP_LOCAL_PORT_RANGE_END 0xffff
+#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)
+#endif
+
const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"TIME_WAIT"
};
+/* last local TCP port */
+static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START;
+
/* Incremented every coarse grained timer shot (typically every 500 ms). */
u32_t tcp_ticks;
const u8_t tcp_backoff[13] =
static u8_t tcp_timer;
static u16_t tcp_new_port(void);
+/**
+ * Initialize this module.
+ */
+void
+tcp_init(void)
+{
+#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND)
+ tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
+#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */
+}
+
/**
* Called periodically to dispatch TCP timers.
- *
*/
void
tcp_tmr(void)
if (port == 0) {
port = tcp_new_port();
+ if (port == 0) {
+ return ERR_BUF;
+ }
}
/* Check if the address already is in use (on all lists) */
}
/**
- * A nastly hack featuring 'goto' statements that allocates a
- * new TCP local port.
+ * Allocate a new local TCP port.
*
* @return a new (free) local TCP port number
*/
static u16_t
tcp_new_port(void)
{
- int i;
+ u8_t i;
+ u16_t n = 0;
struct tcp_pcb *pcb;
-#ifndef TCP_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 TCP_LOCAL_PORT_RANGE_START 0xc000
-#define TCP_LOCAL_PORT_RANGE_END 0xffff
-#endif
- static u16_t port = TCP_LOCAL_PORT_RANGE_START;
- again:
- if (port++ == TCP_LOCAL_PORT_RANGE_END) {
- port = TCP_LOCAL_PORT_RANGE_START;
+again:
+ if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) {
+ tcp_port = TCP_LOCAL_PORT_RANGE_START;
}
/* Check all PCB lists. */
for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
- if (pcb->local_port == port) {
+ if (pcb->local_port == tcp_port) {
+ if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) {
+ return 0;
+ }
goto again;
}
}
}
- return port;
+ return tcp_port;
}
/**
old_local_port = pcb->local_port;
if (pcb->local_port == 0) {
pcb->local_port = tcp_new_port();
+ if (pcb->local_port == 0) {
+ return ERR_BUF;
+ }
}
#if SO_REUSE
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
#include <string.h>
+#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
+#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)
+#endif
+
+/* last local UDP port */
+static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START;
+
/* The list of UDP PCBs */
/* exported in udp.h (was static) */
struct udp_pcb *udp_pcbs;
+/**
+ * Initialize this module.
+ */
+void
+udp_init(void)
+{
+#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND)
+ udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
+#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */
+}
+
+/**
+ * Allocate a new local UDP port.
+ *
+ * @return a new (free) local UDP port number
+ */
+static u16_t
+udp_new_port(void)
+{
+ u16_t n = 0;
+ struct udp_pcb *pcb;
+
+again:
+ if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) {
+ udp_port = UDP_LOCAL_PORT_RANGE_START;
+ }
+ /* Check all PCBs. */
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ if (pcb->local_port == udp_port) {
+ if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) {
+ return 0;
+ }
+ goto again;
+ }
+ }
+ return udp_port;
+#if 0
+ struct udp_pcb *ipcb = udp_pcbs;
+ while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
+ if (ipcb->local_port == udp_port) {
+ /* port is already used by another udp_pcb */
+ udp_port++;
+ /* restart scanning all udp pcbs */
+ ipcb = udp_pcbs;
+ } else {
+ /* go on with next udp pcb */
+ ipcb = ipcb->next;
+ }
+ }
+ if (ipcb != NULL) {
+ return 0;
+ }
+ return udp_port;
+#endif
+}
+
/**
* Process an incoming UDP datagram.
*
/* 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) {
+ port = udp_new_port();
+ if (port == 0) {
/* no more ports available in local range */
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
return ERR_USE;
#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
#endif
+/**
+ * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first
+ * local TCP/UDP pcb (default==0). This can prevent creating predictable port
+ * numbers after booting a device.
+ */
+#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS
+#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0
+#endif
+
/*
----------------------------------
---------- ICMP options ----------
/* Functions for interfacing with TCP: */
/* Lower layer interface to TCP: */
-#define tcp_init() /* Compatibility define, no init needed. */
+void tcp_init (void); /* Initialize this module. */
void tcp_tmr (void); /* Must be called every
TCP_TMR_INTERVAL
ms. (Typically 250 ms). */
/* The following functions are the lower layer interface to UDP. */
void udp_input (struct pbuf *p, struct netif *inp);
-#define udp_init() /* Compatibility define, not init needed. */
+void udp_init (void);
#if LWIP_IPV6
struct udp_pcb * udp_new_ip6(void);