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;
51 SILC_LOG_DEBUG(("Parsing command payload"));
53 new = silc_calloc(1, sizeof(*new));
55 /* Parse the Command Payload */
56 ret = silc_buffer_unformat(buffer,
57 SILC_STR_UI_SHORT(&payload_len),
58 SILC_STR_UI_CHAR(&new->cmd),
59 SILC_STR_UI_CHAR(&args_num),
60 SILC_STR_UI_SHORT(&new->ident),
67 if (payload_len != buffer->len) {
68 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
78 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
80 new->args = silc_argument_payload_parse(buffer, args_num);
86 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
91 /* Encodes Command Payload returning it to SilcBuffer. */
93 SilcBuffer silc_command_payload_encode(SilcCommand cmd,
96 unsigned int *argv_lens,
97 unsigned int *argv_types,
101 SilcBuffer args = NULL;
102 unsigned int len = 0;
104 SILC_LOG_DEBUG(("Encoding command payload"));
107 args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
111 len += SILC_COMMAND_PAYLOAD_LEN;
112 buffer = silc_buffer_alloc(len);
113 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
115 /* Create Command payload */
116 silc_buffer_format(buffer,
117 SILC_STR_UI_SHORT(len),
118 SILC_STR_UI_CHAR(cmd),
119 SILC_STR_UI_CHAR(argc),
120 SILC_STR_UI_SHORT(ident),
125 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
126 silc_buffer_format(buffer,
127 SILC_STR_UI_XNSTRING(args->data, args->len),
129 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
136 /* Same as above but encode the buffer from SilcCommandPayload structure
137 instead of raw data. */
139 SilcBuffer silc_command_payload_encode_payload(SilcCommandPayload payload)
142 SilcBuffer args = NULL;
143 unsigned int len = 0;
144 unsigned int argc = 0;
146 SILC_LOG_DEBUG(("Encoding command payload"));
149 args = silc_argument_payload_encode_payload(payload->args);
151 argc = silc_argument_get_arg_num(payload->args);
154 len += SILC_COMMAND_PAYLOAD_LEN;
155 buffer = silc_buffer_alloc(len);
156 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
158 /* Create Command payload */
159 silc_buffer_format(buffer,
160 SILC_STR_UI_SHORT(len),
161 SILC_STR_UI_CHAR(payload->cmd),
162 SILC_STR_UI_CHAR(argc),
163 SILC_STR_UI_SHORT(payload->ident),
168 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
169 silc_buffer_format(buffer,
170 SILC_STR_UI_XNSTRING(args->data, args->len),
172 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
179 /* Encodes Command payload with variable argument list. The arguments
180 must be: unsigned int, unsigned char *, unsigned int, ... One
181 {unsigned int, unsigned char * and unsigned int} forms one argument,
182 thus `argc' in case when sending one {unsigned int, unsigned char *
183 and unsigned int} equals one (1) and when sending two of those it
184 equals two (2), and so on. This has to be preserved or bad things
185 will happen. The variable arguments is: {type, data, data_len}. */
187 SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
188 unsigned short ident,
189 unsigned int argc, ...)
192 unsigned char **argv;
193 unsigned int *argv_lens = NULL, *argv_types = NULL;
202 argv = silc_calloc(argc, sizeof(unsigned char *));
203 argv_lens = silc_calloc(argc, sizeof(unsigned int));
204 argv_types = silc_calloc(argc, sizeof(unsigned int));
206 for (i = 0, k = 0; i < argc; i++) {
207 x_type = va_arg(ap, unsigned int);
208 x = va_arg(ap, unsigned char *);
209 x_len = va_arg(ap, unsigned int);
211 if (!x_type || !x || !x_len)
214 argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
215 memcpy(argv[k], x, x_len);
216 argv_lens[k] = x_len;
217 argv_types[k] = x_type;
221 buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
224 for (i = 0; i < k; i++)
227 silc_free(argv_lens);
228 silc_free(argv_types);
233 /* Same as above but with va_list. */
235 SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
236 unsigned short ident,
237 unsigned int argc, va_list ap)
239 unsigned char **argv;
240 unsigned int *argv_lens = NULL, *argv_types = NULL;
247 argv = silc_calloc(argc, sizeof(unsigned char *));
248 argv_lens = silc_calloc(argc, sizeof(unsigned int));
249 argv_types = silc_calloc(argc, sizeof(unsigned int));
251 for (i = 0, k = 0; i < argc; i++) {
252 x_type = va_arg(ap, unsigned int);
253 x = va_arg(ap, unsigned char *);
254 x_len = va_arg(ap, unsigned int);
256 if (!x_type || !x || !x_len)
259 argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
260 memcpy(argv[k], x, x_len);
261 argv_lens[k] = x_len;
262 argv_types[k] = x_type;
266 buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
269 for (i = 0; i < k; i++)
272 silc_free(argv_lens);
273 silc_free(argv_types);
278 /* Same as above except that this is used to encode strictly command
279 reply packets. The command status message to be returned is sent as
280 extra argument to this function. The `argc' must not count `status'
284 silc_command_reply_payload_encode_va(SilcCommand cmd,
285 SilcCommandStatus status,
286 unsigned short ident,
287 unsigned int argc, ...)
290 unsigned char **argv;
291 unsigned int *argv_lens = NULL, *argv_types = NULL;
292 unsigned char status_data[2];
302 argv = silc_calloc(argc, sizeof(unsigned char *));
303 argv_lens = silc_calloc(argc, sizeof(unsigned int));
304 argv_types = silc_calloc(argc, sizeof(unsigned int));
306 SILC_PUT16_MSB(status, status_data);
307 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
308 memcpy(argv[0], status_data, sizeof(status_data));
309 argv_lens[0] = sizeof(status_data);
312 for (i = 1, k = 1; i < argc; i++) {
313 x_type = va_arg(ap, unsigned int);
314 x = va_arg(ap, unsigned char *);
315 x_len = va_arg(ap, unsigned int);
317 if (!x_type || !x || !x_len)
320 argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
321 memcpy(argv[k], x, x_len);
322 argv_lens[k] = x_len;
323 argv_types[k] = x_type;
327 buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
330 for (i = 0; i < k; i++)
333 silc_free(argv_lens);
334 silc_free(argv_types);
339 /* Free's Command Payload */
341 void silc_command_free_payload(SilcCommandPayload payload)
344 silc_argument_payload_free(payload->args);
349 /* Returns command */
351 SilcCommand silc_command_get(SilcCommandPayload payload)
356 /* Retuns arguments payload */
358 SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload)
360 return payload->args;
363 /* Returns identifier */
365 unsigned short silc_command_get_ident(SilcCommandPayload payload)
367 return payload->ident;
370 /* Function to set identifier to already allocated Command Payload. Command
371 payloads are frequentlly resent in SILC and thusly this makes it easy
372 to set the identifier. */
374 void silc_command_set_ident(SilcCommandPayload payload, unsigned short ident)
376 payload->ident = ident;
379 /* Function to set the command to already allocated Command Payload. */
381 void silc_command_set_command(SilcCommandPayload payload, SilcCommand command)
383 payload->cmd = command;