Coverage Report

Created: 2025-11-10 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/src/common-channel.c
Line
Count
Source
1
/*
2
 * Dropbear SSH
3
 * 
4
 * Copyright (c) 2002-2004 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
/* Handle the multiplexed channels, such as sessions, x11, agent connections */
26
27
#include "includes.h"
28
#include "session.h"
29
#include "packet.h"
30
#include "ssh.h"
31
#include "buffer.h"
32
#include "circbuffer.h"
33
#include "dbutil.h"
34
#include "channel.h"
35
#include "listener.h"
36
#include "runopts.h"
37
#include "netio.h"
38
39
static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
40
    const char *text, const char *lang);
41
static void send_msg_channel_open_confirmation(const struct Channel* channel,
42
    unsigned int recvwindow, 
43
    unsigned int recvmaxpacket);
44
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
45
  const unsigned char *moredata, unsigned int *morelen);
46
static void send_msg_channel_window_adjust(const struct Channel *channel,
47
    unsigned int incr);
48
static void send_msg_channel_data(struct Channel *channel, int isextended);
49
static void send_msg_channel_eof(struct Channel *channel);
50
static void send_msg_channel_close(struct Channel *channel);
51
static void remove_channel(struct Channel *channel);
52
static unsigned int write_pending(const struct Channel * channel);
53
static void check_close(struct Channel *channel);
54
static void close_chan_fd(struct Channel *channel, int fd, int how);
55
56
0
#define FD_UNINIT (-2)
57
0
#define FD_CLOSED (-1)
58
59
0
#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60
0
#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
61
62
/* allow space for:
63
 * 1 byte  byte      SSH_MSG_CHANNEL_DATA
64
 * 4 bytes uint32    recipient channel
65
 * 4 bytes string    data
66
 */
67
0
#define RECV_MAX_CHANNEL_DATA_LEN (RECV_MAX_PAYLOAD_LEN-(1+4+4))
68
69
/* Initialise all the channels */
70
0
void chaninitialise(const struct ChanType *chantypes[]) {
71
72
  /* may as well create space for a single channel */
73
0
  ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
74
0
  ses.chansize = 1;
75
0
  ses.channels[0] = NULL;
76
0
  ses.chancount = 0;
77
78
0
  ses.chantypes = chantypes;
79
80
0
#if DROPBEAR_LISTENERS
81
0
  listeners_initialise();
82
0
#endif
83
84
0
}
85
86
/* Clean up channels, freeing allocated memory */
87
0
void chancleanup() {
88
89
0
  unsigned int i;
90
91
0
  TRACE(("enter chancleanup"))
92
0
  for (i = 0; i < ses.chansize; i++) {
93
0
    if (ses.channels[i] != NULL) {
94
0
      TRACE(("channel %d closing", i))
95
0
      remove_channel(ses.channels[i]);
96
0
    }
97
0
  }
98
0
  m_free(ses.channels);
99
0
  TRACE(("leave chancleanup"))
100
0
}
101
102
/* Create a new channel entry, send a reply confirm or failure */
103
/* If remotechan, transwindow and transmaxpacket are not know (for a new
104
 * outgoing connection, with them to be filled on confirmation), they should
105
 * all be set to 0 */
