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