]> andersk Git - openssh.git/blob - nchan.c
- Remove references to SSLeay.
[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         if (c->type != SSH_CHANNEL_OPEN) {
143                 debug("channel %d: non-open", c->self);
144                 if (c->istate == CHAN_INPUT_OPEN) {
145                         debug("channel %d: non-open: input open -> wait_oclose", c->self);
146                         chan_shutdown_read(c);
147                         chan_send_ieof1(c);
148                         c->istate = CHAN_INPUT_WAIT_OCLOSE;
149                 } else {
150                         error("channel %d: istate %d != open", c->self, c->istate);
151                 }
152                 if (c->ostate == CHAN_OUTPUT_OPEN) {
153                         debug("channel %d: non-open: output open -> closed", c->self);
154                         chan_send_oclose1(c);
155                         c->ostate = CHAN_OUTPUT_CLOSED;
156                 } else {
157                         error("channel %d: ostate %d != open", c->self, c->ostate);
158                 }
159                 return;
160         }
161         switch (c->ostate) {
162         case CHAN_OUTPUT_OPEN:
163                 debug("channel %d: output open -> drain", c->self);
164                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
165                 break;
166         case CHAN_OUTPUT_WAIT_IEOF:
167                 debug("channel %d: output wait_ieof -> closed", c->self);
168                 c->ostate = CHAN_OUTPUT_CLOSED;
169                 break;
170         default:
171                 error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
172                     c->self, c->ostate);
173                 break;
174         }
175 }
176 static void
177 chan_write_failed1(Channel *c)
178 {
179         debug("channel %d: write failed", c->self);
180         switch (c->ostate) {
181         case CHAN_OUTPUT_OPEN:
182                 debug("channel %d: output open -> wait_ieof", c->self);
183                 chan_send_oclose1(c);
184                 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
185                 break;
186         case CHAN_OUTPUT_WAIT_DRAIN:
187                 debug("channel %d: output wait_drain -> closed", c->self);
188                 chan_send_oclose1(c);
189                 c->ostate = CHAN_OUTPUT_CLOSED;
190                 break;
191         default:
192                 error("channel %d: internal error: chan_write_failed for ostate %d",
193                     c->self, c->ostate);
194                 break;
195         }
196 }
197 static void
198 chan_obuf_empty1(Channel *c)
199 {
200         debug("channel %d: obuf empty", c->self);
201         if (buffer_len(&c->output)) {
202                 error("channel %d: internal error: chan_obuf_empty for non empty buffer",
203                     c->self);
204                 return;
205         }
206         switch (c->ostate) {
207         case CHAN_OUTPUT_WAIT_DRAIN:
208                 debug("channel %d: output drain -> closed", c->self);
209                 chan_send_oclose1(c);
210                 c->ostate = CHAN_OUTPUT_CLOSED;
211                 break;
212         default:
213                 error("channel %d: internal error: chan_obuf_empty for ostate %d",
214                     c->self, c->ostate);
215                 break;
216         }
217 }
218 static void
219 chan_send_ieof1(Channel *c)
220 {
221         debug("channel %d: send ieof", c->self);
222         switch (c->istate) {
223         case CHAN_INPUT_OPEN:
224         case CHAN_INPUT_WAIT_DRAIN:
225                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
226                 packet_put_int(c->remote_id);
227                 packet_send();
228                 break;
229         default:
230                 error("channel %d: internal error: cannot send ieof for istate %d",
231                     c->self, c->istate);
232                 break;
233         }
234 }
235 static void
236 chan_send_oclose1(Channel *c)
237 {
238         debug("channel %d: send oclose", c->self);
239         switch (c->ostate) {
240         case CHAN_OUTPUT_OPEN:
241         case CHAN_OUTPUT_WAIT_DRAIN:
242                 chan_shutdown_write(c);
243                 buffer_consume(&c->output, buffer_len(&c->output));
244                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
245                 packet_put_int(c->remote_id);
246                 packet_send();
247                 break;
248         default:
249                 error("channel %d: internal error: cannot send oclose for ostate %d",
250                      c->self, c->ostate);
251                 break;
252         }
253 }
254 static void
255 chan_delete_if_full_closed1(Channel *c)
256 {
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         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
408                 if (!(c->flags & CHAN_CLOSE_SENT)) {
409                         chan_send_close2(c);
410                 }
411                 if ((c->flags & CHAN_CLOSE_SENT) &&
412                     (c->flags & CHAN_CLOSE_RCVD)) {
413                         debug("channel %d: full closed2", c->self);
414                         channel_free(c->self);
415                 }
416         }
417 }
418
419 /* shared */
420 void
421 chan_init_iostates(Channel *c)
422 {
423         c->ostate = CHAN_OUTPUT_OPEN;
424         c->istate = CHAN_INPUT_OPEN;
425         c->flags = 0;
426 }
427
428 /* init */
429 void
430 chan_init(void)
431 {
432         if (compat20) {
433                 chan_rcvd_oclose                = chan_rcvd_oclose2;
434                 chan_read_failed                = chan_read_failed_12;
435                 chan_ibuf_empty                 = chan_ibuf_empty2;
436
437                 chan_rcvd_ieof                  = chan_rcvd_ieof2;
438                 chan_write_failed               = chan_write_failed2;
439                 chan_obuf_empty                 = chan_obuf_empty2;
440
441                 chan_delete_if_full_closed      = chan_delete_if_full_closed2;
442         } else {
443                 chan_rcvd_oclose                = chan_rcvd_oclose1;
444                 chan_read_failed                = chan_read_failed_12;
445                 chan_ibuf_empty                 = chan_ibuf_empty1;
446
447                 chan_rcvd_ieof                  = chan_rcvd_ieof1;
448                 chan_write_failed               = chan_write_failed1;
449                 chan_obuf_empty                 = chan_obuf_empty1;
450
451                 chan_delete_if_full_closed      = chan_delete_if_full_closed1;
452         }
453 }
454
455 /* helper */
456 static void
457 chan_shutdown_write(Channel *c)
458 {
459         buffer_consume(&c->output, buffer_len(&c->output));
460         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
461                 return;
462         /* shutdown failure is allowed if write failed already */
463         debug("channel %d: close_write", c->self);
464         if (c->sock != -1) {
465                 if (shutdown(c->sock, SHUT_WR) < 0)
466                         debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
467                             c->self, c->sock, strerror(errno));
468         } else {
469                 if (close(c->wfd) < 0)
470                         log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
471                             c->self, c->wfd, strerror(errno));
472                 c->wfd = -1;
473         }
474 }
475 static void
476 chan_shutdown_read(Channel *c)
477 {
478         if (compat20 && c->type == SSH_CHANNEL_LARVAL)
479                 return;
480         debug("channel %d: close_read", c->self);
481         if (c->sock != -1) {
482                 if (shutdown(c->sock, SHUT_RD) < 0)
483                         error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
484                             c->self, c->sock, c->istate, c->ostate, strerror(errno));
485         } else {
486                 if (close(c->rfd) < 0)
487                         log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
488                             c->self, c->rfd, strerror(errno));
489                 c->rfd = -1;
490         }
491 }
This page took 0.232704 seconds and 5 git commands to generate.