106
static struct Channel* newchannel(unsigned int remotechan, 
107
    const struct ChanType *type, 
108
0
    unsigned int transwindow, unsigned int transmaxpacket) {
109
110
0
  struct Channel * newchan;
111
0
  unsigned int i, j;
112
113
0
  TRACE(("enter newchannel"))
114
  
115
  /* first see if we can use existing channels */
116
0
  for (i = 0; i < ses.chansize; i++) {
117
0
    if (ses.channels[i] == NULL) {
118
0
      break;
119
0
    }
120
0
  }
121
122
  /* otherwise extend the list */
123
0
  if (i == ses.chansize) {
124
0
    if (ses.chansize >= MAX_CHANNELS) {
125
0
      TRACE(("leave newchannel: max chans reached"))
126
0
      return NULL;
127
0
    }
128
129
    /* extend the channels */
130
0
    ses.channels = (struct Channel**)m_realloc(ses.channels,
131
0
        (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
132
133
0
    ses.chansize += CHAN_EXTEND_SIZE;
134
135
    /* set the new channels to null */
136
0
    for (j = i; j < ses.chansize; j++) {
137
0
      ses.channels[j] = NULL;
138
0
    }
139
140
0
  }
141
  
142
0
  newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
143
0
  newchan->type = type;
144
0
  newchan->index = i;
145
0
  newchan->sent_close = newchan->recv_close = 0;
146
0
  newchan->sent_eof = newchan->recv_eof = 0;
147
148
0
  newchan->remotechan = remotechan;
149
0
  newchan->transwindow = transwindow;
150
0
  newchan->transmaxpacket = transmaxpacket;
151
  
152
0
  newchan->typedata = NULL;
153
0
  newchan->writefd = FD_UNINIT;
154
0
  newchan->readfd = FD_UNINIT;
155
0
  newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
156
0
  newchan->await_open = 0;
157
158
0
  newchan->writebuf = cbuf_new(opts.recv_window);
159
0
  newchan->recvwindow = opts.recv_window;
160
161
0
  newchan->extrabuf = NULL; /* The user code can set it up */
162
0
  newchan->recvdonelen = 0;
163
0
  newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
164
165
0
  newchan->prio = DROPBEAR_PRIO_NORMAL;
166
167
0
  ses.channels[i] = newchan;
168
0
  ses.chancount++;
169
170
0
  TRACE(("leave newchannel"))
171
172
0
  return newchan;
173
0
}
174
175
/* Returns the channel structure corresponding to the channel in the current
176
 * data packet (ses.payload must be positioned appropriately).
177
 * A valid channel is always returns, it will fail fatally with an unknown
178
 * channel */
179
0
static struct Channel* getchannel_msg(const char* kind) {
180
181
0
  unsigned int chan;
182
183
0
  chan = buf_getint(ses.payload);
184
0
  if (chan >= ses.chansize || ses.channels[chan] == NULL) {
185
0
    if (kind) {
186
0
      dropbear_exit("%s for unknown channel %d", kind, chan);
187
0
    } else {
188
0
      dropbear_exit("Unknown channel %d", chan);
189
0
    }
190
0
  }
191
0
  return ses.channels[chan];
192
0
}
193
194
0
struct Channel* getchannel() {
195
0
  return getchannel_msg(NULL);
196
0
}
197
198
/* Iterate through the channels, performing IO if available */
199
0
void channelio(const fd_set *readfds, const fd_set *writefds) {
200
201
  /* Listeners such as TCP, X11, agent-auth */
202
0
  struct Channel *channel;
203
0
  unsigned int i;
204
205
  /* foreach channel */
206
0
  for (i = 0; i < ses.chansize; i++) {
207
    /* Close checking only needs to occur for channels that had IO events */
208
0
    int do_check_close = 0;
209
210
0
    channel = ses.channels[i];
211
0
    if (channel == NULL) {
212
      /* only process in-use channels */
213
0
      continue;
214
0
    }
215
216
    /* read data and send it over the wire */
217
0
    if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
218
0
      TRACE(("send normal readfd"))
219
0
      send_msg_channel_data(channel, 0);
220
0
      do_check_close = 1;
221
0
    }
222
223
    /* read stderr data and send it over the wire */
224
0
    if (ERRFD_IS_READ(channel) && channel->errfd >= 0 
225
0
      && FD_ISSET(channel->errfd, readfds)) {
226
0
        TRACE(("send normal errfd"))
227
0
        send_msg_channel_data(channel, 1);
228
0
      do_check_close = 1;
229
0
    }
230
231
    /* write to program/pipe stdin */
232
0
    if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
233
0
      writechannel(channel, channel->writefd, channel->writebuf, NULL, NULL);
234
0
      do_check_close = 1;
235
0
    }
236
    
237
    /* stderr for client mode */
238
0
    if (ERRFD_IS_WRITE(channel)
239
0
        && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
240
0
      writechannel(channel, channel->errfd, channel->extrabuf, NULL, NULL);
241
0
      do_check_close = 1;
242
0
    }
243
244
0
    if (ses.channel_signal_pending) {
245
      /* SIGCHLD can change channel state for server sessions */
246
0
      do_check_close = 1;
247
0
    }
248
  
249
    /* handle any channel closing etc */
250
0
    if (do_check_close) {
251
0
      check_close(channel);
252
0
    }
253
0
  }
254
255
0
#if DROPBEAR_LISTENERS
256
0
  handle_listeners(readfds);
257
0
#endif
258
0
}
259
260
261
/* Returns true if there is data remaining to be written to stdin or
262
 * stderr of a channel's endpoint. */
263
0
static unsigned int write_pending(const struct Channel * channel) {
264
265
0
  if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
266
0
    return 1;
267
0
  } else if (channel->errfd >= 0 && channel->extrabuf && 
268
0
      cbuf_getused(channel->extrabuf) > 0) {
269
0
    return 1;
270
0
  }
271
0
  return 0;
272
0
}
273
274
275
/* EOF/close handling */
276
0
static void check_close(struct Channel *channel) {
277
0
  int close_allowed = 0;
278
279
0
  TRACE2(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
280
0
        channel->writefd, channel->readfd,
281
0
        channel->errfd, channel->sent_close, channel->recv_close))
