diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | nchan.c | 97 |
2 files changed, 70 insertions, 31 deletions
@@ -14,7 +14,7 @@ | |||
14 | history | 14 | history |
15 | - (bal) Channels.c and Channels.h -- "Merge Functions, simplify" (draged | 15 | - (bal) Channels.c and Channels.h -- "Merge Functions, simplify" (draged |
16 | out of ssh Attic) | 16 | out of ssh Attic) |
17 | - (bal) nchan.c CVS ID Update. | 17 | - (bal) Ooops.. nchan.c resync from OpenBSD ssh Attic. |
18 | 18 | ||
19 | 20010606 | 19 | 20010606 |
20 | - OpenBSD CVS Sync | 20 | - OpenBSD CVS Sync |
@@ -5526,4 +5526,4 @@ | |||
5526 | - Wrote replacements for strlcpy and mkdtemp | 5526 | - Wrote replacements for strlcpy and mkdtemp |
5527 | - Released 1.0pre1 | 5527 | - Released 1.0pre1 |
5528 | 5528 | ||
5529 | $Id: ChangeLog,v 1.1251 2001/06/09 00:44:44 mouring Exp $ | 5529 | $Id: ChangeLog,v 1.1252 2001/06/09 00:57:39 mouring Exp $ |
@@ -30,10 +30,35 @@ RCSID("$OpenBSD: nchan.c,v 1.28 2001/05/31 10:30:16 markus Exp $"); | |||
30 | #include "buffer.h" | 30 | #include "buffer.h" |
31 | #include "packet.h" | 31 | #include "packet.h" |
32 | #include "channels.h" | 32 | #include "channels.h" |
33 | #include "nchan.h" | ||
34 | #include "compat.h" | 33 | #include "compat.h" |
35 | #include "log.h" | 34 | #include "log.h" |
36 | 35 | ||
36 | /* | ||
37 | * SSH Protocol 1.5 aka New Channel Protocol | ||
38 | * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. | ||
39 | * Written by Markus Friedl in October 1999 | ||
40 | * | ||
41 | * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the | ||
42 | * tear down of channels: | ||
43 | * | ||
44 | * 1.3: strict request-ack-protocol: | ||
45 | * CLOSE -> | ||
46 | * <- CLOSE_CONFIRM | ||
47 | * | ||
48 | * 1.5: uses variations of: | ||
49 | * IEOF -> | ||
50 | * <- OCLOSE | ||
51 | * <- IEOF | ||
52 | * OCLOSE -> | ||
53 | * i.e. both sides have to close the channel | ||
54 | * | ||
55 | * 2.0: the EOF messages are optional | ||
56 | * | ||
57 | * See the debugging output from 'ssh -v' and 'sshd -d' of | ||
58 | * ssh-1.2.27 as an example. | ||
59 | * | ||
60 | */ | ||
61 | |||
37 | /* functions manipulating channel states */ | 62 | /* functions manipulating channel states */ |
38 | /* | 63 | /* |
39 | * EVENTS update channel input/output states execute ACTIONS | 64 | * EVENTS update channel input/output states execute ACTIONS |
@@ -84,7 +109,7 @@ chan_rcvd_oclose1(Channel *c) | |||
84 | c->istate = CHAN_INPUT_CLOSED; | 109 | c->istate = CHAN_INPUT_CLOSED; |
85 | break; | 110 | break; |
86 | default: | 111 | default: |
87 | error("channel %d: protocol error: chan_rcvd_oclose for istate %d", | 112 | error("channel %d: protocol error: rcvd_oclose for istate %d", |
88 | c->self, c->istate); | 113 | c->self, c->istate); |
89 | return; | 114 | return; |
90 | } | 115 | } |
@@ -98,13 +123,15 @@ chan_read_failed_12(Channel *c) | |||
98 | debug("channel %d: input open -> drain", c->self); | 123 | debug("channel %d: input open -> drain", c->self); |
99 | chan_shutdown_read(c); | 124 | chan_shutdown_read(c); |
100 | c->istate = CHAN_INPUT_WAIT_DRAIN; | 125 | c->istate = CHAN_INPUT_WAIT_DRAIN; |
126 | #if 0 | ||
101 | if (buffer_len(&c->input) == 0) { | 127 | if (buffer_len(&c->input) == 0) { |
102 | debug("channel %d: input: no drain shortcut", c->self); | 128 | debug("channel %d: input: no drain shortcut", c->self); |
103 | chan_ibuf_empty(c); | 129 | chan_ibuf_empty(c); |
104 | } | 130 | } |
131 | #endif | ||
105 | break; | 132 | break; |
106 | default: | 133 | default: |
107 | error("channel %d: internal error: we do not read, but chan_read_failed for istate %d", | 134 | error("channel %d: chan_read_failed for istate %d", |
108 | c->self, c->istate); | 135 | c->self, c->istate); |
109 | break; | 136 | break; |
110 | } | 137 | } |
@@ -114,7 +141,7 @@ chan_ibuf_empty1(Channel *c) | |||
114 | { | 141 | { |
115 | debug("channel %d: ibuf empty", c->self); | 142 | debug("channel %d: ibuf empty", c->self); |
116 | if (buffer_len(&c->input)) { | 143 | if (buffer_len(&c->input)) { |
117 | error("channel %d: internal error: chan_ibuf_empty for non empty buffer", | 144 | error("channel %d: chan_ibuf_empty for non empty buffer", |
118 | c->self); | 145 | c->self); |
119 | return; | 146 | return; |
120 | } | 147 | } |
@@ -125,7 +152,7 @@ chan_ibuf_empty1(Channel *c) | |||
125 | c->istate = CHAN_INPUT_WAIT_OCLOSE; | 152 | c->istate = CHAN_INPUT_WAIT_OCLOSE; |
126 | break; | 153 | break; |
127 | default: | 154 | default: |
128 | error("channel %d: internal error: chan_ibuf_empty for istate %d", | 155 | error("channel %d: chan_ibuf_empty for istate %d", |
129 | c->self, c->istate); | 156 | c->self, c->istate); |
130 | break; | 157 | break; |
131 | } | 158 | } |
@@ -137,19 +164,23 @@ chan_rcvd_ieof1(Channel *c) | |||
137 | if (c->type != SSH_CHANNEL_OPEN) { | 164 | if (c->type != SSH_CHANNEL_OPEN) { |
138 | debug("channel %d: non-open", c->self); | 165 | debug("channel %d: non-open", c->self); |
139 | if (c->istate == CHAN_INPUT_OPEN) { | 166 | if (c->istate == CHAN_INPUT_OPEN) { |
140 | debug("channel %d: non-open: input open -> wait_oclose", c->self); | 167 | debug("channel %d: non-open: input open -> wait_oclose", |
168 | c->self); | ||
141 | chan_shutdown_read(c); | 169 | chan_shutdown_read(c); |
142 | chan_send_ieof1(c); | 170 | chan_send_ieof1(c); |
143 | c->istate = CHAN_INPUT_WAIT_OCLOSE; | 171 | c->istate = CHAN_INPUT_WAIT_OCLOSE; |
144 | } else { | 172 | } else { |
145 | error("channel %d: istate %d != open", c->self, c->istate); | 173 | error("channel %d: non-open: istate %d != open", |
174 | c->self, c->istate); | ||
146 | } | 175 | } |
147 | if (c->ostate == CHAN_OUTPUT_OPEN) { | 176 | if (c->ostate == CHAN_OUTPUT_OPEN) { |
148 | debug("channel %d: non-open: output open -> closed", c->self); | 177 | debug("channel %d: non-open: output open -> closed", |
178 | c->self); | ||
149 | chan_send_oclose1(c); | 179 | chan_send_oclose1(c); |
150 | c->ostate = CHAN_OUTPUT_CLOSED; | 180 | c->ostate = CHAN_OUTPUT_CLOSED; |
151 | } else { | 181 | } else { |
152 | error("channel %d: ostate %d != open", c->self, c->ostate); | 182 | error("channel %d: non-open: ostate %d != open", |
183 | c->self, c->ostate); | ||
153 | } | 184 | } |
154 | return; | 185 | return; |
155 | } | 186 | } |
@@ -163,7 +194,7 @@ chan_rcvd_ieof1(Channel *c) | |||
163 | c->ostate = CHAN_OUTPUT_CLOSED; | 194 | c->ostate = CHAN_OUTPUT_CLOSED; |
164 | break; | 195 | break; |
165 | default: | 196 | default: |
166 | error("channel %d: protocol error: chan_rcvd_ieof for ostate %d", | 197 | error("channel %d: protocol error: rcvd_ieof for ostate %d", |
167 | c->self, c->ostate); | 198 | c->self, c->ostate); |
168 | break; | 199 | break; |
169 | } | 200 | } |
@@ -184,7 +215,7 @@ chan_write_failed1(Channel *c) | |||
184 | c->ostate = CHAN_OUTPUT_CLOSED; | 215 | c->ostate = CHAN_OUTPUT_CLOSED; |
185 | break; | 216 | break; |
186 | default: | 217 | default: |
187 | error("channel %d: internal error: chan_write_failed for ostate %d", | 218 | error("channel %d: chan_write_failed for ostate %d", |
188 | c->self, c->ostate); | 219 | c->self, c->ostate); |
189 | break; | 220 | break; |
190 | } | 221 | } |
@@ -194,7 +225,7 @@ chan_obuf_empty1(Channel *c) | |||
194 | { | 225 | { |
195 | debug("channel %d: obuf empty", c->self); | 226 | debug("channel %d: obuf empty", c->self); |
196 | if (buffer_len(&c->output)) { | 227 | if (buffer_len(&c->output)) { |
197 | error("channel %d: internal error: chan_obuf_empty for non empty buffer", | 228 | error("channel %d: chan_obuf_empty for non empty buffer", |
198 | c->self); | 229 | c->self); |
199 | return; | 230 | return; |
200 | } | 231 | } |
@@ -205,7 +236,7 @@ chan_obuf_empty1(Channel *c) | |||
205 | c->ostate = CHAN_OUTPUT_CLOSED; | 236 | c->ostate = CHAN_OUTPUT_CLOSED; |
206 | break; | 237 | break; |
207 | default: | 238 | default: |
208 | error("channel %d: internal error: chan_obuf_empty for ostate %d", | 239 | error("channel %d: internal error: obuf_empty for ostate %d", |
209 | c->self, c->ostate); | 240 | c->self, c->ostate); |
210 | break; | 241 | break; |
211 | } | 242 | } |
@@ -222,7 +253,7 @@ chan_send_ieof1(Channel *c) | |||
222 | packet_send(); | 253 | packet_send(); |
223 | break; | 254 | break; |
224 | default: | 255 | default: |
225 | error("channel %d: internal error: cannot send ieof for istate %d", | 256 | error("channel %d: cannot send ieof for istate %d", |
226 | c->self, c->istate); | 257 | c->self, c->istate); |
227 | break; | 258 | break; |
228 | } | 259 | } |
@@ -241,7 +272,7 @@ chan_send_oclose1(Channel *c) | |||
241 | packet_send(); | 272 | packet_send(); |
242 | break; | 273 | break; |
243 | default: | 274 | default: |
244 | error("channel %d: internal error: cannot send oclose for ostate %d", | 275 | error("channel %d: cannot send oclose for ostate %d", |
245 | c->self, c->ostate); | 276 | c->self, c->ostate); |
246 | break; | 277 | break; |
247 | } | 278 | } |
@@ -265,7 +296,10 @@ chan_rcvd_oclose2(Channel *c) | |||
265 | } | 296 | } |
266 | switch (c->ostate) { | 297 | switch (c->ostate) { |
267 | case CHAN_OUTPUT_OPEN: | 298 | case CHAN_OUTPUT_OPEN: |
268 | /* wait until a data from the channel is consumed if a CLOSE is received */ | 299 | /* |
300 | * wait until a data from the channel is consumed if a CLOSE | ||
301 | * is received | ||
302 | */ | ||
269 | debug("channel %d: output open -> drain", c->self); | 303 | debug("channel %d: output open -> drain", c->self); |
270 | c->ostate = CHAN_OUTPUT_WAIT_DRAIN; | 304 | c->ostate = CHAN_OUTPUT_WAIT_DRAIN; |
271 | break; | 305 | break; |
@@ -287,7 +321,7 @@ chan_ibuf_empty2(Channel *c) | |||
287 | { | 321 | { |
288 | debug("channel %d: ibuf empty", c->self); | 322 | debug("channel %d: ibuf empty", c->self); |
289 | if (buffer_len(&c->input)) { | 323 | if (buffer_len(&c->input)) { |
290 | error("channel %d: internal error: chan_ibuf_empty for non empty buffer", | 324 | error("channel %d: chan_ibuf_empty for non empty buffer", |
291 | c->self); | 325 | c->self); |
292 | return; | 326 | return; |
293 | } | 327 | } |
@@ -299,7 +333,7 @@ chan_ibuf_empty2(Channel *c) | |||
299 | c->istate = CHAN_INPUT_CLOSED; | 333 | c->istate = CHAN_INPUT_CLOSED; |
300 | break; | 334 | break; |
301 | default: | 335 | default: |
302 | error("channel %d: internal error: chan_ibuf_empty for istate %d", | 336 | error("channel %d: chan_ibuf_empty for istate %d", |
303 | c->self, c->istate); | 337 | c->self, c->istate); |
304 | break; | 338 | break; |
305 | } | 339 | } |
@@ -329,7 +363,7 @@ chan_write_failed2(Channel *c) | |||
329 | c->ostate = CHAN_OUTPUT_CLOSED; | 363 | c->ostate = CHAN_OUTPUT_CLOSED; |
330 | break; | 364 | break; |
331 | default: | 365 | default: |
332 | error("channel %d: internal error: chan_write_failed for ostate %d", | 366 | error("channel %d: chan_write_failed for ostate %d", |
333 | c->self, c->ostate); | 367 | c->self, c->ostate); |
334 | break; | 368 | break; |
335 | } | 369 | } |
@@ -339,7 +373,7 @@ chan_obuf_empty2(Channel *c) | |||
339 | { | 373 | { |
340 | debug("channel %d: obuf empty", c->self); | 374 | debug("channel %d: obuf empty", c->self); |
341 | if (buffer_len(&c->output)) { | 375 | if (buffer_len(&c->output)) { |
342 | error("internal error: chan_obuf_empty %d for non empty buffer", | 376 | error("channel %d: chan_obuf_empty for non empty buffer", |
343 | c->self); | 377 | c->self); |
344 | return; | 378 | return; |
345 | } | 379 | } |
@@ -350,7 +384,7 @@ chan_obuf_empty2(Channel *c) | |||
350 | c->ostate = CHAN_OUTPUT_CLOSED; | 384 | c->ostate = CHAN_OUTPUT_CLOSED; |
351 | break; | 385 | break; |
352 | default: | 386 | default: |
353 | error("channel %d: internal error: chan_obuf_empty for ostate %d", | 387 | error("channel %d: chan_obuf_empty for ostate %d", |
354 | c->self, c->ostate); | 388 | c->self, c->ostate); |
355 | break; | 389 | break; |
356 | } | 390 | } |
@@ -366,7 +400,7 @@ chan_send_eof2(Channel *c) | |||
366 | packet_send(); | 400 | packet_send(); |
367 | break; | 401 | break; |
368 | default: | 402 | default: |
369 | error("channel %d: internal error: cannot send eof for istate %d", | 403 | error("channel %d: cannot send eof for istate %d", |
370 | c->self, c->istate); | 404 | c->self, c->istate); |
371 | break; | 405 | break; |
372 | } | 406 | } |
@@ -377,10 +411,10 @@ chan_send_close2(Channel *c) | |||
377 | debug("channel %d: send close", c->self); | 411 | debug("channel %d: send close", c->self); |
378 | if (c->ostate != CHAN_OUTPUT_CLOSED || | 412 | if (c->ostate != CHAN_OUTPUT_CLOSED || |
379 | c->istate != CHAN_INPUT_CLOSED) { | 413 | c->istate != CHAN_INPUT_CLOSED) { |
380 | error("channel %d: internal error: cannot send close for istate/ostate %d/%d", | 414 | error("channel %d: cannot send close for istate/ostate %d/%d", |
381 | c->self, c->istate, c->ostate); | 415 | c->self, c->istate, c->ostate); |
382 | } else if (c->flags & CHAN_CLOSE_SENT) { | 416 | } else if (c->flags & CHAN_CLOSE_SENT) { |
383 | error("channel %d: internal error: already sent close", c->self); | 417 | error("channel %d: already sent close", c->self); |
384 | } else { | 418 | } else { |
385 | packet_start(SSH2_MSG_CHANNEL_CLOSE); | 419 | packet_start(SSH2_MSG_CHANNEL_CLOSE); |
386 | packet_put_int(c->remote_id); | 420 | packet_put_int(c->remote_id); |
@@ -480,11 +514,13 @@ chan_shutdown_write(Channel *c) | |||
480 | debug("channel %d: close_write", c->self); | 514 | debug("channel %d: close_write", c->self); |
481 | if (c->sock != -1) { | 515 | if (c->sock != -1) { |
482 | if (shutdown(c->sock, SHUT_WR) < 0) | 516 | if (shutdown(c->sock, SHUT_WR) < 0) |
483 | debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s", | 517 | debug("channel %d: chan_shutdown_write: " |
518 | "shutdown() failed for fd%d: %.100s", | ||
484 | c->self, c->sock, strerror(errno)); | 519 | c->self, c->sock, strerror(errno)); |
485 | } else { | 520 | } else { |
486 | if (close(c->wfd) < 0) | 521 | if (close(c->wfd) < 0) |
487 | log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s", | 522 | log("channel %d: chan_shutdown_write: " |
523 | "close() failed for fd%d: %.100s", | ||
488 | c->self, c->wfd, strerror(errno)); | 524 | c->self, c->wfd, strerror(errno)); |
489 | c->wfd = -1; | 525 | c->wfd = -1; |
490 | } | 526 | } |
@@ -503,11 +539,14 @@ chan_shutdown_read(Channel *c) | |||
503 | */ | 539 | */ |
504 | if (shutdown(c->sock, SHUT_RD) < 0 | 540 | if (shutdown(c->sock, SHUT_RD) < 0 |
505 | && (errno != ENOTCONN && errno != EINVAL)) | 541 | && (errno != ENOTCONN && errno != EINVAL)) |
506 | error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s", | 542 | error("channel %d: chan_shutdown_read: " |
507 | c->self, c->sock, c->istate, c->ostate, strerror(errno)); | 543 | "shutdown() failed for fd%d [i%d o%d]: %.100s", |
544 | c->self, c->sock, c->istate, c->ostate, | ||
545 | strerror(errno)); | ||
508 | } else { | 546 | } else { |
509 | if (close(c->rfd) < 0) | 547 | if (close(c->rfd) < 0) |
510 | log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s", | 548 | log("channel %d: chan_shutdown_read: " |
549 | "close() failed for fd%d: %.100s", | ||
511 | c->self, c->rfd, strerror(errno)); | 550 | c->self, c->rfd, strerror(errno)); |
512 | c->rfd = -1; | 551 | c->rfd = -1; |
513 | } | 552 | } |