5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
23 #include "silccommand.h"
25 /******************************************************************************
29 ******************************************************************************/
31 /* Command Payload structure. Contents of this structure is parsed
33 struct SilcCommandPayloadStruct {
36 SilcArgumentPayload args;
39 /* Length of the command payload */
40 #define SILC_COMMAND_PAYLOAD_LEN 6
42 /* Parses command payload returning new command payload structure */
44 SilcCommandPayload silc_command_payload_parse(SilcBuffer buffer)
46 SilcCommandPayload new;
47 unsigned char args_num;
48 unsigned short payload_len;
50 SILC_LOG_DEBUG(("Parsing command payload"));
52 new = silc_calloc(1, sizeof(*new));
54 /* Parse the Command Payload */
55 silc_buffer_unformat(buffer,
56 SILC_STR_UI_SHORT(&payload_len),
57 SILC_STR_UI_CHAR(&new->cmd),
58 SILC_STR_UI_CHAR(&args_num),
59 SILC_STR_UI_SHORT(&new->ident),
62 if (payload_len != buffer->len) {
63 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
73 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
74 new->args = silc_argument_payload_parse(buffer, args_num);
79 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
84 /* Encodes Command Payload returning it to SilcBuffer. */
86 SilcBuffer silc_command_payload_encode(SilcCommand cmd,
89 unsigned int *argv_lens,
90 unsigned int *argv_types,
94 SilcBuffer args = NULL;
97 SILC_LOG_DEBUG(("Encoding command payload"));
100 args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
104 len += SILC_COMMAND_PAYLOAD_LEN;
105 buffer = silc_buffer_alloc(len);
106 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
108 /* Create Command payload */
109 silc_buffer_format(buffer,
110 SILC_STR_UI_SHORT(len),
111 SILC_STR_UI_CHAR(cmd),
112 SILC_STR_UI_CHAR(argc),
113 SILC_STR_UI_SHORT(ident),
118 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
119 silc_buffer_format(buffer,
120 SILC_STR_UI_XNSTRING(args->data, args->len),
122 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
129 /* Same as above but encode the buffer from SilcCommandPayload structure
130 instead of raw data. */
132 SilcBuffer silc_command_payload_encode_payload(SilcCommandPayload payload)
135 SilcBuffer args = NULL;
136 unsigned int len = 0;
137 unsigned int argc = 0;
139 SILC_LOG_DEBUG(("Encoding command payload"));
142 args = silc_argument_payload_encode_payload(payload->args);
144 argc = silc_argument_get_arg_num(payload->args);
147 len += SILC_COMMAND_PAYLOAD_LEN;
148 buffer = silc_buffer_alloc(len);
149 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
151 /* Create Command payload */
152 silc_buffer_format(buffer,
153 SILC_STR_UI_SHORT(len),
154 SILC_STR_UI_CHAR(payload->cmd),
155 SILC_STR_UI_CHAR(argc),
156 SILC_STR_UI_SHORT(payload->ident),
161 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
162 silc_buffer_format(buffer,
163 SILC_STR_UI_XNSTRING(args->data, args->len),
165 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
172 /* Encodes Command payload with variable argument list. The arguments
173 must be: unsigned int, unsigned char *, unsigned int, ... One
174 {unsigned int, unsigned char * and unsigned int} forms one argument,
175 thus `argc' in case when sending one {unsigned int, unsigned char *
176 and unsigned int} equals one (1) and when sending two of those it
177 equals two (2), and so on. This has to be preserved or bad things
178 will happen. The variable arguments is: {type, data, data_len}. */
180 SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
181 unsigned short ident,
182 unsigned int argc, ...)
185 unsigned char **argv;
186 unsigned int *argv_lens = NULL, *argv_types = NULL;
195 argv = silc_calloc(argc, sizeof(unsigned char *));
196 argv_lens = silc_calloc(argc, sizeof(unsigned int));
197 argv_types = silc_calloc(argc, sizeof(unsigned int));
199 for (i = 0; i < argc; i++) {
200 x_type = va_arg(ap, unsigned int);
201 x = va_arg(ap, unsigned char *);
202 x_len = va_arg(ap, unsigned int);
204 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
205 memcpy(argv[i], x, x_len);
206 argv_lens[i] = x_len;
207 argv_types[i] = x_type;
210 buffer = silc_command_payload_encode(cmd, argc, argv,
211 argv_lens, argv_types, ident);
213 for (i = 0; i < argc; i++)
216 silc_free(argv_lens);
217 silc_free(argv_types);
222 /* Same as above but with va_list. */
224 SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
225 unsigned short ident,
226 unsigned int argc, va_list ap)
228 unsigned char **argv;
229 unsigned int *argv_lens = NULL, *argv_types = NULL;
236 argv = silc_calloc(argc, sizeof(unsigned char *));
237 argv_lens = silc_calloc(argc, sizeof(unsigned int));
238 argv_types = silc_calloc(argc, sizeof(unsigned int));
240 for (i = 0; i < argc; i++) {
241 x_type = va_arg(ap, unsigned int);
242 x = va_arg(ap, unsigned char *);
243 x_len = va_arg(ap, unsigned int);
245 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
246 memcpy(argv[i], x, x_len);
247 argv_lens[i] = x_len;
248 argv_types[i] = x_type;
251 buffer = silc_command_payload_encode(cmd, argc, argv,
252 argv_lens, argv_types, ident);
254 for (i = 0; i < argc; i++)
257 silc_free(argv_lens);
258 silc_free(argv_types);
263 /* Same as above except that this is used to encode strictly command
264 reply packets. The command status message to be returned is sent as
265 extra argument to this function. The `argc' must not count `status'
269 silc_command_reply_payload_encode_va(SilcCommand cmd,
270 SilcCommandStatus status,
271 unsigned short ident,
272 unsigned int argc, ...)
275 unsigned char **argv;
276 unsigned int *argv_lens = NULL, *argv_types = NULL;
277 unsigned char status_data[2];
287 argv = silc_calloc(argc, sizeof(unsigned char *));
288 argv_lens = silc_calloc(argc, sizeof(unsigned int));
289 argv_types = silc_calloc(argc, sizeof(unsigned int));
291 SILC_PUT16_MSB(status, status_data);
292 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
293 memcpy(argv[0], status_data, sizeof(status_data));
294 argv_lens[0] = sizeof(status_data);
297 for (i = 1; i < argc; i++) {
298 x_type = va_arg(ap, unsigned int);
299 x = va_arg(ap, unsigned char *);
300 x_len = va_arg(ap, unsigned int);
302 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
303 memcpy(argv[i], x, x_len);
304 argv_lens[i] = x_len;
305 argv_types[i] = x_type;
308 buffer = silc_command_payload_encode(cmd, argc, argv,
309 argv_lens, argv_types, ident);
311 for (i = 0; i < argc; i++)
314 silc_free(argv_lens);
315 silc_free(argv_types);
320 /* Free's Command Payload */
322 void silc_command_free_payload(SilcCommandPayload payload)
325 silc_argument_payload_free(payload->args);
330 /* Returns command */
332 SilcCommand silc_command_get(SilcCommandPayload payload)
337 /* Retuns arguments payload */
339 SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload)
341 return payload->args;
344 /* Returns identifier */
346 unsigned short silc_command_get_ident(SilcCommandPayload payload)
348 return payload->ident;
351 /* Function to set identifier to already allocated Command Payload. Command
352 payloads are frequentlly resent in SILC and thusly this makes it easy
353 to set the identifier. */
355 void silc_command_set_ident(SilcCommandPayload payload, unsigned short ident)
357 payload->ident = ident;
360 /* Function to set the command to already allocated Command Payload. */
362 void silc_command_set_command(SilcCommandPayload payload, SilcCommand command)
364 payload->cmd = command;