282
0
  TRACE2(("writebuf size %d extrabuf size %d",
283
0
        channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
284
0
        channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
285
286
  /* if a type-specific check_close is defined we will only exit
287
     once that has been triggered. this is only used for a server "session"
288
     channel, to ensure that the shell has exited (and the exit status
289
     retrieved) before we close things up. */
290
0
  if (!channel->type->check_close
291
0
    || channel->sent_close
292
0
    || channel->type->check_close(channel)) {
293
0
    close_allowed = 1;
294
0
  }
295
296
  /* In flushing mode we close FDs as soon as pipes are empty.
297
  This is used to drain out FDs when the process exits, in the case
298
  where the FD doesn't have EOF - "sleep 10&echo hello" case */
299
0
  if (channel->flushing) {
300
0
    if (channel->readfd >= 0 && !fd_read_pending(channel->readfd)) {
301
0
      close_chan_fd(channel, channel->readfd, SHUT_RD);
302
0
    }
303
0
    if (ERRFD_IS_READ(channel)
304
0
      && channel->errfd >= 0 && !fd_read_pending(channel->errfd)) {
305
0
      close_chan_fd(channel, channel->errfd, SHUT_RD);
306
0
    }
307
0
  }
308
309
0
  if (channel->recv_close && !write_pending(channel) && close_allowed) {
310
0
    if (!channel->sent_close) {
311
0
      TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
312
0
      send_msg_channel_close(channel);
313
0
    }
314
0
    remove_channel(channel);
315
0
    return;
316
0
  }
317
318
0
  if ((channel->recv_eof && !write_pending(channel))
319
    /* have a server "session" and child has exited */
320
0
    || (channel->writefd != FD_UNINIT
321
0
      && channel->type->check_close && close_allowed)) {
322
0
    close_chan_fd(channel, channel->writefd, SHUT_WR);
323
0
  }
324
325
  /* If we're not going to send any more data, send EOF */
326
0
  if (!channel->sent_eof
327
0
      && channel->readfd == FD_CLOSED 
328
0
      && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
329
0
    send_msg_channel_eof(channel);
330
0
  }
331
332
  /* And if we can't receive any more data from them either, close up */
333
0
  if (channel->readfd == FD_CLOSED
334
0
      && channel->writefd == FD_CLOSED
335
0
      && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
336
0
      && !channel->sent_close
337
0
      && close_allowed
338
0
      && !write_pending(channel)) {
339
0
    TRACE(("sending close, readfd is closed"))
340
0
    send_msg_channel_close(channel);
341
0
  }
342
0
}
343
344
/* Check whether a deferred (EINPROGRESS) connect() was successful, and
345
 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
346
 * it is important that the channel reference isn't used after a call to this
347
 * function */
348
0
void channel_connect_done(int result, int sock, void* user_data, const char* errstring) {
349
0
  struct Channel *channel = user_data;
350
351
0
  TRACE(("enter channel_connect_done"))
352
353
0
  if (result == DROPBEAR_SUCCESS)
354
0
  {
355
0
    channel->readfd = channel->writefd = sock;
356
0
    channel->bidir_fd = 1;
357
0
    channel->conn_pending = NULL;
358
0
    send_msg_channel_open_confirmation(channel, channel->recvwindow,
359
0
        channel->recvmaxpacket);
360
0
    TRACE(("leave channel_connect_done: success"))
361
0
  }
362
0
  else
363
0
  {
364
0
    send_msg_channel_open_failure(channel->remotechan,
365
0
        SSH_OPEN_CONNECT_FAILED, errstring, "");
366
0
    remove_channel(channel);
367
0
    TRACE(("leave check_in_progress: fail. internal errstring: %s", errstring))
368
0
  }
369
0
}
370
371
372
/* Send the close message and set the channel as closed */
373
0
static void send_msg_channel_close(struct Channel *channel) {
374
375
0
  TRACE(("enter send_msg_channel_close %p", (void*)channel))
376
0
  if (channel->type->closehandler) {
377
0
    channel->type->closehandler(channel);
378
0
  }
379
  
380
0
  CHECKCLEARTOWRITE();
381
382
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
383
0
  buf_putint(ses.writepayload, channel->remotechan);
384
385
0
  encrypt_packet();
386
387
0
  channel->sent_eof = 1;
388
0
  channel->sent_close = 1;
389
0
  close_chan_fd(channel, channel->readfd, SHUT_RD);
390
0
  close_chan_fd(channel, channel->errfd, SHUT_RDWR);
391
0
  close_chan_fd(channel, channel->writefd, SHUT_WR);
392
0
  TRACE(("leave send_msg_channel_close"))
393
0
}
394
395
/* call this when trans/eof channels are closed */
396
0
static void send_msg_channel_eof(struct Channel *channel) {
397
398
0
  TRACE(("enter send_msg_channel_eof"))
399
0
  CHECKCLEARTOWRITE();
400
401
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
402
0
  buf_putint(ses.writepayload, channel->remotechan);
403
404
0
  encrypt_packet();
405
406
0
  channel->sent_eof = 1;
407
408
0
  TRACE(("leave send_msg_channel_eof"))
409
0
}
410
411
#ifndef HAVE_WRITEV
412
static int writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf,
413
  const unsigned char *UNUSED(moredata), unsigned int *morelen) {
414
415
  unsigned char *circ_p1, *circ_p2;
416
  unsigned int circ_len1, circ_len2;
417
  ssize_t written;
418
419
  if (morelen) {
420
    /* fallback doesn't consume moredata */
421
    *morelen = 0;
422
  }
423
424
  /* Write the first portion of the circular buffer */
425
  cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
426
  written = write(fd, circ_p1, circ_len1);
427
  if (written < 0) {
428
    if (errno != EINTR && errno != EAGAIN) {
429
      TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
430
      close_chan_fd(channel, fd, SHUT_WR);
431
      return DROPBEAR_FAILURE;
432
    }
433
  } else {
434
    cbuf_incrread(cbuf, written);
435
    channel->recvdonelen += written;
436
  }
437
  return DROPBEAR_SUCCESS;
438
}
439
#endif /* !HAVE_WRITEV */
440
441
#ifdef HAVE_WRITEV
442
static int writechannel_writev(struct Channel* channel, int fd, circbuffer *cbuf,
443
0
  const unsigned char *moredata, unsigned int *morelen) {
444
445
0
  struct iovec iov[3];
446
0
  unsigned char *circ_p1, *circ_p2;
447
0
  unsigned int circ_len1, circ_len2;
448
0
  int io_count = 0;
449
450
0
  ssize_t written;
451
452
0
  cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
453
454
0
  if (circ_len1 > 0) {
455
0
    TRACE(("circ1 %d", circ_len1))
456
0
    iov[io_count].iov_base = circ_p1;
457
0
    iov[io_count].iov_len = circ_len1;
458
0
    io_count++;
459
0
  }
460
461
0
  if (circ_len2 > 0) {
462
0
    TRACE(("circ2 %d", circ_len2))
463
0
    iov[io_count].iov_base = circ_p2;
464
0
    iov[io_count].iov_len = circ_len2;
465
0
    io_count++;
466
0
  }
467
468
0
  if (morelen) {
469
0
    assert(moredata);
470
0
    TRACE(("more %d", *morelen))
471
0
    iov[io_count].iov_base = (void*)moredata;
472
0
    iov[io_count].iov_len  = *morelen;
473
0
    io_count++;
474
0
  }
475
476
0
  if (io_count == 0) {
477
    /* writechannel may sometimes be called twice in a main loop iteration.
478
    From common_recv_msg_channel_data() then channelio().
479
    The second call may not have any data to write, so we just return. */
480
0
    TRACE(("leave writechannel, no data"))
481
0
    return DROPBEAR_SUCCESS;
482
0
  }
483
484
0
  if (morelen) {
485
    /* Default return value, none consumed */
486
0
    *morelen = 0;
487
0
  }
488
489
0
  written = writev(fd, iov, io_count);
490
491
0
  if (written < 0) {
492
0
    if (errno != EINTR && errno != EAGAIN) {
493
0
      TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
494
0
      close_chan_fd(channel, fd, SHUT_WR);
495
0
      return DROPBEAR_FAILURE;
496
0
    }
497
0
  } else {
498
0
    int cbuf_written = MIN(circ_len1+circ_len2, (unsigned int)written);
499
0
    cbuf_incrread(cbuf, cbuf_written);
500
0
    if (morelen) {
501
0
      *morelen = written - cbuf_written;
502
0
    }
503
0
    channel->recvdonelen += written;
504
0
  }
505
0
  return DROPBEAR_SUCCESS;
506
0
}
507
#endif /* HAVE_WRITEV */
508
509
/* Called to write data out to the local side of the channel. 
510
   Writes the circular buffer contents and also the "moredata" buffer
511
   if not null. Will ignore EAGAIN.
512
   Returns DROPBEAR_FAILURE if writing to fd had an error and the channel is being closed, DROPBEAR_SUCCESS otherwise */
