Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Aug 2011 19:14:22 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r224638 - head/crypto/openssh
Message-ID:  <201108031914.p73JEMeh026068@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Wed Aug  3 19:14:22 2011
New Revision: 224638
URL: http://svn.freebsd.org/changeset/base/224638

Log:
  Add support for dynamically adjusted buffers to allow the full use of
  the bandwidth of long fat pipes (i.e. 100Mbps+ trans-oceanic or
  trans-continental links).  Bandwidth-delay products up to 64MB are
  supported.
  
  Also add support (not compiled by default) for the None cypher.  The
  None cypher can only be enabled on non-interactive sessions (those
  without a pty where -T was not used) and must be enabled in both
  the client and server configuration files and on the client command
  line.  Additionally, the None cypher will only be activated after
  authentication is complete.  To enable the None cypher you must add
  -DNONE_CIPHER_ENABLED to CFLAGS via the make command line or in
  /etc/make.conf.
  
  This code is a style(9) compliant version of these features extracted
  from the patches published at:
  
  http://www.psc.edu/networking/projects/hpn-ssh/
  
  Merging this patch has been a collaboration between me and Bjoern.
  
  Reviewed by:	bz
  Approved by:	re (kib), des (maintainer)

Added:
  head/crypto/openssh/README.hpn
Modified:
  head/crypto/openssh/buffer.c
  head/crypto/openssh/buffer.h
  head/crypto/openssh/channels.c
  head/crypto/openssh/channels.h
  head/crypto/openssh/cipher.c
  head/crypto/openssh/clientloop.c
  head/crypto/openssh/compat.c
  head/crypto/openssh/compat.h
  head/crypto/openssh/kex.c
  head/crypto/openssh/kex.h
  head/crypto/openssh/misc.c
  head/crypto/openssh/misc.h
  head/crypto/openssh/myproposal.h
  head/crypto/openssh/packet.c
  head/crypto/openssh/packet.h
  head/crypto/openssh/readconf.c
  head/crypto/openssh/readconf.h
  head/crypto/openssh/servconf.c
  head/crypto/openssh/servconf.h
  head/crypto/openssh/serverloop.c
  head/crypto/openssh/session.c
  head/crypto/openssh/sftp.1
  head/crypto/openssh/sftp.c
  head/crypto/openssh/ssh.c
  head/crypto/openssh/sshconnect.c
  head/crypto/openssh/sshconnect2.c
  head/crypto/openssh/sshd.c
  head/crypto/openssh/sshd_config
  head/crypto/openssh/version.c
  head/crypto/openssh/version.h

