summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_pcb.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-02-22 21:32:23 +0000
committerpeter <peter@FreeBSD.org>1996-02-22 21:32:23 +0000
commitfe35eac01c2144b50535ae23a00660c11524fd22 (patch)
tree00ca04534534b22254d22056ecd77387d0c0ec90 /sys/netinet/in_pcb.c
parentf7cfae926eb054cccf8e9a58065b4e8a2874d530 (diff)
downloadFreeBSD-src-fe35eac01c2144b50535ae23a00660c11524fd22.zip
FreeBSD-src-fe35eac01c2144b50535ae23a00660c11524fd22.tar.gz
Make the default behavior of local port assignment match traditional
systems (my last change did not mix well with some firewall configurations). As much as I dislike firewalls, this is one thing I I was not prepared to break by default.. :-) Allow the user to nominate one of three ranges of port numbers as candidates for selecting a local address to replace a zero port number. The ranges are selected via a setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &arg) call. The three ranges are: default, high (to bypass firewalls) and low (to get a port below 1024). The default and high port ranges are sysctl settable under sysctl net.inet.ip.portrange.* This code also fixes a potential deadlock if the system accidently ran out of local port addresses. It'd drop into an infinite while loop. The secure port selection (for root) should reduce overheads and increase reliability of rlogin/rlogind/rsh/rshd if they are modified to take advantage of it. Partly suggested by: pst Reviewed by: wollman
Diffstat (limited to 'sys/netinet/in_pcb.c')
-rw-r--r--sys/netinet/in_pcb.c82
1 files changed, 68 insertions, 14 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 6fa0d2f..85496a6 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
- * $Id: in_pcb.c,v 1.15 1995/11/14 20:33:59 phk Exp $
+ * $Id: in_pcb.c,v 1.16 1996/01/19 08:00:58 peter Exp $
*/
#include <sys/param.h>
@@ -65,13 +65,21 @@ struct in_addr zeroin_addr;
* These configure the range of local port addresses assigned to
* "unspecified" outgoing connections/packets/whatever.
*/
-static int ipport_firstauto = IPPORT_FIRSTAUTO;
-static int ipport_lastauto = IPPORT_LASTAUTO;
+static int ipport_firstauto = IPPORT_RESERVED; /* 1024 */
+static int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */
+static int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 40000 */
+static int ipport_hilastauto = IPPORT_HILASTAUTO; /* 44999 */
-SYSCTL_INT(_net_inet_ip, OID_AUTO, port_first_auto, CTLFLAG_RW,
+SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports");
+
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, first, CTLFLAG_RW,
&ipport_firstauto, 0, "");
-SYSCTL_INT(_net_inet_ip, OID_AUTO, port_last_auto, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, last, CTLFLAG_RW,
&ipport_lastauto, 0, "");
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLFLAG_RW,
+ &ipport_hifirstauto, 0, "");
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, hilast, CTLFLAG_RW,
+ &ipport_hilastauto, 0, "");
static void in_pcbinshash __P((struct inpcb *));
static void in_rtchange __P((struct inpcb *, int));
@@ -162,15 +170,61 @@ in_pcbbind(inp, nam)
}
inp->inp_laddr = sin->sin_addr;
}
- if (lport == 0)
- do {
- ++*lastport;
- if (*lastport < ipport_firstauto ||
- *lastport > ipport_lastauto)
- *lastport = ipport_firstauto;
- lport = htons(*lastport);
- } while (in_pcblookup(head,
- zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ if (lport == 0) {
+ ushort first, last;
+ int count;
+
+ if (inp->inp_flags & INP_HIGHPORT) {
+ first = ipport_hifirstauto; /* sysctl */
+ last = ipport_hilastauto;
+ } else if (inp->inp_flags & INP_LOWPORT) {
+ if (error = suser(p->p_ucred, &p->p_acflag))
+ return (EACCES);
+ first = IPPORT_RESERVED - 1; /* 1023 */
+ last = 1;
+ } else {
+ first = ipport_firstauto; /* sysctl */
+ last = ipport_lastauto;
+ }
+ /*
+ * Simple check to ensure all ports are not used up causing
+ * a deadlock here.
+ *
+ * We split the two cases (up and down) so that the direction
+ * is not being tested on each round of the loop.
+ */
+ if (first > last) {
+ /*
+ * counting down
+ */
+ count = first - last;
+
+ do {
+ if (count-- <= 0) /* completely used? */
+ return (EADDRNOTAVAIL);
+ --*lastport;
+ if (*lastport > first || *lastport < last)
+ *lastport = first;
+ lport = htons(*lastport);
+ } while (in_pcblookup(head,
+ zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ } else {
+ /*
+ * counting up
+ */
+ count = last - first;
+
+ do {
+ if (count-- <= 0) /* completely used? */
+ return (EADDRNOTAVAIL);
+ ++*lastport;
+ if (*lastport < first || *lastport > last)
+ *lastport = first;
+ lport = htons(*lastport);
+ } while (in_pcblookup(head,
+ zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ }
+ }
inp->inp_lport = lport;
in_pcbrehash(inp);
return (0);
OpenPOWER on IntegriCloud