mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-28 14:54:05 +00:00
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);
fixed a possible endless loop in tcp_new_port() if the number of active PCBs exceeds the number of available ports;
This commit is contained in:
parent
5be300736e
commit
112158b056
@ -6,6 +6,11 @@ HISTORY
|
|||||||
|
|
||||||
++ New features:
|
++ 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
|
2011-09-03: Simon Goldschmidt
|
||||||
* dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302)
|
* dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302)
|
||||||
|
|
||||||
|
@ -58,6 +58,14 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#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[] = {
|
const char * const tcp_state_str[] = {
|
||||||
"CLOSED",
|
"CLOSED",
|
||||||
"LISTEN",
|
"LISTEN",
|
||||||
@ -72,6 +80,9 @@ const char * const tcp_state_str[] = {
|
|||||||
"TIME_WAIT"
|
"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). */
|
/* Incremented every coarse grained timer shot (typically every 500 ms). */
|
||||||
u32_t tcp_ticks;
|
u32_t tcp_ticks;
|
||||||
const u8_t tcp_backoff[13] =
|
const u8_t tcp_backoff[13] =
|
||||||
@ -104,9 +115,19 @@ struct tcp_pcb *tcp_tmp_pcb;
|
|||||||
static u8_t tcp_timer;
|
static u8_t tcp_timer;
|
||||||
static u16_t tcp_new_port(void);
|
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.
|
* Called periodically to dispatch TCP timers.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
tcp_tmr(void)
|
tcp_tmr(void)
|
||||||
@ -415,6 +436,9 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
port = tcp_new_port();
|
port = tcp_new_port();
|
||||||
|
if (port == 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the address already is in use (on all lists) */
|
/* Check if the address already is in use (on all lists) */
|
||||||
@ -628,37 +652,33 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A nastly hack featuring 'goto' statements that allocates a
|
* Allocate a new local TCP port.
|
||||||
* new TCP local port.
|
|
||||||
*
|
*
|
||||||
* @return a new (free) local TCP port number
|
* @return a new (free) local TCP port number
|
||||||
*/
|
*/
|
||||||
static u16_t
|
static u16_t
|
||||||
tcp_new_port(void)
|
tcp_new_port(void)
|
||||||
{
|
{
|
||||||
int i;
|
u8_t i;
|
||||||
|
u16_t n = 0;
|
||||||
struct tcp_pcb *pcb;
|
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:
|
again:
|
||||||
if (port++ == TCP_LOCAL_PORT_RANGE_END) {
|
if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) {
|
||||||
port = TCP_LOCAL_PORT_RANGE_START;
|
tcp_port = TCP_LOCAL_PORT_RANGE_START;
|
||||||
}
|
}
|
||||||
/* Check all PCB lists. */
|
/* Check all PCB lists. */
|
||||||
for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
|
for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
|
||||||
for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
|
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;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return port;
|
return tcp_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -709,6 +729,9 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
|
|||||||
old_local_port = pcb->local_port;
|
old_local_port = pcb->local_port;
|
||||||
if (pcb->local_port == 0) {
|
if (pcb->local_port == 0) {
|
||||||
pcb->local_port = tcp_new_port();
|
pcb->local_port = tcp_new_port();
|
||||||
|
if (pcb->local_port == 0) {
|
||||||
|
return ERR_BUF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if SO_REUSE
|
#if SO_REUSE
|
||||||
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
|
if ((pcb->so_options & SOF_REUSEADDR) != 0) {
|
||||||
|
@ -68,10 +68,77 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#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 */
|
/* The list of UDP PCBs */
|
||||||
/* exported in udp.h (was static) */
|
/* exported in udp.h (was static) */
|
||||||
struct udp_pcb *udp_pcbs;
|
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.
|
* Process an incoming UDP datagram.
|
||||||
*
|
*
|
||||||
@ -854,26 +921,8 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
|||||||
|
|
||||||
/* no port specified? */
|
/* no port specified? */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
port = udp_new_port();
|
||||||
/* From http://www.iana.org/assignments/port-numbers:
|
if (port == 0) {
|
||||||
"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 */
|
/* no more ports available in local range */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
|
||||||
return ERR_USE;
|
return ERR_USE;
|
||||||
|
@ -606,6 +606,15 @@
|
|||||||
#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
|
#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
|
||||||
#endif
|
#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 ----------
|
---------- ICMP options ----------
|
||||||
|
@ -52,7 +52,7 @@ extern "C" {
|
|||||||
/* Functions for interfacing with TCP: */
|
/* Functions for interfacing with TCP: */
|
||||||
|
|
||||||
/* Lower layer interface to 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
|
void tcp_tmr (void); /* Must be called every
|
||||||
TCP_TMR_INTERVAL
|
TCP_TMR_INTERVAL
|
||||||
ms. (Typically 250 ms). */
|
ms. (Typically 250 ms). */
|
||||||
|
@ -178,7 +178,7 @@ err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
/* The following functions are the lower layer interface to UDP. */
|
/* The following functions are the lower layer interface to UDP. */
|
||||||
void udp_input (struct pbuf *p, struct netif *inp);
|
void udp_input (struct pbuf *p, struct netif *inp);
|
||||||
|
|
||||||
#define udp_init() /* Compatibility define, not init needed. */
|
void udp_init (void);
|
||||||
|
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
struct udp_pcb * udp_new_ip6(void);
|
struct udp_pcb * udp_new_ip6(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user