Mercurial > dropbear
comparison common-channel.c @ 165:0cfba3034be5
Fixed DEBUG_TRACE macro so that we don't get semicolons left about the place
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 02 Jan 2005 20:25:56 +0000 |
parents | 8c2b3506f112 |
children | 161557a9dde8 |
comparison
equal
deleted
inserted
replaced
161:b9d3f725e00b | 165:0cfba3034be5 |
---|---|
79 /* Clean up channels, freeing allocated memory */ | 79 /* Clean up channels, freeing allocated memory */ |
80 void chancleanup() { | 80 void chancleanup() { |
81 | 81 |
82 unsigned int i; | 82 unsigned int i; |
83 | 83 |
84 TRACE(("enter chancleanup")); | 84 TRACE(("enter chancleanup")) |
85 for (i = 0; i < ses.chansize; i++) { | 85 for (i = 0; i < ses.chansize; i++) { |
86 if (ses.channels[i] != NULL) { | 86 if (ses.channels[i] != NULL) { |
87 TRACE(("channel %d closing", i)); | 87 TRACE(("channel %d closing", i)) |
88 removechannel(ses.channels[i]); | 88 removechannel(ses.channels[i]); |
89 } | 89 } |
90 } | 90 } |
91 m_free(ses.channels); | 91 m_free(ses.channels); |
92 TRACE(("leave chancleanup")); | 92 TRACE(("leave chancleanup")) |
93 } | 93 } |
94 | 94 |
95 /* Create a new channel entry, send a reply confirm or failure */ | 95 /* Create a new channel entry, send a reply confirm or failure */ |
96 /* If remotechan, transwindow and transmaxpacket are not know (for a new | 96 /* If remotechan, transwindow and transmaxpacket are not know (for a new |
97 * outgoing connection, with them to be filled on confirmation), they should | 97 * outgoing connection, with them to be filled on confirmation), they should |
101 unsigned int transwindow, unsigned int transmaxpacket) { | 101 unsigned int transwindow, unsigned int transmaxpacket) { |
102 | 102 |
103 struct Channel * newchan; | 103 struct Channel * newchan; |
104 unsigned int i, j; | 104 unsigned int i, j; |
105 | 105 |
106 TRACE(("enter newchannel")); | 106 TRACE(("enter newchannel")) |
107 | 107 |
108 /* first see if we can use existing channels */ | 108 /* first see if we can use existing channels */ |
109 for (i = 0; i < ses.chansize; i++) { | 109 for (i = 0; i < ses.chansize; i++) { |
110 if (ses.channels[i] == NULL) { | 110 if (ses.channels[i] == NULL) { |
111 break; | 111 break; |
113 } | 113 } |
114 | 114 |
115 /* otherwise extend the list */ | 115 /* otherwise extend the list */ |
116 if (i == ses.chansize) { | 116 if (i == ses.chansize) { |
117 if (ses.chansize >= MAX_CHANNELS) { | 117 if (ses.chansize >= MAX_CHANNELS) { |
118 TRACE(("leave newchannel: max chans reached")); | 118 TRACE(("leave newchannel: max chans reached")) |
119 return NULL; | 119 return NULL; |
120 } | 120 } |
121 | 121 |
122 /* extend the channels */ | 122 /* extend the channels */ |
123 ses.channels = (struct Channel**)m_realloc(ses.channels, | 123 ses.channels = (struct Channel**)m_realloc(ses.channels, |
155 newchan->recvmaxpacket = RECV_MAXPACKET; | 155 newchan->recvmaxpacket = RECV_MAXPACKET; |
156 | 156 |
157 ses.channels[i] = newchan; | 157 ses.channels[i] = newchan; |
158 ses.chancount++; | 158 ses.chancount++; |
159 | 159 |
160 TRACE(("leave newchannel")); | 160 TRACE(("leave newchannel")) |
161 | 161 |
162 return newchan; | 162 return newchan; |
163 } | 163 } |
164 | 164 |
165 /* Get the channel structure corresponding to a channel number */ | 165 /* Get the channel structure corresponding to a channel number */ |
244 | 244 |
245 | 245 |
246 /* do all the EOF/close type stuff checking for a channel */ | 246 /* do all the EOF/close type stuff checking for a channel */ |
247 static void checkclose(struct Channel *channel) { | 247 static void checkclose(struct Channel *channel) { |
248 | 248 |
249 TRACE(("checkclose: infd %d, outfd %d, errfd %d, sentclosed %d, recvclosed %d", | 249 TRACE(("checkclose: infd %d, outfd %d, errfd %d, sentclosed %d, recvclosed %d", |
250 channel->infd, channel->outfd, | 250 channel->infd, channel->outfd, |
251 channel->errfd, channel->sentclosed, channel->recvclosed)); | 251 channel->errfd, channel->sentclosed, channel->recvclosed)) |
252 TRACE(("writebuf %d extrabuf %s extrabuf %d", | 252 TRACE(("writebuf %d extrabuf %s extrabuf %d", |
253 cbuf_getused(channel->writebuf), | 253 cbuf_getused(channel->writebuf), |
254 channel->writebuf, | 254 channel->writebuf, |
255 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))); | 255 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) |
256 | 256 |
257 if (!channel->sentclosed) { | 257 if (!channel->sentclosed) { |
258 | 258 |
259 /* check for exited - currently only used for server sessions, | 259 /* check for exited - currently only used for server sessions, |
260 * if the shell has exited etc */ | 260 * if the shell has exited etc */ |
287 * SSH_MSG_CHANNEL_EOF. | 287 * SSH_MSG_CHANNEL_EOF. |
288 * (from draft-ietf-secsh-connect) | 288 * (from draft-ietf-secsh-connect) |
289 */ | 289 */ |
290 if (channel->recvclosed) { | 290 if (channel->recvclosed) { |
291 if (! channel->sentclosed) { | 291 if (! channel->sentclosed) { |
292 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same.")); | 292 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same.")) |
293 send_msg_channel_close(channel); | 293 send_msg_channel_close(channel); |
294 } | 294 } |
295 removechannel(channel); | 295 removechannel(channel); |
296 } | 296 } |
297 } | 297 } |
304 static void checkinitdone(struct Channel *channel) { | 304 static void checkinitdone(struct Channel *channel) { |
305 | 305 |
306 int val; | 306 int val; |
307 socklen_t vallen = sizeof(val); | 307 socklen_t vallen = sizeof(val); |
308 | 308 |
309 TRACE(("enter checkinitdone")); | 309 TRACE(("enter checkinitdone")) |
310 | 310 |
311 if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) | 311 if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) |
312 || val != 0) { | 312 || val != 0) { |
313 send_msg_channel_open_failure(channel->remotechan, | 313 send_msg_channel_open_failure(channel->remotechan, |
314 SSH_OPEN_CONNECT_FAILED, "", ""); | 314 SSH_OPEN_CONNECT_FAILED, "", ""); |
315 close(channel->infd); | 315 close(channel->infd); |
316 deletechannel(channel); | 316 deletechannel(channel); |
317 TRACE(("leave checkinitdone: fail")); | 317 TRACE(("leave checkinitdone: fail")) |
318 } else { | 318 } else { |
319 send_msg_channel_open_confirmation(channel, channel->recvwindow, | 319 send_msg_channel_open_confirmation(channel, channel->recvwindow, |
320 channel->recvmaxpacket); | 320 channel->recvmaxpacket); |
321 channel->outfd = channel->infd; | 321 channel->outfd = channel->infd; |
322 channel->initconn = 0; | 322 channel->initconn = 0; |
323 TRACE(("leave checkinitdone: success")); | 323 TRACE(("leave checkinitdone: success")) |
324 } | 324 } |
325 } | 325 } |
326 | 326 |
327 | 327 |
328 | 328 |
329 /* Send the close message and set the channel as closed */ | 329 /* Send the close message and set the channel as closed */ |
330 static void send_msg_channel_close(struct Channel *channel) { | 330 static void send_msg_channel_close(struct Channel *channel) { |
331 | 331 |
332 TRACE(("enter send_msg_channel_close")); | 332 TRACE(("enter send_msg_channel_close")) |
333 /* XXX server */ | 333 /* XXX server */ |
334 if (channel->type->closehandler) { | 334 if (channel->type->closehandler) { |
335 channel->type->closehandler(channel); | 335 channel->type->closehandler(channel); |
336 } | 336 } |
337 | 337 |
342 | 342 |
343 encrypt_packet(); | 343 encrypt_packet(); |
344 | 344 |
345 channel->senteof = 1; | 345 channel->senteof = 1; |
346 channel->sentclosed = 1; | 346 channel->sentclosed = 1; |
347 TRACE(("leave send_msg_channel_close")); | 347 TRACE(("leave send_msg_channel_close")) |
348 } | 348 } |
349 | 349 |
350 /* call this when trans/eof channels are closed */ | 350 /* call this when trans/eof channels are closed */ |
351 static void send_msg_channel_eof(struct Channel *channel) { | 351 static void send_msg_channel_eof(struct Channel *channel) { |
352 | 352 |
353 TRACE(("enter send_msg_channel_eof")); | 353 TRACE(("enter send_msg_channel_eof")) |
354 CHECKCLEARTOWRITE(); | 354 CHECKCLEARTOWRITE(); |
355 | 355 |
356 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF); | 356 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF); |
357 buf_putint(ses.writepayload, channel->remotechan); | 357 buf_putint(ses.writepayload, channel->remotechan); |
358 | 358 |
359 encrypt_packet(); | 359 encrypt_packet(); |
360 | 360 |
361 channel->senteof = 1; | 361 channel->senteof = 1; |
362 | 362 |
363 TRACE(("leave send_msg_channel_eof")); | 363 TRACE(("leave send_msg_channel_eof")) |
364 } | 364 } |
365 | 365 |
366 /* Called to write data out to the local side of the channel. | 366 /* Called to write data out to the local side of the channel. |
367 * Only called when we know we can write to a channel, writes as much as | 367 * Only called when we know we can write to a channel, writes as much as |
368 * possible */ | 368 * possible */ |
369 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) { | 369 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) { |
370 | 370 |
371 int len, maxlen; | 371 int len, maxlen; |
372 | 372 |
373 TRACE(("enter writechannel")); | 373 TRACE(("enter writechannel")) |
374 | 374 |
375 maxlen = cbuf_readlen(cbuf); | 375 maxlen = cbuf_readlen(cbuf); |
376 | 376 |
377 /* Write the data out */ | 377 /* Write the data out */ |
378 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); | 378 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); |
380 if (len < 0 && errno != EINTR) { | 380 if (len < 0 && errno != EINTR) { |
381 /* no more to write - we close it even if the fd was stderr, since | 381 /* no more to write - we close it even if the fd was stderr, since |
382 * that's a nasty failure too */ | 382 * that's a nasty failure too */ |
383 closeinfd(channel); | 383 closeinfd(channel); |
384 } | 384 } |
385 TRACE(("leave writechannel: len <= 0")); | 385 TRACE(("leave writechannel: len <= 0")) |
386 return; | 386 return; |
387 } | 387 } |
388 | 388 |
389 cbuf_incrread(cbuf, len); | 389 cbuf_incrread(cbuf, len); |
390 channel->recvdonelen += len; | 390 channel->recvdonelen += len; |
391 | 391 |
392 if (fd == channel->infd && len == maxlen && channel->recveof) { | 392 if (fd == channel->infd && len == maxlen && channel->recveof) { |
393 /* Check if we're closing up */ | 393 /* Check if we're closing up */ |
394 closeinfd(channel); | 394 closeinfd(channel); |
395 TRACE(("leave writechannel: recveof set")); | 395 TRACE(("leave writechannel: recveof set")) |
396 return; | 396 return; |
397 } | 397 } |
398 | 398 |
399 /* Window adjust handling */ | 399 /* Window adjust handling */ |
400 if (channel->recvdonelen >= RECV_WINDOWEXTEND) { | 400 if (channel->recvdonelen >= RECV_WINDOWEXTEND) { |
408 assert(channel->recvwindow <= cbuf_getavail(channel->writebuf)); | 408 assert(channel->recvwindow <= cbuf_getavail(channel->writebuf)); |
409 assert(channel->extrabuf == NULL || | 409 assert(channel->extrabuf == NULL || |
410 channel->recvwindow <= cbuf_getavail(channel->extrabuf)); | 410 channel->recvwindow <= cbuf_getavail(channel->extrabuf)); |
411 | 411 |
412 | 412 |
413 TRACE(("leave writechannel")); | 413 TRACE(("leave writechannel")) |
414 } | 414 } |
415 | 415 |
416 /* Set the file descriptors for the main select in session.c | 416 /* Set the file descriptors for the main select in session.c |
417 * This avoid channels which don't have any window available, are closed, etc*/ | 417 * This avoid channels which don't have any window available, are closed, etc*/ |
418 void setchannelfds(fd_set *readfd, fd_set *writefd) { | 418 void setchannelfds(fd_set *readfd, fd_set *writefd) { |
442 /* For checking FD status (ie closure etc) - we don't actually | 442 /* For checking FD status (ie closure etc) - we don't actually |
443 * read data from infd */ | 443 * read data from infd */ |
444 TRACE(("infd = %d, outfd %d, errfd %d, bufused %d", | 444 TRACE(("infd = %d, outfd %d, errfd %d, bufused %d", |
445 channel->infd, channel->outfd, | 445 channel->infd, channel->outfd, |
446 channel->errfd, | 446 channel->errfd, |
447 cbuf_getused(channel->writebuf) )); | 447 cbuf_getused(channel->writebuf) )) |
448 if (channel->infd >= 0 && channel->infd != channel->outfd) { | 448 if (channel->infd >= 0 && channel->infd != channel->outfd) { |
449 FD_SET(channel->infd, readfd); | 449 FD_SET(channel->infd, readfd); |
450 } | 450 } |
451 | 451 |
452 /* Stuff from the wire, to local program/shell/user etc */ | 452 /* Stuff from the wire, to local program/shell/user etc */ |
475 void recv_msg_channel_eof() { | 475 void recv_msg_channel_eof() { |
476 | 476 |
477 unsigned int chan; | 477 unsigned int chan; |
478 struct Channel * channel; | 478 struct Channel * channel; |
479 | 479 |
480 TRACE(("enter recv_msg_channel_eof")); | 480 TRACE(("enter recv_msg_channel_eof")) |
481 | 481 |
482 chan = buf_getint(ses.payload); | 482 chan = buf_getint(ses.payload); |
483 channel = getchannel(chan); | 483 channel = getchannel(chan); |
484 | 484 |
485 if (channel == NULL) { | 485 if (channel == NULL) { |
491 && (channel->extrabuf == NULL | 491 && (channel->extrabuf == NULL |
492 || cbuf_getused(channel->extrabuf) == 0)) { | 492 || cbuf_getused(channel->extrabuf) == 0)) { |
493 closeinfd(channel); | 493 closeinfd(channel); |
494 } | 494 } |
495 | 495 |
496 TRACE(("leave recv_msg_channel_eof")); | 496 TRACE(("leave recv_msg_channel_eof")) |
497 } | 497 } |
498 | 498 |
499 | 499 |
500 /* Handle channel closure(), respond in kind and close the channels */ | 500 /* Handle channel closure(), respond in kind and close the channels */ |
501 void recv_msg_channel_close() { | 501 void recv_msg_channel_close() { |
502 | 502 |
503 unsigned int chan; | 503 unsigned int chan; |
504 struct Channel * channel; | 504 struct Channel * channel; |
505 | 505 |
506 TRACE(("enter recv_msg_channel_close")); | 506 TRACE(("enter recv_msg_channel_close")) |
507 | 507 |
508 chan = buf_getint(ses.payload); | 508 chan = buf_getint(ses.payload); |
509 TRACE(("close channel = %d", chan)); | 509 TRACE(("close channel = %d", chan)) |
510 channel = getchannel(chan); | 510 channel = getchannel(chan); |
511 | 511 |
512 if (channel == NULL) { | 512 if (channel == NULL) { |
513 /* disconnect ? */ | 513 /* disconnect ? */ |
514 dropbear_exit("Close for unknown channel"); | 514 dropbear_exit("Close for unknown channel"); |
519 | 519 |
520 if (channel->sentclosed) { | 520 if (channel->sentclosed) { |
521 removechannel(channel); | 521 removechannel(channel); |
522 } | 522 } |
523 | 523 |
524 TRACE(("leave recv_msg_channel_close")); | 524 TRACE(("leave recv_msg_channel_close")) |
525 } | 525 } |
526 | 526 |
527 /* Remove a channel entry, this is only executed after both sides have sent | 527 /* Remove a channel entry, this is only executed after both sides have sent |
528 * channel close */ | 528 * channel close */ |
529 static void removechannel(struct Channel * channel) { | 529 static void removechannel(struct Channel * channel) { |
530 | 530 |
531 TRACE(("enter removechannel")); | 531 TRACE(("enter removechannel")) |
532 TRACE(("channel index is %d", channel->index)); | 532 TRACE(("channel index is %d", channel->index)) |
533 | 533 |
534 cbuf_free(channel->writebuf); | 534 cbuf_free(channel->writebuf); |
535 channel->writebuf = NULL; | 535 channel->writebuf = NULL; |
536 | 536 |
537 if (channel->extrabuf) { | 537 if (channel->extrabuf) { |
548 | 548 |
549 channel->typedata = NULL; | 549 channel->typedata = NULL; |
550 | 550 |
551 deletechannel(channel); | 551 deletechannel(channel); |
552 | 552 |
553 TRACE(("leave removechannel")); | 553 TRACE(("leave removechannel")) |
554 } | 554 } |
555 | 555 |
556 /* Remove a channel entry */ | 556 /* Remove a channel entry */ |
557 static void deletechannel(struct Channel *channel) { | 557 static void deletechannel(struct Channel *channel) { |
558 | 558 |
568 void recv_msg_channel_request() { | 568 void recv_msg_channel_request() { |
569 | 569 |
570 unsigned int chan; | 570 unsigned int chan; |
571 struct Channel *channel; | 571 struct Channel *channel; |
572 | 572 |
573 TRACE(("enter recv_msg_channel_request")); | 573 TRACE(("enter recv_msg_channel_request")) |
574 | 574 |
575 chan = buf_getint(ses.payload); | 575 chan = buf_getint(ses.payload); |
576 channel = getchannel(chan); | 576 channel = getchannel(chan); |
577 | 577 |
578 if (channel == NULL) { | 578 if (channel == NULL) { |
584 channel->type->reqhandler(channel); | 584 channel->type->reqhandler(channel); |
585 } else { | 585 } else { |
586 send_msg_channel_failure(channel); | 586 send_msg_channel_failure(channel); |
587 } | 587 } |
588 | 588 |
589 TRACE(("leave recv_msg_channel_request")); | 589 TRACE(("leave recv_msg_channel_request")) |
590 | 590 |
591 } | 591 } |
592 | 592 |
593 /* Reads data from the server's program/shell/etc, and puts it in a | 593 /* Reads data from the server's program/shell/etc, and puts it in a |
594 * channel_data packet to send. | 594 * channel_data packet to send. |
601 buffer *buf; | 601 buffer *buf; |
602 int len; | 602 int len; |
603 unsigned int maxlen; | 603 unsigned int maxlen; |
604 int fd; | 604 int fd; |
605 | 605 |
606 /* TRACE(("enter send_msg_channel_data")); | 606 /* TRACE(("enter send_msg_channel_data")) |
607 TRACE(("extended = %d type = %d", isextended, exttype));*/ | 607 TRACE(("extended = %d type = %d", isextended, exttype))*/ |
608 | 608 |
609 CHECKCLEARTOWRITE(); | 609 CHECKCLEARTOWRITE(); |
610 | 610 |
611 assert(!channel->sentclosed); | 611 assert(!channel->sentclosed); |
612 | 612 |
621 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and | 621 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and |
622 * exttype if is extended */ | 622 * exttype if is extended */ |
623 maxlen = MIN(maxlen, | 623 maxlen = MIN(maxlen, |
624 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0)); | 624 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0)); |
625 if (maxlen == 0) { | 625 if (maxlen == 0) { |
626 TRACE(("leave send_msg_channel_data: no window")); | 626 TRACE(("leave send_msg_channel_data: no window")) |
627 return; /* the data will get written later */ | 627 return; /* the data will get written later */ |
628 } | 628 } |
629 | 629 |
630 /* read the data */ | 630 /* read the data */ |
631 TRACE(("maxlen %d", maxlen)); | 631 TRACE(("maxlen %d", maxlen)) |
632 buf = buf_new(maxlen); | 632 buf = buf_new(maxlen); |
633 TRACE(("buf pos %d data %x", buf->pos, buf->data)); | 633 TRACE(("buf pos %d data %x", buf->pos, buf->data)) |
634 len = read(fd, buf_getwriteptr(buf, maxlen), maxlen); | 634 len = read(fd, buf_getwriteptr(buf, maxlen), maxlen); |
635 if (len <= 0) { | 635 if (len <= 0) { |
636 /* on error/eof, send eof */ | 636 /* on error/eof, send eof */ |
637 if (len == 0 || errno != EINTR) { | 637 if (len == 0 || errno != EINTR) { |
638 closeoutfd(channel, fd); | 638 closeoutfd(channel, fd); |
658 buf = NULL; | 658 buf = NULL; |
659 | 659 |
660 channel->transwindow -= len; | 660 channel->transwindow -= len; |
661 | 661 |
662 encrypt_packet(); | 662 encrypt_packet(); |
663 TRACE(("leave send_msg_channel_data")); | 663 TRACE(("leave send_msg_channel_data")) |
664 } | 664 } |
665 | 665 |
666 /* We receive channel data */ | 666 /* We receive channel data */ |
667 void recv_msg_channel_data() { | 667 void recv_msg_channel_data() { |
668 | 668 |
687 unsigned int datalen; | 687 unsigned int datalen; |
688 unsigned int maxdata; | 688 unsigned int maxdata; |
689 unsigned int buflen; | 689 unsigned int buflen; |
690 unsigned int len; | 690 unsigned int len; |
691 | 691 |
692 TRACE(("enter recv_msg_channel_data")); | 692 TRACE(("enter recv_msg_channel_data")) |
693 | 693 |
694 if (channel->recveof) { | 694 if (channel->recveof) { |
695 dropbear_exit("received data after eof"); | 695 dropbear_exit("received data after eof"); |
696 } | 696 } |
697 | 697 |
728 | 728 |
729 assert(channel->recvwindow >= datalen); | 729 assert(channel->recvwindow >= datalen); |
730 channel->recvwindow -= datalen; | 730 channel->recvwindow -= datalen; |
731 assert(channel->recvwindow <= RECV_MAXWINDOW); | 731 assert(channel->recvwindow <= RECV_MAXWINDOW); |
732 | 732 |
733 TRACE(("leave recv_msg_channel_data")); | 733 TRACE(("leave recv_msg_channel_data")) |
734 } | 734 } |
735 | 735 |
736 /* Increment the outgoing data window for a channel - the remote end limits | 736 /* Increment the outgoing data window for a channel - the remote end limits |
737 * the amount of data which may be transmitted, this window is decremented | 737 * the amount of data which may be transmitted, this window is decremented |
738 * as data is sent, and incremented upon receiving window-adjust messages */ | 738 * as data is sent, and incremented upon receiving window-adjust messages */ |
748 if (channel == NULL) { | 748 if (channel == NULL) { |
749 dropbear_exit("Unknown channel"); | 749 dropbear_exit("Unknown channel"); |
750 } | 750 } |
751 | 751 |
752 incr = buf_getint(ses.payload); | 752 incr = buf_getint(ses.payload); |
753 TRACE(("received window increment %d", incr)); | 753 TRACE(("received window increment %d", incr)) |
754 incr = MIN(incr, MAX_TRANS_WIN_INCR); | 754 incr = MIN(incr, MAX_TRANS_WIN_INCR); |
755 | 755 |
756 channel->transwindow += incr; | 756 channel->transwindow += incr; |
757 channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW); | 757 channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW); |
758 | 758 |
761 /* Increment the incoming data window for a channel, and let the remote | 761 /* Increment the incoming data window for a channel, and let the remote |
762 * end know */ | 762 * end know */ |
763 static void send_msg_channel_window_adjust(struct Channel* channel, | 763 static void send_msg_channel_window_adjust(struct Channel* channel, |
764 unsigned int incr) { | 764 unsigned int incr) { |
765 | 765 |
766 TRACE(("sending window adjust %d", incr)); | 766 TRACE(("sending window adjust %d", incr)) |
767 CHECKCLEARTOWRITE(); | 767 CHECKCLEARTOWRITE(); |
768 | 768 |
769 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST); | 769 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST); |
770 buf_putint(ses.writepayload, channel->remotechan); | 770 buf_putint(ses.writepayload, channel->remotechan); |
771 buf_putint(ses.writepayload, incr); | 771 buf_putint(ses.writepayload, incr); |
785 const struct ChanType *chantype; | 785 const struct ChanType *chantype; |
786 unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE; | 786 unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE; |
787 int ret; | 787 int ret; |
788 | 788 |
789 | 789 |
790 TRACE(("enter recv_msg_channel_open")); | 790 TRACE(("enter recv_msg_channel_open")) |
791 | 791 |
792 /* get the packet contents */ | 792 /* get the packet contents */ |
793 type = buf_getstring(ses.payload, &typelen); | 793 type = buf_getstring(ses.payload, &typelen); |
794 | 794 |
795 remotechan = buf_getint(ses.payload); | 795 remotechan = buf_getint(ses.payload); |
813 break; | 813 break; |
814 } | 814 } |
815 } | 815 } |
816 | 816 |
817 if (chantype == NULL) { | 817 if (chantype == NULL) { |
818 TRACE(("No matching type for '%s'", type)); | 818 TRACE(("No matching type for '%s'", type)) |
819 goto failure; | 819 goto failure; |
820 } | 820 } |
821 | 821 |
822 TRACE(("matched type '%s'", type)); | 822 TRACE(("matched type '%s'", type)) |
823 | 823 |
824 /* create the channel */ | 824 /* create the channel */ |
825 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket); | 825 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket); |
826 | 826 |
827 if (channel == NULL) { | 827 if (channel == NULL) { |
828 TRACE(("newchannel returned NULL")); | 828 TRACE(("newchannel returned NULL")) |
829 goto failure; | 829 goto failure; |
830 } | 830 } |
831 | 831 |
832 if (channel->type->inithandler) { | 832 if (channel->type->inithandler) { |
833 ret = channel->type->inithandler(channel); | 833 ret = channel->type->inithandler(channel); |
836 /* We'll send the confirmation later */ | 836 /* We'll send the confirmation later */ |
837 goto cleanup; | 837 goto cleanup; |
838 } | 838 } |
839 errtype = ret; | 839 errtype = ret; |
840 deletechannel(channel); | 840 deletechannel(channel); |
841 TRACE(("inithandler returned failure %d", ret)); | 841 TRACE(("inithandler returned failure %d", ret)) |
842 goto failure; | 842 goto failure; |
843 } | 843 } |
844 } | 844 } |
845 | 845 |
846 /* success */ | 846 /* success */ |
847 send_msg_channel_open_confirmation(channel, channel->recvwindow, | 847 send_msg_channel_open_confirmation(channel, channel->recvwindow, |
848 channel->recvmaxpacket); | 848 channel->recvmaxpacket); |
849 goto cleanup; | 849 goto cleanup; |
850 | 850 |
851 failure: | 851 failure: |
852 TRACE(("recv_msg_channel_open failure")); | 852 TRACE(("recv_msg_channel_open failure")) |
853 send_msg_channel_open_failure(remotechan, errtype, "", ""); | 853 send_msg_channel_open_failure(remotechan, errtype, "", ""); |
854 | 854 |
855 cleanup: | 855 cleanup: |
856 m_free(type); | 856 m_free(type); |
857 | 857 |
858 TRACE(("leave recv_msg_channel_open")); | 858 TRACE(("leave recv_msg_channel_open")) |
859 } | 859 } |
860 | 860 |
861 /* Send a failure message */ | 861 /* Send a failure message */ |
862 void send_msg_channel_failure(struct Channel *channel) { | 862 void send_msg_channel_failure(struct Channel *channel) { |
863 | 863 |
864 TRACE(("enter send_msg_channel_failure")); | 864 TRACE(("enter send_msg_channel_failure")) |
865 CHECKCLEARTOWRITE(); | 865 CHECKCLEARTOWRITE(); |
866 | 866 |
867 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); | 867 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); |
868 buf_putint(ses.writepayload, channel->remotechan); | 868 buf_putint(ses.writepayload, channel->remotechan); |
869 | 869 |
870 encrypt_packet(); | 870 encrypt_packet(); |
871 TRACE(("leave send_msg_channel_failure")); | 871 TRACE(("leave send_msg_channel_failure")) |
872 } | 872 } |
873 | 873 |
874 /* Send a success message */ | 874 /* Send a success message */ |
875 void send_msg_channel_success(struct Channel *channel) { | 875 void send_msg_channel_success(struct Channel *channel) { |
876 | 876 |
877 TRACE(("enter send_msg_channel_success")); | 877 TRACE(("enter send_msg_channel_success")) |
878 CHECKCLEARTOWRITE(); | 878 CHECKCLEARTOWRITE(); |
879 | 879 |
880 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); | 880 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); |
881 buf_putint(ses.writepayload, channel->remotechan); | 881 buf_putint(ses.writepayload, channel->remotechan); |
882 | 882 |
883 encrypt_packet(); | 883 encrypt_packet(); |
884 TRACE(("leave send_msg_channel_success")); | 884 TRACE(("leave send_msg_channel_success")) |
885 } | 885 } |
886 | 886 |
887 /* Send a channel open failure message, with a corresponding reason | 887 /* Send a channel open failure message, with a corresponding reason |
888 * code (usually resource shortage or unknown chan type) */ | 888 * code (usually resource shortage or unknown chan type) */ |
889 static void send_msg_channel_open_failure(unsigned int remotechan, | 889 static void send_msg_channel_open_failure(unsigned int remotechan, |
890 int reason, const unsigned char *text, const unsigned char *lang) { | 890 int reason, const unsigned char *text, const unsigned char *lang) { |
891 | 891 |
892 TRACE(("enter send_msg_channel_open_failure")); | 892 TRACE(("enter send_msg_channel_open_failure")) |
893 CHECKCLEARTOWRITE(); | 893 CHECKCLEARTOWRITE(); |
894 | 894 |
895 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE); | 895 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE); |
896 buf_putint(ses.writepayload, remotechan); | 896 buf_putint(ses.writepayload, remotechan); |
897 buf_putint(ses.writepayload, reason); | 897 buf_putint(ses.writepayload, reason); |
898 buf_putstring(ses.writepayload, text, strlen((char*)text)); | 898 buf_putstring(ses.writepayload, text, strlen((char*)text)); |
899 buf_putstring(ses.writepayload, lang, strlen((char*)lang)); | 899 buf_putstring(ses.writepayload, lang, strlen((char*)lang)); |
900 | 900 |
901 encrypt_packet(); | 901 encrypt_packet(); |
902 TRACE(("leave send_msg_channel_open_failure")); | 902 TRACE(("leave send_msg_channel_open_failure")) |
903 } | 903 } |
904 | 904 |
905 /* Confirm a channel open, and let the remote end know what number we've | 905 /* Confirm a channel open, and let the remote end know what number we've |
906 * allocated and the receive parameters */ | 906 * allocated and the receive parameters */ |
907 static void send_msg_channel_open_confirmation(struct Channel* channel, | 907 static void send_msg_channel_open_confirmation(struct Channel* channel, |
908 unsigned int recvwindow, | 908 unsigned int recvwindow, |
909 unsigned int recvmaxpacket) { | 909 unsigned int recvmaxpacket) { |
910 | 910 |
911 TRACE(("enter send_msg_channel_open_confirmation")); | 911 TRACE(("enter send_msg_channel_open_confirmation")) |
912 CHECKCLEARTOWRITE(); | 912 CHECKCLEARTOWRITE(); |
913 | 913 |
914 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | 914 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION); |
915 buf_putint(ses.writepayload, channel->remotechan); | 915 buf_putint(ses.writepayload, channel->remotechan); |
916 buf_putint(ses.writepayload, channel->index); | 916 buf_putint(ses.writepayload, channel->index); |
917 buf_putint(ses.writepayload, recvwindow); | 917 buf_putint(ses.writepayload, recvwindow); |
918 buf_putint(ses.writepayload, recvmaxpacket); | 918 buf_putint(ses.writepayload, recvmaxpacket); |
919 | 919 |
920 encrypt_packet(); | 920 encrypt_packet(); |
921 TRACE(("leave send_msg_channel_open_confirmation")); | 921 TRACE(("leave send_msg_channel_open_confirmation")) |
922 } | 922 } |
923 | 923 |
924 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT) | 924 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT) |
925 /* Create a new channel, and start the open request. This is intended | 925 /* Create a new channel, and start the open request. This is intended |
926 * for X11, agent, tcp forwarding, and should be filled with channel-specific | 926 * for X11, agent, tcp forwarding, and should be filled with channel-specific |
929 * DROPBEAR_SUCCESS is returned */ | 929 * DROPBEAR_SUCCESS is returned */ |
930 int send_msg_channel_open_init(int fd, const struct ChanType *type) { | 930 int send_msg_channel_open_init(int fd, const struct ChanType *type) { |
931 | 931 |
932 struct Channel* chan; | 932 struct Channel* chan; |
933 | 933 |
934 TRACE(("enter send_msg_channel_open_init()")); | 934 TRACE(("enter send_msg_channel_open_init()")) |
935 chan = newchannel(0, type, 0, 0); | 935 chan = newchannel(0, type, 0, 0); |
936 if (!chan) { | 936 if (!chan) { |
937 TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()")); | 937 TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()")) |
938 return DROPBEAR_FAILURE; | 938 return DROPBEAR_FAILURE; |
939 } | 939 } |
940 | 940 |
941 /* set fd non-blocking */ | 941 /* set fd non-blocking */ |
942 setnonblocking(fd); | 942 setnonblocking(fd); |
951 buf_putstring(ses.writepayload, type->name, strlen(type->name)); | 951 buf_putstring(ses.writepayload, type->name, strlen(type->name)); |
952 buf_putint(ses.writepayload, chan->index); | 952 buf_putint(ses.writepayload, chan->index); |
953 buf_putint(ses.writepayload, RECV_MAXWINDOW); | 953 buf_putint(ses.writepayload, RECV_MAXWINDOW); |
954 buf_putint(ses.writepayload, RECV_MAXPACKET); | 954 buf_putint(ses.writepayload, RECV_MAXPACKET); |
955 | 955 |
956 TRACE(("leave send_msg_channel_open_init()")); | 956 TRACE(("leave send_msg_channel_open_init()")) |
957 return DROPBEAR_SUCCESS; | 957 return DROPBEAR_SUCCESS; |
958 } | 958 } |
959 | 959 |
960 /* Confirmation that our channel open request (for forwardings) was | 960 /* Confirmation that our channel open request (for forwardings) was |
961 * successful*/ | 961 * successful*/ |
963 | 963 |
964 unsigned int chan; | 964 unsigned int chan; |
965 struct Channel * channel; | 965 struct Channel * channel; |
966 int ret; | 966 int ret; |
967 | 967 |
968 TRACE(("enter recv_msg_channel_open_confirmation")); | 968 TRACE(("enter recv_msg_channel_open_confirmation")) |
969 chan = buf_getint(ses.payload); | 969 chan = buf_getint(ses.payload); |
970 | 970 |
971 channel = getchannel(chan); | 971 channel = getchannel(chan); |
972 if (channel == NULL) { | 972 if (channel == NULL) { |
973 dropbear_exit("Unknown channel"); | 973 dropbear_exit("Unknown channel"); |
975 | 975 |
976 channel->remotechan = buf_getint(ses.payload); | 976 channel->remotechan = buf_getint(ses.payload); |
977 channel->transwindow = buf_getint(ses.payload); | 977 channel->transwindow = buf_getint(ses.payload); |
978 channel->transmaxpacket = buf_getint(ses.payload); | 978 channel->transmaxpacket = buf_getint(ses.payload); |
979 | 979 |
980 TRACE(("new chan remote %d localho %d", channel->remotechan, chan)); | 980 TRACE(("new chan remote %d localho %d", channel->remotechan, chan)) |
981 | 981 |
982 /* Run the inithandler callback */ | 982 /* Run the inithandler callback */ |
983 if (channel->type->inithandler) { | 983 if (channel->type->inithandler) { |
984 ret = channel->type->inithandler(channel); | 984 ret = channel->type->inithandler(channel); |
985 if (ret > 0) { | 985 if (ret > 0) { |
986 removechannel(channel); | 986 removechannel(channel); |
987 TRACE(("inithandler returned failure %d", ret)); | 987 TRACE(("inithandler returned failure %d", ret)) |
988 } | 988 } |
989 } | 989 } |
990 | 990 |
991 | 991 |
992 TRACE(("leave recv_msg_channel_open_confirmation")); | 992 TRACE(("leave recv_msg_channel_open_confirmation")) |
993 } | 993 } |
994 | 994 |
995 /* Notification that our channel open request failed */ | 995 /* Notification that our channel open request failed */ |
996 void recv_msg_channel_open_failure() { | 996 void recv_msg_channel_open_failure() { |
997 | 997 |
1011 /* close a stdout/stderr fd */ | 1011 /* close a stdout/stderr fd */ |
1012 static void closeoutfd(struct Channel * channel, int fd) { | 1012 static void closeoutfd(struct Channel * channel, int fd) { |
1013 | 1013 |
1014 /* don't close it if it is the same as infd, | 1014 /* don't close it if it is the same as infd, |
1015 * unless infd is already set -1 */ | 1015 * unless infd is already set -1 */ |
1016 TRACE(("enter closeoutfd")); | 1016 TRACE(("enter closeoutfd")) |
1017 closechanfd(channel, fd, 0); | 1017 closechanfd(channel, fd, 0); |
1018 TRACE(("leave closeoutfd")); | 1018 TRACE(("leave closeoutfd")) |
1019 } | 1019 } |
1020 | 1020 |
1021 /* close a stdin fd */ | 1021 /* close a stdin fd */ |
1022 static void closeinfd(struct Channel * channel) { | 1022 static void closeinfd(struct Channel * channel) { |
1023 | 1023 |
1024 TRACE(("enter closeinfd")); | 1024 TRACE(("enter closeinfd")) |
1025 closechanfd(channel, channel->infd, 1); | 1025 closechanfd(channel, channel->infd, 1); |
1026 TRACE(("leave closeinfd")); | 1026 TRACE(("leave closeinfd")) |
1027 } | 1027 } |
1028 | 1028 |
1029 /* close a fd, how is 0 for stdout/stderr, 1 for stdin */ | 1029 /* close a fd, how is 0 for stdout/stderr, 1 for stdin */ |
1030 static void closechanfd(struct Channel *channel, int fd, int how) { | 1030 static void closechanfd(struct Channel *channel, int fd, int how) { |
1031 | 1031 |