aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet6/in6_src.c
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2011-03-12 21:46:37 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2011-03-12 21:46:37 +0000
commitefc76f729a310b7d56af307d9e7009b46bd6ccbf (patch)
tree2c624cee0eb5ca0598a24a7eb17008dbe6b098de /sys/netinet6/in6_src.c
parente729c4f2fdf47d5be39525c14cf799edff3d11ab (diff)
downloadsrc-efc76f729a310b7d56af307d9e7009b46bd6ccbf.tar.gz
src-efc76f729a310b7d56af307d9e7009b46bd6ccbf.zip
Merge the two identical implementations for local port selections from
in_pcbbind_setup() and in6_pcbsetport() in a single in_pcb_lport(). MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=219579
Diffstat (limited to 'sys/netinet6/in6_src.c')
-rw-r--r--sys/netinet6/in6_src.c74
1 files changed, 7 insertions, 67 deletions
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 2bf99fe19375..b491e0e7ab10 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -850,9 +850,11 @@ int
in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
{
struct socket *so = inp->inp_socket;
- u_int16_t lport = 0, first, last, *lastport;
- int count, error, wild = 0, dorandom;
+ u_int16_t lport = 0;
+ int error, wild = 0;
+#ifdef INVARIANTS
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+#endif
INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
@@ -868,71 +870,9 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
inp->inp_flags |= INP_ANONPORT;
- if (inp->inp_flags & INP_HIGHPORT) {
- first = V_ipport_hifirstauto; /* sysctl */
- last = V_ipport_hilastauto;
- lastport = &pcbinfo->ipi_lasthi;
- } else if (inp->inp_flags & INP_LOWPORT) {
- error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0);
- if (error)
- return error;
- first = V_ipport_lowfirstauto; /* 1023 */
- last = V_ipport_lowlastauto; /* 600 */
- lastport = &pcbinfo->ipi_lastlow;
- } else {
- first = V_ipport_firstauto; /* sysctl */
- last = V_ipport_lastauto;
- lastport = &pcbinfo->ipi_lastport;
- }
-
- /*
- * For UDP, use random port allocation as long as the user
- * allows it. For TCP (and as of yet unknown) connections,
- * use random port allocation only if the user allows it AND
- * ipport_tick() allows it.
- */
- if (V_ipport_randomized &&
- (!V_ipport_stoprandom || pcbinfo == &V_udbinfo))
- dorandom = 1;
- else
- dorandom = 0;
- /*
- * It makes no sense to do random port allocation if
- * we have the only port available.
- */
- if (first == last)
- dorandom = 0;
- /* Make sure to not include UDP packets in the count. */
- if (pcbinfo != &V_udbinfo)
- V_ipport_tcpallocs++;
-
- /*
- * Instead of having two loops further down counting up or down
- * make sure that first is always <= last and go with only one
- * code path implementing all logic.
- */
- if (first > last) {
- u_int16_t aux;
-
- aux = first;
- first = last;
- last = aux;
- }
-
- if (dorandom)
- *lastport = first + (arc4random() % (last - first));
-
- count = last - first;
-
- do {
- if (count-- < 0) /* completely used? */
- return (EADDRNOTAVAIL);
- ++*lastport;
- if (*lastport < first || *lastport > last)
- *lastport = first;
- lport = htons(*lastport);
- } while (in6_pcblookup_local(pcbinfo, &inp->in6p_laddr,
- lport, wild, cred));
+ error = in_pcb_lport(inp, NULL, &lport, cred, wild);
+ if (error != 0)
+ return (error);
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {