]> andersk Git - openssh.git/blob - nchan.c
- markus@cvs.openbsd.org 2002/01/10 12:38:26
[openssh.git] / nchan.c
1 /*
2  * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26 RCSID("$OpenBSD: nchan.c,v 1.35 2002/01/10 12:38:26 markus Exp $");
27
28 #include "ssh1.h"
29 #include "ssh2.h"
30 #include "buffer.h"
31 #include "packet.h"
32 #include "channels.h"
33 #include "compat.h"
34 #include "log.h"
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
62 /* functions manipulating channel states */
63 /*
64  * EVENTS update channel input/output states execute ACTIONS
65  */
66 /* events concerning the INPUT from socket for channel (istate) */
67 chan_event_fn *chan_rcvd_oclose                 = NULL;
68 chan_event_fn *chan_read_failed                 = NULL;
69 chan_event_fn *chan_ibuf_empty                  = NULL;
70 /* events concerning the OUTPUT from channel for socket (ostate) */
71 chan_event_fn *chan_rcvd_ieof                   = NULL;
72 chan_event_fn *chan_write_failed                = NULL;
73 chan_event_fn *chan_obuf_empty                  = NULL;
74 /*
75  * ACTIONS: should never update the channel states
76  */
77 static void     chan_send_ieof1(Channel *);
78 static void     chan_send_oclose1(Channel *);
79 static void     chan_send_close2(Channel *);
80 static void     chan_send_eof2(Channel *);
81
82 /* helper */
83 static void     chan_shutdown_write(Channel *);
84 static void     chan_shutdown_read(Channel *);
85
86 /*
87  * SSH1 specific implementation of event functions
88  */
89
90 static void
91 chan_rcvd_oclose1(Channel *c)
92 {
93         debug("channel %d: rcvd oclose", c->self);
94         switch (c->istate) {
95         case CHAN_INPUT_WAIT_OCLOSE:
96                 debug("channel %d: input wait_oclose -> closed", c->self);
97                 c->istate = CHAN_INPUT_CLOSED;
98                 break;
99         case CHAN_INPUT_OPEN:
100                 debug("channel %d: input open -> closed", c->self);
101                 chan_shutdown_read(c);
102                 chan_send_ieof1(c);
103                 c->istate = CHAN_INPUT_CLOSED;
104                 break;
105         case CHAN_INPUT_WAIT_DRAIN:
106                 /* both local read_failed and remote write_failed  */
107                 log("channel %d: input drain -> closed", c->self);
108                 chan_send_ieof1(c);
109                 c->istate = CHAN_INPUT_CLOSED;
110                 break;
111         default:
112                 error("channel %d: protocol error: rcvd_oclose for istate %d",
113                     c->self, c->istate);
114                 return;
115         }
116 }
117 static void
118 chan_read_failed_12(Channel *c)
119 {
120         debug("channel %d: read failed", c->self);
121         switch (c->istate) {
122         case CHAN_INPUT_OPEN:
123                 debug("channel %d: input open -> drain", c->self);
124                 chan_shutdown_read(c);
125                 c->istate = CHAN_INPUT_WAIT_DRAIN;
126                 break;
127         default:
128                 error("channel %d: chan_read_failed for istate %d",
129                     c->self, c->istate);
130                 break;
131         }
132 }
133 static void
134 chan_ibuf_empty1(Channel *c)
135 {
136         debug("channel %d: ibuf empty", c->self);
137         if (buffer_len(&c->input)) {
138                 error("channel %d: chan_ibuf_empty for non empty buffer",
139                     c->self);
140                 return;
141         }
142         switch (c->istate) {
143         case CHAN_INPUT_WAIT_DRAIN:
144                 debug("channel %d: input drain -> wait_oclose", c->self);
145                 chan_send_ieof1(c);
146                 c->istate = CHAN_INPUT_WAIT_OCLOSE;
147                 break;
148         default:
149                 error("channel %d: chan_ibuf_empty for istate %d",
150                     c->self, c->istate);
151                 break;
152         }
153 }
154 static void
155 chan_rcvd_ieof1(Channel *c)
156 {
157         debug("channel %d: rcvd ieof", c->self);
158         if (c->type != SSH_CHANNEL_OPEN) {
159                 debug("channel %d: non-open", c->self);
160                 if (c->istate == CHAN_INPUT_OPEN) {
161                         debug("channel %d: non-open: input open -> wait_oclose",
162                             c->self);
163                         chan_shutdown_read(c);
164                         chan_send_ieof1(c);
165                         c->istate = CHAN_INPUT_WAIT_OCLOSE;
166                 } else {
167                         error("channel %d: non-open: istate %d != open",
168                             c->self, c->istate);
169                 }
170                 if (c->ostate == CHAN_OUTPUT_OPEN) {
171                         debug("channel %d: non-open: output open -> closed",
172                             c->self);
173                         chan_send_oclose1(c);
174                         c->ostate = CHAN_OUTPUT_CLOSED;
175                 } else {
176                         error("channel %d: non-open: ostate %d != open",
177                             c->self, c->ostate);
178                 }
179                 return;
180         }
181         switch (c->ostate) {
182         case CHAN_OUTPUT_OPEN:
183                 debug("channel %d: output open -> drain", c->self);
184                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
185                 break;
186         case CHAN_OUTPUT_WAIT_IEOF:
187                 debug("channel %d: output wait_ieof -> closed", c->self);
188                 c->ostate = CHAN_OUTPUT_CLOSED;
189                 break;
190         default:
191                 error("channel %d: protocol error: rcvd_ieof for ostate %d",
192                     c->self, c->ostate);
193                 break;
194         }
195 }
196 static void
197 chan_write_failed1(Channel *c)
198 {
199         debug("channel %d: write failed", c->self);
200         switch (c->ostate) {
201         case CHAN_OUTPUT_OPEN:
202                 debug("channel %d: output open -> wait_ieof", c->self);
203                 chan_send_oclose1(c);
204                 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
205                 break;
206         case CHAN_OUTPUT_WAIT_DRAIN:
207                 debug("channel %d: output wait_drain -> closed", c->self);
208                 chan_send_oclose1(c);
209                 c->ostate = CHAN_OUTPUT_CLOSED;
210                 break;
211         default:
212                 error("channel %d: chan_write_failed for ostate %d",
213                     c->self, c->ostate);
214                 break;
215         }
216 }
217 static void
218 chan_obuf_empty1(Channel *c)
219 {
220         debug("channel %d: obuf empty", c->self);
221         if (buffer_len(&c->output)) {
222                 error("channel %d: chan_obuf_empty for non empty buffer",
223                     c->self);
224                 return;
225         }
226         switch (c->ostate) {
227         case CHAN_OUTPUT_WAIT_DRAIN:
228                 debug("channel %d: output drain -> closed", c->self);
229                 chan_send_oclose1(c);
230                 c->ostate = CHAN_OUTPUT_CLOSED;
231                 break;
232         default:
233                 error("channel %d: internal error: obuf_empty for ostate %d",
234                     c->self, c->ostate);
235                 break;
236         }
237 }
238 static void
239 chan_send_ieof1(Channel *c)
240 {
241         debug("channel %d: send ieof", c->self);
242         switch (c->istate) {
243         case CHAN_INPUT_OPEN:
244         case CHAN_INPUT_WAIT_DRAIN:
245                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
246                 packet_put_int(c->remote_id);
247                 packet_send();
248                 break;
249         default:
250                 error("channel %d: cannot send ieof for istate %d",
251                     c->self, c->istate);
252                 break;
253         }
254 }
255 static void
256 chan_send_oclose1(Channel *c)
257 {
258         debug("channel %d: send oclose", c->self);
259         switch (c->ostate) {
260         case CHAN_OUTPUT_OPEN:
261         case CHAN_OUTPUT_WAIT_DRAIN:
262                 chan_shutdown_write(c);
263                 buffer_clear(&c->output);
264                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
265                 packet_put_int(c->remote_id);
266                 packet_send();
267                 break;
268         default:
269                 error("channel %d: cannot send oclose for ostate %d",
270                     c->self, c->ostate);
271                 break;
272         }
273 }
274
275 /*
276  * the same for SSH2
277  */
278 static void
279 chan_rcvd_oclose2(Channel *c)
280 {
281         debug("channel %d: rcvd close", c->self);
282         if (c->flags & CHAN_CLOSE_RCVD)
283                 error("channel %d: protocol error: close rcvd twice", c->self);
284         c->flags |= CHAN_CLOSE_RCVD;
285         if (c->type == SSH_CHANNEL_LARVAL) {
286                 /* tear down larval channels immediately */
287                 c->ostate = CHAN_OUTPUT_CLOSED;
288                 c->istate = CHAN_INPUT_CLOSED;
289                 return;
290         }
291         switch (c->ostate) {
292         case CHAN_OUTPUT_OPEN:
293                 /*
294                  * wait until a data from the channel is consumed if a CLOSE
295                  * is received
296                  */
297                 debug("channel %d: output open -> drain", c->self);
298                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
299                 break;
300         }
301         switch (c->istate) {
302         case CHAN_INPUT_OPEN:
303                 debug("channel %d: input open -> closed", c->self);
304                 chan_shutdown_read(c);
305                 break;
306         case CHAN_INPUT_WAIT_DRAIN:
307                 debug("channel %d: input drain -> closed", c->self);
308                 chan_send_eof2(c);
309                 break;
310         }
311         c->istate = CHAN_INPUT_CLOSED;
312 }
313 static void
314 chan_ibuf_empty2(Channel *c)
315 {
316         debug("channel %d: ibuf empty", c->self);
317         if (buffer_len(&c->input)) {
318                 error("channel %d: chan_ibuf_empty for non empty buffer",
319                     c->self);
320                 return;
321         }
322         switch (c->istate) {
323         case CHAN_INPUT_WAIT_DRAIN:
324                 debug("channel %d: input drain -> closed", c->self);
325                 if (!(c->flags & CHAN_CLOSE_SENT))
326                         chan_send_eof2(c);
327                 c->istate = CHAN_INPUT_CLOSED;
328                 break;
329         default:
330                 error("channel %d: chan_ibuf_empty for istate %d",
331                     c->self, c->istate);
332                 break;
333         }
334 }
335 static void
336 chan_rcvd_ieof2(Channel *c)
337 {
338         debug("channel %d: rcvd eof", c->self);
339         if (c->ostate == CHAN_OUTPUT_OPEN) {
340                 debug("channel %d: output open -> drain", c->self);
341                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
342         }
343 }
344 static void
345 chan_write_failed2(Channel *c)
346 {
347         debug("channel %d: write failed", c->self);
348         switch (c->ostate) {
349         case CHAN_OUTPUT_OPEN:
350                 debug("channel %d: output open -> closed", c->self);
351                 chan_shutdown_write(c); /* ?? */
352                 c->ostate = CHAN_OUTPUT_CLOSED;
353                 break;
354         case CHAN_OUTPUT_WAIT_DRAIN:
355                 debug("channel %d: output drain -> closed", c->self);
356                 chan_shutdown_write(c);
357                 c->ostate = CHAN_OUTPUT_CLOSED;
358                 break;
359         default:
360                 error("channel %d: chan_write_failed for ostate %d",
361                     c->self, c->ostate);
362                 break;
363         }
364 }
365 static void
366 chan_obuf_empty2(Channel *c)
367 {
368         debug("channel %d: obuf empty", c->self);
369         if (buffer_len(&c->output)) {
370                 error("channel %d: chan_obuf_empty for non empty buffer",
371                     c->self);
372                 return;
373         }
374         switch (c->ostate) {
375         case CHAN_OUTPUT_WAIT_DRAIN:
376                 debug("channel %d: output drain -> closed", c->self);
377                 chan_shutdown_write(c);
378                 c->ostate = CHAN_OUTPUT_CLOSED;
379                 break;
380         default:
381                 error("channel %d: chan_obuf_empty for ostate %d",
382                     c->self, c->ostate);
383                 break;
384         }
385 }
386 static void
387 chan_send_eof2(Channel *c)
388 {
389         debug("channel %d: send eof", c->self);
390         switch (c->istate) {
391         case CHAN_INPUT_WAIT_DRAIN:
392                 packet_start(SSH2_MSG_CHANNEL_EOF);
393                 packet_put_int(c->remote_id);
394                 packet_send();
395                 break;
396         default:
397                 error("channel %d: cannot send eof for istate %d",
398                     c->self, c->istate);
399                 break;
400         }
401 }
402 static void
403 chan_send_close2(Channel *c)
404 {
405         debug("channel %d: send close", c->self);
406         if (c->ostate != CHAN_OUTPUT_CLOSED ||
407             c->istate != CHAN_INPUT_CLOSED) {
408                 error("channel %d: cannot send close for istate/ostate %d/%d",
409                     c->self, c->istate, c->ostate);
410         } else if (c->flags & CHAN_CLOSE_SENT) {
411                 error("channel %d: already sent close", c->self);
412         } else {
413                 packet_start(SSH2_MSG_CHANNEL_CLOSE);
414                 packet_put_int(c->remote_id);
415                 packet_send();
416                 c->flags |= CHAN_CLOSE_SENT;
417         }
418 }
419
420 /* shared */
421
422 void
423 chan_mark_dead(Channel *c)
424 {
425         c->type = SSH_CHANNEL_ZOMBIE;
426 }
427
428 int
429 chan_is_dead(Channel *c, int send)
430 {
431         if (c->type == SSH_CHANNEL_ZOMBIE) {
432                 debug("channel %d: zombie", c->self);
433                 return 1;
434         }
435         if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
436                 return 0;
437         if (!compat20) {
438                 debug("channel %d: is dead", c->self);
439                 return 1;
440         }
441         /*
442          * we have to delay the close message if the efd (for stderr) is
443          * still active
444          */
445         if (((c->extended_usage != CHAN_EXTENDED_IGNORE) &&
446             buffer_len(&c->extended) > 0)
447 #if 0
448             || ((c->extended_usage == CHAN_EXTENDED_READ) &&
449             c->efd != -1)
450 #endif
451             ) {
452                 debug2("channel %d: active efd: %d len %d type %s",
453                     c->self, c->efd, buffer_len(&c->extended),
454                     c->extended_usage==CHAN_EXTENDED_READ ?
455                     "read": "write");
456         } else {
457                 if (!(c->flags & CHAN_CLOSE_SENT)) {
458                         if (send) {
459                                 chan_send_close2(c);
460                         } else {
461                                 /* channel would be dead if we sent a close */
462                                 if (c->flags & CHAN_CLOSE_RCVD) {
463                                         debug("channel %d: almost dead",
464                                             c->self);
465                                         return 1;
466                                 }
467                         }
468                 }
469                 if ((c->flags & CHAN_CLOSE_SENT) &&
470                     (c->flags & CHAN_CLOSE_RCVD)) {
471                         debug("channel %d: is dead", c->self);
472                         return 1;
473                 }
474         }
475         return 0;
476 }
477
478 void
479 chan_init_iostates(Channel *c)
480 {
481         c->ostate = CHAN_OUTPUT_OPEN;
482         c->istate = CHAN_INPUT_OPEN;
483         c->flags = 0;
484 }
485
486 /* init */
487 void
488 chan_init(void)
489 {
490         if (compat20) {
491                 chan_rcvd_oclose                = chan_rcvd_oclose2;
492                 chan_read_failed                = chan_read_failed_12;
493                 chan_ibuf_empty                 = chan_ibuf_empty2;
494
495                 chan_rcvd_ieof                  = chan_rcvd_ieof2;
496                 chan_write_failed               = chan_write_failed2;
497                 chan_obuf_empty                 = chan_obuf_empty2;
498         } else {
499                 chan_rcvd_oclose                = chan_rcvd_oclose1;
500                 chan_read_failed                = chan_read_failed_12;
501                 chan_ibuf_empty                 = chan_ibuf_empty1;
502
503                 chan_rcvd_ieof                  = chan_rcvd_ieof1;
504                 chan_write_failed               = chan_write_failed1;
505                 chan_obuf_empty                 = chan_obuf_empty1;
506         }
507 }
508
509 /* helper */
510 static void
511 chan_shutdown_write(Channel *c)
512 {
513         buffer_clear(&c->output);
514         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
515                 return;
516         /* shutdown failure is allowed if write failed already */
517         debug("channel %d: close_write", c->self);
518         if (c->sock != -1) {
519                 if (shutdown(c->sock, SHUT_WR) < 0)
520                         debug("channel %d: chan_shutdown_write: "
521                             "shutdown() failed for fd%d: %.100s",
522                             c->self, c->sock, strerror(errno));
523         } else {
524                 if (channel_close_fd(&c->wfd) < 0)
525                         log("channel %d: chan_shutdown_write: "
526                             "close() failed for fd%d: %.100s",
527                             c->self, c->wfd, strerror(errno));
528         }
529 }
530 static void
531 chan_shutdown_read(Channel *c)
532 {
533         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
534                 return;
535         debug("channel %d: close_read", c->self);
536         if (c->sock != -1) {
537                 /*
538                  * shutdown(sock, SHUT_READ) may return ENOTCONN if the
539                  * write side has been closed already. (bug on Linux)
540                  * HP-UX may return ENOTCONN also.
541                  */
542                 if (shutdown(c->sock, SHUT_RD) < 0
543                     && errno != ENOTCONN)
544                         error("channel %d: chan_shutdown_read: "
545                             "shutdown() failed for fd%d [i%d o%d]: %.100s",
546                             c->self, c->sock, c->istate, c->ostate,
547                             strerror(errno));
548         } else {
549                 if (channel_close_fd(&c->rfd) < 0)
550                         log("channel %d: chan_shutdown_read: "
551                             "close() failed for fd%d: %.100s",
552                             c->self, c->rfd, strerror(errno));
553         }
554 }
This page took 0.117977 seconds and 5 git commands to generate.