Diff

Differences From Artifact [ce8b94020a]:

To Artifact [68ae0d0216]:


556
557
558
559
560
561
562
563
564
565
566






567
568
569
570
571
572
573
556
557
558
559
560
561
562




563
564
565
566
567
568
569
570
571
572
573
574
575







-
-
-
-
+
+
+
+
+
+







     *   2   We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
     *   4   We have received SSH1_MSG_CHANNEL_CLOSE.
     *   8   We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
     * 
     * A channel is completely finished with when all four bits are set.
     */
    int closes;
    union {
	struct ssh1_data_channel {
	    int throttling;
	} v1;
    /*
     * True if this channel is causing the underlying connection to be
     * throttled.
     */
    int throttling_conn;
    union {
	struct ssh2_data_channel {
	    bufchain outbuffer;
	    unsigned remwindow, remmaxpkt;
	    /* locwindow is signed so we can cope with excess data. */
	    int locwindow, locmaxwin;
	    /*
	     * remlocwin is the amount of local window that we think
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822







-
+








    Pkt_KCtx pkt_kctx;
    Pkt_ACtx pkt_actx;

    void *x11auth;

    int version;
    int v1_throttle_count;
    int conn_throttle_count;
    int overall_bufsize;
    int throttled_all;
    int v1_stdout_throttling;
    unsigned long v2_outgoing_sequence;

    int ssh1_rdpkt_crstate;
    int ssh2_rdpkt_crstate;
2869
2870
2871
2872
2873
2874
2875
2876

2877
2878
2879
2880
2881




2882
2883

2884
2885
2886
2887
2888
2889
2890
2871
2872
2873
2874
2875
2876
2877

2878
2879




2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
2892







-
+

-
-
-
-
+
+
+
+

-
+








    return NULL;
}

/*
 * Throttle or unthrottle the SSH connection.
 */
static void ssh1_throttle(Ssh ssh, int adjust)
static void ssh_throttle_conn(Ssh ssh, int adjust)
{
    int old_count = ssh->v1_throttle_count;
    ssh->v1_throttle_count += adjust;
    assert(ssh->v1_throttle_count >= 0);
    if (ssh->v1_throttle_count && !old_count) {
    int old_count = ssh->conn_throttle_count;
    ssh->conn_throttle_count += adjust;
    assert(ssh->conn_throttle_count >= 0);
    if (ssh->conn_throttle_count && !old_count) {
	ssh_set_frozen(ssh, 1);
    } else if (!ssh->v1_throttle_count && old_count) {
    } else if (!ssh->conn_throttle_count && old_count) {
	ssh_set_frozen(ssh, 0);
    }
}

/*
 * Throttle or unthrottle _all_ local data streams (for when sends
 * on the SSH connection itself back up).
4050
4051
4052
4053
4054
4055
4056

4057
4058
4059
4060
4061
4062

4063
4064
4065
4066
4067






4068
4069
4070
4071
4072
4073
4074
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064

4065



4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079







+





-
+
-
-
-

-
+
+
+
+
+
+







	return ssh2_try_send(c);
    }
}

void sshfwd_unthrottle(struct ssh_channel *c, int bufsize)
{
    Ssh ssh = c->ssh;
    int buflimit;

    if (ssh->state == SSH_STATE_CLOSED)
	return;

    if (ssh->version == 1) {
	if (c->v.v1.throttling && bufsize < SSH1_BUFFER_LIMIT) {
	buflimit = SSH1_BUFFER_LIMIT;
	    c->v.v1.throttling = 0;
	    ssh1_throttle(ssh, -1);
	}
    } else {
	ssh2_set_window(c, c->v.v2.locmaxwin - bufsize);
	buflimit = c->v.v2.locmaxwin;
	ssh2_set_window(c, bufsize < buflimit ? buflimit - bufsize : 0);
    }
    if (c->throttling_conn && bufsize <= buflimit) {
	c->throttling_conn = 0;
	ssh_throttle_conn(ssh, -1);
    }
}

static void ssh_queueing_handler(Ssh ssh, struct Packet *pktin)
{
    struct queued_handler *qh = ssh->qhead;

4489
4490
4491
4492
4493
4494
4495
4496

4497
4498
4499
4500
4501
4502
4503
4494
4495
4496
4497
4498
4499
4500

4501
4502
4503
4504
4505
4506
4507
4508







-
+







	return;
    }

    bufsize = from_backend(ssh->frontend, pktin->type == SSH1_SMSG_STDERR_DATA,
			   string, stringlen);
    if (!ssh->v1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
	ssh->v1_stdout_throttling = 1;
	ssh1_throttle(ssh, +1);
	ssh_throttle_conn(ssh, +1);
    }
}

static void ssh1_smsg_x11_open(Ssh ssh, struct Packet *pktin)
{
    /* Remote side is trying to open a channel to talk to our
     * X-Server. Give them back a local channel number. */
4523
4524
4525
4526
4527
4528
4529
4530

4531
4532
4533
4534
4535
4536
4537
4528
4529
4530
4531
4532
4533
4534

4535
4536
4537
4538
4539
4540
4541
4542







-
+







	} else {
	    logevent
		("Opening X11 forward connection succeeded");
	    c->remoteid = remoteid;
	    c->halfopen = FALSE;
	    c->localid = alloc_channel_id(ssh);
	    c->closes = 0;
	    c->v.v1.throttling = 0;
	    c->throttling_conn = 0;
	    c->type = CHAN_X11;	/* identify channel type */
	    add234(ssh->channels, c);
	    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
			PKT_INT, c->remoteid, PKT_INT,
			c->localid, PKT_END);
	    logevent("Opened X11 forward channel");
	}
4552
4553
4554
4555
4556
4557
4558
4559

4560
4561
4562
4563
4564
4565
4566
4557
4558
4559
4560
4561
4562
4563

4564
4565
4566
4567
4568
4569
4570
4571







-
+







    } else {
	c = snew(struct ssh_channel);
	c->ssh = ssh;
	c->remoteid = remoteid;
	c->halfopen = FALSE;
	c->localid = alloc_channel_id(ssh);
	c->closes = 0;
	c->v.v1.throttling = 0;
	c->throttling_conn = 0;
	c->type = CHAN_AGENT;	/* identify channel type */
	c->u.a.lensofar = 0;
	add234(ssh->channels, c);
	send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
		    PKT_INT, c->remoteid, PKT_INT, c->localid,
		    PKT_END);
    }