Added: head/crypto/openssh/README.hpn
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/crypto/openssh/README.hpn	Wed Aug  3 19:14:22 2011	(r224638)
@@ -0,0 +1,120 @@
+Notes:
+
+NONE CIPHER:
+  To use the NONE option you must have the NoneEnabled switch set on the server
+  and you MUST have *both* NoneEnabled and NoneSwitch set to yes on the client.
+  The NONE feature works with ALL ssh subsystems (as far as we can tell)
+  as long as there is no tty allocated.
+  If a user uses the -T switch to prevent a tty being created the NONE cipher
+  will be disabled. 
+
+
+PERFORMANCE:
+  The performance increase will only be as good as the network and TCP stack
+  tuning on the reciever side of the connection allows.  As a rule of thumb a
+  user will need at least 10Mb/s connection with a 100ms RTT to see a doubling
+  of performance.
+  The HPN-SSH home page  http://www.psc.edu/networking/projects/hpn-ssh
+  describes this in greater detail. 
+
+
+BUFFER SIZES:
+- if HPN is disabled the receive buffer size will be set to the OpenSSH default
+  of 64K.
+
+- if a HPN system connects to a non-HPN system the receive buffer will
+  be set to the HPNBufferSize value. The default is 2MB but user adjustable.
+
+- If a HPN to HPN connection is established a number of different things might
+  happen based on the user options and conditions. 
+
+  Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set 
+  Result: HPN Buffer Size = up to 64MB 
+    This is the default state.  The HPN buffer size will grow to a maximum of
+    64MB as the TCP receive buffer grows.  The maximum HPN Buffer size of 64MB
+    is geared towards 10GigE transcontinental connections. 
+
+  Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set
+  Result: HPN Buffer Size = TCP receive buffer value. 
+    Users on non-autotuning systesm should disable TCPRcvBufPoll in the 
+    ssh_cofig and sshd_config
+
+  Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set
+  Result: HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. 
+    This would be the system defined TCP receive buffer (RWIN).
+
+  Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET
+  Result: HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. 
+    Generally there is no need to set both.
+
+  Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set
+  Result: HPN Buffer Size = grows to HPNBufferSize
+    The buffer will grow up to the maximum size specified here. 
+
+  Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET
+  Result: HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. 
+    Generally there is no need to set both of these, especially on autotuning 
+    systems. However, if the users wishes to override the autotuning this would
+    be one way to do it.
+
+  Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET
+  Result: HPN Buffer Size = TCPRcvBuf. 
+   This will override autotuning and set the TCP recieve buffer to the user
+   defined value.
+
+
+HPN SPECIFIC CONFIGURATION OPTIONS:
+
+- HPNDisabled=[yes/no] client/server
+  In some situations, such as transfers on a local area network, the impact 
+  of the HPN code produces a net decrease in performance.  In these cases it is 
+  helpful to disable the HPN functionality. By default HPNDisabled is set to no. 
+
+- HPNBufferSize=[int]KB client/server
+  This is the default buffer size the HPN functionality uses when interacting
+  with non-HPN SSH installations.  Conceptually this is similar to the TcpRcvBuf
+  option as applied to the internal SSH flow control.  This value can range from 
+  1KB to 64MB (1-65536).  Use of oversized or undersized buffers can cause
+  performance problems depending on the roud trip time of the network path.
+  The default size of this buffer is 2MB.
+
+- TcpRcvBufPoll=[yes/no] client/server
+  Enable or disable the polling of the TCP receive buffer through the life 
+  of the connection.  You would want to make sure that this option is enabled 
+  for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista,
+  FreeBSD 7.x and later). Default is yes.
+
+- TcpRcvBuf=[int]KB client
+  Set the TCP socket receive buffer to n Kilobytes.  It can be set up to the 
+  maximum socket size allowed by the system.  This is useful in situations where 
+  the TCP receive window is set low but the maximum buffer size is set higher
+  (as is typical).  This works on a per TCP connection basis.  You can also use
+  this to artifically limit the transfer rate of the connection.  In these cases
+  the throughput will be no more than n/RTT.  The minimum buffer size is 1KB. 
+  Default is the current system wide TCP receive buffer size.
+
+- NoneEnabled=[yes/no] client/server
+  Enable or disable the use of the None cipher.  Care must always be used when
+  enabling this as it will allow users to send data in the clear.  However, it
+  is important to note that authentication information remains encrypted even
+  if this option is enabled.  Set to no by default.
+
+- NoneSwitch=[yes/no] client
+  Switch the encryption cipher being used to the None cipher after
+  authentication takes place.  NoneEnabled must be enabled on both the client
+  and server side of the connection.  When the connection switches to the NONE
+  cipher a warning is sent to STDERR.  The connection attempt will fail with an
+  error if a client requests a NoneSwitch from the server that does not
+  explicitly have NoneEnabled set to yes.
+  Note: The NONE cipher cannot be used in interactive (shell) sessions and it
+  will fail silently.  Set to no by default.
+
+
+CREDITS:
+
+  This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu)
+  The majority of the actual coding for versions up to HPN12v1 was performed
+  by Michael Stevens (mstevens@andrew.cmu.edu).
+  The MT-AES-CTR cipher was implemented by Ben Bennet (ben@psc.edu).
+  This work was financed, in part, by Cisco System, Inc., the National Library
+  of Medicine, and the National Science Foundation. 

Modified: head/crypto/openssh/buffer.c
==============================================================================
--- head/crypto/openssh/buffer.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/buffer.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: buffer.c,v 1.32 2010/02/09 03:56:28 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -25,7 +26,7 @@
 #include "log.h"
 
 #define	BUFFER_MAX_CHUNK	0x100000
-#define	BUFFER_MAX_LEN		0xa00000
+#define	BUFFER_MAX_LEN		0x4000000	/* 64MB */
 #define	BUFFER_ALLOCSZ		0x008000
 
 /* Initializes the buffer structure. */
@@ -165,6 +166,13 @@ buffer_len(const Buffer *buffer)
 	return buffer->end - buffer->offset;
 }
 
+/* Returns the maximum number of bytes of data that may be in the buffer. */
+u_int
+buffer_get_max_len(void)
+{
+	return (BUFFER_MAX_LEN);
+}
+
 /* Gets data from the beginning of the buffer. */
 
 int

