changeset 14084:9919574e3322

3895 {tcp,udp}_{largest,smallest}_anon_port should reality-check Reviewed by: Marcel Telka <marcel@telka.sk> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Garrett D'Amore <garrett@damore.org>
author Dan McDonald <danmcd@nexenta.com>
date Thu, 18 Jul 2013 22:44:14 -0400
parents eac51815a73b
children c1602d3adc9b
files usr/src/uts/common/inet/tcp/tcp_bind.c usr/src/uts/common/inet/tcp/tcp_tunables.c usr/src/uts/common/inet/udp/udp.c usr/src/uts/common/inet/udp/udp_tunables.c
diffstat 4 files changed, 107 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/tcp/tcp_bind.c	Thu Jul 18 15:18:41 2013 -0400
+++ b/usr/src/uts/common/inet/tcp/tcp_bind.c	Thu Jul 18 22:44:14 2013 -0400
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
@@ -212,7 +212,7 @@
 in_port_t
 tcp_update_next_port(in_port_t port, const tcp_t *tcp, boolean_t random)
 {
-	int i;
+	int i, bump;
 	boolean_t restart = B_FALSE;
 	tcp_stack_t *tcps = tcp->tcp_tcps;
 
@@ -230,9 +230,14 @@
 		 */
 		if ((port < tcps->tcps_smallest_anon_port) ||
 		    (port > tcps->tcps_largest_anon_port)) {
-			port = tcps->tcps_smallest_anon_port +
-			    port % (tcps->tcps_largest_anon_port -
-			    tcps->tcps_smallest_anon_port);
+			if (tcps->tcps_smallest_anon_port ==
+			    tcps->tcps_largest_anon_port) {
+				bump = 0;
+			} else {
+				bump = port % (tcps->tcps_largest_anon_port -
+				    tcps->tcps_smallest_anon_port);
+			}
+			port = tcps->tcps_smallest_anon_port + bump;
 		}
 	}
 
--- a/usr/src/uts/common/inet/tcp/tcp_tunables.c	Thu Jul 18 15:18:41 2013 -0400
+++ b/usr/src/uts/common/inet/tcp/tcp_tunables.c	Thu Jul 18 22:44:14 2013 -0400
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -188,6 +189,46 @@
 }
 
 /*
+ * Special checkers for smallest/largest anonymous port so they don't
+ * ever happen to be (largest < smallest).
+ */
+/* ARGSUSED */
+static int
+tcp_smallest_anon_set(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
+    const char *ifname, const void *pval, uint_t flags)
+{
+	unsigned long new_value;
+	tcp_stack_t *tcps = (tcp_stack_t *)cbarg;
+	int err;
+
+	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
+		return (err);
+	/* mod_uint32_value() + pinfo guarantees we're in TCP port range. */
+	if ((uint32_t)new_value > tcps->tcps_largest_anon_port)
+		return (ERANGE);
+	pinfo->prop_cur_uval = (uint32_t)new_value;
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+tcp_largest_anon_set(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
+    const char *ifname, const void *pval, uint_t flags)
+{
+	unsigned long new_value;
+	tcp_stack_t *tcps = (tcp_stack_t *)cbarg;
+	int err;
+
+	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
+		return (err);
+	/* mod_uint32_value() + pinfo guarantees we're in TCP port range. */
+	if ((uint32_t)new_value < tcps->tcps_smallest_anon_port)
+		return (ERANGE);
+	pinfo->prop_cur_uval = (uint32_t)new_value;
+	return (0);
+}
+
+/*
  * All of these are alterable, within the min/max values given, at run time.
  *
  * Note: All those tunables which do not start with "_" are Committed and
@@ -308,11 +349,11 @@
 	    {B_FALSE}, {B_FALSE} },
 
 	{ "smallest_anon_port", MOD_PROTO_TCP,
-	    mod_set_uint32, mod_get_uint32,
+	    tcp_smallest_anon_set, mod_get_uint32,
 	    {1024, ULP_MAX_PORT, 32*1024}, {32*1024} },
 
 	{ "largest_anon_port", MOD_PROTO_TCP,
-	    mod_set_uint32, mod_get_uint32,
+	    tcp_largest_anon_set, mod_get_uint32,
 	    {1024, ULP_MAX_PORT, ULP_MAX_PORT},
 	    {ULP_MAX_PORT} },
 
--- a/usr/src/uts/common/inet/udp/udp.c	Thu Jul 18 15:18:41 2013 -0400
+++ b/usr/src/uts/common/inet/udp/udp.c	Thu Jul 18 22:44:14 2013 -0400
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -2522,7 +2522,7 @@
 static in_port_t
 udp_update_next_port(udp_t *udp, in_port_t port, boolean_t random)
 {
-	int i;
+	int i, bump;
 	in_port_t nextport;
 	boolean_t restart = B_FALSE;
 	udp_stack_t *us = udp->udp_us;
@@ -2541,9 +2541,15 @@
 		 */
 		if ((port < us->us_smallest_anon_port) ||
 		    (port > us->us_largest_anon_port)) {
-			port = us->us_smallest_anon_port +
-			    port % (us->us_largest_anon_port -
-			    us->us_smallest_anon_port);
+			if (us->us_smallest_anon_port ==
+			    us->us_largest_anon_port) {
+				bump = 0;
+			} else {
+				bump = port % (us->us_largest_anon_port -
+				    us->us_smallest_anon_port);
+			}
+
+			port = us->us_smallest_anon_port + bump;
 		}
 	}
 
