channel_forward.c 3.76 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* channel_forward.h
 *
 * General channel type for forwarding data to an fd
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998, 2001 Balzs Scheidler, Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "channel_forward.h"

#include "io.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"

#include <assert.h>
#include <errno.h>
#include <string.h>

#define GABA_DEFINE
#include "channel_forward.h.x"
#undef GABA_DEFINE

/* NOTE: Adds the socket to the channel's resource list */
42
43
44
void
init_channel_forward(struct channel_forward *self,
		     struct lsh_fd *socket, UINT32 initial_window)
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
  assert(socket);
  
  init_channel(&self->super);

  /* The rest of the callbacks are not set up until tcpip_start_io. */

  /* NOTE: We don't need a close handler, as the channel's resource
   * list is taken care of automatically. */
  
  self->super.rec_window_size = initial_window;

  /* FIXME: Make maximum packet size configurable. */
  self->super.rec_max_packet = SSH_MAX_PACKET - SSH_CHANNEL_MAX_PACKET_FUZZ;
  
  self->socket = socket;

  REMEMBER_RESOURCE(self->super.resources, &socket->super);
63
64
65
66
67
68
69
}

struct channel_forward *
make_channel_forward(struct lsh_fd *socket, UINT32 initial_window)
{
  NEW(channel_forward, self);
  init_channel_forward(self, socket, initial_window);
70
  
71
  return self;
72
73
74
75
}

static void
do_channel_forward_receive(struct ssh_channel *c,
76
			   int type, struct lsh_string *data)
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
{
  CAST(channel_forward, closure, c);
  
  switch (type)
    {
    case CHANNEL_DATA:
      A_WRITE(&closure->socket->write_buffer->super, data);
      break;
    case CHANNEL_STDERR_DATA:
      werror("Ignoring unexpected stderr data.\n");
      lsh_string_free(data);
      break;
    default:
      fatal("Internal error. do_channel_forward_receive");
    }
}

static void
do_channel_forward_send_adjust(struct ssh_channel *s,
		     UINT32 i UNUSED)
{
  CAST(channel_forward, self, s);
  
100
  lsh_oop_register_read_fd(self->socket);
101
102
103
104
105
106
107
}

static void
do_channel_forward_eof(struct ssh_channel *s)
{
  CAST(channel_forward, self, s);

108
109
110
  /* We won't write any more. io.c should make sure that shutdown is called
   * once the write_buffer is empty. */
  close_fd_write(self->socket);
111
112
113
114
115
116
117
118
119
}


/* NOTE: Because this function is called by
 * do_open_forwarded_tcpip_continuation, the same restrictions apply.
 * I.e we can not assume that the channel is completely initialized
 * (channel_open_continuation has not yet done its work), and we can't
 * send any packets. */
void
120
channel_forward_start_io(struct channel_forward *channel)
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
{
  channel->super.receive = do_channel_forward_receive;
  channel->super.send_adjust = do_channel_forward_send_adjust;
  channel->super.eof = do_channel_forward_eof;
  
  /* Install callbacks on the local socket.
   * NOTE: We don't install any channel_io_exception_handler. */
  io_read_write(channel->socket,
		make_channel_read_data(&channel->super),
		/* FIXME: Make this configurable */
		SSH_MAX_PACKET * 10, /* self->block_size, */
		make_channel_read_close_callback(&channel->super));
  
  /* Flow control */
  channel->socket->write_buffer->report = &channel->super.super;
}