513
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
514
0
  const unsigned char *moredata, unsigned int *morelen) {
515
0
  int ret = DROPBEAR_SUCCESS;
516
0
  TRACE(("enter writechannel fd %d", fd))
517
0
#ifdef HAVE_WRITEV
518
0
  ret = writechannel_writev(channel, fd, cbuf, moredata, morelen);
519
#else
520
  ret = writechannel_fallback(channel, fd, cbuf, moredata, morelen);
521
#endif
522
523
  /* Window adjust handling */
524
0
  if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
525
0
    send_msg_channel_window_adjust(channel, channel->recvdonelen);
526
0
    channel->recvwindow += channel->recvdonelen;
527
0
    channel->recvdonelen = 0;
528
0
  }
529
530
0
  dropbear_assert(channel->recvwindow <= opts.recv_window);
531
0
  dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
532
0
  dropbear_assert(channel->extrabuf == NULL ||
533
0
      channel->recvwindow <= cbuf_getavail(channel->extrabuf));
534
  
535
0
  TRACE(("leave writechannel"))
536
0
  return ret;
537
0
}
538
539
540
/* Set the file descriptors for the main select in session.c
541
 * This avoid channels which don't have any window available, are closed, etc*/
542
0
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
543
  
544
0
  unsigned int i;
545
0
  struct Channel * channel;
546
  
547
0
  for (i = 0; i < ses.chansize; i++) {
548
549
0
    channel = ses.channels[i];
550
0
    if (channel == NULL) {
551
0
      continue;
552
0
    }
553
554
    /* Stuff to put over the wire. 
555
    Avoid queueing data to send if we're in the middle of a 
556
    key re-exchange (!dataallowed), but still read from the 
557
    FD if there's the possibility of "~."" to kill an 
558
    interactive session (the read_mangler) */
559
0
    if (channel->transwindow > 0
560
0
       && ((ses.dataallowed && allow_reads) || channel->read_mangler)) {
561
562
0
      if (channel->readfd >= 0) {
563
0
        FD_SET(channel->readfd, readfds);
564
0
      }
565
      
566
0
      if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
567
0
          FD_SET(channel->errfd, readfds);
568
0
      }
569
0
    }
570
571
    /* Stuff from the wire */
572
0
    if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
573
0
        FD_SET(channel->writefd, writefds);
574
0
    }
575
576
0
    if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0 
577
0
        && cbuf_getused(channel->extrabuf) > 0) {
578
0
        FD_SET(channel->errfd, writefds);
579
0
    }
580
581
0
  } /* foreach channel */
582
583
0
#if DROPBEAR_LISTENERS
584
0
  set_listener_fds(readfds);
585
0
#endif
586
587
0
}
588
589
/* handle the channel EOF event, by closing the channel filedescriptor. The
590
 * channel isn't closed yet, it is left until the incoming (from the program
591
 * etc) FD is also EOF */
592
0
void recv_msg_channel_eof() {
593
594
0
  struct Channel * channel;
595
596
0
  TRACE(("enter recv_msg_channel_eof"))
597
598
0
  channel = getchannel_msg("EOF");
599
600
0
  channel->recv_eof = 1;
601
602
0
  check_close(channel);
603
0
  TRACE(("leave recv_msg_channel_eof"))
604
0
}
605
606
607
/* Handle channel closure(), respond in kind and close the channels */
608
0
void recv_msg_channel_close() {
609
610
0
  struct Channel * channel;
611
612
0
  TRACE(("enter recv_msg_channel_close"))
613
614
0
  channel = getchannel_msg("Close");
615
616
0
  channel->recv_eof = 1;
617
0
  channel->recv_close = 1;
618
619
0
  check_close(channel);
620
0
  TRACE(("leave recv_msg_channel_close"))
621
0
}
622
623
/* Remove a channel entry, this is only executed after both sides have sent
624
 * channel close */
