summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/in.h63
-rw-r--r--sys/netinet/in_pcb.c76
-rw-r--r--sys/netinet/in_pcb.h4
-rw-r--r--sys/netinet/ip_input.c20
-rw-r--r--sys/netinet/ip_output.c47
5 files changed, 196 insertions, 14 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 9bfe6041ec2..7e9c0fa0dc4 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.5 1996/03/03 22:30:29 niklas Exp $ */
+/* $OpenBSD: in.h,v 1.6 1996/07/29 02:34:29 downsj Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -66,7 +66,42 @@
/*
+ * From FreeBSD:
+ *
* Local port number conventions:
+ *
+ * When a user does a bind(2) or connect(2) with a port number of zero,
+ * a non-conflicting local port address is chosen.
+ * The default range is IPPORT_RESERVED through
+ * IPPORT_USERRESERVED, although that is settable by sysctl.
+ *
+ * A user may set the IPPROTO_IP option IP_PORTRANGE to change this
+ * default assignment range.
+ *
+ * The value IP_PORTRANGE_DEFAULT causes the default behavior.
+ *
+ * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers
+ * into the "high" range. These are reserved for client outbound connections
+ * which do not want to be filtered by any firewalls.
+ *
+ * The value IP_PORTRANGE_LOW changes the range to the "low" are
+ * that is (by convention) restricted to privileged processes. This
+ * convention is based on "vouchsafe" principles only. It is only secure
+ * if you trust the remote host to restrict these ports.
+ *
+ * The default range of ports and the high range can be changed by
+ * sysctl(3). (net.inet.ip.port{hi}{first,last})
+ *
+ * Changing those values has bad security implications if you are
+ * using a a stateless firewall that is allowing packets outside of that
+ * range in order to allow transparent outgoing connections.
+ *
+ * Such a firewall configuration will generally depend on the use of these
+ * default values. If you change them, you may find your Security
+ * Administrator looking for you with a heavy object.
+ */
+
+/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root).
* Ports > IPPORT_USERRESERVED are reserved
@@ -76,6 +111,12 @@
#define IPPORT_USERRESERVED 5000
/*
+ * Default local port range to use by setting IP_PORTRANGE_HIGH
+ */
+#define IPPORT_HIFIRSTAUTO 40000
+#define IPPORT_HILASTAUTO 44999
+
+/*
* Internet address (a structure for historical reasons)
*/
struct in_addr {
@@ -186,6 +227,8 @@ struct ip_opts {
#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */
#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */
#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
+ /* 14-17 left empty for future compatibility with FreeBSD */
+#define IP_PORTRANGE 19 /* int; range to choose for unspec port */
/*
* Defaults and limits for options
@@ -203,6 +246,14 @@ struct ip_mreq {
};
/*
+ * Argument for IP_PORTRANGE:
+ * - which range to search when port is unspecified at bind() or connect()
+ */
+#define IP_PORTRANGE_DEFAULT 0 /* default range */
+#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
+#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
+
+/*
* Definitions for inet sysctl operations.
*
* Third level is protocol number.
@@ -247,7 +298,11 @@ struct ip_mreq {
#endif
#define IPCTL_SOURCEROUTE 5 /* may perform source routes */
#define IPCTL_DIRECTEDBCAST 6 /* default broadcast behavior */
-#define IPCTL_MAXID 7
+#define IPCTL_IPPORT_FIRSTAUTO 7
+#define IPCTL_IPPORT_LASTAUTO 8
+#define IPCTL_IPPORT_HIFIRSTAUTO 9
+#define IPCTL_IPPORT_HILASTAUTO 10
+#define IPCTL_MAXID 11
#define IPCTL_NAMES { \
{ 0, 0 }, \
@@ -257,6 +312,10 @@ struct ip_mreq {
{ "mtu", CTLTYPE_INT }, \
{ "sourceroute", CTLTYPE_INT }, \
{ "directed-broadcast", CTLTYPE_INT }, \
+ { "portfirst", CTLTYPE_INT }, \
+ { "portlast", CTLTYPE_INT }, \
+ { "porthifirst", CTLTYPE_INT }, \
+ { "porthilast", CTLTYPE_INT }, \
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 90a6392fba7..a2b195ee83a 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.4 1996/05/14 19:37:34 deraadt Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.5 1996/07/29 02:34:29 downsj Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -60,6 +60,15 @@
struct in_addr zeroin_addr;
+/*
+ * These configure the range of local port addresses assigned to
+ * "unspecified" outgoing connections/packets/whatever.
+ */
+int ipport_firstauto = IPPORT_RESERVED; /* 1024 */
+int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */
+int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 40000 */
+int ipport_hilastauto = IPPORT_HILASTAUTO; /* 44999 */
+
#define INPCBHASH(table, faddr, fport, laddr, lport) \
&(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)]
@@ -106,6 +115,7 @@ in_pcbbind(v, nam)
register struct inpcb *inp = v;
register struct socket *so = inp->inp_socket;
register struct inpcbtable *table = inp->inp_table;
+ u_int16_t *lastport = &inp->inp_table->inpt_lastport;
register struct sockaddr_in *sin;
struct proc *p = curproc; /* XXX */
u_int16_t lport = 0;
@@ -170,14 +180,62 @@ in_pcbbind(v, nam)
}
inp->inp_laddr = sin->sin_addr;
}
- if (lport == 0)
- do {
- if (table->inpt_lastport++ < IPPORT_RESERVED ||
- table->inpt_lastport > IPPORT_USERRESERVED)
- table->inpt_lastport = IPPORT_RESERVED;
- lport = htons(table->inpt_lastport);
- } while (in_pcblookup(table,
- 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 = IPPORT_RESERVED / 2; /* traditional - 512 */
+ *lastport = first; /* restart each time */
+ } 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(table,
+ 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(table,
+ zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ }
+ }
inp->inp_lport = lport;
in_pcbrehash(inp);
return (0);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 6a533ca4703..32f8116678d 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.h,v 1.2 1996/03/03 22:30:32 niklas Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.3 1996/07/29 02:34:30 downsj Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
@@ -75,6 +75,8 @@ struct inpcbtable {
#define INP_RECVDSTADDR 0x04 /* receive IP dst address */
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR)
#define INP_HDRINCL 0x08 /* user supplies entire IP header */
+#define INP_HIGHPORT 0x10 /* user wants "high" port binding */
+#define INP_LOWPORT 0x20 /* user wants "low" port binding */
#define INPLOOKUP_WILDCARD 1
#define INPLOOKUP_SETLOCAL 2
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 5b8b0ba031f..1c9149297ce 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.13 1996/07/18 05:01:04 dm Exp $ */
+/* $OpenBSD: ip_input.c,v 1.14 1996/07/29 02:34:30 downsj Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -93,6 +93,12 @@ int ip_directedbcast = IPDIRECTEDBCAST;
int ipprintfs = 0;
#endif
+/* from in_pcb.c */
+extern int ipport_firstauto;
+extern int ipport_lastauto;
+extern int ipport_hifirstauto;
+extern int ipport_hilastauto;
+
extern struct domain inetdomain;
extern struct protosw inetsw[];
u_char ip_protox[IPPROTO_MAX];
@@ -1221,6 +1227,18 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
case IPCTL_DIRECTEDBCAST:
return (sysctl_int(oldp, oldlenp, newp, newlen,
&ip_directedbcast));
+ case IPCTL_IPPORT_FIRSTAUTO:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ipport_firstauto));
+ case IPCTL_IPPORT_LASTAUTO:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ipport_lastauto));
+ case IPCTL_IPPORT_HIFIRSTAUTO:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ipport_hifirstauto));
+ case IPCTL_IPPORT_HILASTAUTO:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ipport_hilastauto));
default:
return (EOPNOTSUPP);
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 4cf3e2f7fce..2b31d8dd9f2 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.5 1996/03/04 10:34:33 mickey Exp $ */
+/* $OpenBSD: ip_output.c,v 1.6 1996/07/29 02:34:31 downsj Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -583,6 +583,37 @@ ip_ctloutput(op, so, level, optname, mp)
error = ip_setmoptions(optname, &inp->inp_moptions, m);
break;
+ case IP_PORTRANGE:
+ if (m == 0 || m->m_len != sizeof(int))
+ error = EINVAL;
+ else {
+ optval = *mtod(m, int *);
+
+ switch (optval) {
+
+ case IP_PORTRANGE_DEFAULT:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ break;
+
+ case IP_PORTRANGE_HIGH:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags |= INP_HIGHPORT;
+ break;
+
+ case IP_PORTRANGE_LOW:
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ inp->inp_flags |= INP_LOWPORT;
+ break;
+
+ default:
+
+ error = EINVAL;
+ break;
+ }
+ }
+ break;
+
default:
error = ENOPROTOOPT;
break;
@@ -646,6 +677,20 @@ ip_ctloutput(op, so, level, optname, mp)
error = ip_getmoptions(optname, inp->inp_moptions, mp);
break;
+ case IP_PORTRANGE:
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(int);
+
+ if (inp->inp_flags & INP_HIGHPORT)
+ optval = IP_PORTRANGE_HIGH;
+ else if (inp->inp_flags & INP_LOWPORT)
+ optval = IP_PORTRANGE_LOW;
+ else
+ optval = 0;
+
+ *mtod(m, int *) = optval;
+ break;
+
default:
error = ENOPROTOOPT;
break;