4606
4607
4608
4609
4610
4611
4612
4613

4614
4615
4616
4617
4618
4619
4620
4611
4612
4613
4614
4615
4616
4617

4618
4619
4620
4621
4622
4623
4624
4625







-
+







	    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
			PKT_INT, remoteid, PKT_END);
	} else {
	    c->remoteid = remoteid;
	    c->halfopen = FALSE;
	    c->localid = alloc_channel_id(ssh);
	    c->closes = 0;
	    c->v.v1.throttling = 0;
	    c->throttling_conn = 0;
	    c->type = CHAN_SOCKDATA;	/* identify channel type */
	    add234(ssh->channels, c);
	    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
			PKT_INT, c->remoteid, PKT_INT,
			c->localid, PKT_END);
	    logevent("Forwarded port opened successfully");
	}
4628
4629
4630
4631
4632
4633
4634
4635

4636
4637
4638
4639
4640
4641
4642
4633
4634
4635
4636
4637
4638
4639

4640
4641
4642
4643
4644
4645
4646
4647







-
+







    struct ssh_channel *c;

    c = find234(ssh->channels, &remoteid, ssh_channelfind);
    if (c && c->type == CHAN_SOCKDATA_DORMANT) {
	c->remoteid = localid;
	c->halfopen = FALSE;
	c->type = CHAN_SOCKDATA;
	c->v.v1.throttling = 0;
	c->throttling_conn = 0;
	pfd_confirm(c->u.pfd.s);
    }

    if (c && c->closes) {
	/*
	 * We have a pending close on this channel,
	 * which we decided on before the server acked
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773



4774
4775
4776
4777
4778
4779
4780
4769
4770
4771
4772
4773
4774
4775



4776
4777
4778
4779
4780
4781
4782
4783
4784
4785







-
-
-
+
+
+







		    sfree(c->u.a.message);
		    c->u.a.lensofar = 0;
		}
	    }
	    bufsize = 0;   /* agent channels never back up */
	    break;
	}
	if (!c->v.v1.throttling && bufsize > SSH1_BUFFER_LIMIT) {
	    c->v.v1.throttling = 1;
	    ssh1_throttle(ssh, +1);
	if (!c->throttling_conn && bufsize > SSH1_BUFFER_LIMIT) {
	    c->throttling_conn = 1;
	    ssh_throttle_conn(ssh, +1);
	}
    }
}

