/* open new channel for a session */ static int ssh_session2_open(void) { Channel *c; int window, packetmax, in, out, err; int sock; int socksize; int socksizelen = sizeof(int); if (stdin_null_flag) { in = open(_PATH_DEVNULL, O_RDONLY); } else { in = dup(STDIN_FILENO); } out = dup(STDOUT_FILENO); err = dup(STDERR_FILENO); if (in < 0 || out < 0 || err < 0) fatal("dup() in/out/err failed"); /* enable nonblocking unless tty */ if (!isatty(in)) set_nonblock(in); if (!isatty(out)) set_nonblock(out); if (!isatty(err)) set_nonblock(err); /* we need to check to see if what they want to do about buffer */ /* sizes here. In a hpn to nonhpn connection we want to limit */ /* the window size to something reasonable in case the far side */ /* has the large window bug. In hpn to hpn connection we want to */ /* use the max window size but allow the user to override it */ /* lastly if they disabled hpn then use the ssh std window size */ /* so why don't we just do a getsockopt() here and set the */ /* ssh window to that? In the case of a autotuning receive */ /* window the window would get stuck at the initial buffer */ /* size generally less than 96k. Therefore we need to set the */ /* maximum ssh window size to the maximum hpn buffer size */ /* unless the user has specifically set the tcprcvbufpoll */ /* to no. In which case we *can* just set the window to the */ /* minimum of the hpn buffer size and tcp receive buffer size */ if (tty_flag) options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; else options.hpn_buffer_size = 2*1024*1024; if (datafellows & SSH_BUG_LARGEWINDOW) { debug("HPN to Non-HPN Connection"); } else { if (options.tcp_rcv_buf_poll <= 0) { sock = socket(AF_INET, SOCK_STREAM, 0); getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); close(sock); debug("socksize %d", socksize); options.hpn_buffer_size = socksize; debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); } else { if (options.tcp_rcv_buf > 0) { /*create a socket but don't connect it */ /* we use that the get the rcv socket size */ sock = socket(AF_INET, SOCK_STREAM, 0); /* if they are using the tcp_rcv_buf option */ /* attempt to set the buffer size to that */ if (options.tcp_rcv_buf) setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, sizeof(options.tcp_rcv_buf)); getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); close(sock); debug("socksize %d", socksize); options.hpn_buffer_size = socksize; debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); } } } debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); window = options.hpn_buffer_size; channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window = 4*CHAN_SES_PACKET_DEFAULT; window >>= 1; packetmax >>= 1; } c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { c->dynamic_window = 1; debug ("Enabled Dynamic Window Scaling\n"); } debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); if (!no_shell_flag) channel_register_open_confirm(c->self, ssh_session2_setup, NULL); return c->self; }
/* open new channel for a session */ static int ssh_session2_open(void) { Channel *c; int window, packetmax, in, out, err; if (stdin_null_flag) { in = open(_PATH_DEVNULL, O_RDONLY); } else { in = dup(STDIN_FILENO); } out = dup(STDOUT_FILENO); err = dup(STDERR_FILENO); if (in < 0 || out < 0 || err < 0) fatal("dup() in/out/err failed"); /* enable nonblocking unless tty */ if (!isatty(in)) set_nonblock(in); if (!isatty(out)) set_nonblock(out); if (!isatty(err)) set_nonblock(err); /* * We need to check to see what to do about buffer sizes here. * - In an HPN to non-HPN connection we want to limit the window size to * something reasonable in case the far side has the large window bug. * - In an HPN to HPN connection we want to use the max window size but * allow the user to override it. * - Lastly if HPN is disabled then use the ssh standard window size. * * We cannot just do a getsockopt() here and set the ssh window to that * as in case of autotuning of socket buffers the window would get stuck * at the initial buffer size, generally less than 96k. Therefore we * need to set the maximum ssh window size to the maximum HPN buffer * size unless the user has set TcpRcvBufPoll to no. In that case we * can just set the window to the minimum of HPN buffer size and TCP * receive buffer size. */ if (tty_flag) options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; else options.hpn_buffer_size = CHAN_HPN_MIN_WINDOW_DEFAULT; if (datafellows & SSH_BUG_LARGEWINDOW) { debug("HPN to Non-HPN Connection"); } else if (options.tcp_rcv_buf_poll <= 0) { sock_get_rcvbuf(&options.hpn_buffer_size, 0); debug("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); } else if (options.tcp_rcv_buf > 0) { sock_get_rcvbuf(&options.hpn_buffer_size, options.tcp_rcv_buf); debug("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); } debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); window = options.hpn_buffer_size; packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window = CHAN_SES_WINDOW_DEFAULT; window >>= 1; packetmax >>= 1; } c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); if (!options.hpn_disabled && options.tcp_rcv_buf_poll > 0) { c->dynamic_window = 1; debug("Enabled Dynamic Window Scaling\n"); } debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); if (!no_shell_flag) channel_register_open_confirm(c->self, ssh_session2_setup, NULL); return c->self; }