summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--clientloop.c5
-rw-r--r--misc.c56
-rw-r--r--misc.h3
-rw-r--r--packet.c9
-rw-r--r--packet.h4
-rw-r--r--readconf.c30
-rw-r--r--readconf.h4
-rw-r--r--servconf.c38
-rw-r--r--servconf.h4
-rw-r--r--session.c8
-rw-r--r--ssh.c7
-rw-r--r--ssh_config.541
-rw-r--r--sshd_config.541
14 files changed, 230 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 0f9ed852..1ddba8a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,13 @@
[kexdhc.c kexdhs.c kexgexc.c kexgexs.c key.c moduli.c]
use only libcrypto APIs that are retained with OPENSSL_NO_DEPRECATED.
these have been around for years by this time. ok markus
+ - djm@cvs.openbsd.org 2010/11/13 23:27:51
+ [clientloop.c misc.c misc.h packet.c packet.h readconf.c readconf.h]
+ [servconf.c servconf.h session.c ssh.c ssh_config.5 sshd_config.5]
+ allow ssh and sshd to set arbitrary TOS/DSCP/QoS values instead of
+ hardcoding lowdelay/throughput.
+
+ bz#1733 patch from philipp AT redfish-solutions.com; ok markus@ deraadt@
20101111
- (djm) [servconf.c ssh-add.c ssh-keygen.c] don't look for ECDSA keys on
diff --git a/clientloop.c b/clientloop.c
index 848aacd4..52dcb4c0 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.223 2010/10/06 06:39:28 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.224 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1973,6 +1973,9 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
if ((c = channel_lookup(id)) == NULL)
fatal("client_session2_setup: channel %d: unknown channel", id);
+ packet_set_interactive(want_tty,
+ options.ip_qos_interactive, options.ip_qos_bulk);
+
if (want_tty) {
struct winsize ws;
diff --git a/misc.c b/misc.c
index ff09becf..b88f5aaa 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.82 2010/09/24 13:33:00 matthew Exp $ */
+/* $OpenBSD: misc.c,v 1.83 2010/11/13 23:27:50 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@@ -38,6 +38,8 @@
#include <unistd.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <errno.h>
@@ -913,6 +915,58 @@ bandwidth_limit(struct bwlimit *bw, size_t read_len)
bw->lamt = 0;
gettimeofday(&bw->bwstart, NULL);
}
+
+static const struct {
+ const char *name;
+ int value;
+} ipqos[] = {
+ { "af11", IPTOS_DSCP_AF11 },
+ { "af12", IPTOS_DSCP_AF12 },
+ { "af13", IPTOS_DSCP_AF13 },
+ { "af14", IPTOS_DSCP_AF21 },
+ { "af22", IPTOS_DSCP_AF22 },
+ { "af23", IPTOS_DSCP_AF23 },
+ { "af31", IPTOS_DSCP_AF31 },
+ { "af32", IPTOS_DSCP_AF32 },
+ { "af33", IPTOS_DSCP_AF33 },
+ { "af41", IPTOS_DSCP_AF41 },
+ { "af42", IPTOS_DSCP_AF42 },
+ { "af43", IPTOS_DSCP_AF43 },
+ { "cs0", IPTOS_DSCP_CS0 },
+ { "cs1", IPTOS_DSCP_CS1 },
+ { "cs2", IPTOS_DSCP_CS2 },
+ { "cs3", IPTOS_DSCP_CS3 },
+ { "cs4", IPTOS_DSCP_CS4 },
+ { "cs5", IPTOS_DSCP_CS5 },
+ { "cs6", IPTOS_DSCP_CS6 },
+ { "cs7", IPTOS_DSCP_CS7 },
+ { "ef", IPTOS_DSCP_EF },
+ { "lowdelay", IPTOS_LOWDELAY },
+ { "throughput", IPTOS_THROUGHPUT },
+ { "reliability", IPTOS_RELIABILITY },
+ { NULL, -1 }
+};
+
+int
+parse_ipqos(const char *cp)
+{
+ u_int i;
+ char *ep;
+ long val;
+
+ if (cp == NULL)
+ return -1;
+ for (i = 0; ipqos[i].name != NULL; i++) {
+ if (strcasecmp(cp, ipqos[i].name) == 0)
+ return ipqos[i].value;
+ }
+ /* Try parsing as an integer */
+ val = strtol(cp, &ep, 0);
+ if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
+ return -1;
+ return val;
+}
+
void
sock_set_v6only(int s)
{
diff --git a/misc.h b/misc.h
index 1368931a..a81ace30 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.45 2010/09/24 13:33:00 matthew Exp $ */
+/* $OpenBSD: misc.h,v 1.46 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -88,6 +88,7 @@ struct bwlimit {
void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t);
void bandwidth_limit(struct bwlimit *, size_t);
+int parse_ipqos(const char *);
/* readpass.c */
diff --git a/packet.c b/packet.c
index 69892001..012c39a3 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.171 2010/11/05 02:46:47 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.172 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1750,7 +1750,7 @@ packet_not_very_much_data_to_write(void)
}
static void
-packet_set_tos(int interactive)
+packet_set_tos(int tos)
{
#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
@@ -1758,6 +1758,7 @@ packet_set_tos(int interactive)
if (!packet_connection_is_on_socket() ||
!packet_connection_is_ipv4())
return;
+ debug3("%s: set IP_TOS 0x%02x", __func__, tos);
if (setsockopt(active_state->connection_in, IPPROTO_IP, IP_TOS, &tos,
sizeof(tos)) < 0)
error("setsockopt IP_TOS %d: %.100s:",
@@ -1768,7 +1769,7 @@ packet_set_tos(int interactive)
/* Informs that the current session is interactive. Sets IP flags for that. */
void
-packet_set_interactive(int interactive)
+packet_set_interactive(int interactive, int qos_interactive, int qos_bulk)
{
if (active_state->set_interactive_called)
return;
@@ -1781,7 +1782,7 @@ packet_set_interactive(int interactive)
if (!packet_connection_is_on_socket())
return;
set_nodelay(active_state->connection_in);
- packet_set_tos(interactive);
+ packet_set_tos(interactive ? qos_interactive : qos_bulk);
}
/* Returns true if the current connection is interactive. */
diff --git a/packet.h b/packet.h
index 864b8285..d516aae8 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.54 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.55 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -34,7 +34,7 @@ u_int packet_get_encryption_key(u_char *);
void packet_set_protocol_flags(u_int);
u_int packet_get_protocol_flags(void);
void packet_start_compression(int);
-void packet_set_interactive(int);
+void packet_set_interactive(int, int, int);
int packet_is_interactive(void);
void packet_set_server(void);
void packet_set_authenticated(void);
diff --git a/readconf.c b/readconf.c
index da7efd19..eb4a8b9e 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.189 2010/09/22 05:01:29 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -19,6 +19,8 @@
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
#include <ctype.h>
#include <errno.h>
@@ -132,7 +134,7 @@ typedef enum {
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
- oKexAlgorithms,
+ oKexAlgorithms, oIPQoS,
oDeprecated, oUnsupported
} OpCodes;
@@ -242,6 +244,7 @@ static struct {
{ "zeroknowledgepasswordauthentication", oUnsupported },
#endif
{ "kexalgorithms", oKexAlgorithms },
+ { "ipqos", oIPQoS },
{ NULL, oBadOption }
};
@@ -973,6 +976,23 @@ parse_int:
intptr = &options->visual_host_key;
goto parse_flag;
+ case oIPQoS:
+ arg = strdelim(&s);
+ if ((value = parse_ipqos(arg)) == -1)
+ fatal("%s line %d: Bad IPQoS value: %s",
+ filename, linenum, arg);
+ arg = strdelim(&s);
+ if (arg == NULL)
+ value2 = value;
+ else if ((value2 = parse_ipqos(arg)) == -1)
+ fatal("%s line %d: Bad IPQoS value: %s",
+ filename, linenum, arg);
+ if (*activep) {
+ options->ip_qos_interactive = value;
+ options->ip_qos_bulk = value2;
+ }
+ break;
+
case oUseRoaming:
intptr = &options->use_roaming;
goto parse_flag;
@@ -1135,6 +1155,8 @@ initialize_options(Options * options)
options->use_roaming = -1;
options->visual_host_key = -1;
options->zero_knowledge_password_authentication = -1;
+ options->ip_qos_interactive = -1;
+ options->ip_qos_bulk = -1;
}
/*
@@ -1289,6 +1311,10 @@ fill_default_options(Options * options)
options->visual_host_key = 0;
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
+ if (options->ip_qos_interactive == -1)
+ options->ip_qos_interactive = IPTOS_LOWDELAY;
+ if (options->ip_qos_bulk == -1)
+ options->ip_qos_bulk = IPTOS_THROUGHPUT;
/* options->local_command should not be set by default */
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */
diff --git a/readconf.h b/readconf.h
index ae61466d..ee160dfe 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.87 2010/09/22 05:01:29 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -59,6 +59,8 @@ typedef struct {
int compression_level; /* Compression level 1 (fast) to 9
* (best). */
int tcp_keep_alive; /* Set SO_KEEPALIVE. */
+ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
+ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
diff --git a/servconf.c b/servconf.c
index 4e5fd2f0..e2f20a3d 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.212 2010/09/30 11:04:51 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -15,6 +15,10 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
@@ -133,6 +137,8 @@ initialize_server_options(ServerOptions *options)
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
+ options->ip_qos_interactive = -1;
+ options->ip_qos_bulk = -1;
}
void
@@ -271,6 +277,10 @@ fill_default_server_options(ServerOptions *options)
options->permit_tun = SSH_TUNMODE_NO;
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
+ if (options->ip_qos_interactive == -1)
+ options->ip_qos_interactive = IPTOS_LOWDELAY;
+ if (options->ip_qos_bulk == -1)
+ options->ip_qos_bulk = IPTOS_THROUGHPUT;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -317,7 +327,7 @@ typedef enum {
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
- sKexAlgorithms,
+ sKexAlgorithms, sIPQoS,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -441,6 +451,7 @@ static struct {
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+ { "ipqos", sIPQoS, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -670,7 +681,7 @@ process_server_config_line(ServerOptions *options, char *line,
const char *host, const char *address)
{
char *cp, **charptr, *arg, *p;
- int cmdline = 0, *intptr, value, n;
+ int cmdline = 0, *intptr, value, value2, n;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
@@ -1370,6 +1381,23 @@ process_server_config_line(ServerOptions *options, char *line,
charptr = &options->revoked_keys_file;
goto parse_filename;
+ case sIPQoS:
+ arg = strdelim(&cp);
+ if ((value = parse_ipqos(arg)) == -1)
+ fatal("%s line %d: Bad IPQoS value: %s",
+ filename, linenum, arg);
+ arg = strdelim(&cp);
+ if (arg == NULL)
+ value2 = value;
+ else if ((value2 = parse_ipqos(arg)) == -1)
+ fatal("%s line %d: Bad IPQoS value: %s",
+ filename, linenum, arg);
+ if (*activep) {
+ options->ip_qos_interactive = value;
+ options->ip_qos_bulk = value2;
+ }
+ break;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1480,6 +1508,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(max_sessions);
M_CP_INTOPT(max_authtries);
+ M_CP_INTOPT(ip_qos_interactive);
+ M_CP_INTOPT(ip_qos_bulk);
M_CP_STROPT(banner);
if (preauth)
@@ -1745,5 +1775,7 @@ dump_config(ServerOptions *o)
}
dump_cfg_string(sPermitTunnel, s);
+ printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk);
+
channel_print_adm_permitted_opens();
}
diff --git a/servconf.h b/servconf.h
index ad13f2ed..5a058a41 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.94 2010/09/22 05:01:29 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.95 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -70,6 +70,8 @@ typedef struct {
char *xauth_location; /* Location of xauth program */
int strict_modes; /* If true, require string home dir modes. */
int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
+ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
+ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
char *ciphers; /* Supported SSH2 ciphers. */
char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
diff --git a/session.c b/session.c
index 58e68128..8c6022bf 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.256 2010/06/25 07:20:04 djm Exp $ */
+/* $OpenBSD: session.c,v 1.257 2010/11/13 23:27:50 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -585,7 +585,8 @@ do_exec_no_pty(Session *s, const char *command)
s->pid = pid;
/* Set interactive/non-interactive mode. */
- packet_set_interactive(s->display != NULL);
+ packet_set_interactive(s->display != NULL,
+ options.ip_qos_interactive, options.ip_qos_bulk);
/*
* Clear loginmsg, since it's the child's responsibility to display
@@ -739,7 +740,8 @@ do_exec_pty(Session *s, const char *command)
/* Enter interactive session. */
s->ptymaster = ptymaster;
- packet_set_interactive(1);
+ packet_set_interactive(1,
+ options.ip_qos_interactive, options.ip_qos_bulk);
if (compat20) {
session_set_fds(s, ptyfd, fdout, -1, 1, 1);
} else {
diff --git a/ssh.c b/ssh.c
index 7632cf51..f413f8a5 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.353 2010/10/06 06:39:28 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.354 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1224,7 +1224,8 @@ ssh_session(void)
}
}
/* Tell the packet module whether this is an interactive session. */
- packet_set_interactive(interactive);
+ packet_set_interactive(interactive,
+ options.ip_qos_interactive, options.ip_qos_bulk);
/* Request authentication agent forwarding if appropriate. */
check_agent_present();
@@ -1322,8 +1323,6 @@ ssh_session2_setup(int id, int success, void *arg)
client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
NULL, fileno(stdin), &command, environ);
-
- packet_set_interactive(interactive);
}
/* open new channel for a session */
diff --git a/ssh_config.5 b/ssh_config.5
index dd39bfaf..9e82fa86 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.142 2010/10/28 18:33:28 jmc Exp $
-.Dd $Mdocdate: October 28 2010 $
+.\" $OpenBSD: ssh_config.5,v 1.143 2010/11/13 23:27:50 djm Exp $
+.Dd $Mdocdate: November 13 2010 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -626,6 +626,43 @@ escape characters:
It is possible to have
multiple identity files specified in configuration files; all these
identities will be tried in sequence.
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to use keyboard-interactive authentication.
The argument to this keyword must be
diff --git a/sshd_config.5 b/sshd_config.5
index d0c02ca7..60808d23 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.128 2010/10/28 18:33:28 jmc Exp $
-.Dd $Mdocdate: October 28 2010 $
+.\" $OpenBSD: sshd_config.5,v 1.129 2010/11/13 23:27:51 djm Exp $
+.Dd $Mdocdate: November 13 2010 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -512,6 +512,43 @@ or
.Cm HostbasedAuthentication .
The default is
.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
.It Cm KerberosAuthentication
Specifies whether the password provided by the user for
.Cm PasswordAuthentication