]> andersk Git - openssh.git/blob - nchan.c
- (djm) Merge OpenBSD changes:
[openssh.git] / nchan.c
1 /*
2  * Copyright (c) 1999 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.19 2000/09/07 20:27:52 deraadt Exp $");
27
28 #include "ssh.h"
29
30 #include "buffer.h"
31 #include "packet.h"
32 #include "channels.h"
33 #include "nchan.h"
34
35 #include "ssh2.h"
36 #include "compat.h"
37
38 /* functions manipulating channel states */
39 /*
40  * EVENTS update channel input/output states execute ACTIONS
41  */
42 /* events concerning the INPUT from socket for channel (istate) */
43 chan_event_fn *chan_rcvd_oclose                 = NULL;
44 chan_event_fn *chan_read_failed                 = NULL;
45 chan_event_fn *chan_ibuf_empty                  = NULL;
46 /* events concerning the OUTPUT from channel for socket (ostate) */
47 chan_event_fn *chan_rcvd_ieof                   = NULL;
48 chan_event_fn *chan_write_failed                = NULL;
49 chan_event_fn *chan_obuf_empty                  = NULL;
50 /*
51  * ACTIONS: should never update the channel states
52  */
53 static void     chan_send_ieof1(Channel *c);
54 static void     chan_send_oclose1(Channel *c);
55 static void     chan_send_close2(Channel *c);
56 static void     chan_send_eof2(Channel *c);
57
58 /* channel cleanup */
59 chan_event_fn *chan_delete_if_full_closed       = NULL;
60
61 /* helper */
62 static void     chan_shutdown_write(Channel *c);
63 static void     chan_shutdown_read(Channel *c);
64
65 /*
66  * SSH1 specific implementation of event functions
67  */
68
69 static void
70 chan_rcvd_oclose1(Channel *c)
71 {
72         debug("channel %d: rcvd oclose", c->self);
73         switch (c->istate) {
74         case CHAN_INPUT_WAIT_OCLOSE:
75                 debug("channel %d: input wait_oclose -> closed", c->self);
76                 c->istate = CHAN_INPUT_CLOSED;
77                 break;
78         case CHAN_INPUT_OPEN:
79                 debug("channel %d: input open -> closed", c->self);
80                 chan_shutdown_read(c);
81                 chan_send_ieof1(c);
82                 c->istate = CHAN_INPUT_CLOSED;
83                 break;
84         case CHAN_INPUT_WAIT_DRAIN:
85                 /* both local read_failed and remote write_failed  */
86                 log("channel %d: input drain -> closed", c->self);
87                 chan_send_ieof1(c);
88                 c->istate = CHAN_INPUT_CLOSED;
89                 break;
90         default:
91                 error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
92                     c->self, c->istate);
93                 return;
94         }
95 }
96 static void
97 chan_read_failed_12(Channel *c)
98 {
99         debug("channel %d: read failed", c->self);
100         switch (c->istate) {
101         case CHAN_INPUT_OPEN:
102                 debug("channel %d: input open -> drain", c->self);
103                 chan_shutdown_read(c);
104                 c->istate = CHAN_INPUT_WAIT_DRAIN;
105                 if (buffer_len(&c->input) == 0) {
106                         debug("channel %d: input: no drain shortcut", c->self);
107                         chan_ibuf_empty(c);
108                 }
109                 break;
110         default:
111                 error("channel %d: internal error: we do not read, but chan_read_failed for istate %d",
112                     c->self, c->istate);
113                 break;
114         }
115 }
116 static void
117 chan_ibuf_empty1(Channel *c)
118 {
119         debug("channel %d: ibuf empty", c->self);
120         if (buffer_len(&c->input)) {
121                 error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
122                     c->self);
123                 return;
124         }
125         switch (c->istate) {
126         case CHAN_INPUT_WAIT_DRAIN:
127                 debug("channel %d: input drain -> wait_oclose", c->self);
128                 chan_send_ieof1(c);
129                 c->istate = CHAN_INPUT_WAIT_OCLOSE;
130                 break;
131         default:
132                 error("channel %d: internal error: chan_ibuf_empty for istate %d",
133                     c->self, c->istate);
134                 break;
135         }
136 }
137 static void
138 chan_rcvd_ieof1(Channel *c)
139 {
140         debug("channel %d: rcvd ieof", c->self);
141         if (c->type != SSH_CHANNEL_OPEN) {
142                 debug("channel %d: non-open", c->self);
143                 if (c->istate == CHAN_INPUT_OPEN) {
144                         debug("channel %d: non-open: input open -> wait_oclose", c->self);
145                         chan_shutdown_read(c);
146                         chan_send_ieof1(c);
147                         c->istate = CHAN_INPUT_WAIT_OCLOSE;
148                 } else {
149                         error("channel %d: istate %d != open", c->self, c->istate);
150                 }
151                 if (c->ostate == CHAN_OUTPUT_OPEN) {
152                         debug("channel %d: non-open: output open -> closed", c->self);
153                         chan_send_oclose1(c);
154                         c->ostate = CHAN_OUTPUT_CLOSED;
155                 } else {
156                         error("channel %d: ostate %d != open", c->self, c->ostate);
157                 }
158                 return;
159         }
160         switch (c->ostate) {
161         case CHAN_OUTPUT_OPEN:
162                 debug("channel %d: output open -> drain", c->self);
163                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
164                 break;
165         case CHAN_OUTPUT_WAIT_IEOF:
166                 debug("channel %d: output wait_ieof -> closed", c->self);
167                 c->ostate = CHAN_OUTPUT_CLOSED;
168                 break;
169         default:
170                 error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
171                     c->self, c->ostate);
172                 break;
173         }
174 }
175 static void
176 chan_write_failed1(Channel *c)
177 {
178         debug("channel %d: write failed", c->self);
179         switch (c->ostate) {
180         case CHAN_OUTPUT_OPEN:
181                 debug("channel %d: output open -> wait_ieof", c->self);
182                 chan_send_oclose1(c);
183                 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
184                 break;
185         case CHAN_OUTPUT_WAIT_DRAIN:
186                 debug("channel %d: output wait_drain -> closed", c->self);
187                 chan_send_oclose1(c);
188                 c->ostate = CHAN_OUTPUT_CLOSED;
189                 break;
190         default:
191                 error("channel %d: internal error: chan_write_failed for ostate %d",
192                     c->self, c->ostate);
193                 break;
194         }
195 }
196 static void
197 chan_obuf_empty1(Channel *c)
198 {
199         debug("channel %d: obuf empty", c->self);
200         if (buffer_len(&c->output)) {
201                 error("channel %d: internal error: chan_obuf_empty for non empty buffer",
202                     c->self);
203                 return;
204         }
205         switch (c->ostate) {
206         case CHAN_OUTPUT_WAIT_DRAIN:
207                 debug("channel %d: output drain -> closed", c->self);
208                 chan_send_oclose1(c);
209                 c->ostate = CHAN_OUTPUT_CLOSED;
210                 break;
211         default:
212                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
213                     c->self, c->ostate);
214                 break;
215         }
216 }
217 static void
218 chan_send_ieof1(Channel *c)
219 {
220         debug("channel %d: send ieof", c->self);
221         switch (c->istate) {
222         case CHAN_INPUT_OPEN:
223         case CHAN_INPUT_WAIT_DRAIN:
224                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
225                 packet_put_int(c->remote_id);
226                 packet_send();
227                 break;
228         default:
229                 error("channel %d: internal error: cannot send ieof for istate %d",
230                     c->self, c->istate);
231                 break;
232         }
233 }
234 static void
235 chan_send_oclose1(Channel *c)
236 {
237         debug("channel %d: send oclose", c->self);
238         switch (c->ostate) {
239         case CHAN_OUTPUT_OPEN:
240         case CHAN_OUTPUT_WAIT_DRAIN:
241                 chan_shutdown_write(c);
242                 buffer_consume(&c->output, buffer_len(&c->output));
243                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
244                 packet_put_int(c->remote_id);
245                 packet_send();
246                 break;
247         default:
248                 error("channel %d: internal error: cannot send oclose for ostate %d",
249                      c->self, c->ostate);
250                 break;
251         }
252 }
253 static void
254 chan_delete_if_full_closed1(Channel *c)
255 {
256         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
257                 debug("channel %d: full closed", c->self);
258                 channel_free(c->self);
259         }
260 }
261
262 /*
263  * the same for SSH2
264  */
265 static void
266 chan_rcvd_oclose2(Channel *c)
267 {
268         debug("channel %d: rcvd close", c->self);
269         if (c->flags & CHAN_CLOSE_RCVD)
270                 error("channel %d: protocol error: close rcvd twice", c->self);
271         c->flags |= CHAN_CLOSE_RCVD;
272         if (c->type == SSH_CHANNEL_LARVAL) {
273                 /* tear down larval channels immediately */
274                 c->ostate = CHAN_OUTPUT_CLOSED;
275                 c->istate = CHAN_INPUT_CLOSED;
276                 return;
277         }
278         switch (c->ostate) {
279         case CHAN_OUTPUT_OPEN:
280                 /* wait until a data from the channel is consumed if a CLOSE is received */
281                 debug("channel %d: output open -> drain", c->self);
282                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
283                 break;
284         }
285         switch (c->istate) {
286         case CHAN_INPUT_OPEN:
287                 debug("channel %d: input open -> closed", c->self);
288                 chan_shutdown_read(c);
289                 break;
290         case CHAN_INPUT_WAIT_DRAIN:
291                 debug("channel %d: input drain -> closed", c->self);
292                 chan_send_eof2(c);
293                 break;
294         }
295         c->istate = CHAN_INPUT_CLOSED;
296 }
297 static void
298 chan_ibuf_empty2(Channel *c)
299 {
300         debug("channel %d: ibuf empty", c->self);
301         if (buffer_len(&c->input)) {
302                 error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
303                      c->self);
304                 return;
305         }
306         switch (c->istate) {
307         case CHAN_INPUT_WAIT_DRAIN:
308                 debug("channel %d: input drain -> closed", c->self);
309                 if (!(c->flags & CHAN_CLOSE_SENT))
310                         chan_send_eof2(c);
311                 c->istate = CHAN_INPUT_CLOSED;
312                 break;
313         default:
314                 error("channel %d: internal error: chan_ibuf_empty for istate %d",
315                      c->self, c->istate);
316                 break;
317         }
318 }
319 static void
320 chan_rcvd_ieof2(Channel *c)
321 {
322         debug("channel %d: rcvd eof", c->self);
323         if (c->ostate == CHAN_OUTPUT_OPEN) {
324                 debug("channel %d: output open -> drain", c->self);
325                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
326         }
327 }
328 static void
329 chan_write_failed2(Channel *c)
330 {
331         debug("channel %d: write failed", c->self);
332         switch (c->ostate) {
333         case CHAN_OUTPUT_OPEN:
334                 debug("channel %d: output open -> closed", c->self);
335                 chan_shutdown_write(c); /* ?? */
336                 c->ostate = CHAN_OUTPUT_CLOSED;
337                 break;
338         case CHAN_OUTPUT_WAIT_DRAIN:
339                 debug("channel %d: output drain -> closed", c->self);
340                 chan_shutdown_write(c);
341                 c->ostate = CHAN_OUTPUT_CLOSED;
342                 break;
343         default:
344                 error("channel %d: internal error: chan_write_failed for ostate %d",
345                     c->self, c->ostate);
346                 break;
347         }
348 }
349 static void
350 chan_obuf_empty2(Channel *c)
351 {
352         debug("channel %d: obuf empty", c->self);
353         if (buffer_len(&c->output)) {
354                 error("internal error: chan_obuf_empty %d for non empty buffer",
355                     c->self);
356                 return;
357         }
358         switch (c->ostate) {
359         case CHAN_OUTPUT_WAIT_DRAIN:
360                 debug("channel %d: output drain -> closed", c->self);
361                 chan_shutdown_write(c);
362                 c->ostate = CHAN_OUTPUT_CLOSED;
363                 break;
364         default:
365                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
366                     c->self, c->ostate);
367                 break;
368         }
369 }
370 static void
371 chan_send_eof2(Channel *c)
372 {
373         debug("channel %d: send eof", c->self);
374         switch (c->istate) {
375         case CHAN_INPUT_WAIT_DRAIN:
376                 packet_start(SSH2_MSG_CHANNEL_EOF);
377                 packet_put_int(c->remote_id);
378                 packet_send();
379                 break;
380         default:
381                 error("channel %d: internal error: cannot send eof for istate %d",
382                     c->self, c->istate);
383                 break;
384         }
385 }
386 static void
387 chan_send_close2(Channel *c)
388 {
389         debug("channel %d: send close", c->self);
390         if (c->ostate != CHAN_OUTPUT_CLOSED ||
391             c->istate != CHAN_INPUT_CLOSED) {
392                 error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
393                     c->self, c->istate, c->ostate);
394         } else if (c->flags & CHAN_CLOSE_SENT) {
395                 error("channel %d: internal error: already sent close", c->self);
396         } else {
397                 packet_start(SSH2_MSG_CHANNEL_CLOSE);
398                 packet_put_int(c->remote_id);
399                 packet_send();
400                 c->flags |= CHAN_CLOSE_SENT;
401         }
402 }
403 static void
404 chan_delete_if_full_closed2(Channel *c)
405 {
406         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
407                 if (!(c->flags & CHAN_CLOSE_SENT)) {
408                         chan_send_close2(c);
409                 }
410                 if ((c->flags & CHAN_CLOSE_SENT) &&
411                     (c->flags & CHAN_CLOSE_RCVD)) {
412                         debug("channel %d: full closed2", c->self);
413                         channel_free(c->self);
414                 }
415         }
416 }
417
418 /* shared */
419 void
420 chan_init_iostates(Channel *c)
421 {
422         c->ostate = CHAN_OUTPUT_OPEN;
423         c->istate = CHAN_INPUT_OPEN;
424         c->flags = 0;
425 }
426
427 /* init */
428 void
429 chan_init(void)
430 {
431         if (compat20) {
432                 chan_rcvd_oclose                = chan_rcvd_oclose2;
433                 chan_read_failed                = chan_read_failed_12;
434                 chan_ibuf_empty                 = chan_ibuf_empty2;
435
436                 chan_rcvd_ieof                  = chan_rcvd_ieof2;
437                 chan_write_failed               = chan_write_failed2;
438                 chan_obuf_empty                 = chan_obuf_empty2;
439
440                 chan_delete_if_full_closed      = chan_delete_if_full_closed2;
441         } else {
442                 chan_rcvd_oclose                = chan_rcvd_oclose1;
443                 chan_read_failed                = chan_read_failed_12;
444                 chan_ibuf_empty                 = chan_ibuf_empty1;
445
446                 chan_rcvd_ieof                  = chan_rcvd_ieof1;
447                 chan_write_failed               = chan_write_failed1;
448                 chan_obuf_empty                 = chan_obuf_empty1;
449
450                 chan_delete_if_full_closed      = chan_delete_if_full_closed1;
451         }
452 }
453
454 /* helper */
455 static void
456 chan_shutdown_write(Channel *c)
457 {
458         buffer_consume(&c->output, buffer_len(&c->output));
459         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
460                 return;
461         /* shutdown failure is allowed if write failed already */
462         debug("channel %d: close_write", c->self);
463         if (c->sock != -1) {
464                 if (shutdown(c->sock, SHUT_WR) < 0)
465                         debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
466                             c->self, c->sock, strerror(errno));
467         } else {
468                 if (close(c->wfd) < 0)
469                         log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
470                             c->self, c->wfd, strerror(errno));
471                 c->wfd = -1;
472         }
473 }
474 static void
475 chan_shutdown_read(Channel *c)
476 {
477         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
478                 return;
479         debug("channel %d: close_read", c->self);
480         if (c->sock != -1) {
481                 /* 
482                  * shutdown(sock, SHUT_READ) may return ENOTCONN if the
483                  * write side has been closed already. (bug on Linux)
484                  */
485                 if (shutdown(c->sock, SHUT_RD) < 0
486                     && (errno != ENOTCONN
487                         || c->ostate == CHAN_OUTPUT_OPEN
488                         || c->ostate == CHAN_OUTPUT_WAIT_DRAIN))
489                         error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
490                             c->self, c->sock, c->istate, c->ostate, strerror(errno));
491         } else {
492                 if (close(c->rfd) < 0)
493                         log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
494                             c->self, c->rfd, strerror(errno));
495                 c->rfd = -1;
496         }
497 }
This page took 0.579953 seconds and 5 git commands to generate.