static void ssh1_smsg_exit_status(Ssh ssh, struct Packet *pktin)
{
    ssh->exitcode = ssh_pkt_getuint32(pktin);
6454
6455
6456
6457
6458
6459
6460











6461
6462
6463
6464
6465
6466
6467
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483







+
+
+
+
+
+
+
+
+
+
+







	 * enlarge the window again at the remote side.
	 * If we are buffering too much, we may still
	 * need to adjust the window if the server's
	 * sent excess data.
	 */
	ssh2_set_window(c, bufsize < c->v.v2.locmaxwin ?
			c->v.v2.locmaxwin - bufsize : 0);
	/*
	 * If we're either buffering way too much data, or if we're
	 * buffering anything at all and we're in "simple" mode,
	 * throttle the whole channel.
	 */
	if ((bufsize > c->v.v2.locmaxwin ||
	     (ssh->cfg.ssh_simple && bufsize > 0)) &&
	    !c->throttling_conn) {
	    c->throttling_conn = 1;
	    ssh_throttle_conn(ssh, +1);
	}
    }
}

static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
{
    struct ssh_channel *c;

6901
6902
6903
6904
6905
6906
6907

6908
6909
6910
6911
6912
6913
6914
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931







+







	ssh2_pkt_addstring(pktout, "en");	/* language tag */
	ssh2_pkt_send(ssh, pktout);
	logeventf(ssh, "Rejected channel open: %s", error);
	sfree(c);
    } else {
	c->localid = alloc_channel_id(ssh);
	c->closes = 0;
	c->throttling_conn = FALSE;
	c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
	c->v.v2.remwindow = winsize;
	c->v.v2.remmaxpkt = pktsize;
	c->v.v2.remlocwin = OUR_V2_WINSIZE;
	c->v.v2.winadj_head = c->v.v2.winadj_tail = NULL;
	c->v.v2.throttle_state = UNTHROTTLED;
	bufchain_init(&c->v.v2.outbuffer);
8115
8116
8117
8118
8119
8120
8121

8122
8123
8124
8125
8126
8127
8128
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146







+







	ssh->mainchan->localid = alloc_channel_id(ssh);
	logeventf(ssh,
		  "Opening direct-tcpip channel to %s:%d in place of session",
		  ssh->cfg.ssh_nc_host, ssh->cfg.ssh_nc_port);
	s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
	ssh2_pkt_addstring(s->pktout, "direct-tcpip");
	ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
	ssh->mainchan->throttling_conn = FALSE;
	ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
	    ssh->mainchan->v.v2.remlocwin =
	    ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
	ssh->mainchan->v.v2.winadj_head = NULL;
	ssh->mainchan->v.v2.winadj_tail = NULL;
	ssh->mainchan->v.v2.throttle_state = UNTHROTTLED;
	ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
8162
8163
8164
8165
8166
8167
8168

8169
8170
8171
8172
8173
8174
8175
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194







+







    } else {
	ssh->mainchan = snew(struct ssh_channel);
	ssh->mainchan->ssh = ssh;
	ssh->mainchan->localid = alloc_channel_id(ssh);
	s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
	ssh2_pkt_addstring(s->pktout, "session");
	ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
	ssh->mainchan->throttling_conn = FALSE;
	ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
	    ssh->mainchan->v.v2.remlocwin =
	    ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
	ssh->mainchan->v.v2.winadj_head = NULL;
	ssh->mainchan->v.v2.winadj_tail = NULL;
	ssh->mainchan->v.v2.throttle_state = UNTHROTTLED;
	ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
8788
8789
8790
8791
8792
8793
8794
8795

8796
8797
8798
8799
8800
8801
8802
8807
8808
8809
8810
8811
8812
8813

8814
8815
8816
8817
8818
8819
8820
8821







-
+







    ssh->channels = NULL;
    ssh->rportfwds = NULL;
    ssh->portfwds = NULL;

    ssh->send_ok = 0;
    ssh->editing = 0;
    ssh->echoing = 0;
    ssh->v1_throttle_count = 0;
    ssh->conn_throttle_count = 0;
    ssh->overall_bufsize = 0;
    ssh->fallback_cmd = 0;

    ssh->protocol = NULL;

    ssh->protocol_initial_phase_done = FALSE;

9235
9236
9237
9238
9239
9240
9241


9242
9243
9244
9245

9246
9247
9248

9249

9250










9251
9252
9253
9254
9255
9256
9257
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265

9266
9267
9268

9269
9270
9271

9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288







+
+



-
+


-
+

+
-
+
+
+
+
+
+
+
+
+
+







/*
 * This is called when stdout/stderr (the entity to which
 * from_backend sends data) manages to clear some backlog.
 */
static void ssh_unthrottle(void *handle, int bufsize)
{
    Ssh ssh = (Ssh) handle;
    int buflimit;

    if (ssh->version == 1) {
	if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
	    ssh->v1_stdout_throttling = 0;
	    ssh1_throttle(ssh, -1);
	    ssh_throttle_conn(ssh, -1);
	}
    } else {
	if (ssh->mainchan)
	if (ssh->mainchan) {
	    ssh2_set_window(ssh->mainchan,
			    bufsize < ssh->mainchan->v.v2.locmaxwin ?
			    ssh->mainchan->v.v2.locmaxwin - bufsize);
			    ssh->mainchan->v.v2.locmaxwin - bufsize : 0);
	    if (ssh->cfg.ssh_simple)
		buflimit = 0;
	    else
		buflimit = ssh->mainchan->v.v2.locmaxwin;
	    if (ssh->mainchan->throttling_conn && bufsize <= buflimit) {
		ssh->mainchan->throttling_conn = 0;
		ssh_throttle_conn(ssh, -1);
	    }
	}
    }
}

void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
{
    struct ssh_channel *c = (struct ssh_channel *)channel;
    Ssh ssh = c->ssh;
9266
9267
9268
9269
9270
9271
9272

9273
9274
9275
9276
9277
9278
9279
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311







+







		    PKT_INT, port,
		    /* PKT_STR, <org:orgport>, */
		    PKT_END);
    } else {
	pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
	ssh2_pkt_addstring(pktout, "direct-tcpip");
	ssh2_pkt_adduint32(pktout, c->localid);
	c->throttling_conn = FALSE;
	c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
	c->v.v2.remlocwin = OUR_V2_WINSIZE;
	c->v.v2.winadj_head = c->v.v2.winadj_head = NULL;
	c->v.v2.throttle_state = UNTHROTTLED;
	ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
	ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT);      /* our max pkt size */
	ssh2_pkt_addstring(pktout, hostname);