channel_commands.c 6.17 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
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
/* channel_commands.c
 *
 * $Id$
 */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Möller
 *
 * 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_commands.h"

27
#include "ssh.h"
Niels Möller's avatar
Niels Möller committed
28
29
30
#include "werror.h"
#include "xalloc.h"

Niels Möller's avatar
Niels Möller committed
31
32
33
34
#define GABA_DEFINE
#include "channel_commands.h.x"
#undef GABA_DEFINE

35
36
37
38
#include "channel_commands.c.x"

#include <assert.h>

39
40
41
42
43
void
do_channel_open_command(struct command *s,
			struct lsh_object *x,
			struct command_continuation *c,
			struct exception_handler *e)
Niels Möller's avatar
Niels Möller committed
44
45
{
  CAST_SUBTYPE(channel_open_command, self, s);
46
  CAST(ssh_connection, connection, x);
Niels Möller's avatar
Niels Möller committed
47
  struct lsh_string *request;
48
  struct ssh_channel *channel;
Niels Möller's avatar
Niels Möller committed
49

50
51
52
  int index = alloc_channel(connection->table);

  if (index < 0)
Niels Möller's avatar
Niels Möller committed
53
    {
54
      /* We have run out of channel numbers. */
55
      werror("do_channel_open_command: alloc_channel failed\n");
56
57
58
59
      EXCEPTION_RAISE(e,
		      make_channel_open_exception(
			SSH_OPEN_RESOURCE_SHORTAGE,
			"Allocating a local channel number failed."));
Niels Möller's avatar
Niels Möller committed
60
    }
61
62
63
64
65
66
67
68

  channel = NEW_CHANNEL(self, connection, index, &request);

  if (!channel)
    {
      werror("do_channel_open_command: NEW_CHANNEL failed\n");
      dealloc_channel(connection->table, index);
    }
Niels Möller's avatar
Niels Möller committed
69
70
  else
    {
71
72
      /* FIXME: Set up channel->write here? If we do that, perhaps we
       * need not pass the connection to NEW_CHANNEL. */
Niels Möller's avatar
Niels Möller committed
73
      channel->open_continuation = c;
74
75
76
      channel->e = e;
      register_channel(connection, index, channel, 0);

Niels Möller's avatar
Niels Möller committed
77
      C_WRITE(connection, request);
Niels Möller's avatar
Niels Möller committed
78
79
    }
}
80

81
82
83
84
85
void
do_channel_request_command(struct command *s,
			   struct lsh_object *x,
			   struct command_continuation *c,
			   struct exception_handler *e)
86
87
88
89
90
{
  CAST_SUBTYPE(channel_request_command, self, s);
  CAST_SUBTYPE(ssh_channel, channel, x);

  struct lsh_string *request
91
    = FORMAT_CHANNEL_REQUEST(self, channel, &c);
92

Niels Möller's avatar
Niels Möller committed
93
  if (CONTINUATION_USED_P(c))
94
95
96
    object_queue_add_tail(&channel->pending_requests,
			  &make_command_context(c, e)->super);
  
97
  A_WRITE(channel->write, request);
98
99
}

100
101
102
103
104
void
do_channel_global_command(struct command *s,
			  struct lsh_object *x,
			  struct command_continuation *c,
			  struct exception_handler *e)
105
106
107
108
109
110
111
{
  CAST_SUBTYPE(global_request_command, self, s);
  CAST_SUBTYPE(ssh_connection, connection, x);

  struct lsh_string *request
    = FORMAT_GLOBAL_REQUEST(self, connection, &c);

Niels Möller's avatar
Niels Möller committed
112
  if (CONTINUATION_USED_P(c))
Niels Möller's avatar
Niels Möller committed
113
    object_queue_add_tail(&connection->table->pending_global_requests,
114
			  &make_command_context(c, e)->super);
115

Niels Möller's avatar
Niels Möller committed
116
  C_WRITE(connection, request);
117
}
118

119
120
121
122
123
124
void
do_install_global_request_handler(struct command_2 *s,
				  struct lsh_object *a1,
				  struct lsh_object *a2,
				  struct command_continuation *c,
				  struct exception_handler *e UNUSED)
