Bugzilla – Attachment 2329 Details for
Bug 2016
SCTP Support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
update patch against CVS as of today
0001-openssh-add-sctp-support.patch (text/plain), 26.14 KB, created by
Sebastian A. Siewior
on 2013-08-19 05:21:40 AEST
(
hide
)
Description:
update patch against CVS as of today
Filename:
MIME Type:
Creator:
Sebastian A. Siewior
Created:
2013-08-19 05:21:40 AEST
Size:
26.14 KB
patch
obsolete
>From 6fb5c9bdc82c9796f05f9d5b54b525a3c0c270f3 Mon Sep 17 00:00:00 2001 >From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> >Date: Fri, 16 Aug 2013 21:47:32 +0200 >Subject: [PATCH] openssh: add sctp support > >Patch from #2016 >https://bugzilla.mindrot.org/show_bug.cgi?id=2016 >Changes to the original patch: >- s/xfree/free >- clash in command args parse fixup >- configure.ac: check for sctp support if enabled. This avoids passing > the configure script and having later errors at compile time errors > due to missing headers or libs. >- uset setsockopt() for SCTP instead of getsockopt() a second time in > set_nodelay() >- update man pages for scp.1, ssh.1, ssh_config.5, sshd_config.5 >- use strcasecmp() for option checking so "SCTP" can be specified as well > as "sctp" > >Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> >--- > configure.ac | 14 ++++++ > misc.c | 39 +++++++++++++--- > readconf.c | 29 ++++++++++++ > readconf.h | 7 +++ > scp.1 | 5 ++- > scp.c | 7 +++ > servconf.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > servconf.h | 12 +++++ > ssh.1 | 5 ++- > ssh.c | 15 ++++++- > ssh_config.5 | 6 +++ > sshconnect.c | 56 +++++++++++++++++++++++ > sshd.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > sshd_config.5 | 11 +++++ > 14 files changed, 471 insertions(+), 10 deletions(-) > >diff --git a/configure.ac b/configure.ac >index f9e6d54..609992c 100644 >--- a/configure.ac >+++ b/configure.ac >@@ -3688,6 +3688,19 @@ AC_ARG_WITH([selinux], > AC_SUBST([SSHLIBS]) > AC_SUBST([SSHDLIBS]) > >+#check whether user wants SCTP support >+SCTP_MSG="no" >+AC_ARG_WITH(sctp, >+ [ --with-sctp Enable SCTP support], >+ [ if test "x$withval" != "xno" ; then >+ AC_DEFINE(SCTP,1,[Define if you want SCTP support.]) >+ AC_CHECK_FUNCS(sctp_recvmsg, , AC_CHECK_LIB(sctp, sctp_recvmsg, , >+ [AC_MSG_ERROR([*** Can not use SCTP - maybe libsctp-dev is missing ***])] >+ )) >+ SCTP_MSG="yes" >+ fi ] >+) >+ > # Check whether user wants Kerberos 5 support > KRB5_MSG="no" > AC_ARG_WITH([kerberos5], >@@ -4610,6 +4623,7 @@ echo " PAM support: $PAM_MSG" > echo " OSF SIA support: $SIA_MSG" > echo " KerberosV support: $KRB5_MSG" > echo " SELinux support: $SELINUX_MSG" >+echo " SCTP support: $SCTP_MSG" > echo " Smartcard support: $SCARD_MSG" > echo " S/KEY support: $SKEY_MSG" > echo " TCP Wrappers support: $TCPW_MSG" >diff --git a/misc.c b/misc.c >index c3c8099..2755dcc 100644 >--- a/misc.c >+++ b/misc.c >@@ -59,6 +59,10 @@ > #include "log.h" > #include "ssh.h" > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > /* remove newline at end of string */ > char * > chop(char *s) >@@ -137,21 +141,46 @@ void > set_nodelay(int fd) > { > int opt; >+ int is_tcp = 1; >+ int ret; > socklen_t optlen; > > optlen = sizeof opt; > if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { >- debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); >+#ifdef SCTP >+ /* TCP_NODELAY failed, try SCTP_NODELAY */ >+ if (getsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, &opt, &optlen) == -1) { >+ debug("getsockopt TCP_NODELAY/SCTP_NODELAY: %.100s", strerror(errno)); >+ return; >+ } >+ is_tcp = 0; >+#else > return; >+#endif > } > if (opt == 1) { >- debug2("fd %d is TCP_NODELAY", fd); >+ debug2("fd %d is TCP_NODELAY/SCTP_NODELAY", fd); > return; > } > opt = 1; >- debug2("fd %d setting TCP_NODELAY", fd); >- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) >- error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); >+ debug2("fd %d setting TCP_NODELAY/SCTP_NODELAY", fd); >+ >+ if (is_tcp) { >+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, >+ sizeof(opt)); >+ if (ret < 0) >+ error("setsockopt TCP_NODELAY: %.100s", >+ strerror(errno)); >+ } >+#ifdef SCTP >+ else { >+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, &opt, >+ sizeof(opt)); >+ if (ret < 0) >+ error("setsockopt SCTP_NODELAY: %.100s", >+ strerror(errno)); >+ } >+#endif > } > > /* Characters considered whitespace in strsep calls. */ >diff --git a/readconf.c b/readconf.c >index 1464430..21d4b94 100644 >--- a/readconf.c >+++ b/readconf.c >@@ -120,6 +120,9 @@ typedef enum { > oPasswordAuthentication, oRSAAuthentication, > oChallengeResponseAuthentication, oXAuthLocation, > oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, >+#ifdef SCTP >+ oTransport, >+#endif > oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, > oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, > oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, >@@ -185,6 +188,9 @@ static struct { > { "hostname", oHostName }, > { "hostkeyalias", oHostKeyAlias }, > { "proxycommand", oProxyCommand }, >+#ifdef SCTP >+ { "transport", oTransport }, >+#endif > { "port", oPort }, > { "cipher", oCipher }, > { "ciphers", oCiphers }, >@@ -683,6 +689,22 @@ process_config_line(Options *options, const char *host, > *charptr = xstrdup(s + len); > return 0; > >+#ifdef SCTP >+ case oTransport: >+ arg = strdelim(&s); >+ if (!arg || *arg == '\0') >+ fatal("%s line %d: missing transport protocol specification", >+ filename, linenum); >+ if (strcasecmp(arg, "tcp") == 0) >+ options->transport = TRANSPORT_TCP; >+ else if (strcasecmp(arg, "sctp") == 0) >+ options->transport = TRANSPORT_SCTP; >+ else >+ fatal("%s line %d: unknown transport protocol specified", >+ filename, linenum); >+ break; >+#endif >+ > case oPort: > intptr = &options->port; > parse_int: >@@ -1180,6 +1202,9 @@ initialize_options(Options * options) > options->compression = -1; > options->tcp_keep_alive = -1; > options->compression_level = -1; >+#ifdef SCTP >+ options->transport = -1; >+#endif > options->port = -1; > options->address_family = -1; > options->connection_attempts = -1; >@@ -1290,6 +1315,10 @@ fill_default_options(Options * options) > options->tcp_keep_alive = 1; > if (options->compression_level == -1) > options->compression_level = 6; >+#ifdef SCTP >+ if (options->transport == -1) >+ options->transport = TRANSPORT_TCP; >+#endif > if (options->port == -1) > options->port = 0; /* Filled in ssh_connect. */ > if (options->address_family == -1) >diff --git a/readconf.h b/readconf.h >index 23fc500..d74948e 100644 >--- a/readconf.h >+++ b/readconf.h >@@ -31,6 +31,10 @@ typedef struct { > #define MAX_SEND_ENV 256 > #define SSH_MAX_HOSTS_FILES 256 > >+/* Transport protocols */ >+#define TRANSPORT_TCP 1 >+#define TRANSPORT_SCTP 2 >+ > typedef struct { > int forward_agent; /* Forward authentication agent. */ > int forward_x11; /* Forward X11 display. */ >@@ -65,6 +69,9 @@ typedef struct { > int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ > LogLevel log_level; /* Level for logging. */ > >+#ifdef SCTP >+ int transport; /* Transport protocol used. */ >+#endif > int port; /* Port to connect. */ > int address_family; > int connection_attempts; /* Max attempts (seconds) before >diff --git a/scp.1 b/scp.1 >index c0258d6..138320e 100644 >--- a/scp.1 >+++ b/scp.1 >@@ -19,7 +19,7 @@ > .Sh SYNOPSIS > .Nm scp > .Bk -words >-.Op Fl 12346BCpqrv >+.Op Fl 12346BCpqrvz > .Op Fl c Ar cipher > .Op Fl F Ar ssh_config > .Op Fl i Ar identity_file >@@ -175,6 +175,7 @@ For full details of the options listed below, and their possible values, see > .It ServerAliveCountMax > .It StrictHostKeyChecking > .It TCPKeepAlive >+.It Transport > .It UsePrivilegedPort > .It User > .It UserKnownHostsFile >@@ -216,6 +217,8 @@ and > to print debugging messages about their progress. > This is helpful in > debugging connection, authentication, and configuration problems. >+.It Fl z >+Use the SCTP protocol for connection instead of TCP which is the default. > .El > .Sh EXIT STATUS > .Ex -std scp >diff --git a/scp.c b/scp.c >index 28ded5e..966bb88 100644 >--- a/scp.c >+++ b/scp.c >@@ -395,7 +395,11 @@ main(int argc, char **argv) > addargs(&args, "-oClearAllForwardings=yes"); > > fflag = tflag = 0; >+#ifdef SCTP >+ while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:z")) != -1) >+#else > while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) >+#endif > switch (ch) { > /* User-visible flags. */ > case '1': >@@ -403,6 +407,9 @@ main(int argc, char **argv) > case '4': > case '6': > case 'C': >+#ifdef SCTP >+ case 'z': >+#endif > addargs(&args, "-%c", ch); > addargs(&remote_remote_args, "-%c", ch); > break; >diff --git a/servconf.c b/servconf.c >index 747edde..09f3cfc 100644 >--- a/servconf.c >+++ b/servconf.c >@@ -126,6 +126,9 @@ initialize_server_options(ServerOptions *options) > options->ciphers = NULL; > options->macs = NULL; > options->kex_algorithms = NULL; >+#ifdef SCTP >+ options->transport = -1; >+#endif > options->protocol = SSH_PROTO_UNKNOWN; > options->gateway_ports = -1; > options->num_subsystems = 0; >@@ -264,6 +267,10 @@ fill_default_server_options(ServerOptions *options) > options->allow_tcp_forwarding = FORWARD_ALLOW; > if (options->allow_agent_forwarding == -1) > options->allow_agent_forwarding = 1; >+#ifdef SCTP >+ if (options->transport == -1) >+ options->transport = TRANSPORT_TCP; >+#endif > if (options->gateway_ports == -1) > options->gateway_ports = 0; > if (options->max_startups == -1) >@@ -327,6 +334,9 @@ typedef enum { > sKerberosTgtPassing, sChallengeResponseAuthentication, > sPasswordAuthentication, sKbdInteractiveAuthentication, > sListenAddress, sAddressFamily, >+#ifdef SCTP >+ sTransport, sListenMultipleAddresses, >+#endif > sPrintMotd, sPrintLastLog, sIgnoreRhosts, > sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, > sStrictModes, sEmptyPasswd, sTCPKeepAlive, >@@ -420,6 +430,9 @@ static struct { > #endif > { "checkmail", sDeprecated, SSHCFG_GLOBAL }, > { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, >+#ifdef SCTP >+ { "listenmultipleaddresses", sListenMultipleAddresses, SSHCFG_GLOBAL }, >+#endif > { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, > { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, > { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, >@@ -445,6 +458,9 @@ static struct { > { "denygroups", sDenyGroups, SSHCFG_ALL }, > { "ciphers", sCiphers, SSHCFG_GLOBAL }, > { "macs", sMacs, SSHCFG_GLOBAL }, >+#ifdef SCTP >+ { "transport", sTransport, SSHCFG_GLOBAL }, >+#endif > { "protocol", sProtocol, SSHCFG_GLOBAL }, > { "gatewayports", sGatewayPorts, SSHCFG_ALL }, > { "subsystem", sSubsystem, SSHCFG_GLOBAL }, >@@ -578,6 +594,81 @@ get_connection_info(int populate, int use_dns) > return &ci; > } > >+#ifdef SCTP >+static void >+add_one_listen_multiple_addr(ServerOptions *options, char *addr, int port, int last) >+{ >+ struct addrinfo hints, *ai, *aitop; >+ char strport[NI_MAXSERV]; >+ int gaierr; >+ >+ memset(&hints, 0, sizeof(hints)); >+ hints.ai_family = options->address_family; >+ hints.ai_socktype = SOCK_STREAM; >+ hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; >+ snprintf(strport, sizeof strport, "%d", port); >+ if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) >+ fatal("bad addr or host: %s (%s)", >+ addr ? addr : "<NULL>", >+ ssh_gai_strerror(gaierr)); >+ /* Mark addresses as multihomed */ >+ for (ai = aitop; ai->ai_next; ai = ai->ai_next) >+ ai->ai_flags = IS_MULTIPLE_ADDR; >+ ai->ai_flags = IS_MULTIPLE_ADDR; >+ ai->ai_next = options->listen_addrs; >+ options->listen_addrs = aitop; >+ >+ if (last) { >+ aitop->ai_flags = 0; >+ } >+} >+ >+static void >+add_listen_multiple_addrs(ServerOptions *options, char *addrs, int port) >+{ >+ u_int i, num_addrs; >+ char **addrsptr, *p; >+ >+ if (options->num_ports == 0) >+ options->ports[options->num_ports++] = SSH_DEFAULT_PORT; >+ if (options->address_family == -1) >+ options->address_family = AF_UNSPEC; >+ >+ num_addrs = 1; >+ p = addrs; >+ while ((p = strchr(p, ',')) != NULL) { >+ num_addrs++; >+ p++; >+ } >+ debug("found %d addresses for multi-homing", num_addrs); >+ >+ addrsptr = xmalloc(num_addrs * sizeof(char*)); >+ p = addrs; >+ for (i = 0; i < num_addrs; i++) { >+ addrsptr[i] = p; >+ p = strchr(p+1, ','); >+ if (p != NULL) >+ *(p++) = '\0'; >+ } >+ >+ if (port == 0) >+ for (i = 0; i < options->num_ports; i++) { >+ while (--num_addrs) { >+ add_one_listen_multiple_addr(options, addrsptr[num_addrs], options->ports[i], 0); >+ } >+ add_one_listen_multiple_addr(options, addrs, options->ports[i], 1); >+ } >+ else { >+ while (--num_addrs) { >+ add_one_listen_multiple_addr(options, addrsptr[num_addrs], port, 0); >+ } >+ add_one_listen_multiple_addr(options, addrs, port, 1); >+ } >+ >+ free(addrsptr); >+} >+#endif >+ > /* > * The strategy for the Match blocks is that the config file is parsed twice. > * >@@ -911,6 +1002,26 @@ process_server_config_line(ServerOptions *options, char *line, > intptr = &options->key_regeneration_time; > goto parse_time; > >+#ifdef SCTP >+ case sListenMultipleAddresses: >+ arg = strdelim(&cp); >+ if (arg == NULL || *arg == '\0') >+ fatal("%s line %d: missing addresses", >+ filename, linenum); >+ >+ /* Check for appended port */ >+ p = strchr(arg, ';'); >+ if (p != NULL) { >+ if ((port = a2port(p + 1)) <= 0) >+ fatal("%s line %d: bad port number", filename, linenum); >+ *p = '\0'; >+ } else { >+ port = 0; >+ } >+ add_listen_multiple_addrs(options, arg, port); >+ break; >+#endif >+ > case sListenAddress: > arg = strdelim(&cp); > if (arg == NULL || *arg == '\0') >@@ -1300,6 +1411,24 @@ process_server_config_line(ServerOptions *options, char *line, > options->kex_algorithms = xstrdup(arg); > break; > >+#ifdef SCTP >+ case sTransport: >+ arg = strdelim(&cp); >+ if (!arg || *arg == '\0') >+ fatal("%s line %d: missing transport protocol specification", >+ filename, linenum); >+ if (strcasecmp(arg, "all") == 0) >+ options->transport = TRANSPORT_ALL; >+ else if (strcasecmp(arg, "tcp") == 0) >+ options->transport = TRANSPORT_TCP; >+ else if (strcasecmp(arg, "sctp") == 0) >+ options->transport = TRANSPORT_SCTP; >+ else >+ fatal("%s line %d: unknown transport protocol specified", >+ filename, linenum); >+ break; >+#endif >+ > case sProtocol: > intptr = &options->protocol; > arg = strdelim(&cp); >@@ -1764,6 +1893,9 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) > M_CP_INTOPT(allow_tcp_forwarding); > M_CP_INTOPT(allow_agent_forwarding); > M_CP_INTOPT(permit_tun); >+#ifdef SCTP >+ M_CP_INTOPT(transport); >+#endif > M_CP_INTOPT(gateway_ports); > M_CP_INTOPT(x11_display_offset); > M_CP_INTOPT(x11_forwarding); >@@ -2004,6 +2136,9 @@ dump_config(ServerOptions *o) > dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); > dump_cfg_fmtint(sUseLogin, o->use_login); > dump_cfg_fmtint(sCompression, o->compression); >+#ifdef SCTP >+ dump_cfg_fmtint(sTransport, o->transport); >+#endif > dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); > dump_cfg_fmtint(sUseDNS, o->use_dns); > dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); >diff --git a/servconf.h b/servconf.h >index 98aad8b..6f14ce1 100644 >--- a/servconf.h >+++ b/servconf.h >@@ -54,6 +54,15 @@ > /* Magic name for internal sftp-server */ > #define INTERNAL_SFTP_NAME "internal-sftp" > >+#ifdef SCTP >+/* Transport protocols */ >+#define TRANSPORT_TCP 1 >+#define TRANSPORT_SCTP 2 >+#define TRANSPORT_ALL (TRANSPORT_TCP | TRANSPORT_SCTP) >+ >+#define IS_MULTIPLE_ADDR 0x1000 >+#endif >+ > typedef struct { > u_int num_ports; > u_int ports_from_cmdline; >@@ -89,6 +98,9 @@ typedef struct { > char *ciphers; /* Supported SSH2 ciphers. */ > char *macs; /* Supported SSH2 macs. */ > char *kex_algorithms; /* SSH2 kex methods in order of preference. */ >+#ifdef SCTP >+ int transport; /* Transport protocol(s) used */ >+#endif > int protocol; /* Supported protocol versions. */ > int gateway_ports; /* If true, allow remote connects to forwarded ports. */ > SyslogFacility log_facility; /* Facility for system logging. */ >diff --git a/ssh.1 b/ssh.1 >index 025eb9f..95b6b7f 100644 >--- a/ssh.1 >+++ b/ssh.1 >@@ -43,7 +43,7 @@ > .Sh SYNOPSIS > .Nm ssh > .Bk -words >-.Op Fl 1246AaCfgKkMNnqsTtVvXxYy >+.Op Fl 1246AaCfgKkMNnqsTtVvXxYyz > .Op Fl b Ar bind_address > .Op Fl c Ar cipher_spec > .Op Fl D Oo Ar bind_address : Oc Ns Ar port >@@ -476,6 +476,7 @@ For full details of the options listed below, and their possible values, see > .It ServerAliveCountMax > .It StrictHostKeyChecking > .It TCPKeepAlive >+.It Transport > .It Tunnel > .It TunnelDevice > .It UsePrivilegedPort >@@ -668,6 +669,8 @@ Trusted X11 forwardings are not subjected to the X11 SECURITY extension > controls. > .It Fl y > Send log information using the >+.It Fl z >+Use the SCTP protocol for connection instead of TCP which is the default. > .Xr syslog 3 > system module. > By default this information is sent to stderr. >diff --git a/ssh.c b/ssh.c >index 87233bc..bd642d0 100644 >--- a/ssh.c >+++ b/ssh.c >@@ -191,12 +191,18 @@ extern int muxserver_sock; > extern u_int muxclient_command; > > /* Prints a help message to the user. This function never returns. */ >+#ifdef SCTP >+#define SCTP_OPT "z" >+#else >+#define SCTP_OPT "" >+#endif > > static void > usage(void) > { > fprintf(stderr, >-"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" >+"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy" SCTP_OPT "] [-b bind_address] " >+ "[-c cipher_spec]\n" > " [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" > " [-F configfile] [-I pkcs11] [-i identity_file]\n" > " [-L [bind_address:]port:host:hostport] [-Q protocol_feature]\n" >@@ -326,7 +332,7 @@ main(int ac, char **av) > argv0 = av[0]; > > again: >- while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" >+ while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" SCTP_OPT > "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { > switch (opt) { > case '1': >@@ -540,6 +546,11 @@ main(int ac, char **av) > else > options.control_master = SSHCTL_MASTER_YES; > break; >+#ifdef SCTP >+ case 'z': >+ options.transport = TRANSPORT_SCTP; >+ break; >+#endif > case 'p': > options.port = a2port(optarg); > if (options.port <= 0) { >diff --git a/ssh_config.5 b/ssh_config.5 >index 003d7f4..14986b1 100644 >--- a/ssh_config.5 >+++ b/ssh_config.5 >@@ -1158,6 +1158,12 @@ This is important in scripts, and many users want it too. > .Pp > To disable TCP keepalive messages, the value should be set to > .Dq no . >+.It Cm Transport >+Specifies the transport protocol while connecting. Valid values are >+.Dq TCP >+and >+.Dq SCTP . >+The default is TCP. > .It Cm Tunnel > Request > .Xr tun 4 >diff --git a/sshconnect.c b/sshconnect.c >index 483eb85..94cd382 100644 >--- a/sshconnect.c >+++ b/sshconnect.c >@@ -62,6 +62,10 @@ > #include "ssh2.h" > #include "version.h" > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > char *client_version_string = NULL; > char *server_version_string = NULL; > >@@ -196,6 +200,9 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > { > int sock, gaierr; > struct addrinfo hints, *res; >+#ifdef SCTP >+ char *more_addrs, *next_addr; >+#endif > > /* > * If we are running as root and want to connect to a privileged >@@ -224,10 +231,22 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > if (options.bind_address == NULL) > return sock; > >+#ifdef SCTP >+ /* Check if multiple addresses have been specified */ >+ if ((more_addrs = strchr(options.bind_address, ',')) != NULL) { >+ *(more_addrs++) = '\0'; >+ } >+#endif >+ > memset(&hints, 0, sizeof(hints)); > hints.ai_family = ai->ai_family; > hints.ai_socktype = ai->ai_socktype; >+#ifndef SCTP >+ /* Only specify protocol if SCTP is not used, due >+ * to the lack of SCTP support for getaddrinfo() >+ */ > hints.ai_protocol = ai->ai_protocol; >+#endif > hints.ai_flags = AI_PASSIVE; > gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res); > if (gaierr) { >@@ -242,6 +261,34 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > freeaddrinfo(res); > return -1; > } >+#ifdef SCTP >+ /* If there are multiple addresses, bind them too */ >+ if (more_addrs) { >+ do { >+ next_addr = strchr(more_addrs, ','); >+ if (next_addr != NULL) { >+ *(next_addr++) = '\0'; >+ } >+ >+ gaierr = getaddrinfo(more_addrs, NULL, &hints, &res); >+ if (gaierr) { >+ error("getaddrinfo: %s: %s", more_addrs, >+ ssh_gai_strerror(gaierr)); >+ close(sock); >+ return -1; >+ } >+ if (sctp_bindx(sock, (struct sockaddr *)res->ai_addr, >+ 1, SCTP_BINDX_ADD_ADDR) != 0) { >+ error("bind: %s: %s", options.bind_address, strerror(errno)); >+ close(sock); >+ freeaddrinfo(res); >+ return -1; >+ } >+ >+ more_addrs = next_addr; >+ } while (next_addr != NULL); >+ } >+#endif > freeaddrinfo(res); > return sock; > } >@@ -367,6 +414,15 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, > fatal("%s: Could not resolve hostname %.100s: %s", __progname, > host, ssh_gai_strerror(gaierr)); > >+#ifdef SCTP >+ /* Use SCTP if requested */ >+ if (options.transport == TRANSPORT_SCTP) { >+ for (ai = aitop; ai; ai = ai->ai_next) { >+ ai->ai_protocol = IPPROTO_SCTP; >+ } >+ } >+#endif >+ > for (attempt = 0; attempt < connection_attempts; attempt++) { > if (attempt > 0) { > /* Sleep a moment before retrying. */ >diff --git a/sshd.c b/sshd.c >index 174cc7a..cb87df9 100644 >--- a/sshd.c >+++ b/sshd.c >@@ -129,6 +129,10 @@ int allow_severity; > int deny_severity; > #endif /* LIBWRAP */ > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > #ifndef O_NOCTTY > #define O_NOCTTY 0 > #endif >@@ -1067,6 +1071,12 @@ server_listen(void) > for (ai = options.listen_addrs; ai; ai = ai->ai_next) { > if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) > continue; >+#ifdef SCTP >+ /* Ignore multi-homing addresses for TCP */ >+ if (ai->ai_flags & IS_MULTIPLE_ADDR || >+ (ai->ai_next != NULL && ai->ai_next->ai_flags & IS_MULTIPLE_ADDR)) >+ continue; >+#endif > if (num_listen_socks >= MAX_LISTEN_SOCKS) > fatal("Too many listen sockets. " > "Enlarge MAX_LISTEN_SOCKS"); >@@ -1125,6 +1135,127 @@ server_listen(void) > fatal("Cannot bind any address."); > } > >+#ifdef SCTP >+/* >+ * Listen for SCTP connections >+ */ >+static void >+server_listen_sctp(void) >+{ >+ int ret, listen_sock, on = 1; >+ struct addrinfo *ai, *aiv6; >+ char ntop[NI_MAXHOST], strport[NI_MAXSERV]; >+ >+ for (ai = options.listen_addrs; ai; ai = ai->ai_next) { >+ if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) >+ continue; >+ /* Ignore multi-homing addresses at this point */ >+ if (ai->ai_flags & IS_MULTIPLE_ADDR) >+ continue; >+ if (num_listen_socks >= MAX_LISTEN_SOCKS) >+ fatal("Too many listen sockets. " >+ "Enlarge MAX_LISTEN_SOCKS"); >+ if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, >+ ntop, sizeof(ntop), strport, sizeof(strport), >+ NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { >+ error("getnameinfo failed: %.100s", >+ ssh_gai_strerror(ret)); >+ continue; >+ } >+ /* Check for multi-homed IPv6 addresses if family is IPv4 */ >+ if (ai->ai_family == AF_INET) { >+ aiv6 = ai->ai_next; >+ while (aiv6 != NULL && aiv6->ai_flags & IS_MULTIPLE_ADDR) { >+ if (aiv6->ai_family == AF_INET6) { >+ ai->ai_family = AF_INET6; >+ break; >+ } >+ aiv6 = aiv6->ai_next; >+ } >+ } >+ >+ /* Create socket for listening. */ >+ listen_sock = socket(ai->ai_family, ai->ai_socktype, >+ IPPROTO_SCTP); >+ if (listen_sock < 0) { >+ /* kernel may not support ipv6 */ >+ verbose("SCTP socket: %.100s", strerror(errno)); >+ continue; >+ } >+ if (set_nonblock(listen_sock) == -1) { >+ close(listen_sock); >+ continue; >+ } >+ /* >+ * Set socket options. >+ * Allow local port reuse in TIME_WAIT. >+ */ >+ if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, >+ &on, sizeof(on)) == -1) >+ error("SCTP setsockopt SO_REUSEADDR: %s", strerror(errno)); >+ >+ /* Only communicate in IPv6 over AF_INET6 sockets if not multi-homed. */ >+ if (ai->ai_family == AF_INET6 && (ai->ai_next == NULL || >+ (ai->ai_next != NULL && ai->ai_next->ai_flags == 0))) >+ sock_set_v6only(listen_sock); >+ >+ if (ai->ai_next != NULL && ai->ai_next->ai_flags & IS_MULTIPLE_ADDR) >+ debug("Bind multi-homed to SCTP port %s on %s.", strport, ntop); >+ else >+ debug("Bind to SCTP port %s on %s.", strport, ntop); >+ >+ /* Bind the socket to the desired port. */ >+ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { >+ error("Bind to SCTP port %s on %s failed: %.200s.", >+ strport, ntop, strerror(errno)); >+ close(listen_sock); >+ continue; >+ } >+ >+ /* Bind multi-homing addresses */ >+ while (ai->ai_next != NULL && >+ ai->ai_next->ai_flags & IS_MULTIPLE_ADDR) { >+ ai = ai->ai_next; >+ >+ if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, >+ ntop, sizeof(ntop), strport, sizeof(strport), >+ NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { >+ error("getnameinfo failed: %.100s", >+ ssh_gai_strerror(ret)); >+ continue; >+ } >+ >+ debug("Bind multi-homed to SCTP port %s on %s.", strport, ntop); >+ >+ if (sctp_bindx(listen_sock, (struct sockaddr *)ai->ai_addr, 1, SCTP_BINDX_ADD_ADDR) != 0) { >+ error("Bind to SCTP port %s on %s failed: %.200s.", >+ strport, ntop, strerror(errno)); >+ close(listen_sock); >+ continue; >+ } >+ } >+ >+ listen_socks[num_listen_socks] = listen_sock; >+ num_listen_socks++; >+ >+ /* Start listening on the port. */ >+ if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) >+ fatal("SCTP listen on [%s]:%s: %.100s", >+ ntop, strport, strerror(errno)); >+ if (ai->ai_flags & IS_MULTIPLE_ADDR) >+ logit("Server listening multi-homed with SCTP on port %s.", strport); >+ else >+ logit("Server listening with SCTP on %s port %s.", ntop, strport); >+ } >+ /* Only free addresses if SCTP is the only used protocol */ >+ if (options.transport == TRANSPORT_SCTP) >+ freeaddrinfo(options.listen_addrs); >+ >+ if (!num_listen_socks) >+ fatal("Cannot bind any address for SCTP."); >+} >+#endif >+ > /* > * The main TCP accept loop. Note that, for the non-debug case, returns > * from this function are in a forked subprocess. >@@ -1875,7 +2006,14 @@ main(int ac, char **av) > server_accept_inetd(&sock_in, &sock_out); > } else { > platform_pre_listen(); >- server_listen(); >+ >+#ifdef SCTP >+ if (options.transport & TRANSPORT_SCTP) >+ server_listen_sctp(); >+ >+ if (options.transport & TRANSPORT_TCP) >+#endif >+ server_listen(); > > if (options.protocol & SSH_PROTO_1) > generate_ephemeral_server_key(); >diff --git a/sshd_config.5 b/sshd_config.5 >index 2769c7b..ca8bc80 100644 >--- a/sshd_config.5 >+++ b/sshd_config.5 >@@ -1119,6 +1119,17 @@ This avoids infinitely hanging sessions. > .Pp > To disable TCP keepalive messages, the value should be set to > .Dq no . >+.It Cm Transport >+Specifies the transport protocol that should be used by >+.Xr sshd 8 . >+Valid values are >+.Dq TCP , >+.Dq SCTP , >+.Dq all. >+The value >+.Dq all >+means to listen on TCP and SCTP sockets. The default is to listen only on >+TCP sockets. > .It Cm TrustedUserCAKeys > Specifies a file containing public keys of certificate authorities that are > trusted to sign user certificates for authentication. >-- >1.8.4.rc2 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2016
:
2163
|
2329
|
2423
|
2496