5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2001 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(const unsigned char *payload,
47 SilcBufferStruct buffer;
48 SilcCommandPayload new;
49 unsigned char args_num;
53 SILC_LOG_DEBUG(("Parsing command payload"));
55 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
56 new = silc_calloc(1, sizeof(*new));
58 /* Parse the Command Payload */
59 ret = silc_buffer_unformat(&buffer,
60 SILC_STR_UI_SHORT(&p_len),
61 SILC_STR_UI_CHAR(&new->cmd),
62 SILC_STR_UI_CHAR(&args_num),
63 SILC_STR_UI_SHORT(&new->ident),
70 if (p_len != buffer.len) {
71 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
81 silc_buffer_pull(&buffer, SILC_COMMAND_PAYLOAD_LEN);
83 new->args = silc_argument_payload_parse(buffer.data, buffer.len, args_num);
89 silc_buffer_push(&buffer, SILC_COMMAND_PAYLOAD_LEN);
94 /* Encodes Command Payload returning it to SilcBuffer. */
96 SilcBuffer silc_command_payload_encode(SilcCommand cmd,
104 SilcBuffer args = NULL;
107 SILC_LOG_DEBUG(("Encoding command payload"));
110 args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
114 len += SILC_COMMAND_PAYLOAD_LEN;
115 buffer = silc_buffer_alloc(len);
116 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
118 /* Create Command payload */
119 silc_buffer_format(buffer,
120 SILC_STR_UI_SHORT(len),
121 SILC_STR_UI_CHAR(cmd),
122 SILC_STR_UI_CHAR(argc),
123 SILC_STR_UI_SHORT(ident),
128 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
129 silc_buffer_format(buffer,
130 SILC_STR_UI_XNSTRING(args->data, args->len),
132 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
133 silc_buffer_free(args);
139 /* Same as above but encode the buffer from SilcCommandPayload structure
140 instead of raw data. */
142 SilcBuffer silc_command_payload_encode_payload(SilcCommandPayload payload)
145 SilcBuffer args = NULL;
149 SILC_LOG_DEBUG(("Encoding command payload"));
152 args = silc_argument_payload_encode_payload(payload->args);
154 argc = silc_argument_get_arg_num(payload->args);
157 len += SILC_COMMAND_PAYLOAD_LEN;
158 buffer = silc_buffer_alloc(len);
159 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
161 /* Create Command payload */
162 silc_buffer_format(buffer,
163 SILC_STR_UI_SHORT(len),
164 SILC_STR_UI_CHAR(payload->cmd),
165 SILC_STR_UI_CHAR(argc),
166 SILC_STR_UI_SHORT(payload->ident),
171 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
172 silc_buffer_format(buffer,
173 SILC_STR_UI_XNSTRING(args->data, args->len),
175 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
176 silc_buffer_free(args);
182 /* Encodes Command payload with variable argument list. The arguments
183 must be: uint32, unsigned char *, unsigned int, ... One
184 {uint32, unsigned char * and unsigned int} forms one argument,
185 thus `argc' in case when sending one {uint32, unsigned char *
186 and uint32} equals one (1) and when sending two of those it
187 equals two (2), and so on. This has to be preserved or bad things
188 will happen. The variable arguments is: {type, data, data_len}. */
190 SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
198 buffer = silc_command_payload_encode_vap(cmd, ident, argc, ap);
204 /* Same as above but with va_list. */
206 SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
208 uint32 argc, va_list ap)
210 unsigned char **argv = NULL;
211 uint32 *argv_lens = NULL, *argv_types = NULL;
219 argv = silc_calloc(argc, sizeof(unsigned char *));
220 argv_lens = silc_calloc(argc, sizeof(uint32));
221 argv_types = silc_calloc(argc, sizeof(uint32));
223 for (i = 0, k = 0; i < argc; i++) {
224 x_type = va_arg(ap, uint32);
225 x = va_arg(ap, unsigned char *);
226 x_len = va_arg(ap, uint32);
228 if (!x_type || !x || !x_len)
231 argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
232 memcpy(argv[k], x, x_len);
233 argv_lens[k] = x_len;
234 argv_types[k] = x_type;
239 buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
242 for (i = 0; i < k; i++)
245 silc_free(argv_lens);
246 silc_free(argv_types);
251 /* Same as above except that this is used to encode strictly command
252 reply packets. The command status message to be returned is sent as
253 extra argument to this function. The `argc' must not count `status'
257 silc_command_reply_payload_encode_va(SilcCommand cmd,
258 SilcCommandStatus status,
266 buffer = silc_command_reply_payload_encode_vap(cmd, status, ident, argc, ap);
273 silc_command_reply_payload_encode_vap(SilcCommand cmd,
274 SilcCommandStatus status,
275 uint16 ident, uint32 argc,
278 unsigned char **argv;
279 uint32 *argv_lens = NULL, *argv_types = NULL;
280 unsigned char status_data[2];
288 argv = silc_calloc(argc, sizeof(unsigned char *));
289 argv_lens = silc_calloc(argc, sizeof(uint32));
290 argv_types = silc_calloc(argc, sizeof(uint32));
292 SILC_PUT16_MSB(status, status_data);
293 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
294 memcpy(argv[0], status_data, sizeof(status_data));
295 argv_lens[0] = sizeof(status_data);
298 for (i = 1, k = 1; i < argc; i++) {
299 x_type = va_arg(ap, uint32);
300 x = va_arg(ap, unsigned char *);
301 x_len = va_arg(ap, uint32);
303 if (!x_type || !x || !x_len)
306 argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
307 memcpy(argv[k], x, x_len);
308 argv_lens[k] = x_len;
309 argv_types[k] = x_type;
313 buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
316 for (i = 0; i < k; i++)
319 silc_free(argv_lens);
320 silc_free(argv_types);
325 /* Frees Command Payload */
327 void silc_command_payload_free(SilcCommandPayload payload)
330 silc_argument_payload_free(payload->args);
335 /* Returns command */
337 SilcCommand silc_command_get(SilcCommandPayload payload)
342 /* Retuns arguments payload */
344 SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload)
346 return payload->args;
349 /* Returns identifier */
351 uint16 silc_command_get_ident(SilcCommandPayload payload)
353 return payload->ident;
356 /* Function to set identifier to already allocated Command Payload. Command
357 payloads are frequentlly resent in SILC and thusly this makes it easy
358 to set the identifier. */
360 void silc_command_set_ident(SilcCommandPayload payload, uint16 ident)
362 payload->ident = ident;
365 /* Function to set the command to already allocated Command Payload. */
367 void silc_command_set_command(SilcCommandPayload payload, SilcCommand command)
369 payload->cmd = command;