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);
79 new->args = silc_argument_payload_parse(buffer, args_num);
84 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
89 /* Encodes Command Payload returning it to SilcBuffer. */
91 SilcBuffer silc_command_payload_encode(SilcCommand cmd,
94 unsigned int *argv_lens,
95 unsigned int *argv_types,
99 SilcBuffer args = NULL;
100 unsigned int len = 0;
102 SILC_LOG_DEBUG(("Encoding command payload"));
105 args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
109 len += SILC_COMMAND_PAYLOAD_LEN;
110 buffer = silc_buffer_alloc(len);
111 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
113 /* Create Command payload */
114 silc_buffer_format(buffer,
115 SILC_STR_UI_SHORT(len),
116 SILC_STR_UI_CHAR(cmd),
117 SILC_STR_UI_CHAR(argc),
118 SILC_STR_UI_SHORT(ident),
123 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
124 silc_buffer_format(buffer,
125 SILC_STR_UI_XNSTRING(args->data, args->len),
127 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
134 /* Same as above but encode the buffer from SilcCommandPayload structure
135 instead of raw data. */
137 SilcBuffer silc_command_payload_encode_payload(SilcCommandPayload payload)
140 SilcBuffer args = NULL;
141 unsigned int len = 0;
142 unsigned int argc = 0;
144 SILC_LOG_DEBUG(("Encoding command payload"));
147 args = silc_argument_payload_encode_payload(payload->args);
149 argc = silc_argument_get_arg_num(payload->args);
152 len += SILC_COMMAND_PAYLOAD_LEN;
153 buffer = silc_buffer_alloc(len);
154 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
156 /* Create Command payload */
157 silc_buffer_format(buffer,
158 SILC_STR_UI_SHORT(len),
159 SILC_STR_UI_CHAR(payload->cmd),
160 SILC_STR_UI_CHAR(argc),
161 SILC_STR_UI_SHORT(payload->ident),
166 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
167 silc_buffer_format(buffer,
168 SILC_STR_UI_XNSTRING(args->data, args->len),
170 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
177 /* Encodes Command payload with variable argument list. The arguments
178 must be: unsigned int, unsigned char *, unsigned int, ... One
179 {unsigned int, unsigned char * and unsigned int} forms one argument,
180 thus `argc' in case when sending one {unsigned int, unsigned char *
181 and unsigned int} equals one (1) and when sending two of those it
182 equals two (2), and so on. This has to be preserved or bad things
183 will happen. The variable arguments is: {type, data, data_len}. */
185 SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
186 unsigned short ident,
187 unsigned int argc, ...)
190 unsigned char **argv;
191 unsigned int *argv_lens = NULL, *argv_types = NULL;
200 argv = silc_calloc(argc, sizeof(unsigned char *));
201 argv_lens = silc_calloc(argc, sizeof(unsigned int));
202 argv_types = silc_calloc(argc, sizeof(unsigned int));
204 for (i = 0; i < argc; i++) {
205 x_type = va_arg(ap, unsigned int);
206 x = va_arg(ap, unsigned char *);
207 x_len = va_arg(ap, unsigned int);
209 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
210 memcpy(argv[i], x, x_len);
211 argv_lens[i] = x_len;
212 argv_types[i] = x_type;
215 buffer = silc_command_payload_encode(cmd, argc, argv,
216 argv_lens, argv_types, ident);
218 for (i = 0; i < argc; i++)
221 silc_free(argv_lens);
222 silc_free(argv_types);
227 /* Same as above but with va_list. */
229 SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
230 unsigned short ident,
231 unsigned int argc, va_list ap)
233 unsigned char **argv;
234 unsigned int *argv_lens = NULL, *argv_types = NULL;
241 argv = silc_calloc(argc, sizeof(unsigned char *));
242 argv_lens = silc_calloc(argc, sizeof(unsigned int));
243 argv_types = silc_calloc(argc, sizeof(unsigned int));
245 for (i = 0; i < argc; i++) {
246 x_type = va_arg(ap, unsigned int);
247 x = va_arg(ap, unsigned char *);
248 x_len = va_arg(ap, unsigned int);
250 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
251 memcpy(argv[i], x, x_len);
252 argv_lens[i] = x_len;
253 argv_types[i] = x_type;
256 buffer = silc_command_payload_encode(cmd, argc, argv,
257 argv_lens, argv_types, ident);
259 for (i = 0; i < argc; i++)
262 silc_free(argv_lens);
263 silc_free(argv_types);
268 /* Same as above except that this is used to encode strictly command
269 reply packets. The command status message to be returned is sent as
270 extra argument to this function. The `argc' must not count `status'
274 silc_command_reply_payload_encode_va(SilcCommand cmd,
275 SilcCommandStatus status,
276 unsigned short ident,
277 unsigned int argc, ...)
280 unsigned char **argv;
281 unsigned int *argv_lens = NULL, *argv_types = NULL;
282 unsigned char status_data[2];
292 argv = silc_calloc(argc, sizeof(unsigned char *));
293 argv_lens = silc_calloc(argc, sizeof(unsigned int));
294 argv_types = silc_calloc(argc, sizeof(unsigned int));
296 SILC_PUT16_MSB(status, status_data);
297 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
298 memcpy(argv[0], status_data, sizeof(status_data));
299 argv_lens[0] = sizeof(status_data);
302 for (i = 1; i < argc; i++) {
303 x_type = va_arg(ap, unsigned int);
304 x = va_arg(ap, unsigned char *);
305 x_len = va_arg(ap, unsigned int);
307 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
308 memcpy(argv[i], x, x_len);
309 argv_lens[i] = x_len;
310 argv_types[i] = x_type;
313 buffer = silc_command_payload_encode(cmd, argc, argv,
314 argv_lens, argv_types, ident);
316 for (i = 0; i < argc; i++)
319 silc_free(argv_lens);
320 silc_free(argv_types);
325 /* Free's Command Payload */
327 void silc_command_free_payload(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 unsigned short 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, unsigned short 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;