]> 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.20 2000/11/06 23:04:56 markus 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         debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d",
257             c->self, c->istate, c->ostate);
258         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
259                 debug("channel %d: full closed", c->self);
260                 channel_free(c->self);
261         }
262 }
263
264 /*
265  * the same for SSH2
266  */
267 static void
268 chan_rcvd_oclose2(Channel *c)
269 {
270         debug("channel %d: rcvd close", c->self);
271         if (c->flags & CHAN_CLOSE_RCVD)
272                 error("channel %d: protocol error: close rcvd twice", c->self);
273         c->flags |= CHAN_CLOSE_RCVD;
274         if (c->type == SSH_CHANNEL_LARVAL) {
275                 /* tear down larval channels immediately */
276                 c->ostate = CHAN_OUTPUT_CLOSED;
277                 c->istate = CHAN_INPUT_CLOSED;
278                 return;
279         }
280         switch (c->ostate) {
281         case CHAN_OUTPUT_OPEN:
282                 /* wait until a data from the channel is consumed if a CLOSE is received */
283                 debug("channel %d: output open -> drain", c->self);
284                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
285                 break;
286         }
287         switch (c->istate) {
288         case CHAN_INPUT_OPEN:
289                 debug("channel %d: input open -> closed", c->self);
290                 chan_shutdown_read(c);
291                 break;
292         case CHAN_INPUT_WAIT_DRAIN:
293                 debug("channel %d: input drain -> closed", c->self);
294                 chan_send_eof2(c);
295                 break;
296         }
297         c->istate = CHAN_INPUT_CLOSED;
298 }
299 static void
300 chan_ibuf_empty2(Channel *c)
301 {
302         debug("channel %d: ibuf empty", c->self);
303         if (buffer_len(&c->input)) {
304                 error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
305                      c->self);
306                 return;
307         }
308         switch (c->istate) {
309         case CHAN_INPUT_WAIT_DRAIN:
310                 debug("channel %d: input drain -> closed", c->self);
311                 if (!(c->flags & CHAN_CLOSE_SENT))
312                         chan_send_eof2(c);
313                 c->istate = CHAN_INPUT_CLOSED;
314                 break;
315         default:
316                 error("channel %d: internal error: chan_ibuf_empty for istate %d",
317                      c->self, c->istate);
318                 break;
319         }
320 }
321 static void
322 chan_rcvd_ieof2(Channel *c)
323 {
324         debug("channel %d: rcvd eof", c->self);
325         if (c->ostate == CHAN_OUTPUT_OPEN) {
326                 debug("channel %d: output open -> drain", c->self);
327                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
328         }
329 }
330 static void
331 chan_write_failed2(Channel *c)
332 {
333         debug("channel %d: write failed", c->self);
334         switch (c->ostate) {
335         case CHAN_OUTPUT_OPEN:
336                 debug("channel %d: output open -> closed", c->self);
337                 chan_shutdown_write(c); /* ?? */
338                 c->ostate = CHAN_OUTPUT_CLOSED;
339                 break;
340         case CHAN_OUTPUT_WAIT_DRAIN:
341                 debug("channel %d: output drain -> closed", c->self);
342                 chan_shutdown_write(c);
343                 c->ostate = CHAN_OUTPUT_CLOSED;
344                 break;
345         default:
346                 error("channel %d: internal error: chan_write_failed for ostate %d",
347                     c->self, c->ostate);
348                 break;
349         }
350 }
351 static void
352 chan_obuf_empty2(Channel *c)
353 {
354         debug("channel %d: obuf empty", c->self);
355         if (buffer_len(&c->output)) {
356                 error("internal error: chan_obuf_empty %d for non empty buffer",
357                     c->self);
358                 return;
359         }
360         switch (c->ostate) {
361         case CHAN_OUTPUT_WAIT_DRAIN:
362                 debug("channel %d: output drain -> closed", c->self);
363                 chan_shutdown_write(c);
364                 c->ostate = CHAN_OUTPUT_CLOSED;
365                 break;
366         default:
367                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
368                     c->self, c->ostate);
369                 break;
370         }
371 }
372 static void
373 chan_send_eof2(Channel *c)
374 {
375         debug("channel %d: send eof", c->self);
376         switch (c->istate) {
377         case CHAN_INPUT_WAIT_DRAIN:
378                 packet_start(SSH2_MSG_CHANNEL_EOF);
379                 packet_put_int(c->remote_id);
380                 packet_send();
381                 break;
382         default:
383                 error("channel %d: internal error: cannot send eof for istate %d",
384                     c->self, c->istate);
385                 break;
386         }
387 }
388 static void
389 chan_send_close2(Channel *c)
390 {
391         debug("channel %d: send close", c->self);
392         if (c->ostate != CHAN_OUTPUT_CLOSED ||
393             c->istate != CHAN_INPUT_CLOSED) {
394                 error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
395                     c->self, c->istate, c->ostate);
396         } else if (c->flags & CHAN_CLOSE_SENT) {
397                 error("channel %d: internal error: already sent close", c->self);
398         } else {
399                 packet_start(SSH2_MSG_CHANNEL_CLOSE);
400                 packet_put_int(c->remote_id);
401                 packet_send();
402                 c->flags |= CHAN_CLOSE_SENT;
403         }
404 }
405 static void
406 chan_delete_if_full_closed2(Channel *c)
407 {
408         debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d",
409             c->self, c->istate, c->ostate);
410         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
411                 if (!(c->flags & CHAN_CLOSE_SENT)) {
412                         chan_send_close2(c);
413                 }
414                 if ((c->flags & CHAN_CLOSE_SENT) &&
415                     (c->flags & CHAN_CLOSE_RCVD)) {
416                         debug("channel %d: full closed2", c->self);
417                         channel_free(c->self);
418                 }
419         }
420 }
421
422 /* shared */
423 void
424 chan_init_iostates(Channel *c)
425 {
426         c->ostate = CHAN_OUTPUT_OPEN;
427         c->istate = CHAN_INPUT_OPEN;
428         c->flags = 0;
429 }
430
431 /* init */
432 void
433 chan_init(void)
434 {
435         if (compat20) {
436                 chan_rcvd_oclose                = chan_rcvd_oclose2;
437                 chan_read_failed                = chan_read_failed_12;
438                 chan_ibuf_empty                 = chan_ibuf_empty2;
439
440                 chan_rcvd_ieof                  = chan_rcvd_ieof2;
441                 chan_write_failed               = chan_write_failed2;
442                 chan_obuf_empty                 = chan_obuf_empty2;
443
444                 chan_delete_if_full_closed      = chan_delete_if_full_closed2;
445         } else {
446                 chan_rcvd_oclose                = chan_rcvd_oclose1;
447                 chan_read_failed                = chan_read_failed_12;
448                 chan_ibuf_empty                 = chan_ibuf_empty1;
449
450                 chan_rcvd_ieof                  = chan_rcvd_ieof1;
451                 chan_write_failed               = chan_write_failed1;
452                 chan_obuf_empty                 = chan_obuf_empty1;
453
454                 chan_delete_if_full_closed      = chan_delete_if_full_closed1;
455         }
456 }
457
458 /* helper */
459 static void
460 chan_shutdown_write(Channel *c)
461 {
462         buffer_consume(&c->output, buffer_len(&c->output));
463         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
464                 return;
465         /* shutdown failure is allowed if write failed already */
466         debug("channel %d: close_write", c->self);
467         if (c->sock != -1) {
468                 if (shutdown(c->sock, SHUT_WR) < 0)
469                         debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
470                             c->self, c->sock, strerror(errno));
471         } else {
472                 if (close(c->wfd) < 0)
473                         log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
474                             c->self, c->wfd, strerror(errno));
475                 c->wfd = -1;
476         }
477 }
478 static void
479 chan_shutdown_read(Channel *c)
480 {
481         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
482                 return;
483         debug("channel %d: close_read", c->self);
484         if (c->sock != -1) {
485                 /* 
486                  * shutdown(sock, SHUT_READ) may return ENOTCONN if the
487                  * write side has been closed already. (bug on Linux)
488                  */
489                 if (shutdown(c->sock, SHUT_RD) < 0
490                     && (errno != ENOTCONN
491                         || c->ostate == CHAN_OUTPUT_OPEN
492                         || c->ostate == CHAN_OUTPUT_WAIT_DRAIN))
493                         error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
494                             c->self, c->sock, c->istate, c->ostate, strerror(errno));
495         } else {
496                 if (close(c->rfd) < 0)
497                         log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
498                             c->self, c->rfd, strerror(errno));
499                 c->rfd = -1;
500         }
501 }
This page took 0.078532 seconds and 5 git commands to generate.