Bugzilla – Attachment 3346 Details for
Bug 1604
SCTP support for openssh
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
openssh-8.1-0248ec7c763dee9ff730a589e3d166eac5c74d7c.patch
openssh-8.1-0248ec7c763dee9ff730a589e3d166eac5c74d7c.patch (text/plain), 25.36 KB, created by
Mike Frysinger
on 2020-01-02 17:18:25 AEDT
(
hide
)
Description:
openssh-8.1-0248ec7c763dee9ff730a589e3d166eac5c74d7c.patch
Filename:
MIME Type:
Creator:
Mike Frysinger
Created:
2020-01-02 17:18:25 AEDT
Size:
25.36 KB
patch
obsolete
>From 58342e81b78ad00201ea13fdb62ce1cd5ef40882 Mon Sep 17 00:00:00 2001 >From: rse <seggelmann@fh-muenster.de> >Date: Thu, 19 Mar 2015 20:08:09 -0400 >Subject: [PATCH] add sctp support > >https://bugzilla.mindrot.org/show_bug.cgi?id=1604 >https://bugzilla.mindrot.org/show_bug.cgi?id=2016 > >People who have helped out: >Jan F. Chadima <jchadima@redhat.com> >rse <seggelmann@fh-muenster.de> ><openssh@ml.breakpoint.cc> >Joshua Kinard <kumba@gentoo.org> >Mike Frysinger <vapier@gentoo.org> >--- > configure.ac | 13 +++++ > misc.c | 39 ++++++++++++-- > readconf.c | 23 ++++++++ > readconf.h | 5 ++ > scp.1 | 5 +- > scp.c | 7 ++- > servconf.c | 123 +++++++++++++++++++++++++++++++++++++++++++ > servconf.h | 8 +++ > ssh.1 | 5 +- > ssh.c | 10 +++- > ssh_config.5 | 6 +++ > sshconnect.c | 52 ++++++++++++++++++ > sshd.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++- > sshd_config.5 | 11 ++++ > 14 files changed, 439 insertions(+), 11 deletions(-) > >diff --git a/configure.ac b/configure.ac >index 2671c4afe411..69d2070be723 100644 >--- a/configure.ac >+++ b/configure.ac >@@ -4432,6 +4432,18 @@ 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([SCTP support requires sctp_recvmsg and maybe libsctp-dev])])) >+ SCTP_MSG="yes" >+ fi ] >+) >+ > # Check whether user wants Kerberos 5 support > KRB5_MSG="no" > AC_ARG_WITH([kerberos5], >@@ -5365,6 +5377,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 " MD5 password support: $MD5_MSG" > echo " libedit support: $LIBEDIT_MSG" > echo " libldns support: $LDNS_MSG" >diff --git a/misc.c b/misc.c >index 5204c1e9f22f..529cab7f37d6 100644 >--- a/misc.c >+++ b/misc.c >@@ -75,6 +75,10 @@ > #include "ssherr.h" > #include "platform.h" > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > /* remove newline at end of string */ > char * > chop(char *s) >@@ -153,21 +157,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 > } > > /* Allow local port reuse in TIME_WAIT */ >diff --git a/readconf.c b/readconf.c >index cb3ae6dc7ea7..1b1f060b5aa0 100644 >--- a/readconf.c >+++ b/readconf.c >@@ -148,6 +148,7 @@ typedef enum { > oChallengeResponseAuthentication, oXAuthLocation, > oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, > oCertificateFile, oAddKeysToAgent, oIdentityAgent, >+ oTransport, > oUser, oEscapeChar, oProxyCommand, > oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, > oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, >@@ -242,6 +243,11 @@ static struct { > { "hostname", oHostname }, > { "hostkeyalias", oHostKeyAlias }, > { "proxycommand", oProxyCommand }, >+#ifdef SCTP >+ { "transport", oTransport }, >+#else >+ { "transport", oUnsupported }, >+#endif > { "port", oPort }, > { "ciphers", oCiphers }, > { "macs", oMacs }, >@@ -1199,6 +1205,20 @@ parse_command: > } > return 0; > >+ 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; >+ > case oPort: > arg = strdelim(&s); > if (!arg || *arg == '\0') >@@ -1903,6 +1923,7 @@ initialize_options(Options * options) > options->strict_host_key_checking = -1; > options->compression = -1; > options->tcp_keep_alive = -1; >+ options->transport = -1; > options->port = -1; > options->address_family = -1; > options->connection_attempts = -1; >@@ -2058,6 +2079,8 @@ fill_default_options(Options * options) > options->compression = 0; > if (options->tcp_keep_alive == -1) > options->tcp_keep_alive = 1; >+ if (options->transport == -1) >+ options->transport = TRANSPORT_TCP; > 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 dcecfc54afe1..6b228d2697e4 100644 >--- a/readconf.h >+++ b/readconf.h >@@ -27,6 +27,10 @@ struct allowed_cname { > char *target_list; > }; > >+/* Transport protocols */ >+#define TRANSPORT_TCP 1 >+#define TRANSPORT_SCTP 2 >+ > typedef struct { > int forward_agent; /* Forward authentication agent. */ > char *forward_agent_sock_path; /* Optional path of the agent. */ >@@ -56,6 +60,7 @@ typedef struct { > SyslogFacility log_facility; /* Facility for system logging. */ > LogLevel log_level; /* Level for logging. */ > >+ int transport; /* Transport protocol used. */ > int port; /* Port to connect. */ > int address_family; > int connection_attempts; /* Max attempts (seconds) before >diff --git a/scp.1 b/scp.1 >index 9c3a85366490..aab62f913fed 100644 >--- a/scp.1 >+++ b/scp.1 >@@ -18,7 +18,7 @@ > .Nd OpenSSH secure file copy > .Sh SYNOPSIS > .Nm scp >-.Op Fl 346BCpqrTv >+.Op Fl 346BCpqrTvz > .Op Fl c Ar cipher > .Op Fl F Ar ssh_config > .Op Fl i Ar identity_file >@@ -191,6 +191,7 @@ For full details of the options listed below, and their possible values, see > .It SetEnv > .It StrictHostKeyChecking > .It TCPKeepAlive >+.It Transport > .It UpdateHostKeys > .It User > .It UserKnownHostsFile >@@ -241,6 +242,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 762286c73aaa..725e324cc59e 100644 >--- a/scp.c >+++ b/scp.c >@@ -428,7 +428,7 @@ main(int argc, char **argv) > > fflag = Tflag = tflag = 0; > while ((ch = getopt(argc, argv, >- "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) { >+ "dfl:prtTvBCc:i:P:q12346S:o:F:J:z")) != -1) { > switch (ch) { > /* User-visible flags. */ > case '1': >@@ -437,6 +437,11 @@ main(int argc, char **argv) > case '2': > /* Ignored */ > break; >+ case 'z': >+#ifndef SCTP >+ fatal("SCTP support not available"); >+ break; >+#endif > case '4': > case '6': > case 'C': >diff --git a/servconf.c b/servconf.c >index 09e9df8bd648..f6fb4063762d 100644 >--- a/servconf.c >+++ b/servconf.c >@@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options) > options->macs = NULL; > options->kex_algorithms = NULL; > options->ca_sign_algorithms = NULL; >+ options->transport = -1; > options->fwd_opts.gateway_ports = -1; > options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; > options->fwd_opts.streamlocal_bind_unlink = -1; >@@ -383,6 +384,8 @@ fill_default_server_options(ServerOptions *options) > options->allow_streamlocal_forwarding = FORWARD_ALLOW; > if (options->allow_agent_forwarding == -1) > options->allow_agent_forwarding = 1; >+ if (options->transport == -1) >+ options->transport = TRANSPORT_TCP; > if (options->fwd_opts.gateway_ports == -1) > options->fwd_opts.gateway_ports = 0; > if (options->max_startups == -1) >@@ -493,6 +496,7 @@ typedef enum { > sKerberosGetAFSToken, sChallengeResponseAuthentication, > sPasswordAuthentication, sKbdInteractiveAuthentication, > sListenAddress, sAddressFamily, >+ sTransport, sListenMultipleAddresses, > sPrintMotd, sPrintLastLog, sIgnoreRhosts, > sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, > sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, >@@ -593,6 +597,13 @@ static struct { > { "skeyauthentication", sDeprecated, SSHCFG_GLOBAL }, > { "checkmail", sDeprecated, SSHCFG_GLOBAL }, > { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, >+#ifdef SCTP >+ { "listenmultipleaddresses", sListenMultipleAddresses, SSHCFG_GLOBAL }, >+ { "transport", sTransport, SSHCFG_GLOBAL }, >+#else >+ { "listenmultipleaddresses", sUnsupported, SSHCFG_GLOBAL }, >+ { "transport", sUnsupported, SSHCFG_GLOBAL }, >+#endif > { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, > { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, > #ifdef DISABLE_LASTLOG >@@ -947,6 +958,79 @@ get_connection_info(struct ssh *ssh, 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. > * >@@ -1315,6 +1399,25 @@ process_server_config_line(ServerOptions *options, char *line, > *intptr = value; > break; > >+#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') >@@ -1778,6 +1881,22 @@ process_server_config_line(ServerOptions *options, char *line, > options->kex_algorithms = xstrdup(arg); > break; > >+ 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; >+ > case sSubsystem: > if (options->num_subsystems >= MAX_SUBSYSTEMS) { > fatal("%s line %d: too many subsystems defined.", >@@ -2347,6 +2466,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) > M_CP_INTOPT(disable_forwarding); > M_CP_INTOPT(expose_userauth_info); > M_CP_INTOPT(permit_tun); >+ M_CP_INTOPT(transport); > M_CP_INTOPT(fwd_opts.gateway_ports); > M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); > M_CP_INTOPT(x11_display_offset); >@@ -2647,6 +2767,9 @@ dump_config(ServerOptions *o) > dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); > dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); > dump_cfg_fmtint(sCompression, o->compression); >+#ifdef SCTP >+ dump_cfg_fmtint(sTransport, o->transport); >+#endif > dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.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 6fc1efb2c8a2..6741d556680b 100644 >--- a/servconf.h >+++ b/servconf.h >@@ -65,6 +65,13 @@ struct listenaddr { > struct addrinfo *addrs; > }; > >+/* Transport protocols */ >+#define TRANSPORT_TCP 1 >+#define TRANSPORT_SCTP 2 >+#define TRANSPORT_ALL (TRANSPORT_TCP | TRANSPORT_SCTP) >+ >+#define IS_MULTIPLE_ADDR 0x1000 >+ > typedef struct { > u_int num_ports; > u_int ports_from_cmdline; >@@ -107,6 +114,7 @@ typedef struct { > char *ciphers; /* Supported SSH2 ciphers. */ > char *macs; /* Supported SSH2 macs. */ > char *kex_algorithms; /* SSH2 kex methods in order of preference. */ >+ int transport; /* Transport protocol(s) used */ > struct ForwardOptions fwd_opts; /* forwarding options */ > SyslogFacility log_facility; /* Facility for system logging. */ > LogLevel log_level; /* Level for system logging. */ >diff --git a/ssh.1 b/ssh.1 >index 97133752058e..d57605d6647f 100644 >--- a/ssh.1 >+++ b/ssh.1 >@@ -42,7 +42,7 @@ > .Nd OpenSSH remote login client > .Sh SYNOPSIS > .Nm ssh >-.Op Fl 46AaCfGgKkMNnqsTtVvXxYy >+.Op Fl 46AaCfGgKkMNnqsTtVvXxYyz > .Op Fl B Ar bind_interface > .Op Fl b Ar bind_address > .Op Fl c Ar cipher_spec >@@ -547,6 +547,7 @@ For full details of the options listed below, and their possible values, see > .It StreamLocalBindUnlink > .It StrictHostKeyChecking > .It TCPKeepAlive >+.It Transport > .It Tunnel > .It TunnelDevice > .It UpdateHostKeys >@@ -803,6 +804,8 @@ controls. > .Pp > .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 12760af298ee..c60c57d79173 100644 >--- a/ssh.c >+++ b/ssh.c >@@ -203,7 +203,7 @@ static void > usage(void) > { > fprintf(stderr, >-"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]\n" >+"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYyz] [-B bind_interface]\n" > " [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]\n" > " [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]\n" > " [-i identity_file] [-J [user@]host[:port]] [-L address]\n" >@@ -667,7 +667,7 @@ main(int ac, char **av) > > again: > while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" >- "AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { >+ "AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYyz")) != -1) { > switch (opt) { > case '1': > fatal("SSH protocol v.1 is no longer supported"); >@@ -909,6 +909,12 @@ main(int ac, char **av) > else > options.control_master = SSHCTL_MASTER_YES; > break; >+ case 'z': >+#ifndef SCTP >+ fatal("SCTP support not available"); >+#endif >+ options.transport = TRANSPORT_SCTP; >+ break; > case 'p': > if (options.port == -1) { > options.port = a2port(optarg); >diff --git a/ssh_config.5 b/ssh_config.5 >index d3d45b53a1e4..d5a473ff8f14 100644 >--- a/ssh_config.5 >+++ b/ssh_config.5 >@@ -1628,6 +1628,12 @@ To disable TCP keepalive messages, the value should be set to > See also > .Cm ServerAliveInterval > for protocol-level keepalives. >+.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 0b33ea58b8ef..c22a50a447fe 100644 >--- a/sshconnect.c >+++ b/sshconnect.c >@@ -69,6 +69,10 @@ > #include "authfd.h" > #include "kex.h" > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > struct sshkey *previous_host_key = NULL; > > static int matching_host_key_dns = 0; >@@ -368,6 +372,9 @@ ssh_create_socket(struct addrinfo *ai) > struct sockaddr_storage bindaddr; > socklen_t bindaddrlen = 0; > struct addrinfo hints, *res = NULL; >+#ifdef SCTP >+ char *more_addrs = NULL, *next_addr; >+#endif > #ifdef HAVE_IFADDRS_H > struct ifaddrs *ifaddrs = NULL; > #endif >@@ -385,10 +392,21 @@ ssh_create_socket(struct addrinfo *ai) > return sock; > > if (options.bind_address != NULL) { >+#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; > if ((r = getaddrinfo(options.bind_address, NULL, > &hints, &res)) != 0) { >@@ -430,6 +448,31 @@ ssh_create_socket(struct addrinfo *ai) > error("bind %s: %s", ntop, strerror(errno)); > goto fail; > } >+#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'; >+ } >+ >+ r = getaddrinfo(more_addrs, NULL, &hints, &res); >+ if (r) { >+ error("getaddrinfo: %s: %s", more_addrs, >+ ssh_gai_strerror(r)); >+ goto fail; >+ } >+ if (sctp_bindx(sock, (struct sockaddr *)res->ai_addr, >+ 1, SCTP_BINDX_ADD_ADDR) != 0) { >+ error("bind: %s: %s", options.bind_address, strerror(errno)); >+ goto fail; >+ } >+ >+ more_addrs = next_addr; >+ } while (next_addr != NULL); >+ } >+#endif > debug("%s: bound to %s", __func__, ntop); > /* success */ > goto out; >@@ -469,6 +512,15 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, > memset(ntop, 0, sizeof(ntop)); > memset(strport, 0, sizeof(strport)); > >+#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 0cf13a741744..14ce3c515110 100644 >--- a/sshd.c >+++ b/sshd.c >@@ -124,6 +124,10 @@ > #include "ssherr.h" > #include "sk-api.h" > >+#ifdef SCTP >+#include <netinet/sctp.h> >+#endif >+ > /* Re-exec fds */ > #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) > #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) >@@ -968,6 +972,12 @@ listen_on_addrs(struct listenaddr *la) > for (ai = la->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"); >@@ -1050,6 +1060,130 @@ server_listen(void) > fatal("Cannot bind any address."); > } > >+#ifdef SCTP >+/* >+ * Listen for SCTP connections >+ */ >+static void >+server_listen_sctp(void) >+{ >+ u_int i; >+ int ret, listen_sock, on = 1; >+ struct addrinfo *ai, *aiv6; >+ char ntop[NI_MAXHOST], strport[NI_MAXSERV]; >+ >+ for (i = 0; i < options.num_listen_addrs; i++) { >+ for (ai = options.listen_addrs[i].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. >@@ -1942,7 +2076,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(); > > signal(SIGHUP, sighup_handler); > signal(SIGCHLD, main_sigchld_handler); >diff --git a/sshd_config.5 b/sshd_config.5 >index 76ec69baf37a..01d72754fe8a 100644 >--- a/sshd_config.5 >+++ b/sshd_config.5 >@@ -1628,6 +1628,17 @@ This avoids infinitely hanging sessions. > .Pp > To disable TCP keepalive messages, the value should be set to > .Cm 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, or >-- >2.23.0
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 1604
:
1646
|
2572
|
2573
| 3346