Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3826f1e authored by Amerigo Wang's avatar Amerigo Wang Committed by David S. Miller
Browse files

net: reserve ports for applications using fixed port numbers



(Dropped the infiniband part, because Tetsuo modified the related code,
I will send a separate patch for it once this is accepted.)

This patch introduces /proc/sys/net/ipv4/ip_local_reserved_ports which
allows users to reserve ports for third-party applications.

The reserved ports will not be used by automatic port assignments
(e.g. when calling connect() or bind() with port number 0). Explicit
port allocation behavior is unchanged.

Signed-off-by: default avatarOctavian Purdila <opurdila@ixiacom.com>
Signed-off-by: default avatarWANG Cong <amwang@redhat.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9f977fb7
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -588,6 +588,37 @@ ip_local_port_range - 2 INTEGERS
	(i.e. by default) range 1024-4999 is enough to issue up to
	2000 connections per second to systems supporting timestamps.

ip_local_reserved_ports - list of comma separated ranges
	Specify the ports which are reserved for known third-party
	applications. These ports will not be used by automatic port
	assignments (e.g. when calling connect() or bind() with port
	number 0). Explicit port allocation behavior is unchanged.

	The format used for both input and output is a comma separated
	list of ranges (e.g. "1,2-4,10-10" for ports 1, 2, 3, 4 and
	10). Writing to the file will clear all previously reserved
	ports and update the current list with the one given in the
	input.

	Note that ip_local_port_range and ip_local_reserved_ports
	settings are independent and both are considered by the kernel
	when determining which ports are available for automatic port
	assignments.

	You can reserve ports which are not in the current
	ip_local_port_range, e.g.:

	$ cat /proc/sys/net/ipv4/ip_local_port_range
	32000	61000
	$ cat /proc/sys/net/ipv4/ip_local_reserved_ports
	8080,9148

	although this is redundant. However such a setting is useful
	if later the port range is changed to a value that will
	include the reserved ports.

	Default: Empty

ip_nonlocal_bind - BOOLEAN
	If set, allows processes to bind() to non-local IP addresses,
	which can be quite useful - but may break some applications.
+6 −0
Original line number Diff line number Diff line
@@ -184,6 +184,12 @@ extern struct local_ports {
} sysctl_local_ports;
extern void inet_get_local_port_range(int *low, int *high);

extern unsigned long *sysctl_local_reserved_ports;
static inline int inet_is_reserved_local_port(int port)
{
	return test_bit(port, sysctl_local_reserved_ports);
}

extern int sysctl_ip_default_ttl;
extern int sysctl_ip_nonlocal_bind;

+7 −1
Original line number Diff line number Diff line
@@ -1573,9 +1573,13 @@ static int __init inet_init(void)

	BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));

	sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
	if (!sysctl_local_reserved_ports)
		goto out;

	rc = proto_register(&tcp_prot, 1);
	if (rc)
		goto out;
		goto out_free_reserved_ports;

	rc = proto_register(&udp_prot, 1);
	if (rc)
@@ -1674,6 +1678,8 @@ out_unregister_udp_proto:
	proto_unregister(&udp_prot);
out_unregister_tcp_proto:
	proto_unregister(&tcp_prot);
out_free_reserved_ports:
	kfree(sysctl_local_reserved_ports);
	goto out;
}

+6 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ struct local_ports sysctl_local_ports __read_mostly = {
	.range = { 32768, 61000 },
};

unsigned long *sysctl_local_reserved_ports;
EXPORT_SYMBOL(sysctl_local_reserved_ports);

void inet_get_local_port_range(int *low, int *high)
{
	unsigned seq;
@@ -108,6 +111,8 @@ again:

		smallest_size = -1;
		do {
			if (inet_is_reserved_local_port(rover))
				goto next_nolock;
			head = &hashinfo->bhash[inet_bhashfn(net, rover,
					hashinfo->bhash_size)];
			spin_lock(&head->lock);
@@ -130,6 +135,7 @@ again:
			break;
		next:
			spin_unlock(&head->lock);
		next_nolock:
			if (++rover > high)
				rover = low;
		} while (--remaining > 0);
+2 −0
Original line number Diff line number Diff line
@@ -456,6 +456,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
		local_bh_disable();
		for (i = 1; i <= remaining; i++) {
			port = low + (i + offset) % remaining;
			if (inet_is_reserved_local_port(port))
				continue;
			head = &hinfo->bhash[inet_bhashfn(net, port,
					hinfo->bhash_size)];
			spin_lock(&head->lock);
Loading