Modified: head/crypto/openssh/buffer.h
==============================================================================
--- head/crypto/openssh/buffer.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/buffer.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: buffer.h,v 1.21 2010/08/31 11:54:45 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -46,6 +47,8 @@ int	 buffer_get_ret(Buffer *, void *, u_
 int	 buffer_consume_ret(Buffer *, u_int);
 int	 buffer_consume_end_ret(Buffer *, u_int);
 
+u_int	 buffer_get_max_len(void);
+
 #include <openssl/bn.h>
 
 void    buffer_put_bignum(Buffer *, const BIGNUM *);

Modified: head/crypto/openssh/channels.c
==============================================================================
--- head/crypto/openssh/channels.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/channels.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: channels.c,v 1.310 2010/11/24 01:24:14 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -170,6 +171,11 @@ static void port_open_helper(Channel *c,
 static int connect_next(struct channel_connect *);
 static void channel_connect_ctx_free(struct channel_connect *);
 
+/* -- HPN */
+
+static int hpn_disabled = 0;
+static u_int buffer_size = CHAN_HPN_MIN_WINDOW_DEFAULT;
+
 /* -- channel core */
 
 Channel *
@@ -309,6 +315,7 @@ channel_new(char *ctype, int type, int r
 	c->self = found;
 	c->type = type;
 	c->ctype = ctype;
+	c->dynamic_window = 0;
 	c->local_window = window;
 	c->local_window_max = window;
 	c->local_consumed = 0;
@@ -808,11 +815,46 @@ channel_pre_open_13(Channel *c, fd_set *
 		FD_SET(c->sock, writeset);
 }
 
+static u_int
+channel_tcpwinsz(void)
+{
+	u_int32_t tcpwinsz;
+	socklen_t optsz;
+	int ret, sd;
+	u_int maxlen;
+
+	/* If we are not on a socket return 128KB. */
+	if (!packet_connection_is_on_socket()) 
+		return (128 * 1024);
+
+	tcpwinsz = 0;
+	optsz = sizeof(tcpwinsz);
+	sd = packet_get_connection_in();
+	ret = getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+
+	/* Return no more than the maximum buffer size. */
+	maxlen = buffer_get_max_len();
+	if ((ret == 0) && tcpwinsz > maxlen)
+		tcpwinsz = maxlen;
+	/* In case getsockopt() failed return a minimum. */
+	if (tcpwinsz == 0)
+		tcpwinsz = CHAN_TCP_WINDOW_DEFAULT;
+	debug2("tcpwinsz: %d for connection: %d", tcpwinsz, sd);
+	return (tcpwinsz);
+}
+
 static void
 channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
 {
-	u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
+	u_int limit;
 
+	/* Check buffer limits. */
+	if (!c->tcpwinsz || c->dynamic_window > 0)
+		c->tcpwinsz = channel_tcpwinsz();
+
+	limit = MIN(compat20 ? c->remote_window : packet_get_maxsize(),
+	    2 * c->tcpwinsz);
+	
 	if (c->istate == CHAN_INPUT_OPEN &&
 	    limit > 0 &&
 	    buffer_len(&c->input) < limit &&
@@ -1789,14 +1831,25 @@ channel_check_window(Channel *c)
 	    c->local_maxpacket*3) ||
 	    c->local_window < c->local_window_max/2) &&
 	    c->local_consumed > 0) {
+		u_int addition = 0;
+
+		/* Adjust max window size if we are in a dynamic environment. */
+		if (c->dynamic_window && c->tcpwinsz > c->local_window_max) {
+			/*
+			 * Grow the window somewhat aggressively to maintain
+			 * pressure.
+			 */
+			addition = 1.5 * (c->tcpwinsz - c->local_window_max);
+			c->local_window_max += addition;
+		}
 		packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
 		packet_put_int(c->remote_id);
-		packet_put_int(c->local_consumed);
+		packet_put_int(c->local_consumed + addition);
 		packet_send();
 		debug2("channel %d: window %d sent adjust %d",
 		    c->self, c->local_window,
 		    c->local_consumed);
-		c->local_window += c->local_consumed;
+		c->local_window += c->local_consumed + addition;
 		c->local_consumed = 0;
 	}
 	return 1;
@@ -2634,6 +2687,15 @@ channel_set_af(int af)
 	IPv4or6 = af;
 }
 
+void 
+channel_set_hpn(int disabled, u_int buf_size)
+{
+      	hpn_disabled = disabled;
+	buffer_size = buf_size;
+	debug("HPN Disabled: %d, HPN Buffer Size: %d",
+	    hpn_disabled, buffer_size);
+}
+
 static int
 channel_setup_fwd_listener(int type, const char *listen_addr,
     u_short listen_port, int *allocated_listen_port,
@@ -2786,10 +2848,18 @@ channel_setup_fwd_listener(int type, con
 			    *allocated_listen_port);
 		}
 
-		/* Allocate a channel number for the socket. */
-		c = channel_new("port listener", type, sock, sock, -1,
-		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
-		    0, "port listener", 1);
+		/*
+		 * Allocate a channel number for the socket.  Explicitly test
+		 * for hpn disabled option.  If true use smaller window size.
+		 */
+		if (hpn_disabled)
+			c = channel_new("port listener", type, sock, sock, -1,
+			    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+			    0, "port listener", 1);
+ 		else
+ 			c = channel_new("port listener", type, sock, sock, -1,
+ 		    	    buffer_size, CHAN_TCP_PACKET_DEFAULT,
+ 		    	    0, "port listener", 1);
 		c->path = xstrdup(host);
 		c->host_port = port_to_connect;
 		c->listening_port = listen_port;
@@ -3334,10 +3404,16 @@ x11_create_display_inet(int x11_display_
 	*chanids = xcalloc(num_socks + 1, sizeof(**chanids));
 	for (n = 0; n < num_socks; n++) {
 		sock = socks[n];
-		nc = channel_new("x11 listener",
-		    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
-		    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
-		    0, "X11 inet listener", 1);
+		if (hpn_disabled)
+			nc = channel_new("x11 listener",
+			    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+			    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+			    0, "X11 inet listener", 1);
+		else
+			nc = channel_new("x11 listener",
+			    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+			    buffer_size, CHAN_X11_PACKET_DEFAULT,
+			    0, "X11 inet listener", 1);
 		nc->single_connection = single_connection;
 		(*chanids)[n] = nc->self;
 	}

Modified: head/crypto/openssh/channels.h
==============================================================================
--- head/crypto/openssh/channels.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/channels.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: channels.h,v 1.104 2010/05/14 23:29:23 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -125,6 +126,8 @@ struct Channel {
 	u_int	local_window_max;
 	u_int	local_consumed;
 	u_int	local_maxpacket;
+	u_int 	tcpwinsz;	
+	int	dynamic_window;
 	int     extended_usage;
 	int	single_connection;
 
@@ -162,11 +165,15 @@ struct Channel {
 /* default window/packet sizes for tcp/x11-fwd-channel */
 #define CHAN_SES_PACKET_DEFAULT	(32*1024)
 #define CHAN_SES_WINDOW_DEFAULT	(64*CHAN_SES_PACKET_DEFAULT)
+
 #define CHAN_TCP_PACKET_DEFAULT	(32*1024)
 #define CHAN_TCP_WINDOW_DEFAULT	(64*CHAN_TCP_PACKET_DEFAULT)
+
 #define CHAN_X11_PACKET_DEFAULT	(16*1024)
 #define CHAN_X11_WINDOW_DEFAULT	(4*CHAN_X11_PACKET_DEFAULT)
 
+#define CHAN_HPN_MIN_WINDOW_DEFAULT	(2*1024*1024)
+
 /* possible input states */
 #define CHAN_INPUT_OPEN			0
 #define CHAN_INPUT_WAIT_DRAIN		1
@@ -294,4 +301,7 @@ void	 chan_rcvd_ieof(Channel *);
 void	 chan_write_failed(Channel *);
 void	 chan_obuf_empty(Channel *);
 
+/* hpn handler */
+void     channel_set_hpn(int, u_int);
+
 #endif

Modified: head/crypto/openssh/cipher.c
==============================================================================
--- head/crypto/openssh/cipher.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/cipher.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -163,7 +164,12 @@ ciphers_valid(const char *names)
 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
 	    (p = strsep(&cp, CIPHER_SEP))) {
 		c = cipher_by_name(p);
-		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+#ifdef NONE_CIPHER_ENABLED
+		if (c == NULL || (c->number != SSH_CIPHER_SSH2 &&
+		    c->number != SSH_CIPHER_NONE)) {
+#else
+		if (c == NULL || (c->number != SSH_CIPHER_SSH2)) {
+#endif
 			debug("bad cipher %s [%s]", p, names);
 			xfree(cipher_list);
 			return 0;
@@ -337,6 +343,9 @@ cipher_get_keyiv(CipherContext *cc, u_ch
 	int evplen;
 
 	switch (c->number) {
+#ifdef	NONE_CIPHER_ENABLED
+	case SSH_CIPHER_NONE:
+#endif
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:
@@ -371,6 +380,9 @@ cipher_set_keyiv(CipherContext *cc, u_ch
 	int evplen = 0;
 
 	switch (c->number) {
+#ifdef	NONE_CIPHER_ENABLED
+	case SSH_CIPHER_NONE:
+#endif
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:

Modified: head/crypto/openssh/clientloop.c
==============================================================================
--- head/crypto/openssh/clientloop.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/clientloop.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1768,9 +1769,14 @@ client_request_x11(const char *request_t
 	sock = x11_connect_display();
 	if (sock < 0)
 		return NULL;
-	c = channel_new("x11",
-	    SSH_CHANNEL_X11_OPEN, sock, sock, -1,
-	    CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+	if (options.hpn_disabled)
+		c = channel_new("x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+		    CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+		    0, "x11", 1);
+	else
+		c = channel_new("x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+		    options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT,
+		    0, "x11", 1);
 	c->force_drain = 1;
 	return c;
 }
@@ -1790,10 +1796,16 @@ client_request_agent(const char *request
 	sock = ssh_get_authentication_socket();
 	if (sock < 0)
 		return NULL;
-	c = channel_new("authentication agent connection",
-	    SSH_CHANNEL_OPEN, sock, sock, -1,
-	    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
-	    "authentication agent connection", 1);
+	if (options.hpn_disabled)
+		c = channel_new("authentication agent connection",
+		    SSH_CHANNEL_OPEN, sock, sock, -1,
+		    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
+		    "authentication agent connection", 1);
+	else
+		c = channel_new("authentication agent connection",
+		    SSH_CHANNEL_OPEN, sock, sock, -1,
+		    options.hpn_buffer_size, options.hpn_buffer_size, 0,
+		    "authentication agent connection", 1);
 	c->force_drain = 1;
 	return c;
 }
@@ -1820,8 +1832,14 @@ client_request_tun_fwd(int tun_mode, int
 		return -1;
 	}
 
-	c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
-	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+	if (options.hpn_disabled)
+		c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+		    0, "tun", 1);
+	else
+		c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+		    options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+		    0, "tun", 1);
 	c->datagram = 1;
 
 #if defined(SSH_TUN_FILTER)

Modified: head/crypto/openssh/compat.c
==============================================================================
--- head/crypto/openssh/compat.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/compat.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: compat.c,v 1.78 2008/09/11 14:22:37 markus Exp $ */
+/* $FreeBSD$ */
 /*
  * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  *
@@ -170,6 +171,16 @@ compat_datafellows(const char *version)
 		    strlen(check[i].pat), 0) == 1) {
 			debug("match: %s pat %s", version, check[i].pat);
 			datafellows = check[i].bugs;
+			/*
+			 * Check to see if the remote side is OpenSSH and not
+			 * HPN.  It is utterly strange to check it from the
+			 * version string and expose the option that way.
+			 */
+			if (strstr(version,"OpenSSH") != NULL &&
+			    strstr(version,"hpn") == NULL) {
+				datafellows |= SSH_BUG_LARGEWINDOW;
+				debug("Remote is not HPN-aware");
+			}
 			return;
 		}
 	}

Modified: head/crypto/openssh/compat.h
==============================================================================
--- head/crypto/openssh/compat.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/compat.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: compat.h,v 1.42 2008/09/11 14:22:37 markus Exp $ */
+/* $FReeBSD$ */
 
 /*
  * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
@@ -58,6 +59,7 @@
 #define SSH_OLD_FORWARD_ADDR	0x01000000
 #define SSH_BUG_RFWD_ADDR	0x02000000
 #define SSH_NEW_OPENSSH		0x04000000
+#define SSH_BUG_LARGEWINDOW	0x08000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);

Modified: head/crypto/openssh/kex.c
==============================================================================
--- head/crypto/openssh/kex.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/kex.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: kex.c,v 1.86 2010/09/22 05:01:29 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -90,8 +91,13 @@ kex_names_valid(const char *names)
 	return 1;
 }
 
-/* put algorithm proposal into buffer */
+/* Put algorithm proposal into buffer. */
+#ifndef NONE_CIPHER_ENABLED
 static void
+#else
+/* Also used in sshconnect2.c. */
+void
+#endif
 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
 	u_int i;
@@ -407,6 +413,9 @@ kex_choose_conf(Kex *kex)
 	int nenc, nmac, ncomp;
 	u_int mode, ctos, need;
 	int first_kex_follows, type;
+#ifdef	NONE_CIPHER_ENABLED
+	int auth_flag;
+#endif
 
 	my   = kex_buf2prop(&kex->my, NULL);
 	peer = kex_buf2prop(&kex->peer, &first_kex_follows);
@@ -430,6 +439,10 @@ kex_choose_conf(Kex *kex)
 	}
 
 	/* Algorithm Negotiation */
+#ifdef	NONE_CIPHER_ENABLED
+	auth_flag = packet_get_authentication_state();
+	debug ("AUTH STATE is %d", auth_flag);
+#endif
 	for (mode = 0; mode < MODE_MAX; mode++) {
 		newkeys = xcalloc(1, sizeof(*newkeys));
 		kex->newkeys[mode] = newkeys;
@@ -441,6 +454,17 @@ kex_choose_conf(Kex *kex)
 		choose_enc (&newkeys->enc,  cprop[nenc],  sprop[nenc]);
 		choose_mac (&newkeys->mac,  cprop[nmac],  sprop[nmac]);
 		choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
+#ifdef	NONE_CIPHER_ENABLED
+		debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
+		if (strcmp(newkeys->enc.name, "none") == 0) {
+			debug("Requesting NONE. Authflag is %d", auth_flag);			
+			if (auth_flag == 1)
+				debug("None requested post authentication.");
+			else
+				fatal("Pre-authentication none cipher requests "
+				    "are not allowed.");
+		} 
+#endif
 		debug("kex: %s %s %s %s",
 		    ctos ? "client->server" : "server->client",
 		    newkeys->enc.name,

Modified: head/crypto/openssh/kex.h
==============================================================================
--- head/crypto/openssh/kex.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/kex.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -140,6 +141,10 @@ struct Kex {
 
 int	 kex_names_valid(const char *);
 
+#ifdef	NONE_CIPHER_ENABLED
+void	 kex_prop2buf(Buffer *, char *[PROPOSAL_MAX]);
+#endif
+
 Kex	*kex_setup(char *[PROPOSAL_MAX]);
 void	 kex_finish(Kex *);
 

Modified: head/crypto/openssh/misc.c
==============================================================================
--- head/crypto/openssh/misc.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/misc.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: misc.c,v 1.84 2010/11/21 01:01:13 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
@@ -996,3 +997,34 @@ sock_set_v6only(int s)
 		error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
 #endif
 }
+
+void
+sock_get_rcvbuf(int *size, int rcvbuf)
+{
+	int sock, socksize;
+	socklen_t socksizelen = sizeof(socksize);
+
+	/*
+	 * Create a socket but do not connect it.  We use it
+	 * only to get the rcv socket size.
+	 */
+	sock = socket(AF_INET6, SOCK_STREAM, 0);
+	if (sock < 0)
+		sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (sock < 0)
+		return;
+
+	/*
+	 * If the tcp_rcv_buf option is set and passed in, attempt to set the
+	 *  buffer size to its value.
+	 */
+	if (rcvbuf)
+		setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf,
+		    sizeof(rcvbuf));
+
+	if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+	    &socksize, &socksizelen) == 0)
+		if (size != NULL)
+			*size = socksize;
+	close(sock);
+}

Modified: head/crypto/openssh/misc.h
==============================================================================
--- head/crypto/openssh/misc.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/misc.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: misc.h,v 1.47 2010/11/21 01:01:13 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -36,6 +37,7 @@ void	 sanitise_stdfd(void);
 void	 ms_subtract_diff(struct timeval *, int *);
 void	 ms_to_timeval(struct timeval *, int);
 void	 sock_set_v6only(int);
+void	 sock_get_rcvbuf(int *, int);
 
 struct passwd *pwcopy(struct passwd *);
 const char *ssh_gai_strerror(int);

Modified: head/crypto/openssh/myproposal.h
==============================================================================
--- head/crypto/openssh/myproposal.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/myproposal.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: myproposal.h,v 1.27 2010/09/01 22:42:13 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -75,6 +76,10 @@
 	"arcfour256,arcfour128," \
 	"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
 	"aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
+#ifdef	NONE_CIPHER_ENABLED
+#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \
+	",none"
+#endif
 #define	KEX_DEFAULT_MAC \
 	"hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \
 	"hmac-ripemd160@openssh.com," \

Modified: head/crypto/openssh/packet.c
==============================================================================
--- head/crypto/openssh/packet.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/packet.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: packet.c,v 1.172 2010/11/13 23:27:50 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -195,6 +196,9 @@ struct session_state {
 };
 
 static struct session_state *active_state, *backup_state;
+#ifdef	NONE_CIPHER_ENABLED
+static int rekey_requested = 0;
+#endif
 
 static struct session_state *
 alloc_session_state(void)
@@ -1861,12 +1865,26 @@ packet_send_ignore(int nbytes)
 	}
 }
 
+#ifdef	NONE_CIPHER_ENABLED
+void
+packet_request_rekeying(void)
+{
+	rekey_requested = 1;
+}
+#endif
+
 #define MAX_PACKETS	(1U<<31)
 int
 packet_need_rekeying(void)
 {
 	if (datafellows & SSH_BUG_NOREKEY)
 		return 0;
+#ifdef	NONE_CIPHER_ENABLED
+	if (rekey_requested == 1) {
+		rekey_requested = 0;
+		return 1;
+	}
+#endif
 	return
 	    (active_state->p_send.packets > MAX_PACKETS) ||
 	    (active_state->p_read.packets > MAX_PACKETS) ||
@@ -1958,3 +1976,11 @@ packet_restore_state(void)
 		add_recv_bytes(len);
 	}
 }
+
+#ifdef	NONE_CIPHER_ENABLED
+int
+packet_get_authentication_state(void)
+{
+	return (active_state->after_authentication);
+}
+#endif

Modified: head/crypto/openssh/packet.h
==============================================================================
--- head/crypto/openssh/packet.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/packet.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: packet.h,v 1.55 2010/11/13 23:27:50 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -38,6 +39,9 @@ void     packet_set_interactive(int, int
 int      packet_is_interactive(void);
 void     packet_set_server(void);
 void     packet_set_authenticated(void);
+#ifdef	NONE_CIPHER_ENABLED
+int      packet_get_authentication_state(void);
+#endif
 
 void     packet_start(u_char);
 void     packet_put_char(int ch);
@@ -117,6 +121,9 @@ do { \
 } while (0)
 
 int	 packet_need_rekeying(void);
+#ifdef	NONE_CIPHER_ENABLED
+void	 packet_request_rekeying(void);
+#endif
 void	 packet_set_rekey_limit(u_int32_t);
 
 void	 packet_backup_state(void);

Modified: head/crypto/openssh/readconf.c
==============================================================================
--- head/crypto/openssh/readconf.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/readconf.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -138,6 +139,10 @@ typedef enum {
 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
 	oKexAlgorithms, oIPQoS,
+	oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf,
+#ifdef NONE_CIPHER_ENABLED
+	oNoneEnabled, oNoneSwitch,
+#endif
 	oVersionAddendum,
 	oDeprecated, oUnsupported
 } OpCodes;
@@ -249,6 +254,14 @@ static struct {
 #endif
 	{ "kexalgorithms", oKexAlgorithms },
 	{ "ipqos", oIPQoS },
+	{ "hpndisabled", oHPNDisabled },
+	{ "hpnbuffersize", oHPNBufferSize },
+	{ "tcprcvbufpoll", oTcpRcvBufPoll },
+	{ "tcprcvbuf", oTcpRcvBuf },
+#ifdef	NONE_CIPHER_ENABLED
+	{ "noneenabled", oNoneEnabled },
+	{ "noneswitch", oNoneSwitch },
+#endif
 
 	{ "versionaddendum", oVersionAddendum },
 	{ NULL, oBadOption }
@@ -1021,6 +1034,47 @@ parse_int:
 		} while (arg != NULL && *arg != '\0');
 		break;
 
+	case oHPNDisabled:
+		intptr = &options->hpn_disabled;
+		goto parse_flag;
+
+	case oHPNBufferSize:
+		intptr = &options->hpn_buffer_size;
+		goto parse_int;
+
+	case oTcpRcvBufPoll:
+		intptr = &options->tcp_rcv_buf_poll;
+		goto parse_flag;
+
+	case oTcpRcvBuf:
+		intptr = &options->tcp_rcv_buf;
+		goto parse_int;
+
+#ifdef	NONE_CIPHER_ENABLED
+	case oNoneEnabled:
+		intptr = &options->none_enabled;
+		goto parse_flag;
+ 
+	/*
+         * We check to see if the command comes from the command line or not.
+	 * If it does then enable it otherwise fail.  NONE must never be a
+	 * default configuration.
+	 */
+	case oNoneSwitch:
+		if (strcmp(filename,"command-line") == 0) {
+			intptr = &options->none_switch;
+			goto parse_flag;
+		} else {
+			debug("NoneSwitch directive found in %.200s.",
+			    filename);
+			error("NoneSwitch is found in %.200s.\n"
+			    "You may only use this configuration option "
+			    "from the command line", filename);
+			error("Continuing...");
+			return 0;
+	        }
+#endif
+
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1181,6 +1235,14 @@ initialize_options(Options * options)
 	options->zero_knowledge_password_authentication = -1;
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
+	options->hpn_disabled = -1;
+	options->hpn_buffer_size = -1;
+	options->tcp_rcv_buf_poll = -1;
+	options->tcp_rcv_buf = -1;
+#ifdef NONE_CIPHER_ENABLED
+	options->none_enabled = -1;
+	options->none_switch = -1;
+#endif
 }
 
 /*
@@ -1345,6 +1407,36 @@ fill_default_options(Options * options)
 	/* options->hostname will be set in the main program if appropriate */
 	/* options->host_key_alias should not be set by default */
 	/* options->preferred_authentications will be set in ssh */
+	if (options->hpn_disabled == -1)
+	        options->hpn_disabled = 0;
+	if (options->hpn_buffer_size > -1)
+	{
+		u_int maxlen;
+
+		/* If a user tries to set the size to 0 set it to 1KB. */
+		if (options->hpn_buffer_size == 0)
+			options->hpn_buffer_size = 1024;
+		/* Limit the buffer to BUFFER_MAX_LEN. */
+		maxlen = buffer_get_max_len();
+		if (options->hpn_buffer_size > (maxlen / 1024)) {
+			debug("User requested buffer larger than %ub: %ub. "
+			    "Request reverted to %ub", maxlen,
+			    options->hpn_buffer_size * 1024, maxlen);
+			options->hpn_buffer_size = maxlen;
+		}
+		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
+	}
+	if (options->tcp_rcv_buf == 0)
+		options->tcp_rcv_buf = 1;
+	if (options->tcp_rcv_buf > -1) 
+		options->tcp_rcv_buf *= 1024;
+	if (options->tcp_rcv_buf_poll == -1)
+		options->tcp_rcv_buf_poll = 1;
+#ifdef	NONE_CIPHER_ENABLED
+	/* options->none_enabled must not be set by default */
+	if (options->none_switch == -1)
+		options->none_switch = 0;
+#endif
 }
 
 /*

Modified: head/crypto/openssh/readconf.h
==============================================================================
--- head/crypto/openssh/readconf.h	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/readconf.h	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
+/* $FreeBSD$ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -132,6 +133,17 @@ typedef struct {
 
 	int	use_roaming;
 
+	int	hpn_disabled;	/* Switch to disable HPN buffer management. */
+	int	hpn_buffer_size;	/* User definable size for HPN buffer
+					 * window. */
+	int	tcp_rcv_buf_poll;	/* Option to poll recv buf every window
+					 * transfer. */
+	int	tcp_rcv_buf;	/* User switch to set tcp recv buffer. */
+
+#ifdef	NONE_CIPHER_ENABLED
+	int	none_enabled;	/* Allow none to be used */
+	int	none_switch;	/* Use none cipher */
+#endif
 }       Options;
 
 #define SSHCTL_MASTER_NO	0

Modified: head/crypto/openssh/servconf.c
==============================================================================
--- head/crypto/openssh/servconf.c	Wed Aug  3 18:50:19 2011	(r224637)
+++ head/crypto/openssh/servconf.c	Wed Aug  3 19:14:22 2011	(r224638)
@@ -1,4 +1,5 @@
 /* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
+/* $FreeBSD$ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -141,6 +142,12 @@ initialize_server_options(ServerOptions 
 	options->authorized_principals_file = NULL;
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
+	options->hpn_disabled = -1;
+	options->hpn_buffer_size = -1;
+	options->tcp_rcv_buf_poll = -1;
+#ifdef	NONE_CIPHER_ENABLED
+	options->none_enabled = -1;
+#endif
 }
 
 void
@@ -283,6 +290,37 @@ fill_default_server_options(ServerOption
 		options->ip_qos_interactive = IPTOS_LOWDELAY;
 	if (options->ip_qos_bulk == -1)
 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
+	if (options->hpn_disabled == -1) 
+		options->hpn_disabled = 0;
+	if (options->hpn_buffer_size == -1) {
+		/*
+		 * HPN buffer size option not explicitly set.  Try to figure
+		 * out what value to use or resort to default.
+		 */
+		options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
+		if (!options->hpn_disabled) {
+			sock_get_rcvbuf(&options->hpn_buffer_size, 0);
+			debug ("HPN Buffer Size: %d", options->hpn_buffer_size);
+		}
+	} else {
+		/*
+		 * In the case that the user sets both values in a
+		 * contradictory manner hpn_disabled overrrides hpn_buffer_size.
+		 */
+		if (options->hpn_disabled <= 0) {
+			u_int maxlen;
+
+			maxlen = buffer_get_max_len();
+			if (options->hpn_buffer_size == 0)
+				options->hpn_buffer_size = 1;
+			/* Limit the maximum buffer to BUFFER_MAX_LEN. */
+			if (options->hpn_buffer_size > maxlen / 1024)
+				options->hpn_buffer_size = maxlen;
+			else
+				options->hpn_buffer_size *= 1024;
+		} else
+			options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT;
+	}
 
 	/* Turn privilege separation on by default */
 	if (use_privsep == -1)
@@ -330,6 +368,10 @@ typedef enum {
 	sZeroKnowledgePasswordAuthentication, sHostCertificate,
 	sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
 	sKexAlgorithms, sIPQoS,
+	sHPNDisabled, sHPNBufferSize, sTcpRcvBufPoll,
+#ifdef NONE_CIPHER_ENABLED
+	sNoneEnabled,
+#endif
 	sVersionAddendum,
 	sDeprecated, sUnsupported
 } ServerOpCodes;
@@ -455,6 +497,12 @@ static struct {
 	{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
 	{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108031914.p73JEMeh026068>