625
0
static void remove_channel(struct Channel * channel) {
626
627
0
  TRACE(("enter remove_channel"))
628
0
  TRACE(("channel index is %d", channel->index))
629
630
0
  cbuf_free(channel->writebuf);
631
0
  channel->writebuf = NULL;
632
633
0
  if (channel->extrabuf) {
634
0
    cbuf_free(channel->extrabuf);
635
0
    channel->extrabuf = NULL;
636
0
  }
637
638
639
0
  if (IS_DROPBEAR_SERVER || (channel->writefd != STDOUT_FILENO)) {
640
    /* close the FDs in case they haven't been done
641
     * yet (they might have been shutdown etc) */
642
0
    TRACE(("CLOSE writefd %d", channel->writefd))
643
0
    m_close(channel->writefd);
644
0
    TRACE(("CLOSE readfd %d", channel->readfd))
645
0
    m_close(channel->readfd);
646
0
    TRACE(("CLOSE errfd %d", channel->errfd))
647
0
    m_close(channel->errfd);
648
0
  }
649
650
0
  if (channel->type->cleanup) {
651
0
    channel->type->cleanup(channel);
652
0
  }
653
654
0
  if (channel->conn_pending) {
655
0
    cancel_connect(channel->conn_pending);
656
0
  }
657
658
0
  ses.channels[channel->index] = NULL;
659
0
  m_free(channel);
660
0
  ses.chancount--;
661
662
0
  update_channel_prio();
663
664
0
  TRACE(("leave remove_channel"))
665
0
}
666
667
/* Handle channel specific requests, passing off to corresponding handlers
668
 * such as chansession or x11fwd */
669
0
void recv_msg_channel_request() {
670
671
0
  struct Channel *channel;
672
673
0
  channel = getchannel();
674
675
0
  TRACE(("enter recv_msg_channel_request %p", (void*)channel))
676
677
0
  if (channel->type->reqhandler) {
678
0
    channel->type->reqhandler(channel);
679
0
  } else {
680
0
    int wantreply;
681
0
    buf_eatstring(ses.payload);
682
0
    wantreply = buf_getbool(ses.payload);
683
0
    if (wantreply) {
684
0
      send_msg_channel_failure(channel);
685
0
    }
686
0
  }
687
688
0
  TRACE(("leave recv_msg_channel_request"))
689
690
0
}
691
692
/* Reads data from the server's program/shell/etc, and puts it in a
693
 * channel_data packet to send.
694
 * chan is the remote channel, isextended is 0 if it is normal data, 1
695
 * if it is extended data. if it is extended, then the type is in
696
 * exttype */
697
0
static void send_msg_channel_data(struct Channel *channel, int isextended) {
698
699
0
  int len;
700
0
  size_t maxlen, size_pos;
701
0
  int fd;
702
703
0
  CHECKCLEARTOWRITE();
704
705
0
  TRACE(("enter send_msg_channel_data"))
706
0
  dropbear_assert(!channel->sent_close);
707
708
0
  if (isextended) {
709
0
    fd = channel->errfd;
710
0
  } else {
711
0
    fd = channel->readfd;
712
0
  }
713
0
  TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
714
0
  dropbear_assert(fd >= 0);
715
716
0
  maxlen = MIN(channel->transwindow, channel->transmaxpacket);
717
  /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and 
718
   * exttype if is extended */
719
0
  maxlen = MIN(maxlen, 
720
0
      ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
721
0
  TRACE(("maxlen %zd", maxlen))
722
0
  if (maxlen == 0) {
723
0
    TRACE(("leave send_msg_channel_data: no window"))
724
0
    return;
725
0
  }
726
727
0
  buf_putbyte(ses.writepayload, 
728
0
      isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
729
0
  buf_putint(ses.writepayload, channel->remotechan);
730
0
  if (isextended) {
731
0
    buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
732
0
  }
733
  /* a dummy size first ...*/
734
0
  size_pos = ses.writepayload->pos;
735
0
  buf_putint(ses.writepayload, 0);
736
737
  /* read the data */
738
0
  len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
739
740
0
  if (len <= 0) {
741
0
    if (len == 0 || errno != EINTR) {
742
      /* This will also get hit in the case of EAGAIN. The only
743
      time we expect to receive EAGAIN is when we're flushing a FD,
744
      in which case it can be treated the same as EOF */
745
0
      close_chan_fd(channel, fd, SHUT_RD);
746
0
    }
747
0
    buf_setpos(ses.writepayload, 0);
748
0
    buf_setlen(ses.writepayload, 0);
749
0
    TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d", 
750
0
          len, errno, fd))
751
0
    return;
752
0
  }
753
754
0
  if (channel->read_mangler) {
755
0
    channel->read_mangler(channel, buf_getwriteptr(ses.writepayload, len), &len);
756
0
    if (len == 0) {
757
0
      buf_setpos(ses.writepayload, 0);
758
0
      buf_setlen(ses.writepayload, 0);
759
0
      return;
760
0
    }
761
0
  }
762
763
0
  TRACE(("send_msg_channel_data: len %d fd %d", len, fd))
764
0
  buf_incrwritepos(ses.writepayload, len);
765
  /* ... real size here */
766
0
  buf_setpos(ses.writepayload, size_pos);
767
0
  buf_putint(ses.writepayload, len);
768
769
0
  channel->transwindow -= len;
770
771
0
  encrypt_packet();
772
0
  TRACE(("leave send_msg_channel_data"))
773
0
}
774
775
/* We receive channel data */
776
0
void recv_msg_channel_data() {
777
778
0
  struct Channel *channel;
779
780
0
  channel = getchannel();
781
782
0
  common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
783
0
}
784
785
/* Shared for data and stderr data - when we receive data, put it in a buffer
786
 * for writing to the local file descriptor */
