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