]> andersk Git - openssh.git/blob - nchan.c
- OpenBSD CVS updates.
[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  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Markus Friedl.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "includes.h"
31 RCSID("$Id$");
32
33 #include "ssh.h"
34
35 #include "buffer.h"
36 #include "packet.h"
37 #include "channels.h"
38 #include "nchan.h"
39
40 #include "ssh2.h"
41 #include "compat.h"
42
43 /* functions manipulating channel states */
44 /*
45  * EVENTS update channel input/output states execute ACTIONS
46  */
47 /* events concerning the INPUT from socket for channel (istate) */
48 chan_event_fn *chan_rcvd_oclose                 = NULL;
49 chan_event_fn *chan_read_failed                 = NULL;
50 chan_event_fn *chan_ibuf_empty                  = NULL;
51 /* events concerning the OUTPUT from channel for socket (ostate) */
52 chan_event_fn *chan_rcvd_ieof                   = NULL;
53 chan_event_fn *chan_write_failed                = NULL;
54 chan_event_fn *chan_obuf_empty                  = NULL;
55 /*
56  * ACTIONS: should never update the channel states
57  */
58 static void     chan_send_ieof1(Channel *c);
59 static void     chan_send_oclose1(Channel *c);
60 static void     chan_send_close2(Channel *c);
61 static void     chan_send_eof2(Channel *c);
62
63 /* channel cleanup */
64 chan_event_fn *chan_delete_if_full_closed       = NULL;
65
66 /* helper */
67 static void     chan_shutdown_write(Channel *c);
68 static void     chan_shutdown_read(Channel *c);
69
70 /*
71  * SSH1 specific implementation of event functions
72  */
73
74 static void
75 chan_rcvd_oclose1(Channel *c)
76 {
77         debug("channel %d: rcvd oclose", c->self);
78         switch (c->istate) {
79         case CHAN_INPUT_WAIT_OCLOSE:
80                 debug("channel %d: input wait_oclose -> closed", c->self);
81                 c->istate = CHAN_INPUT_CLOSED;
82                 break;
83         case CHAN_INPUT_OPEN:
84                 debug("channel %d: input open -> closed", c->self);
85                 chan_shutdown_read(c);
86                 chan_send_ieof1(c);
87                 c->istate = CHAN_INPUT_CLOSED;
88                 break;
89         case CHAN_INPUT_WAIT_DRAIN:
90                 /* both local read_failed and remote write_failed  */
91                 log("channel %d: input drain -> closed", c->self);
92                 chan_send_ieof1(c);
93                 c->istate = CHAN_INPUT_CLOSED;
94                 break;
95         default:
96                 error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
97                     c->self, c->istate);
98                 return;
99         }
100 }
101 static void
102 chan_read_failed_12(Channel *c)
103 {
104         debug("channel %d: read failed", c->self);
105         switch (c->istate) {
106         case CHAN_INPUT_OPEN:
107                 debug("channel %d: input open -> drain", c->self);
108                 chan_shutdown_read(c);
109                 c->istate = CHAN_INPUT_WAIT_DRAIN;
110                 break;
111         default:
112                 error("channel %d: internal error: we do not read, but chan_read_failed for istate %d",
113                     c->self, c->istate);
114                 break;
115         }
116 }
117 static void
118 chan_ibuf_empty1(Channel *c)
119 {
120         debug("channel %d: ibuf empty", c->self);
121         if (buffer_len(&c->input)) {
122                 error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
123                     c->self);
124                 return;
125         }
126         switch (c->istate) {
127         case CHAN_INPUT_WAIT_DRAIN:
128                 debug("channel %d: input drain -> wait_oclose", c->self);
129                 chan_send_ieof1(c);
130                 c->istate = CHAN_INPUT_WAIT_OCLOSE;
131                 break;
132         default:
133                 error("channel %d: internal error: chan_ibuf_empty for istate %d",
134                     c->self, c->istate);
135                 break;
136         }
137 }
138 static void
139 chan_rcvd_ieof1(Channel *c)
140 {
141         debug("channel %d: rcvd ieof", c->self);
142         switch (c->ostate) {
143         case CHAN_OUTPUT_OPEN:
144                 debug("channel %d: output open -> drain", c->self);
145                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
146                 break;
147         case CHAN_OUTPUT_WAIT_IEOF:
148                 debug("channel %d: output wait_ieof -> closed", c->self);
149                 c->ostate = CHAN_OUTPUT_CLOSED;
150                 break;
151         default:
152                 error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
153                     c->self, c->ostate);
154                 break;
155         }
156 }
157 static void
158 chan_write_failed1(Channel *c)
159 {
160         debug("channel %d: write failed", c->self);
161         switch (c->ostate) {
162         case CHAN_OUTPUT_OPEN:
163                 debug("channel %d: output open -> wait_ieof", c->self);
164                 chan_send_oclose1(c);
165                 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
166                 break;
167         case CHAN_OUTPUT_WAIT_DRAIN:
168                 debug("channel %d: output wait_drain -> closed", c->self);
169                 chan_send_oclose1(c);
170                 c->ostate = CHAN_OUTPUT_CLOSED;
171                 break;
172         default:
173                 error("channel %d: internal error: chan_write_failed for ostate %d",
174                     c->self, c->ostate);
175                 break;
176         }
177 }
178 static void
179 chan_obuf_empty1(Channel *c)
180 {
181         debug("channel %d: obuf empty", c->self);
182         if (buffer_len(&c->output)) {
183                 error("channel %d: internal error: chan_obuf_empty for non empty buffer",
184                     c->self);
185                 return;
186         }
187         switch (c->ostate) {
188         case CHAN_OUTPUT_WAIT_DRAIN:
189                 debug("channel %d: output drain -> closed", c->self);
190                 chan_send_oclose1(c);
191                 c->ostate = CHAN_OUTPUT_CLOSED;
192                 break;
193         default:
194                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
195                     c->self, c->ostate);
196                 break;
197         }
198 }
199 static void
200 chan_send_ieof1(Channel *c)
201 {
202         debug("channel %d: send ieof", c->self);
203         switch (c->istate) {
204         case CHAN_INPUT_OPEN:
205         case CHAN_INPUT_WAIT_DRAIN:
206                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
207                 packet_put_int(c->remote_id);
208                 packet_send();
209                 break;
210         default:
211                 error("channel %d: internal error: cannot send ieof for istate %d",
212                     c->self, c->istate);
213                 break;
214         }
215 }
216 static void
217 chan_send_oclose1(Channel *c)
218 {
219         debug("channel %d: send oclose", c->self);
220         switch (c->ostate) {
221         case CHAN_OUTPUT_OPEN:
222         case CHAN_OUTPUT_WAIT_DRAIN:
223                 chan_shutdown_write(c);
224                 buffer_consume(&c->output, buffer_len(&c->output));
225                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
226                 packet_put_int(c->remote_id);
227                 packet_send();
228                 break;
229         default:
230                 error("channel %d: internal error: cannot send oclose for ostate %d",
231                      c->self, c->ostate);
232                 break;
233         }
234 }
235 static void
236 chan_delete_if_full_closed1(Channel *c)
237 {
238         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
239                 debug("channel %d: full closed", c->self);
240                 channel_free(c->self);
241         }
242 }
243
244 /*
245  * the same for SSH2
246  */
247 static void
248 chan_rcvd_oclose2(Channel *c)
249 {
250         debug("channel %d: rcvd close", c->self);
251         if (c->flags & CHAN_CLOSE_RCVD)
252                 error("channel %d: protocol error: close rcvd twice", c->self);
253         c->flags |= CHAN_CLOSE_RCVD;
254         if (c->type == SSH_CHANNEL_LARVAL) {
255                 /* tear down larval channels immediately */
256                 c->ostate = CHAN_OUTPUT_CLOSED;
257                 c->istate = CHAN_INPUT_CLOSED;
258                 return;
259         }
260         switch (c->ostate) {
261         case CHAN_OUTPUT_OPEN:
262                 /* wait until a data from the channel is consumed if a CLOSE is received */
263                 debug("channel %d: output open -> drain", c->self);
264                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
265                 break;
266         }
267         switch (c->istate) {
268         case CHAN_INPUT_OPEN:
269                 debug("channel %d: input open -> closed", c->self);
270                 chan_shutdown_read(c);
271                 break;
272         case CHAN_INPUT_WAIT_DRAIN:
273                 debug("channel %d: input drain -> closed", c->self);
274                 chan_send_eof2(c);
275                 break;
276         }
277         c->istate = CHAN_INPUT_CLOSED;
278 }
279 static void
280 chan_ibuf_empty2(Channel *c)
281 {
282         debug("channel %d: ibuf empty", c->self);
283         if (buffer_len(&c->input)) {
284                 error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
285                      c->self);
286                 return;
287         }
288         switch (c->istate) {
289         case CHAN_INPUT_WAIT_DRAIN:
290                 debug("channel %d: input drain -> closed", c->self);
291                 if (!(c->flags & CHAN_CLOSE_SENT))
292                         chan_send_eof2(c);
293                 c->istate = CHAN_INPUT_CLOSED;
294                 break;
295         default:
296                 error("channel %d: internal error: chan_ibuf_empty for istate %d",
297                      c->self, c->istate);
298                 break;
299         }
300 }
301 static void
302 chan_rcvd_ieof2(Channel *c)
303 {
304         debug("channel %d: rcvd eof", c->self);
305         if (c->ostate == CHAN_OUTPUT_OPEN) {
306                 debug("channel %d: output open -> drain", c->self);
307                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
308         }
309 }
310 static void
311 chan_write_failed2(Channel *c)
312 {
313         debug("channel %d: write failed", c->self);
314         switch (c->ostate) {
315         case CHAN_OUTPUT_OPEN:
316                 debug("channel %d: output open -> closed", c->self);
317                 chan_shutdown_write(c); // ??
318                 c->ostate = CHAN_OUTPUT_CLOSED;
319                 break;
320         case CHAN_OUTPUT_WAIT_DRAIN:
321                 debug("channel %d: output drain -> closed", c->self);
322                 chan_shutdown_write(c);
323                 c->ostate = CHAN_OUTPUT_CLOSED;
324                 break;
325         default:
326                 error("channel %d: internal error: chan_write_failed for ostate %d",
327                     c->self, c->ostate);
328                 break;
329         }
330 }
331 static void
332 chan_obuf_empty2(Channel *c)
333 {
334         debug("channel %d: obuf empty", c->self);
335         if (buffer_len(&c->output)) {
336                 error("internal error: chan_obuf_empty %d for non empty buffer",
337                     c->self);
338                 return;
339         }
340         switch (c->ostate) {
341         case CHAN_OUTPUT_WAIT_DRAIN:
342                 debug("channel %d: output drain -> closed", c->self);
343                 chan_shutdown_write(c);
344                 c->ostate = CHAN_OUTPUT_CLOSED;
345                 break;
346         default:
347                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
348                     c->self, c->ostate);
349                 break;
350         }
351 }
352 static void
353 chan_send_eof2(Channel *c)
354 {
355         debug("channel %d: send eof", c->self);
356         switch (c->istate) {
357         case CHAN_INPUT_WAIT_DRAIN:
358                 packet_start(SSH2_MSG_CHANNEL_EOF);
359                 packet_put_int(c->remote_id);
360                 packet_send();
361                 break;
362         default:
363                 error("channel %d: internal error: cannot send eof for istate %d",
364                     c->self, c->istate);
365                 break;
366         }
367 }
368 static void
369 chan_send_close2(Channel *c)
370 {
371         debug("channel %d: send close", c->self);
372         if (c->ostate != CHAN_OUTPUT_CLOSED ||
373             c->istate != CHAN_INPUT_CLOSED) {
374                 error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
375                     c->self, c->istate, c->ostate);
376         } else if (c->flags & CHAN_CLOSE_SENT) {
377                 error("channel %d: internal error: already sent close", c->self);
378         } else {
379                 packet_start(SSH2_MSG_CHANNEL_CLOSE);
380                 packet_put_int(c->remote_id);
381                 packet_send();
382                 c->flags |= CHAN_CLOSE_SENT;
383         }
384 }
385 static void
386 chan_delete_if_full_closed2(Channel *c)
387 {
388         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
389                 if (!(c->flags & CHAN_CLOSE_SENT)) {
390                         chan_send_close2(c);
391                 }
392                 if ((c->flags & CHAN_CLOSE_SENT) &&
393                     (c->flags & CHAN_CLOSE_RCVD)) {
394                         debug("channel %d: full closed2", c->self);
395                         channel_free(c->self);
396                 }
397         }
398 }
399
400 /* shared */
401 void
402 chan_init_iostates(Channel *c)
403 {
404         c->ostate = CHAN_OUTPUT_OPEN;
405         c->istate = CHAN_INPUT_OPEN;
406         c->flags = 0;
407 }
408
409 /* init */
410 void
411 chan_init(void)
412 {
413         if (compat20) {
414                 chan_rcvd_oclose                = chan_rcvd_oclose2;
415                 chan_read_failed                = chan_read_failed_12;
416                 chan_ibuf_empty                 = chan_ibuf_empty2;
417
418                 chan_rcvd_ieof                  = chan_rcvd_ieof2;
419                 chan_write_failed               = chan_write_failed2;
420                 chan_obuf_empty                 = chan_obuf_empty2;
421
422                 chan_delete_if_full_closed      = chan_delete_if_full_closed2;
423         } else {
424                 chan_rcvd_oclose                = chan_rcvd_oclose1;
425                 chan_read_failed                = chan_read_failed_12;
426                 chan_ibuf_empty                 = chan_ibuf_empty1;
427
428                 chan_rcvd_ieof                  = chan_rcvd_ieof1;
429                 chan_write_failed               = chan_write_failed1;
430                 chan_obuf_empty                 = chan_obuf_empty1;
431
432                 chan_delete_if_full_closed      = chan_delete_if_full_closed1;
433         }
434 }
435
436 /* helper */
437 static void
438 chan_shutdown_write(Channel *c)
439 {
440         buffer_consume(&c->output, buffer_len(&c->output));
441         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
442                 return;
443         /* shutdown failure is allowed if write failed already */
444         debug("channel %d: close_write", c->self);
445         if (c->sock != -1) {
446                 if (shutdown(c->sock, SHUT_WR) < 0)
447                         debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
448                             c->self, c->sock, strerror(errno));
449         } else {
450                 if (close(c->wfd) < 0)
451                         log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
452                             c->self, c->wfd, strerror(errno));
453                 c->wfd = -1;
454         }
455 }
456 static void
457 chan_shutdown_read(Channel *c)
458 {
459         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
460                 return;
461         debug("channel %d: close_read", c->self);
462         if (c->sock != -1) {
463                 if (shutdown(c->sock, SHUT_RD) < 0)
464                         error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
465                             c->self, c->sock, c->istate, c->ostate, strerror(errno));
466         } else {
467                 if (close(c->rfd) < 0)
468                         log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
469                             c->self, c->rfd, strerror(errno));
470                 c->rfd = -1;
471         }
472 }
This page took 1.772653 seconds and 5 git commands to generate.