787
void common_recv_msg_channel_data(struct Channel *channel, int fd, 
788
0
    circbuffer * cbuf) {
789
790
0
  unsigned int datalen;
791
0
  unsigned int maxdata;
792
0
  unsigned int buflen;
793
0
  unsigned int len;
794
0
  unsigned int consumed;
795
0
  int res;
796
797
0
  TRACE(("enter recv_msg_channel_data"))
798
799
0
  if (channel->recv_eof) {
800
0
    dropbear_exit("Received data after eof");
801
0
  }
802
803
0
  if (fd < 0 || !cbuf) {
804
    /* If we have encountered failed write, the far side might still
805
     * be sending data without having yet received our close notification.
806
     * We just drop the data. */
807
0
    return;
808
0
  }
809
810
0
  datalen = buf_getint(ses.payload);
811
0
  TRACE(("length %d", datalen))
812
813
0
  maxdata = cbuf_getavail(cbuf);
814
815
  /* Whilst the spec says we "MAY ignore data past the end" this could
816
   * lead to corrupted file transfers etc (chunks missed etc). It's better to
817
   * just die horribly */
818
0
  if (datalen > maxdata) {
819
0
    dropbear_exit("Oversized packet");
820
0
  }
821
822
0
  dropbear_assert(channel->recvwindow >= datalen);
823
0
  channel->recvwindow -= datalen;
824
0
  dropbear_assert(channel->recvwindow <= opts.recv_window);
825
826
  /* Attempt to write the data immediately without having to put it in the circular buffer */
827
0
  consumed = datalen;
828
0
  res = writechannel(channel, fd, cbuf, buf_getptr(ses.payload, datalen), &consumed);
829
830
0
  datalen -= consumed;
831
0
  buf_incrpos(ses.payload, consumed);
832
833
834
  /* We may have to run throught twice, if the buffer wraps around. Can't
835
   * just "leave it for next time" like with writechannel, since this
836
   * is payload data.
837
   * If the writechannel() failed then remaining data is discarded */
838
0
  if (res == DROPBEAR_SUCCESS) {
839
0
    len = datalen;
840
0
    while (len > 0) {
841
0
      buflen = cbuf_writelen(cbuf);
842
0
      buflen = MIN(buflen, len);
843
844
0
      memcpy(cbuf_writeptr(cbuf, buflen), 
845
0
          buf_getptr(ses.payload, buflen), buflen);
846
0
      cbuf_incrwrite(cbuf, buflen);
847
0
      buf_incrpos(ses.payload, buflen);
848
0
      len -= buflen;
849
0
    }
850
0
  }
851
852
0
  TRACE(("leave recv_msg_channel_data"))
853
0
}
854
855
/* Increment the outgoing data window for a channel - the remote end limits
856
 * the amount of data which may be transmitted, this window is decremented
857
 * as data is sent, and incremented upon receiving window-adjust messages */
858
0
void recv_msg_channel_window_adjust() {
859
860
0
  struct Channel * channel;
861
0
  unsigned int incr, newwin;
862
  
863
0
  channel = getchannel();
864
  
865
0
  incr = buf_getint(ses.payload);
866
0
  TRACE(("received window increment %u", incr))
867
  
868
0
  newwin = channel->transwindow + incr;
869
0
  if (newwin < channel->transwindow) {
870
    /* Integer overflow, clamp it at maximum.
871
     * Behaviour may be unexpected, senders MUST NOT overflow per rfc4254. */
872
0
    TRACE(("overflow window, prev %u", channel->transwindow));
873
0
    newwin = 0xffffffff;
874
0
  }
875
0
  channel->transwindow = newwin;
876
0
}
877
878
/* Increment the incoming data window for a channel, and let the remote
879
 * end know */
880
static void send_msg_channel_window_adjust(const struct Channel* channel,
881
0
    unsigned int incr) {
882
883
0
  TRACE(("sending window adjust %d", incr))
884
0
  CHECKCLEARTOWRITE();
885
886
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
887
0
  buf_putint(ses.writepayload, channel->remotechan);
888
0
  buf_putint(ses.writepayload, incr);
889
890
0
  encrypt_packet();
891
0
}
892
  