--- a/usr/src/uts/common/inet/udp/udp_tunables.c	Thu Jul 18 15:18:41 2013 -0400
+++ b/usr/src/uts/common/inet/udp/udp_tunables.c	Thu Jul 18 22:44:14 2013 -0400
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -29,6 +30,46 @@
 #include <sys/sunddi.h>
 
 /*
+ * Special checkers for smallest/largest anonymous port so they don't
+ * ever happen to be (largest < smallest).
+ */
+/* ARGSUSED */
+static int
+udp_smallest_anon_set(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
+    const char *ifname, const void *pval, uint_t flags)
+{
+	unsigned long new_value;
+	udp_stack_t *us = (udp_stack_t *)cbarg;
+	int err;
+
+	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
+		return (err);
+	/* mod_uint32_value() + pinfo guarantees we're in UDP port range. */
+	if (new_value > us->us_largest_anon_port)
+		return (ERANGE);
+	pinfo->prop_cur_uval = (uint32_t)new_value;
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+udp_largest_anon_set(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
+    const char *ifname, const void *pval, uint_t flags)
+{
+	unsigned long new_value;
+	udp_stack_t *us = (udp_stack_t *)cbarg;
+	int err;
+
+	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
+		return (err);
+	/* mod_uint32_value() + pinfo guarantees we're in UDP port range. */
+	if (new_value < us->us_smallest_anon_port)
+		return (ERANGE);
+	pinfo->prop_cur_uval = (uint32_t)new_value;
+	return (0);
+}
+
+/*
  * All of these are alterable, within the min/max values given, at run time.
  *
  * Note: All those tunables which do not start with "_" are Committed and
@@ -57,11 +98,11 @@
 	    {B_TRUE}, {B_TRUE} },
 
 	{ "smallest_anon_port", MOD_PROTO_UDP,
-	    mod_set_uint32, mod_get_uint32,
+	    udp_smallest_anon_set, mod_get_uint32,
 	    {1024, ULP_MAX_PORT, (32 * 1024)}, {(32 * 1024)} },
 
 	{ "largest_anon_port", MOD_PROTO_UDP,
-	    mod_set_uint32, mod_get_uint32,
+	    udp_largest_anon_set, mod_get_uint32,
 	    {1024, ULP_MAX_PORT, ULP_MAX_PORT}, {ULP_MAX_PORT} },
 
 	{ "send_maxbuf", MOD_PROTO_UDP,