diff --git a/share/man/man4/ip.4 b/share/man/man4/ip.4
index dd86514d1c6b..65dd308d304d 100644
--- a/share/man/man4/ip.4
+++ b/share/man/man4/ip.4
@@ -1,620 +1,635 @@
 .\" Copyright (c) 1983, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
 .\" 1. Redistributions of source code must retain the above copyright
 .\"    notice, this list of conditions and the following disclaimer.
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
 .\" 3. All advertising materials mentioning features or use of this software
 .\"    must display the following acknowledgement:
 .\"	This product includes software developed by the University of
 .\"	California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)ip.4	8.2 (Berkeley) 11/30/93
 .\" $FreeBSD$
 .\"
-.Dd June 14, 2004
+.Dd March 23, 2005
 .Dt IP 4
 .Os
 .Sh NAME
 .Nm ip
 .Nd Internet Protocol
 .Sh SYNOPSIS
 .In sys/types.h
 .In sys/socket.h
 .In netinet/in.h
 .Ft int
 .Fn socket AF_INET SOCK_RAW proto
 .Sh DESCRIPTION
 .Tn IP
 is the transport layer protocol used
 by the Internet protocol family.
 Options may be set at the
 .Tn IP
 level
 when using higher-level protocols that are based on
 .Tn IP
 (such as
 .Tn TCP
 and
 .Tn UDP ) .
 It may also be accessed
 through a
 .Dq raw socket
 when developing new protocols, or
 special-purpose applications.
 .Pp
 There are several
 .Tn IP-level
 .Xr setsockopt 2
 and
 .Xr getsockopt 2
 options.
 .Dv IP_OPTIONS
 may be used to provide
 .Tn IP
 options to be transmitted in the
 .Tn IP
 header of each outgoing packet
 or to examine the header options on incoming packets.
 .Tn IP
 options may be used with any socket type in the Internet family.
 The format of
 .Tn IP
 options to be sent is that specified by the
 .Tn IP
 protocol specification (RFC-791), with one exception:
 the list of addresses for Source Route options must include the first-hop
 gateway at the beginning of the list of gateways.
 The first-hop gateway address will be extracted from the option list
 and the size adjusted accordingly before use.
 To disable previously specified options,
 use a zero-length buffer:
 .Bd -literal
 setsockopt(s, IPPROTO_IP, IP_OPTIONS, NULL, 0);
 .Ed
 .Pp
 .Dv IP_TOS
 and
 .Dv IP_TTL
 may be used to set the type-of-service and time-to-live
 fields in the
 .Tn IP
 header for
 .Dv SOCK_STREAM , SOCK_DGRAM ,
 and certain types of
 .Dv SOCK_RAW
 sockets.
 For example,
 .Bd -literal
 int tos = IPTOS_LOWDELAY;       /* see <netinet/ip.h> */
 setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
 
 int ttl = 60;                   /* max = 255 */
 setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
 .Ed
 .Pp
 If the
 .Dv IP_RECVDSTADDR
 option is enabled on a
 .Dv SOCK_DGRAM
 socket,
 the
 .Xr recvmsg 2
 call will return the destination
 .Tn IP
 address for a
 .Tn UDP
 datagram.
 The
 .Vt msg_control
 field in the
 .Vt msghdr
 structure points to a buffer
 that contains a
 .Vt cmsghdr
 structure followed by the
 .Tn IP
 address.
 The
 .Vt cmsghdr
 fields have the following values:
 .Bd -literal
 cmsg_len = sizeof(struct in_addr)
 cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVDSTADDR
 .Ed
 .Pp
 The source address to be used for outgoing
 .Tn UDP
 datagrams on a socket that is not bound to a specific
 .Tn IP
 address can be specified as ancillary data with a type code of
 .Dv IP_SENDSRCADDR .
 The msg_control field in the msghdr structure should point to a buffer
 that contains a
 .Vt cmsghdr
 structure followed by the
 .Tn IP
 address.
 The cmsghdr fields should have the following values:
 .Bd -literal
 cmsg_len = sizeof(struct in_addr)
 cmsg_level = IPPROTO_IP
 cmsg_type = IP_SENDSRCADDR
 .Ed
 .Pp
 For convenience,
 .Dv IP_SENDSRCADDR
 is defined to have the same value as
 .Dv IP_RECVDSTADDR ,
 so the
 .Dv IP_RECVDSTADDR
 control message from
 .Xr recvmsg 2
 can be used directly as a control message for
 .Xr sendmsg 2 .
 .Pp
 If the
 .Dv IP_ONESBCAST
 option is enabled on a
 .Dv SOCK_DGRAM
 or a
 .Dv SOCK_RAW
 socket, the destination address of outgoing
 broadcast datagrams on that socket will be forced
 to the undirected broadcast address,
 .Dv INADDR_BROADCAST ,
 before transmission.
 This is in contrast to the default behavior of the
 system, which is to transmit undirected broadcasts
 via the first network interface with the
 .Dv IFF_BROADCAST flag set.
 .Pp
 This option allows applications to choose which
 interface is used to transmit an undirected broadcast
 datagram.
 For example, the following code would force an
 undirected broadcast to be transmitted via the interface
 configured with the broadcast address 192.168.2.255:
 .Bd -literal
 char msg[512];
 struct sockaddr_in sin;
 u_char onesbcast = 1;	/* 0 = disable (default), 1 = enable */
 
 setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &onesbcast, sizeof(onesbcast));
 sin.sin_addr.s_addr = inet_addr("192.168.2.255");
 sin.sin_port = htons(1234);
 sendto(s, msg, sizeof(msg), 0, &sin, sizeof(sin));
 .Ed
 .Pp
 It is the application's responsibility to set the
 .Dv IP_TTL option
 to an appropriate value in order to prevent broadcast storms.
 The application must have sufficient credentials to set the
 .Dv SO_BROADCAST
 socket level option, otherwise the
 .Dv IP_ONESBCAST option has no effect.
 .Pp
 If the
 .Dv IP_RECVTTL
 option is enabled on a
 .Dv SOCK_DGRAM
 socket, the
 .Xr recvmsg 2
 call will return the
 .Tn IP
 .Tn TTL
 (time to live) field for a
 .Tn UDP
 datagram.
 The msg_control field in the msghdr structure points to a buffer
 that contains a cmsghdr structure followed by the
 .Tn TTL .
 The cmsghdr fields have the following values:
 .Bd -literal
 cmsg_len = sizeof(u_char)
 cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVTTL
 .Ed
 .Pp
 If the
 .Dv IP_RECVIF
 option is enabled on a
 .Dv SOCK_DGRAM
 socket, the
 .Xr recvmsg 2
 call returns a
 .Vt "struct sockaddr_dl"
 corresponding to the interface on which the
 packet was received.
 The
 .Va msg_control
 field in the
 .Vt msghdr
 structure points to a buffer that contains a
 .Vt cmsghdr
 structure followed by the
 .Vt "struct sockaddr_dl" .
 The
 .Vt cmsghdr
 fields have the following values:
 .Bd -literal
 cmsg_len = sizeof(struct sockaddr_dl)
 cmsg_level = IPPROTO_IP
 cmsg_type = IP_RECVIF
 .Ed
 .Pp
 .Dv IP_PORTRANGE
 may be used to set the port range used for selecting a local port number
 on a socket with an unspecified (zero) port number.
 It has the following
 possible values:
 .Bl -tag -width IP_PORTRANGE_DEFAULT
 .It Dv IP_PORTRANGE_DEFAULT
 use the default range of values, normally
 .Dv IPPORT_HIFIRSTAUTO
 through
 .Dv IPPORT_HILASTAUTO .
 This is adjustable through the sysctl setting:
 .Va net.inet.ip.portrange.first
 and
 .Va net.inet.ip.portrange.last .
 .It Dv IP_PORTRANGE_HIGH
 use a high range of values, normally
 .Dv IPPORT_HIFIRSTAUTO
 and
 .Dv IPPORT_HILASTAUTO .
 This is adjustable through the sysctl setting:
 .Va net.inet.ip.portrange.hifirst
 and
 .Va net.inet.ip.portrange.hilast .
 .It Dv IP_PORTRANGE_LOW
 use a low range of ports, which are normally restricted to
 privileged processes on
 .Ux
 systems.
 The range is normally from
 .Dv IPPORT_RESERVED
 \- 1 down to
 .Li IPPORT_RESERVEDSTART
 in descending order.
 This is adjustable through the sysctl setting:
 .Va net.inet.ip.portrange.lowfirst
 and
 .Va net.inet.ip.portrange.lowlast .
 .El
 .Pp
 The range of privileged ports which only may be opened by
 root-owned processes may be modified by the
 .Va net.inet.ip.portrange.reservedlow
 and
 .Va net.inet.ip.portrange.reservedhigh
 sysctl settings.
 The values default to the traditional range,
 0 through
 .Dv IPPORT_RESERVED
 \- 1
 (0 through 1023), respectively.
 Note that these settings do not affect and are not accounted for in the
 use or calculation of the other
 .Va net.inet.ip.portrange
 values above.
 Changing these values departs from
 .Ux
 tradition and has security
 consequences that the administrator should carefully evaluate before
 modifying these settings.
 .Pp
 Ports are allocated at random within the specified port range in order
 to increase the difficulty of random spoofing attacks.
 In scenarios such as benchmarking, this behavior may be undesirable.
 In these cases,
 .Va net.inet.ip.portrange.randomized
 can be used to toggle randomization off.