125
{
126
127
128
  CAST(install_info, self, s);
  CAST(ssh_connection, connection, a1);
  CAST_SUBTYPE(global_request, handler, a2);
129

130
  assert(handler);
131
132

  trace("Installing global request handler for '%a'\n", self->name);
133
  
Niels Möller's avatar
Niels Möller committed
134
  ALIST_SET(connection->table->global_requests,
135
	    self->name,
Niels Möller's avatar
Niels Möller committed
136
	    &handler->super);
137

138
  COMMAND_RETURN(c, connection);
139
140
}

141
142
143
144
145
146
void
do_install_channel_open_handler(struct command_2 *s,
				struct lsh_object *a1,
				struct lsh_object *a2,
				struct command_continuation *c,
				struct exception_handler *e UNUSED)
147
{
148
149
150
  CAST(install_info, self, s);
  CAST(ssh_connection, connection, a1);
  CAST_SUBTYPE(channel_open, handler, a2);
151

152
153
  assert(handler);
  
154
  trace("Installing channel open handler for '%a'\n", self->name);
155

Niels Möller's avatar
Niels Möller committed
156
  ALIST_SET(connection->table->channel_types,
157
	    self->name,
Niels Möller's avatar
Niels Möller committed
158
	    &handler->super);
159

160
  COMMAND_RETURN(c, connection);
161
162
}

163

164
165
166
167
168
169
170
171
/* Special cases, when the handler is known early */
 
/* Takes a connection as argument, and installs a fix handler */
/* GABA:
   (class
     (name install_global_request_handler)
     (super command)
     (vars
172
       (name . int)
173
174
175
       (handler object global_request)))
*/

Niels Möller's avatar
Niels Möller committed
176
static void
177
178
do_install_fix_global_request_handler(struct command *s,
				      struct lsh_object *x,
179
180
				      struct command_continuation *c,
				      struct exception_handler *e UNUSED)
181
182
183
184
{
  CAST(install_global_request_handler, self, s);
  CAST(ssh_connection, connection, x);

185
  trace("Installing fix global request handler for '%a'\n", self->name);
186
  
Niels Möller's avatar
Niels Möller committed
187
  ALIST_SET(connection->table->global_requests,
188
	    self->name,
Niels Möller's avatar
Niels Möller committed
189
	    &self->handler->super);
190

Niels Möller's avatar
Niels Möller committed
191
  COMMAND_RETURN(c, x);
192
193
194
195
196
}

struct command *
make_install_fix_global_request_handler(UINT32 name,
					struct global_request *handler)
197
{  
198
  NEW(install_global_request_handler, self);
199
200
201

  assert(handler);
  
202
203
204
205
206
207
208
209
210
211
212
213
214
  self->super.call = do_install_fix_global_request_handler;
  self->name = name;
  self->handler = handler;

  return &self->super;
}

/* Takes a connection as argument, and installs a fix handler */
/* GABA:
   (class
     (name install_channel_open_handler)
     (super command)
     (vars
215
       (name . int)
216
217
218
       (handler object channel_open)))
*/

Niels Möller's avatar
Niels Möller committed
219
static void
220
221
do_install_fix_channel_open_handler(struct command *s,
				    struct lsh_object *x,
222
223
				    struct command_continuation *c,
				    struct exception_handler *e UNUSED)
224
225
226
227
{
  CAST(install_channel_open_handler, self, s);
  CAST(ssh_connection, connection, x);

228
  trace("Installing fix channel open handler for type '%a'\n", self->name);
229
  
Niels Möller's avatar
Niels Möller committed
230
231
  ALIST_SET(connection->table
	    ->channel_types,
232
	    self->name,
Niels Möller's avatar
Niels Möller committed
233
	    &self->handler->super);
234

Niels Möller's avatar
Niels Möller committed
235
  COMMAND_RETURN(c, connection);
236
237
238
239
240
241
242
}

struct command *
make_install_fix_channel_open_handler(UINT32 name,
				      struct channel_open *handler)
{
  NEW(install_channel_open_handler, self);
243
244
245

  assert(handler);
  
246
247
248
249
250
251
252
  self->super.call = do_install_fix_channel_open_handler;
  self->name = name;
  self->handler = handler;

  return &self->super;
}