893
/* Handle a new channel request, performing any channel-type-specific setup */
894
0
void recv_msg_channel_open() {
895
896
0
  char *type;
897
0
  unsigned int typelen;
898
0
  unsigned int remotechan, transwindow, transmaxpacket;
899
0
  struct Channel *channel;
900
0
  const struct ChanType **cp;
901
0
  const struct ChanType *chantype;
902
0
  unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
903
0
  int ret;
904
905
906
0
  TRACE(("enter recv_msg_channel_open"))
907
908
  /* get the packet contents */
909
0
  type = buf_getstring(ses.payload, &typelen);
910
911
0
  remotechan = buf_getint(ses.payload);
912
0
  transwindow = buf_getint(ses.payload);
913
0
  transmaxpacket = buf_getint(ses.payload);
914
0
  transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
915
916
  /* figure what type of packet it is */
917
0
  if (typelen > MAX_NAME_LEN) {
918
0
    goto failure;
919
0
  }
920
921
  /* Get the channel type. Client and server style invokation will set up a
922
   * different list for ses.chantypes at startup. We just iterate through
923
   * this list and find the matching name */
924
0
  for (cp = &ses.chantypes[0], chantype = (*cp); 
925
0
      chantype != NULL;
926
0
      cp++, chantype = (*cp)) {
927
0
    if (strcmp(type, chantype->name) == 0) {
928
0
      break;
929
0
    }
930
0
  }
931
932
0
  if (chantype == NULL) {
933
0
    TRACE(("No matching type for '%s'", type))
934
0
    goto failure;
935
0
  }
936
937
0
  TRACE(("matched type '%s'", type))
938
939
  /* create the channel */
940
0
  channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
941
942
0
  if (channel == NULL) {
943
0
    TRACE(("newchannel returned NULL"))
944
0
    errtype = SSH_OPEN_RESOURCE_SHORTAGE;
945
0
    goto failure;
946
0
  }
947
948
0
  if (channel->type->inithandler) {
949
0
    ret = channel->type->inithandler(channel);
950
0
    if (ret == SSH_OPEN_IN_PROGRESS) {
951
      /* We'll send the confirmation later */
952
0
      goto cleanup;
953
0
    }
954
0
    if (ret > 0) {
955
0
      errtype = ret;
956
0
      remove_channel(channel);
957
0
      TRACE(("inithandler returned failure %d", ret))
958
0
      goto failure;
959
0
    }
960
0
  }
961
962
0
  update_channel_prio();
963
964
  /* success */
965
0
  send_msg_channel_open_confirmation(channel, channel->recvwindow,
966
0
      channel->recvmaxpacket);
967
0
  goto cleanup;
968
969
0
failure:
970
0
  TRACE(("recv_msg_channel_open failure"))
971
0
  send_msg_channel_open_failure(remotechan, errtype, "", "");
972
973
0
cleanup:
974
0
  m_free(type);
975
976
0
  TRACE(("leave recv_msg_channel_open"))
977
0
}
978
979
/* Send a failure message */
980
0
void send_msg_channel_failure(const struct Channel *channel) {
981
982
0
  TRACE(("enter send_msg_channel_failure"))
983
984
0
  if (channel->sent_close) {
985
0
    TRACE(("Skipping sending msg_channel_failure for closed channel"))
986
0
    return;
987
0
  }
988
0
  CHECKCLEARTOWRITE();
989
990
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
991
0
  buf_putint(ses.writepayload, channel->remotechan);
992
993
0
  encrypt_packet();
994
0
  TRACE(("leave send_msg_channel_failure"))
995
0
}
996
997
/* Send a success message */
998
0
void send_msg_channel_success(const struct Channel *channel) {
999
1000
0
  TRACE(("enter send_msg_channel_success"))
1001
0
  if (channel->sent_close) {
1002
0
    TRACE(("Skipping sending msg_channel_success for closed channel"))
1003
0
    return;
1004
0
  }
1005
0
  CHECKCLEARTOWRITE();
1006
1007
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
1008
0
  buf_putint(ses.writepayload, channel->remotechan);
1009
1010
0
  encrypt_packet();
1011
0
  TRACE(("leave send_msg_channel_success"))
1012
0
}
1013
1014
/* Send a channel open failure message, with a corresponding reason
1015
 * code (usually resource shortage or unknown chan type) */
1016
static void send_msg_channel_open_failure(unsigned int remotechan, 
1017
0
    int reason, const char *text, const char *lang) {
1018
1019
0
  TRACE(("enter send_msg_channel_open_failure"))
1020
0
  CHECKCLEARTOWRITE();
1021
  
1022
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
1023
0
  buf_putint(ses.writepayload, remotechan);
1024
0
  buf_putint(ses.writepayload, reason);
1025
0
  buf_putstring(ses.writepayload, text, strlen(text));
1026
0
  buf_putstring(ses.writepayload, lang, strlen(lang));
1027
1028
0
  encrypt_packet();
1029
0
  TRACE(("leave send_msg_channel_open_failure"))
1030
0
}
1031
1032
/* Confirm a channel open, and let the remote end know what number we've
1033
 * allocated and the receive parameters */
1034
static void send_msg_channel_open_confirmation(const struct Channel* channel,
1035
    unsigned int recvwindow, 
1036
0
    unsigned int recvmaxpacket) {
1037
1038
0
  TRACE(("enter send_msg_channel_open_confirmation"))
1039
0
  CHECKCLEARTOWRITE();
1040
1041
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1042
0
  buf_putint(ses.writepayload, channel->remotechan);
1043
0
  buf_putint(ses.writepayload, channel->index);
1044
0
  buf_putint(ses.writepayload, recvwindow);
1045
0
  buf_putint(ses.writepayload, recvmaxpacket);
1046
1047
0
  encrypt_packet();
1048
0
  TRACE(("leave send_msg_channel_open_confirmation"))
1049
0
}
1050
1051
/* close a fd, how is SHUT_RD or SHUT_WR */
1052
0
static void close_chan_fd(struct Channel *channel, int fd, int how) {
1053
1054
0
  int closein = 0, closeout = 0;
1055
1056
0
  if (channel->bidir_fd) {
1057
0
    TRACE(("SHUTDOWN(%d, %d)", fd, how))
1058
0
    shutdown(fd, how);
1059
0
    if (how == 0) {
1060
0
      closeout = 1;
1061
0
    } else {
1062
0
      closein = 1;
1063
0
    }
1064
0
  } else {
1065
0
    TRACE(("CLOSE some fd %d", fd))
1066
0
    m_close(fd);
1067
0
    closein = closeout = 1;
1068
0
  }
1069
1070
0
  if (closeout && (fd == channel->readfd)) {
1071
0
    channel->readfd = FD_CLOSED;
1072
0
  }
1073
0
  if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
1074
0
    channel->errfd = FD_CLOSED;
1075
0
  }
1076
1077
0
  if (closein && fd == channel->writefd) {
1078
0
    channel->writefd = FD_CLOSED;
1079
0
  }