+If more than
+.Va net.inet.ip.portrange.randomcps
+ports have been allocated in the last second, then return to sequential
+port allocation.
+Return to random allocation only once the current port allocation rate
+drops below
+.Va net.inet.ip.portrange.randomcps
+for at least
+.Va net.inet.ip.portrange.randomtime
+seconds.
+The default values for
+.Va net.inet.ip.portrange.randomcps
+and
+.Va net.inet.ip.portrange.randomtime
+are 10 port allocations per second and 45 seconds correspondingly.
 .Ss "Multicast Options"
 .Pp
 .Tn IP
 multicasting is supported only on
 .Dv AF_INET
 sockets of type
 .Dv SOCK_DGRAM
 and
 .Dv SOCK_RAW ,
 and only on networks where the interface
 driver supports multicasting.
 .Pp
 The
 .Dv IP_MULTICAST_TTL
 option changes the time-to-live (TTL)
 for outgoing multicast datagrams
 in order to control the scope of the multicasts:
 .Bd -literal
 u_char ttl;	/* range: 0 to 255, default = 1 */
 setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
 .Ed
 .Pp
 Datagrams with a TTL of 1 are not forwarded beyond the local network.
 Multicast datagrams with a TTL of 0 will not be transmitted on any network,
 but may be delivered locally if the sending host belongs to the destination
 group and if multicast loopback has not been disabled on the sending socket
 (see below).
 Multicast datagrams with TTL greater than 1 may be forwarded
 to other networks if a multicast router is attached to the local network.
 .Pp
 For hosts with multiple interfaces, each multicast transmission is
 sent from the primary network interface.
 The
 .Dv IP_MULTICAST_IF
 option overrides the default for
 subsequent transmissions from a given socket:
 .Bd -literal
 struct in_addr addr;
 setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));
 .Ed
 .Pp
 where "addr" is the local
 .Tn IP
 address of the desired interface or
 .Dv INADDR_ANY
 to specify the default interface.
 An interface's local IP address and multicast capability can
 be obtained via the
 .Dv SIOCGIFCONF
 and
 .Dv SIOCGIFFLAGS
 ioctls.
 Normal applications should not need to use this option.
 .Pp
 If a multicast datagram is sent to a group to which the sending host itself
 belongs (on the outgoing interface), a copy of the datagram is, by default,
 looped back by the IP layer for local delivery.
 The
 .Dv IP_MULTICAST_LOOP
 option gives the sender explicit control
 over whether or not subsequent datagrams are looped back:
 .Bd -literal
 u_char loop;	/* 0 = disable, 1 = enable (default) */
 setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
 .Ed
 .Pp
 This option
 improves performance for applications that may have no more than one
 instance on a single host (such as a router daemon), by eliminating
 the overhead of receiving their own transmissions.
 It should generally not
 be used by applications for which there may be more than one instance on a
 single host (such as a conferencing program) or for which the sender does
 not belong to the destination group (such as a time querying program).
 .Pp
 A multicast datagram sent with an initial TTL greater than 1 may be delivered
 to the sending host on a different interface from that on which it was sent,
 if the host belongs to the destination group on that other interface.
 The loopback control option has no effect on such delivery.
 .Pp
 A host must become a member of a multicast group before it can receive
 datagrams sent to the group.
 To join a multicast group, use the
 .Dv IP_ADD_MEMBERSHIP
 option:
 .Bd -literal
 struct ip_mreq mreq;
 setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
 .Ed
 .Pp
 where
 .Fa mreq
 is the following structure:
 .Bd -literal
 struct ip_mreq {
     struct in_addr imr_multiaddr; /* IP multicast address of group */
     struct in_addr imr_interface; /* local IP address of interface */
 }
 .Ed
 .Pp
 .Va imr_interface
 should be set to
 .Dv INADDR_ANY
 to choose the default multicast interface,
 or the
 .Tn IP
 address of a particular multicast-capable interface if
 the host is multihomed.
 Since
 .Fx 4.4 ,
 if the
 .Va imr_interface
 member is within the network range
 .Li 0.0.0.0/8 ,
 it is treated as an interface index in the system interface MIB,
 as per the RIP Version 2 MIB Extension (RFC-1724).
 .Pp
 Membership is associated with a single interface;
 programs running on multihomed hosts may need to
 join the same group on more than one interface.
 Up to
 .Dv IP_MAX_MEMBERSHIPS
 (currently 20) memberships may be added on a
 single socket.
 .Pp
 To drop a membership, use:
 .Bd -literal
 struct ip_mreq mreq;
 setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
 .Ed
 .Pp
 where
 .Fa mreq
 contains the same values as used to add the membership.
 Memberships are dropped when the socket is closed or the process exits.
 .\"-----------------------
 .Ss "Raw IP Sockets"
 .Pp
 Raw
 .Tn IP
 sockets are connectionless,
 and are normally used with the
 .Xr sendto 2
 and
 .Xr recvfrom 2
 calls, though the
 .Xr connect 2
 call may also be used to fix the destination for future
 packets (in which case the
 .Xr read 2
 or
 .Xr recv 2
 and
 .Xr write 2
 or
 .Xr send 2
 system calls may be used).
 .Pp
 If
 .Fa proto
 is 0, the default protocol
 .Dv IPPROTO_RAW
 is used for outgoing
 packets, and only incoming packets destined for that protocol
 are received.
 If
 .Fa proto
 is non-zero, that protocol number will be used on outgoing packets
 and to filter incoming packets.
 .Pp
 Outgoing packets automatically have an
 .Tn IP
 header prepended to
 them (based on the destination address and the protocol
 number the socket is created with),
 unless the
 .Dv IP_HDRINCL
 option has been set.
 Incoming packets are received with
 .Tn IP
 header and options intact.
 .Pp
 .Dv IP_HDRINCL
 indicates the complete IP header is included with the data
 and may be used only with the
 .Dv SOCK_RAW
 type.
 .Bd -literal
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 
 int hincl = 1;                  /* 1 = on, 0 = off */
 setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl));
 .Ed
 .Pp
 Unlike previous
 .Bx
 releases, the program must set all
 the fields of the IP header, including the following:
 .Bd -literal
 ip->ip_v = IPVERSION;
 ip->ip_hl = hlen >> 2;
 ip->ip_id = 0;  /* 0 means kernel set appropriate value */
 ip->ip_off = offset;
 .Ed
 .Pp
 The
 .Va ip_len
 and
 .Va ip_off
 fields
 .Em must
 be provided in host byte order .
 All other fields must be provided in network byte order.
 See
 .Xr byteorder 3
 for more information on network byte order.
 If the
 .Va ip_id
 field is set to 0 then the kernel will choose an
 appropriate value.
 If the header source address is set to
 .Dv INADDR_ANY ,
 the kernel will choose an appropriate address.
 .Sh ERRORS
 A socket operation may fail with one of the following errors returned:
 .Bl -tag -width Er
 .It Bq Er EISCONN
 when trying to establish a connection on a socket which
 already has one, or when trying to send a datagram with the destination
 address specified and the socket is already connected;
 .It Bq Er ENOTCONN
 when trying to send a datagram, but
 no destination address is specified, and the socket has not been
 connected;
 .It Bq Er ENOBUFS
 when the system runs out of memory for
 an internal data structure;
 .It Bq Er EADDRNOTAVAIL
 when an attempt is made to create a
 socket with a network address for which no network interface
 exists.
 .It Bq Er EACCES
 when an attempt is made to create
 a raw IP socket by a non-privileged process.
 .El
 .Pp
 The following errors specific to
 .Tn IP
 may occur when setting or getting
 .Tn IP
 options:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 An unknown socket option name was given.
 .It Bq Er EINVAL
 The IP option field was improperly formed;
 an option field was shorter than the minimum value
 or longer than the option buffer provided.
 .El
 .Pp
 The following errors may occur when attempting to send
 .Tn IP
 datagrams via a
 .Dq raw socket
 with the
 .Dv IP_HDRINCL
 option set:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The user-supplied
 .Va ip_len
 field was not equal to the length of the datagram written to the socket.
 .El
 .Sh SEE ALSO
 .Xr getsockopt 2 ,
 .Xr recv 2 ,
 .Xr send 2 ,
 .Xr byteorder 3 ,
 .Xr icmp 4 ,
 .Xr inet 4 ,
 .Xr intro 4
 .Sh HISTORY
 The
 .Nm
 protocol appeared in
 .Bx 4.2 .
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index efdab898858d..3ff86158a2ae 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,1229 +1,1232 @@
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  *	@(#)in_pcb.c	8.4 (Berkeley) 5/24/95
  * $FreeBSD$
  */
 
 #include "opt_ipsec.h"
 #include "opt_inet6.h"
 #include "opt_mac.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/proc.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
 
 #include <vm/uma.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
 #include <net/route.h>
 
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_var.h>
 #include <netinet/tcp_var.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
 #ifdef INET6
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
 #endif /* INET6 */
 
 #ifdef IPSEC
 #include <netinet6/ipsec.h>
 #include <netkey/key.h>
 #endif /* IPSEC */
 
 #ifdef FAST_IPSEC
 #if defined(IPSEC) || defined(IPSEC_ESP)
 #error "Bad idea: don't compile with both IPSEC and FAST_IPSEC!"
 #endif
 
 #include <netipsec/ipsec.h>
 #include <netipsec/key.h>
 #endif /* FAST_IPSEC */
 
 /*
  * These configure the range of local port addresses assigned to
  * "unspecified" outgoing connections/packets/whatever.
  */
 int	ipport_lowfirstauto  = IPPORT_RESERVED - 1;	/* 1023 */
 int	ipport_lowlastauto = IPPORT_RESERVEDSTART;	/* 600 */
 int	ipport_firstauto = IPPORT_HIFIRSTAUTO;		/* 49152 */
 int	ipport_lastauto  = IPPORT_HILASTAUTO;		/* 65535 */
 int	ipport_hifirstauto = IPPORT_HIFIRSTAUTO;	/* 49152 */
 int	ipport_hilastauto  = IPPORT_HILASTAUTO;		/* 65535 */
 
 /*
  * Reserved ports accessible only to root. There are significant
  * security considerations that must be accounted for when changing these,
  * but the security benefits can be great. Please be careful.
  */
 int	ipport_reservedhigh = IPPORT_RESERVED - 1;	/* 1023 */
 int	ipport_reservedlow = 0;
 
 /* Variables dealing with random ephemeral port allocation. */
 int	ipport_randomized = 1;	/* user controlled via sysctl */
 int	ipport_randomcps = 10;	/* user controlled via sysctl */
 int	ipport_randomtime = 45;	/* user controlled via sysctl */
 int	ipport_stoprandom = 0;	/* toggled by ipport_tick */
 int	ipport_tcpallocs;
 int	ipport_tcplastcount;
 
 #define RANGECHK(var, min, max) \
 	if ((var) < (min)) { (var) = (min); } \
 	else if ((var) > (max)) { (var) = (max); }
 
 static int
 sysctl_net_ipport_check(SYSCTL_HANDLER_ARGS)
 {
 	int error;
 
 	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
 	if (error == 0) {
 		RANGECHK(ipport_lowfirstauto, 1, IPPORT_RESERVED - 1);
 		RANGECHK(ipport_lowlastauto, 1, IPPORT_RESERVED - 1);
 		RANGECHK(ipport_firstauto, IPPORT_RESERVED, IPPORT_MAX);
 		RANGECHK(ipport_lastauto, IPPORT_RESERVED, IPPORT_MAX);
 		RANGECHK(ipport_hifirstauto, IPPORT_RESERVED, IPPORT_MAX);
 		RANGECHK(ipport_hilastauto, IPPORT_RESERVED, IPPORT_MAX);
 	}
 	return (error);
 }
 
 #undef RANGECHK
 
 SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports");
 
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowfirst, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_lowfirstauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowlast, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_lowlastauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, first, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_firstauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, last, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_lastauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", "");
 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedhigh,
 	   CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedhigh, 0, "");
 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedlow,
 	   CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedlow, 0, "");
-SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomized,
-	   CTLFLAG_RW, &ipport_randomized, 0, "");
-SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomcps,
-	   CTLFLAG_RW, &ipport_randomcps, 0, "");
-SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime,
-	   CTLFLAG_RW, &ipport_randomtime, 0, "");
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomized, CTLFLAG_RW,
+	   &ipport_randomized, 0, "Enable random port allocation");
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomcps, CTLFLAG_RW,
+	   &ipport_randomcps, 0, "Maximum number of random port "
+	   "allocations before switching to a sequental one");
+SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime, CTLFLAG_RW,
+	   &ipport_randomtime, 0, "Minimum time to keep sequental port "
+	   "allocation before switching to a random one");
 
 /*
  * in_pcb.c: manage the Protocol Control Blocks.
  *
  * NOTE: It is assumed that most of these functions will be called at
  * splnet(). XXX - There are, unfortunately, a few exceptions to this
  * rule that should be fixed.
  */
 
 /*
  * Allocate a PCB and associate it with the socket.
  */
 int
 in_pcballoc(so, pcbinfo, type)
 	struct socket *so;
 	struct inpcbinfo *pcbinfo;
 	const char *type;
 {
 	register struct inpcb *inp;
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	error = 0;
 	inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO);
 	if (inp == NULL)
 		return (ENOBUFS);
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	inp->inp_pcbinfo = pcbinfo;
 	inp->inp_socket = so;
 #ifdef MAC
 	error = mac_init_inpcb(inp, M_NOWAIT);
 	if (error != 0)
 		goto out;
 	SOCK_LOCK(so);
 	mac_create_inpcb_from_socket(so, inp);
 	SOCK_UNLOCK(so);
 #endif
 #if defined(IPSEC) || defined(FAST_IPSEC)
 #ifdef FAST_IPSEC
 	error = ipsec_init_policy(so, &inp->inp_sp);
 #else
 	error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
 #endif
 	if (error != 0)
 		goto out;
 #endif /*IPSEC*/
 #if defined(INET6)
 	if (INP_SOCKAF(so) == AF_INET6) {
 		inp->inp_vflag |= INP_IPV6PROTO;
 		if (ip6_v6only)
 			inp->inp_flags |= IN6P_IPV6_V6ONLY;
 	}
 #endif
 	LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
 	pcbinfo->ipi_count++;
 	so->so_pcb = (caddr_t)inp;
 	INP_LOCK_INIT(inp, "inp", type);
 #ifdef INET6
 	if (ip6_auto_flowlabel)
 		inp->inp_flags |= IN6P_AUTOFLOWLABEL;
 #endif
 #if defined(IPSEC) || defined(FAST_IPSEC) || defined(MAC)
 out:
 	if (error != 0)
 		uma_zfree(pcbinfo->ipi_zone, inp);
 #endif
 	return (error);
 }
 
 int
 in_pcbbind(inp, nam, cred)
 	register struct inpcb *inp;
 	struct sockaddr *nam;
 	struct ucred *cred;
 {
 	int anonport, error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
 		return (EINVAL);
 	anonport = inp->inp_lport == 0 && (nam == NULL ||
 	    ((struct sockaddr_in *)nam)->sin_port == 0);
 	error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr,
 	    &inp->inp_lport, cred);
 	if (error)
 		return (error);
 	if (in_pcbinshash(inp) != 0) {
 		inp->inp_laddr.s_addr = INADDR_ANY;
 		inp->inp_lport = 0;
 		return (EAGAIN);
 	}
 	if (anonport)
 		inp->inp_flags |= INP_ANONPORT;
 	return (0);
 }
 
 /*
  * Set up a bind operation on a PCB, performing port allocation
  * as required, but do not actually modify the PCB. Callers can
  * either complete the bind by setting inp_laddr/inp_lport and
  * calling in_pcbinshash(), or they can just use the resulting
  * port and address to authorise the sending of a once-off packet.
  *
  * On error, the values of *laddrp and *lportp are not changed.
  */
 int
 in_pcbbind_setup(inp, nam, laddrp, lportp, cred)
 	struct inpcb *inp;
 	struct sockaddr *nam;
 	in_addr_t *laddrp;
 	u_short *lportp;
 	struct ucred *cred;
 {
 	struct socket *so = inp->inp_socket;
 	unsigned short *lastport;
 	struct sockaddr_in *sin;
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct in_addr laddr;
 	u_short lport = 0;
 	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
 	int error, prison = 0;
 	int dorandom;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
 		return (EADDRNOTAVAIL);
 	laddr.s_addr = *laddrp;
 	if (nam != NULL && laddr.s_addr != INADDR_ANY)
 		return (EINVAL);
 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
 		wild = 1;
 	if (nam) {
 		sin = (struct sockaddr_in *)nam;
 		if (nam->sa_len != sizeof (*sin))
 			return (EINVAL);
 #ifdef notdef
 		/*
 		 * We should check the family, but old programs
 		 * incorrectly fail to initialize it.
 		 */
 		if (sin->sin_family != AF_INET)
 			return (EAFNOSUPPORT);
 #endif
 		if (sin->sin_addr.s_addr != INADDR_ANY)
 			if (prison_ip(cred, 0, &sin->sin_addr.s_addr))
 				return(EINVAL);
 		if (sin->sin_port != *lportp) {
 			/* Don't allow the port to change. */
 			if (*lportp != 0)
 				return (EINVAL);
 			lport = sin->sin_port;
 		}
 		/* NB: lport is left as 0 if the port isn't being changed. */
 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
 			/*
 			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
 			 * allow complete duplication of binding if
 			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
 			 * and a multicast address is bound on both
 			 * new and duplicated sockets.
 			 */
 			if (so->so_options & SO_REUSEADDR)
 				reuseport = SO_REUSEADDR|SO_REUSEPORT;
 		} else if (sin->sin_addr.s_addr != INADDR_ANY) {
 			sin->sin_port = 0;		/* yech... */
 			bzero(&sin->sin_zero, sizeof(sin->sin_zero));
 			if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
 				return (EADDRNOTAVAIL);
 		}
 		laddr = sin->sin_addr;
 		if (lport) {
 			struct inpcb *t;
 			/* GROSS */
 			if (ntohs(lport) <= ipport_reservedhigh &&
 			    ntohs(lport) >= ipport_reservedlow &&
 			    suser_cred(cred, SUSER_ALLOWJAIL))
 				return (EACCES);
 			if (jailed(cred))
 				prison = 1;
 			if (so->so_cred->cr_uid != 0 &&
 			    !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
 				t = in_pcblookup_local(inp->inp_pcbinfo,
 				    sin->sin_addr, lport,
 				    prison ? 0 :  INPLOOKUP_WILDCARD);
 	/*
 	 * XXX
 	 * This entire block sorely needs a rewrite.
 	 */
 				if (t &&
 				    ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
 				    (so->so_type != SOCK_STREAM ||
 				     ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
 				    (ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
 				     ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
 				     (t->inp_socket->so_options &
 					 SO_REUSEPORT) == 0) &&
 				    (so->so_cred->cr_uid !=
 				     t->inp_socket->so_cred->cr_uid))
 					return (EADDRINUSE);
 			}
 			if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
 				return (EADDRNOTAVAIL);
 			t = in_pcblookup_local(pcbinfo, sin->sin_addr,
 			    lport, prison ? 0 : wild);
 			if (t && (t->inp_vflag & INP_TIMEWAIT)) {
 				if ((reuseport & intotw(t)->tw_so_options) == 0)
 					return (EADDRINUSE);
 			} else
 			if (t &&
 			    (reuseport & t->inp_socket->so_options) == 0) {
 #if defined(INET6)
 				if (ntohl(sin->sin_addr.s_addr) !=
 				    INADDR_ANY ||
 				    ntohl(t->inp_laddr.s_addr) !=
 				    INADDR_ANY ||
 				    INP_SOCKAF(so) ==
 				    INP_SOCKAF(t->inp_socket))
 #endif /* defined(INET6) */
 				return (EADDRINUSE);
 			}
 		}
 	}
 	if (*lportp != 0)
 		lport = *lportp;
 	if (lport == 0) {
 		u_short first, last;
 		int count;
 
 		if (laddr.s_addr != INADDR_ANY)
 			if (prison_ip(cred, 0, &laddr.s_addr))
 				return (EINVAL);
 
 		if (inp->inp_flags & INP_HIGHPORT) {
 			first = ipport_hifirstauto;	/* sysctl */
 			last  = ipport_hilastauto;
 			lastport = &pcbinfo->lasthi;
 		} else if (inp->inp_flags & INP_LOWPORT) {
 			if ((error = suser_cred(cred, SUSER_ALLOWJAIL)) != 0)
 				return error;
 			first = ipport_lowfirstauto;	/* 1023 */
 			last  = ipport_lowlastauto;	/* 600 */
 			lastport = &pcbinfo->lastlow;
 		} else {
 			first = ipport_firstauto;	/* sysctl */
 			last  = ipport_lastauto;
 			lastport = &pcbinfo->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 (ipport_randomized &&
 			(!ipport_stoprandom || pcbinfo == &udbinfo))
 			dorandom = 1;
 		else
 			dorandom = 0;
 		/* Make sure to not include UDP packets in the count. */
 		if (pcbinfo != &udbinfo)
 			ipport_tcpallocs++;
 		/*
 		 * 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
 			 */
 			if (dorandom)
 				*lastport = first -
 					    (arc4random() % (first - last));
 			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_local(pcbinfo, laddr, lport,
 			    wild));
 		} else {
 			/*
 			 * counting up
 			 */
 			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 (in_pcblookup_local(pcbinfo, laddr, lport,
 			    wild));
 		}
 	}
 	if (prison_ip(cred, 0, &laddr.s_addr))
 		return (EINVAL);
 	*laddrp = laddr.s_addr;
 	*lportp = lport;
 	return (0);
 }
 
 /*
  * Connect from a socket to a specified address.
  * Both address and port must be specified in argument sin.
  * If don't have a local address for this socket yet,
  * then pick one.
  */
 int
 in_pcbconnect(inp, nam, cred)
 	register struct inpcb *inp;
 	struct sockaddr *nam;
 	struct ucred *cred;
 {
 	u_short lport, fport;
 	in_addr_t laddr, faddr;
 	int anonport, error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	lport = inp->inp_lport;
 	laddr = inp->inp_laddr.s_addr;
 	anonport = (lport == 0);
 	error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport,
 	    NULL, cred);
 	if (error)
 		return (error);
 
 	/* Do the initial binding of the local address if required. */
 	if (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0) {
 		inp->inp_lport = lport;
 		inp->inp_laddr.s_addr = laddr;
 		if (in_pcbinshash(inp) != 0) {
 			inp->inp_laddr.s_addr = INADDR_ANY;
 			inp->inp_lport = 0;
 			return (EAGAIN);
 		}
 	}
 
 	/* Commit the remaining changes. */
 	inp->inp_lport = lport;
 	inp->inp_laddr.s_addr = laddr;
 	inp->inp_faddr.s_addr = faddr;
 	inp->inp_fport = fport;
 	in_pcbrehash(inp);
 #ifdef IPSEC
 	if (inp->inp_socket->so_type == SOCK_STREAM)
 		ipsec_pcbconn(inp->inp_sp);
 #endif
 	if (anonport)
 		inp->inp_flags |= INP_ANONPORT;
 	return (0);
 }
 
 /*
  * Set up for a connect from a socket to the specified address.
  * On entry, *laddrp and *lportp should contain the current local
  * address and port for the PCB; these are updated to the values
  * that should be placed in inp_laddr and inp_lport to complete
  * the connect.
  *
  * On success, *faddrp and *fportp will be set to the remote address
  * and port. These are not updated in the error case.
  *
  * If the operation fails because the connection already exists,
  * *oinpp will be set to the PCB of that connection so that the
  * caller can decide to override it. In all other cases, *oinpp
  * is set to NULL.
  */
 int
 in_pcbconnect_setup(inp, nam, laddrp, lportp, faddrp, fportp, oinpp, cred)
 	register struct inpcb *inp;
 	struct sockaddr *nam;
 	in_addr_t *laddrp;
 	u_short *lportp;
 	in_addr_t *faddrp;
 	u_short *fportp;
 	struct inpcb **oinpp;
 	struct ucred *cred;
 {
 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
 	struct in_ifaddr *ia;
 	struct sockaddr_in sa;
 	struct ucred *socred;
 	struct inpcb *oinp;
 	struct in_addr laddr, faddr;
 	u_short lport, fport;
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (oinpp != NULL)
 		*oinpp = NULL;
 	if (nam->sa_len != sizeof (*sin))
 		return (EINVAL);
 	if (sin->sin_family != AF_INET)
 		return (EAFNOSUPPORT);
 	if (sin->sin_port == 0)
 		return (EADDRNOTAVAIL);
 	laddr.s_addr = *laddrp;
 	lport = *lportp;
 	faddr = sin->sin_addr;
 	fport = sin->sin_port;
 	socred = inp->inp_socket->so_cred;
 	if (laddr.s_addr == INADDR_ANY && jailed(socred)) {
 		bzero(&sa, sizeof(sa));
 		sa.sin_addr.s_addr = htonl(prison_getip(socred));
 		sa.sin_len = sizeof(sa);
 		sa.sin_family = AF_INET;
 		error = in_pcbbind_setup(inp, (struct sockaddr *)&sa,
 		    &laddr.s_addr, &lport, cred);
 		if (error)
 			return (error);
 	}
 	if (!TAILQ_EMPTY(&in_ifaddrhead)) {
 		/*
 		 * If the destination address is INADDR_ANY,
 		 * use the primary local address.
 		 * If the supplied address is INADDR_BROADCAST,
 		 * and the primary interface supports broadcast,
 		 * choose the broadcast address for that interface.
 		 */
 		if (faddr.s_addr == INADDR_ANY)
 			faddr = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr;
 		else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
 		    (TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags &
 		    IFF_BROADCAST))
 			faddr = satosin(&TAILQ_FIRST(
 			    &in_ifaddrhead)->ia_broadaddr)->sin_addr;
 	}
 	if (laddr.s_addr == INADDR_ANY) {
 		struct route sro;
 
 		bzero(&sro, sizeof(sro));
 		ia = (struct in_ifaddr *)0;
 		/*
 		 * If route is known our src addr is taken from the i/f,
 		 * else punt.
 		 */
 		if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) {
 			/* Find out route to destination */
 			sro.ro_dst.sa_family = AF_INET;
 			sro.ro_dst.sa_len = sizeof(struct sockaddr_in);
 			((struct sockaddr_in *)&sro.ro_dst)->sin_addr = faddr;
 			rtalloc_ign(&sro, RTF_CLONING);
 		}
 		/*
 		 * If we found a route, use the address
 		 * corresponding to the outgoing interface.
 		 */
 		if (sro.ro_rt) {
 			ia = ifatoia(sro.ro_rt->rt_ifa);
 			RTFREE(sro.ro_rt);
 		}
 		if (ia == 0) {
 			bzero(&sa, sizeof(sa));
 			sa.sin_addr = faddr;
 			sa.sin_len = sizeof(sa);
 			sa.sin_family = AF_INET;
 
 			ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sa)));
 			if (ia == 0)
 				ia = ifatoia(ifa_ifwithnet(sintosa(&sa)));
 			if (ia == 0)
 				return (ENETUNREACH);
 		}
 		/*
 		 * If the destination address is multicast and an outgoing
 		 * interface has been set as a multicast option, use the
 		 * address of that interface as our source address.
 		 */
 		if (IN_MULTICAST(ntohl(faddr.s_addr)) &&
 		    inp->inp_moptions != NULL) {
 			struct ip_moptions *imo;
 			struct ifnet *ifp;
 
 			imo = inp->inp_moptions;
 			if (imo->imo_multicast_ifp != NULL) {
 				ifp = imo->imo_multicast_ifp;
 				TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
 					if (ia->ia_ifp == ifp)
 						break;
 				if (ia == 0)
 					return (EADDRNOTAVAIL);
 			}
 		}
 		laddr = ia->ia_addr.sin_addr;
 	}
 
 	oinp = in_pcblookup_hash(inp->inp_pcbinfo, faddr, fport, laddr, lport,
 	    0, NULL);
 	if (oinp != NULL) {
 		if (oinpp != NULL)
 			*oinpp = oinp;
 		return (EADDRINUSE);
 	}
 	if (lport == 0) {
 		error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport,
 		    cred);
 		if (error)
 			return (error);
 	}
 	*laddrp = laddr.s_addr;
 	*lportp = lport;
 	*faddrp = faddr.s_addr;
 	*fportp = fport;
 	return (0);
 }
 
 void
 in_pcbdisconnect(inp)
 	struct inpcb *inp;
 {
 	INP_LOCK_ASSERT(inp);
 
 	inp->inp_faddr.s_addr = INADDR_ANY;
 	inp->inp_fport = 0;
 	in_pcbrehash(inp);
 #ifdef IPSEC
 	ipsec_pcbdisconn(inp->inp_sp);
 #endif
 	if (inp->inp_socket->so_state & SS_NOFDREF)
 		in_pcbdetach(inp);
 }
 
 void
 in_pcbdetach(inp)
 	struct inpcb *inp;
 {
 	struct socket *so = inp->inp_socket;
 	struct inpcbinfo *ipi = inp->inp_pcbinfo;
 
 	INP_LOCK_ASSERT(inp);
 
 #if defined(IPSEC) || defined(FAST_IPSEC)
 	ipsec4_delete_pcbpolicy(inp);
 #endif /*IPSEC*/
 	inp->inp_gencnt = ++ipi->ipi_gencnt;
 	in_pcbremlists(inp);
 	if (so) {
 		ACCEPT_LOCK();
 		SOCK_LOCK(so);
 		so->so_pcb = NULL;
 		sotryfree(so);
 	}
 	if (inp->inp_options)
 		(void)m_free(inp->inp_options);
 	ip_freemoptions(inp->inp_moptions);
 	inp->inp_vflag = 0;
 	INP_LOCK_DESTROY(inp);
 #ifdef MAC
 	mac_destroy_inpcb(inp);
 #endif
 	uma_zfree(ipi->ipi_zone, inp);
 }
 
 struct sockaddr *
 in_sockaddr(port, addr_p)
 	in_port_t port;
 	struct in_addr *addr_p;
 {
 	struct sockaddr_in *sin;
 
 	MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME,
 		M_WAITOK | M_ZERO);
 	sin->sin_family = AF_INET;
 	sin->sin_len = sizeof(*sin);
 	sin->sin_addr = *addr_p;
 	sin->sin_port = port;
 
 	return (struct sockaddr *)sin;
 }
 
 /*
  * The wrapper function will pass down the pcbinfo for this function to lock.
  * The socket must have a valid
  * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
  * except through a kernel programming error, so it is acceptable to panic
  * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
  * because there actually /is/ a programming error somewhere... XXX)
  */
 int
 in_setsockaddr(so, nam, pcbinfo)
 	struct socket *so;
 	struct sockaddr **nam;
 	struct inpcbinfo *pcbinfo;
 {
 	int s;
 	register struct inpcb *inp;
 	struct in_addr addr;
 	in_port_t port;
 
 	s = splnet();
 	INP_INFO_RLOCK(pcbinfo);
 	inp = sotoinpcb(so);
 	if (!inp) {
 		INP_INFO_RUNLOCK(pcbinfo);
 		splx(s);
 		return ECONNRESET;
 	}
 	INP_LOCK(inp);
 	port = inp->inp_lport;
 	addr = inp->inp_laddr;
 	INP_UNLOCK(inp);
 	INP_INFO_RUNLOCK(pcbinfo);
 	splx(s);
 
 	*nam = in_sockaddr(port, &addr);
 	return 0;
 }
 
 /*
  * The wrapper function will pass down the pcbinfo for this function to lock.
  */
 int
 in_setpeeraddr(so, nam, pcbinfo)
 	struct socket *so;
 	struct sockaddr **nam;
 	struct inpcbinfo *pcbinfo;
 {
 	int s;
 	register struct inpcb *inp;
 	struct in_addr addr;
 	in_port_t port;
 
 	s = splnet();
 	INP_INFO_RLOCK(pcbinfo);
 	inp = sotoinpcb(so);
 	if (!inp) {
 		INP_INFO_RUNLOCK(pcbinfo);
 		splx(s);
 		return ECONNRESET;
 	}
 	INP_LOCK(inp);
 	port = inp->inp_fport;
 	addr = inp->inp_faddr;
 	INP_UNLOCK(inp);
 	INP_INFO_RUNLOCK(pcbinfo);
 	splx(s);
 
 	*nam = in_sockaddr(port, &addr);
 	return 0;
 }
 
 void
 in_pcbnotifyall(pcbinfo, faddr, errno, notify)
 	struct inpcbinfo *pcbinfo;
 	struct in_addr faddr;
 	int errno;
 	struct inpcb *(*notify)(struct inpcb *, int);
 {
 	struct inpcb *inp, *ninp;
 	struct inpcbhead *head;
 	int s;
 
 	s = splnet();
 	INP_INFO_WLOCK(pcbinfo);
 	head = pcbinfo->listhead;
 	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
 		INP_LOCK(inp);
 		ninp = LIST_NEXT(inp, inp_list);
 #ifdef INET6
 		if ((inp->inp_vflag & INP_IPV4) == 0) {
 			INP_UNLOCK(inp);
 			continue;
 		}
 #endif
 		if (inp->inp_faddr.s_addr != faddr.s_addr ||
 		    inp->inp_socket == NULL) {
 			INP_UNLOCK(inp);
 			continue;
 		}
 		if ((*notify)(inp, errno))
 			INP_UNLOCK(inp);
 	}
 	INP_INFO_WUNLOCK(pcbinfo);
 	splx(s);
 }
 
 void
 in_pcbpurgeif0(pcbinfo, ifp)
 	struct inpcbinfo *pcbinfo;
 	struct ifnet *ifp;
 {
 	struct inpcb *inp;
 	struct ip_moptions *imo;
 	int i, gap;
 
 	/* why no splnet here? XXX */
 	INP_INFO_RLOCK(pcbinfo);
 	LIST_FOREACH(inp, pcbinfo->listhead, inp_list) {
 		INP_LOCK(inp);
 		imo = inp->inp_moptions;
 		if ((inp->inp_vflag & INP_IPV4) &&
 		    imo != NULL) {
 			/*
 			 * Unselect the outgoing interface if it is being
 			 * detached.
 			 */
 			if (imo->imo_multicast_ifp == ifp)
 				imo->imo_multicast_ifp = NULL;
 
 			/*
 			 * Drop multicast group membership if we joined
 			 * through the interface being detached.
 			 */
 			for (i = 0, gap = 0; i < imo->imo_num_memberships;
 			    i++) {
 				if (imo->imo_membership[i]->inm_ifp == ifp) {
 					in_delmulti(imo->imo_membership[i]);
 					gap++;
 				} else if (gap != 0)
 					imo->imo_membership[i - gap] =
 					    imo->imo_membership[i];
 			}
 			imo->imo_num_memberships -= gap;
 		}
 		INP_UNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(pcbinfo);
 }
 
 /*
  * Lookup a PCB based on the local address and port.
  */
 struct inpcb *
 in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
 	struct inpcbinfo *pcbinfo;
 	struct in_addr laddr;
 	u_int lport_arg;
 	int wild_okay;
 {
 	register struct inpcb *inp;
 	int matchwild = 3, wildcard;
 	u_short lport = lport_arg;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 
 	if (!wild_okay) {
 		struct inpcbhead *head;
 		/*
 		 * Look for an unconnected (wildcard foreign addr) PCB that
 		 * matches the local address and port we're looking for.
 		 */
 		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
 		LIST_FOREACH(inp, head, inp_hash) {
 #ifdef INET6
 			if ((inp->inp_vflag & INP_IPV4) == 0)
 				continue;
 #endif
 			if (inp->inp_faddr.s_addr == INADDR_ANY &&
 			    inp->inp_laddr.s_addr == laddr.s_addr &&
 			    inp->inp_lport == lport) {
 				/*
 				 * Found.
 				 */
 				return (inp);
 			}
 		}
 		/*
 		 * Not found.
 		 */
 		return (NULL);
 	} else {
 		struct inpcbporthead *porthash;
 		struct inpcbport *phd;
 		struct inpcb *match = NULL;
 		/*
 		 * Best fit PCB lookup.
 		 *
 		 * First see if this local port is in use by looking on the
 		 * port hash list.
 		 */
 		retrylookup:
 		porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
 		    pcbinfo->porthashmask)];
 		LIST_FOREACH(phd, porthash, phd_hash) {
 			if (phd->phd_port == lport)
 				break;
 		}
 		if (phd != NULL) {
 			/*
 			 * Port is in use by one or more PCBs. Look for best
 			 * fit.
 			 */
 			LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
 				wildcard = 0;
 #ifdef INET6
 				if ((inp->inp_vflag & INP_IPV4) == 0)
 					continue;
 #endif
 				/*
 				 * Clean out old time_wait sockets if they
 				 * are clogging up needed local ports.
 				 */
 				if ((inp->inp_vflag & INP_TIMEWAIT) != 0) {
 					if (tcp_twrecycleable((struct tcptw *)inp->inp_ppcb)) {
 						INP_LOCK(inp);
 						tcp_twclose((struct tcptw *)inp->inp_ppcb, 0);
 						match = NULL;
 						goto retrylookup;
 					}
 				}
 				if (inp->inp_faddr.s_addr != INADDR_ANY)
 					wildcard++;
 				if (inp->inp_laddr.s_addr != INADDR_ANY) {
 					if (laddr.s_addr == INADDR_ANY)
 						wildcard++;
 					else if (inp->inp_laddr.s_addr != laddr.s_addr)
 						continue;
 				} else {
 					if (laddr.s_addr != INADDR_ANY)
 						wildcard++;
 				}
 				if (wildcard < matchwild) {
 					match = inp;
 					matchwild = wildcard;
 					if (matchwild == 0) {
 						break;
 					}
 				}
 			}
 		}
 		return (match);
 	}
 }
 
 /*
  * Lookup PCB in hash list.
  */
 struct inpcb *
 in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard,
 		  ifp)
 	struct inpcbinfo *pcbinfo;
 	struct in_addr faddr, laddr;
 	u_int fport_arg, lport_arg;
 	int wildcard;
 	struct ifnet *ifp;
 {
 	struct inpcbhead *head;
 	register struct inpcb *inp;
 	u_short fport = fport_arg, lport = lport_arg;
 
 	INP_INFO_RLOCK_ASSERT(pcbinfo);
 	/*
 	 * First look for an exact match.
 	 */
 	head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];
 	LIST_FOREACH(inp, head, inp_hash) {
 #ifdef INET6
 		if ((inp->inp_vflag & INP_IPV4) == 0)
 			continue;
 #endif
 		if (inp->inp_faddr.s_addr == faddr.s_addr &&
 		    inp->inp_laddr.s_addr == laddr.s_addr &&
 		    inp->inp_fport == fport &&
 		    inp->inp_lport == lport) {
 			/*
 			 * Found.
 			 */
 			return (inp);
 		}
 	}
 	if (wildcard) {
 		struct inpcb *local_wild = NULL;
 #if defined(INET6)
 		struct inpcb *local_wild_mapped = NULL;
 #endif /* defined(INET6) */
 
 		head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
 		LIST_FOREACH(inp, head, inp_hash) {
 #ifdef INET6
 			if ((inp->inp_vflag & INP_IPV4) == 0)
 				continue;
 #endif
 			if (inp->inp_faddr.s_addr == INADDR_ANY &&
 			    inp->inp_lport == lport) {
 				if (ifp && ifp->if_type == IFT_FAITH &&
 				    (inp->inp_flags & INP_FAITH) == 0)
 					continue;
 				if (inp->inp_laddr.s_addr == laddr.s_addr)
 					return (inp);
 				else if (inp->inp_laddr.s_addr == INADDR_ANY) {
 #if defined(INET6)
 					if (INP_CHECK_SOCKAF(inp->inp_socket,
 							     AF_INET6))
 						local_wild_mapped = inp;
 					else
 #endif /* defined(INET6) */
 					local_wild = inp;
 				}
 			}
 		}
 #if defined(INET6)
 		if (local_wild == NULL)
 			return (local_wild_mapped);
 #endif /* defined(INET6) */
 		return (local_wild);
 	}
 
 	/*
 	 * Not found.
 	 */
 	return (NULL);
 }
 
 /*
  * Insert PCB onto various hash lists.
  */
 int
 in_pcbinshash(inp)
 	struct inpcb *inp;
 {
 	struct inpcbhead *pcbhash;
 	struct inpcbporthead *pcbporthash;
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct inpcbport *phd;
 	u_int32_t hashkey_faddr;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
 		hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
 	else
 #endif /* INET6 */
 	hashkey_faddr = inp->inp_faddr.s_addr;
 
 	pcbhash = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
 		 inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
 
 	pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport,
 	    pcbinfo->porthashmask)];
 
 	/*
 	 * Go through port list and look for a head for this lport.
 	 */
 	LIST_FOREACH(phd, pcbporthash, phd_hash) {
 		if (phd->phd_port == inp->inp_lport)
 			break;
 	}
 	/*
 	 * If none exists, malloc one and tack it on.
 	 */
 	if (phd == NULL) {
 		MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_NOWAIT);
 		if (phd == NULL) {
 			return (ENOBUFS); /* XXX */
 		}
 		phd->phd_port = inp->inp_lport;
 		LIST_INIT(&phd->phd_pcblist);
 		LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
 	}
 	inp->inp_phd = phd;
 	LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
 	LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
 	return (0);
 }
 
 /*
  * Move PCB to the proper hash bucket when { faddr, fport } have  been
  * changed. NOTE: This does not handle the case of the lport changing (the
  * hashed port list would have to be updated as well), so the lport must
  * not change after in_pcbinshash() has been called.
  */
 void
 in_pcbrehash(inp)
 	struct inpcb *inp;
 {
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct inpcbhead *head;
 	u_int32_t hashkey_faddr;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	INP_LOCK_ASSERT(inp);
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
 		hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
 	else
 #endif /* INET6 */
 	hashkey_faddr = inp->inp_faddr.s_addr;
 
 	head = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
 		inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
 
 	LIST_REMOVE(inp, inp_hash);
 	LIST_INSERT_HEAD(head, inp, inp_hash);
 }
 
 /*
  * Remove PCB from various lists.
  */
 void
 in_pcbremlists(inp)
 	struct inpcb *inp;
 {
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	if (inp->inp_lport) {
 		struct inpcbport *phd = inp->inp_phd;
 
 		LIST_REMOVE(inp, inp_hash);
 		LIST_REMOVE(inp, inp_portlist);
 		if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
 			LIST_REMOVE(phd, phd_hash);
 			free(phd, M_PCB);
 		}
 	}
 	LIST_REMOVE(inp, inp_list);
 	pcbinfo->ipi_count--;
 }
 
 /*
  * A set label operation has occurred at the socket layer, propagate the
  * label change into the in_pcb for the socket.
  */
 void
 in_pcbsosetlabel(so)
 	struct socket *so;
 {
 #ifdef MAC
 	struct inpcb *inp;
 
 	inp = (struct inpcb *)so->so_pcb;
 	INP_LOCK(inp);
 	SOCK_LOCK(so);
 	mac_inpcb_sosetlabel(so, inp);
 	SOCK_UNLOCK(so);
 	INP_UNLOCK(inp);
 #endif
 }
 
 /*
  * ipport_tick runs once per second, determining if random port
  * allocation should be continued.  If more than ipport_randomcps
  * ports have been allocated in the last second, then we return to
  * sequential port allocation. We return to random allocation only
- * once we drop below ipport_randomcps for at least 5 seconds.
+ * once we drop below ipport_randomcps for at least ipport_randomtime
+ * seconds.
  */
 
 void
 ipport_tick(xtp)
 	void *xtp;
 {
 	if (ipport_tcpallocs > ipport_tcplastcount + ipport_randomcps) {
 		ipport_stoprandom = ipport_randomtime;
 	} else {
 		if (ipport_stoprandom > 0)
 			ipport_stoprandom--;
 	}
 	ipport_tcplastcount = ipport_tcpallocs;
 	callout_reset(&ipport_tick_callout, hz, ipport_tick, NULL);
 }