1080
0
  if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
1081
0
    channel->errfd = FD_CLOSED;
1082
0
  }
1083
1084
  /* if we called shutdown on it and all references are gone, then we 
1085
   * need to close() it to stop it lingering */
1086
0
  if (channel->bidir_fd && channel->readfd == FD_CLOSED 
1087
0
    && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
1088
0
    TRACE(("CLOSE (finally) of %d", fd))
1089
0
    m_close(fd);
1090
0
  }
1091
0
}
1092
1093
1094
#if (DROPBEAR_LISTENERS) || (DROPBEAR_CLIENT)
1095
/* Create a new channel, and start the open request. This is intended
1096
 * for X11, agent, tcp forwarding, and should be filled with channel-specific
1097
 * options, with the calling function calling encrypt_packet() after
1098
 * completion. It is mandatory for the caller to encrypt_packet() if
1099
 * a channel is returned. NULL is returned on failure. */
1100
0
int send_msg_channel_open_init(int fd, const struct ChanType *type) {
1101
1102
0
  struct Channel* chan;
1103
1104
0
  TRACE(("enter send_msg_channel_open_init()"))
1105
0
  chan = newchannel(0, type, 0, 0);
1106
0
  if (!chan) {
1107
0
    TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
1108
0
    return DROPBEAR_FAILURE;
1109
0
  }
1110
1111
  /* Outbound opened channels don't make use of in-progress connections,
1112
   * we can set it up straight away */
1113
1114
  /* set fd non-blocking */
1115
0
  setnonblocking(fd);
1116
1117
0
  chan->writefd = chan->readfd = fd;
1118
0
  ses.maxfd = MAX(ses.maxfd, fd);
1119
0
  chan->bidir_fd = 1;
1120
1121
0
  chan->await_open = 1;
1122
1123
  /* now open the channel connection */
1124
0
  CHECKCLEARTOWRITE();
1125
1126
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
1127
0
  buf_putstring(ses.writepayload, type->name, strlen(type->name));
1128
0
  buf_putint(ses.writepayload, chan->index);
1129
0
  buf_putint(ses.writepayload, opts.recv_window);
1130
0
  buf_putint(ses.writepayload, RECV_MAX_CHANNEL_DATA_LEN);
1131
1132
0
  TRACE(("leave send_msg_channel_open_init()"))
1133
0
  return DROPBEAR_SUCCESS;
1134
0
}
1135
1136
/* Confirmation that our channel open request was 
1137
 * successful*/
1138
0
void recv_msg_channel_open_confirmation() {
1139
1140
0
  struct Channel * channel;
1141
0
  int ret;
1142
1143
0
  TRACE(("enter recv_msg_channel_open_confirmation"))
1144
1145
0
  channel = getchannel();
1146
1147
0
  if (!channel->await_open) {
1148
0
    dropbear_exit("Unexpected channel reply");
1149
0
  }
1150
0
  channel->await_open = 0;
1151
1152
0
  channel->remotechan =  buf_getint(ses.payload);
1153
0
  channel->transwindow = buf_getint(ses.payload);
1154
0
  channel->transmaxpacket = buf_getint(ses.payload);
1155
  
1156
0
  TRACE(("new chan remote %d local %d", 
1157
0
        channel->remotechan, channel->index))
1158
1159
  /* Run the inithandler callback */
1160
0
  if (channel->type->inithandler) {
1161
0
    ret = channel->type->inithandler(channel);
1162
0
    if (ret > 0) {
1163
0
      remove_channel(channel);
1164
0
      TRACE(("inithandler returned failure %d", ret))
1165
0
      return;
1166
0
    }
1167
0
  }
1168
1169
0
  update_channel_prio();
1170
1171
0
  TRACE(("leave recv_msg_channel_open_confirmation"))
1172
0
}
1173
1174
/* Notification that our channel open request failed */
1175
0
void recv_msg_channel_open_failure() {
1176
1177
0
  struct Channel * channel;
1178
1179
0
  channel = getchannel();
1180
1181
0
  if (!channel->await_open) {
1182
0
    dropbear_exit("Unexpected channel reply");
1183
0
  }
1184
0
  channel->await_open = 0;
1185
1186
0
  remove_channel(channel);
1187
0
}
1188
#endif /* DROPBEAR_LISTENERS */
1189
1190
0
void send_msg_request_success() {
1191
0
  CHECKCLEARTOWRITE();
1192
0
  buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
1193
0
  encrypt_packet();
1194
0
}
1195
1196
0
void send_msg_request_failure() {
1197
0
  CHECKCLEARTOWRITE();
1198
0
  buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
1199
0
  encrypt_packet();
1200
0
}
1201
1202
0
struct Channel* get_any_ready_channel() {
1203
0
  size_t i;
1204
0
  if (ses.chancount == 0) {
1205
0
    return NULL;
1206
0
  }
1207
0
  for (i = 0; i < ses.chansize; i++) {
1208
0
    struct Channel *chan = ses.channels[i];
1209
0
    if (chan
1210
0
        && !(chan->sent_eof || chan->recv_eof)
1211
0
        && !(chan->await_open)) {
1212
0
      return chan;
1213
0
    }
1214
0
  }
1215
0
  return NULL;
1216
0
}
1217
1218
void start_send_channel_request(const struct Channel *channel,
1219
0
    const char *type) {
1220
1221
0
  CHECKCLEARTOWRITE();
1222
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
1223
0
  buf_putint(ses.writepayload, channel->remotechan);
1224
1225
0
  buf_putstring(ses.writepayload, type, strlen(type));
1226
1227
0
}