3 server_st_command_reply.c
5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcserver.h"
22 #include "server_internal.h"
24 /************************** Types and definitions ***************************/
26 /* All functions that call the COMMAND_CHECK_STATUS macros must have
27 out: and err: goto labels. */
29 #define COMMAND_CHECK_STATUS \
31 SILC_LOG_DEBUG(("Start")); \
32 if (!silc_command_get_status(cmd->payload, &status, &error)) { \
33 if (SILC_STATUS_IS_ERROR(status)) \
35 if (status == SILC_STATUS_LIST_END) \
42 /************************ Static utility functions **************************/
44 /* Free's command reply context */
46 static void silc_server_command_reply_free(SilcServerCommand cmd)
48 /* If pending commmands existed, they will eventually free this context */
50 silc_server_command_free(cmd);
54 /************************* Command reply received ***************************/
56 /* Received a COMMAND_REPLY packet. We parse the packet and process the
59 SILC_FSM_STATE(silc_server_st_packet_command_reply)
61 SilcServerThread thread = fsm_context;
62 SilcPacket packet = state_context;
63 SilcEntryData data = silc_packet_get_context(packet->stream);
64 SilcServerCommand cmd;
65 SilcCommandPayload payload;
68 SILC_LOG_DEBUG(("Process command reply"));
70 /* Allocate command context. */
71 cmd = silc_server_command_alloc(thread);
73 silc_packet_free(packet);
74 return SILC_FSM_FINISH;
79 /* Get command reply payload from packet */
80 cmd->payload = silc_command_payload_parse(packet->buffer.data,
81 silc_buffer_len(&packet->buffer));
83 SILC_LOG_DEBUG(("Bad command reply payload"));
84 silc_server_command_reply_free(cmd);
85 return SILC_FSM_FINISH;
88 /* Client is allowed to send reply only to WHOIS command. */
89 if (data->type == SILC_CONN_CLIENT &&
90 silc_command_get(cmd->payload) != SILC_COMMAND_WHOIS) {
91 silc_server_command_reply_free(cmd);
92 return SILC_FSM_FINISH;
95 /* Get all command pending for this reply */
97 silc_server_command_pending_get(thread,
98 silc_command_get_ident(cmd->payload));
100 silc_fsm_set_state_context(fsm, cmd);
102 /* Process command reply */
103 switch (silc_command_get(cmd->payload)) {
105 case SILC_COMMAND_WHOIS:
106 /** Command reply WHOIS */
107 silc_fsm_next(fsm, silc_server_st_command_reply_whois);
110 case SILC_COMMAND_WHOWAS:
111 /** Command reply WHOWAS */
112 silc_fsm_next(fsm, silc_server_st_command_reply_whowas);
115 case SILC_COMMAND_IDENTIFY:
116 /** Command reply IDENTIFY */
117 silc_fsm_next(fsm, silc_server_st_command_reply_identify);
120 case SILC_COMMAND_LIST:
121 /** Command reply LIST */
122 silc_fsm_next(fsm, silc_server_st_command_reply_list);
125 case SILC_COMMAND_INFO:
126 /** Command reply INFO */
127 silc_fsm_next(fsm, silc_server_st_command_reply_info);
130 case SILC_COMMAND_STATS:
131 /** Command reply STATS */
132 silc_fsm_next(fsm, silc_server_st_command_reply_stats);
135 case SILC_COMMAND_PING:
136 /** Command reply PING */
137 silc_fsm_next(fsm, silc_server_st_command_reply_ping);
140 case SILC_COMMAND_JOIN:
141 /** Command reply JOIN */
142 silc_fsm_next(fsm, silc_server_st_command_reply_join);
145 case SILC_COMMAND_MOTD:
146 /** Command reply MOTD */
147 silc_fsm_next(fsm, silc_server_st_command_reply_motd);
150 case SILC_COMMAND_WATCH:
151 /** Command reply WATCH */
152 silc_fsm_next(fsm, silc_server_st_command_reply_watch);
155 case SILC_COMMAND_USERS:
156 /** Command reply USERS */
157 silc_fsm_next(fsm, silc_server_st_command_reply_users);
160 case SILC_COMMAND_GETKEY:
161 /** Command reply SERVICE */
162 silc_fsm_next(fsm, silc_server_st_command_reply_getkey);
165 case SILC_COMMAND_SERVICE:
166 /** Command reply SERVICE */
167 silc_fsm_next(fsm, silc_server_st_command_reply_service);
171 SILC_LOG_DEBUG(("Unknown command %d", silc_command_get(cmd->payload)));
173 silc_server_command_reply_free(cmd);
174 return SILC_FSM_FINISH;
180 return SILC_FSM_CONTINUE;
184 /********************************* WHOIS ************************************/
186 SILC_FSM_STATE(silc_server_st_command_reply_whois)
188 SilcServerThread thread = fsm_context;
189 SilcServerCommand cmd = state_context;
190 SilcStatus status, error;
192 COMMAND_CHECK_STATUS;
195 silc_server_command_pending_signal(cmd);
197 silc_server_command_reply_free(cmd);
199 return SILC_FSM_FINISH;
203 /********************************* WHOWAS ***********************************/
205 SILC_FSM_STATE(silc_server_st_command_reply_whowas)
207 SilcServerThread thread = fsm_context;
208 SilcServerCommand cmd = state_context;
209 SilcStatus status, error;
211 COMMAND_CHECK_STATUS;
214 silc_server_command_pending_signal(cmd);
216 silc_server_command_reply_free(cmd);
218 return SILC_FSM_FINISH;
222 /******************************** IDENTIFY **********************************/
224 SILC_FSM_STATE(silc_server_st_command_reply_identify)
226 SilcServerThread thread = fsm_context;
227 SilcServerCommand cmd = state_context;
228 SilcStatus status, error;
230 COMMAND_CHECK_STATUS;
233 silc_server_command_pending_signal(cmd);
235 silc_server_command_reply_free(cmd);
237 return SILC_FSM_FINISH;
241 /********************************** LIST ************************************/
243 SILC_FSM_STATE(silc_server_st_command_reply_list)
245 SilcServerThread thread = fsm_context;
246 SilcServerCommand cmd = state_context;
247 SilcStatus status, error;
249 COMMAND_CHECK_STATUS;
252 silc_server_command_pending_signal(cmd);
254 silc_server_command_reply_free(cmd);
256 return SILC_FSM_FINISH;
260 /********************************** INFO ************************************/
262 SILC_FSM_STATE(silc_server_st_command_reply_info)
264 SilcServerThread thread = fsm_context;
265 SilcServerCommand cmd = state_context;
266 SilcStatus status, error;
268 COMMAND_CHECK_STATUS;
271 silc_server_command_pending_signal(cmd);
273 silc_server_command_reply_free(cmd);
275 return SILC_FSM_FINISH;
279 /********************************** STATS ***********************************/
281 SILC_FSM_STATE(silc_server_st_command_reply_stats)
283 SilcServerThread thread = fsm_context;
284 SilcServer server = thread->server;
285 SilcServerCommand cmd = state_context;
286 SilcArgumentPayload args = silc_command_get_args(cmd->payload);
287 SilcStatus status, error;
290 SilcBufferStruct buf;
292 COMMAND_CHECK_STATUS;
294 /* Get statistics structure */
295 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
296 if (server->server_type != SILC_ROUTER && tmp) {
297 silc_buffer_set(&buf, tmp, tmp_len);
298 silc_buffer_unformat(&buf,
299 SILC_STR_UI_INT(NULL),
300 SILC_STR_UI_INT(NULL),
301 SILC_STR_UI_INT(NULL),
302 SILC_STR_UI_INT(NULL),
303 SILC_STR_UI_INT(NULL),
304 SILC_STR_UI_INT(NULL),
305 SILC_STR_UI_INT(&server->stat.cell_clients),
306 SILC_STR_UI_INT(&server->stat.cell_channels),
307 SILC_STR_UI_INT(&server->stat.cell_servers),
308 SILC_STR_UI_INT(&server->stat.clients),
309 SILC_STR_UI_INT(&server->stat.channels),
310 SILC_STR_UI_INT(&server->stat.servers),
311 SILC_STR_UI_INT(&server->stat.routers),
312 SILC_STR_UI_INT(&server->stat.server_ops),
313 SILC_STR_UI_INT(&server->stat.router_ops),
318 silc_server_command_pending_signal(cmd);
320 silc_server_command_reply_free(cmd);
322 return SILC_FSM_FINISH;
326 /********************************** PING ************************************/
328 SILC_FSM_STATE(silc_server_st_command_reply_ping)
330 SilcServerThread thread = fsm_context;
331 SilcServerCommand cmd = state_context;
332 SilcStatus status, error;
334 COMMAND_CHECK_STATUS;
337 silc_server_command_pending_signal(cmd);
339 silc_server_command_reply_free(cmd);
341 return SILC_FSM_FINISH;
345 /********************************** JOIN ************************************/
347 SILC_FSM_STATE(silc_server_st_command_reply_join)
349 SilcServerThread thread = fsm_context;
350 SilcServerCommand cmd = state_context;
351 SilcStatus status, error;
353 COMMAND_CHECK_STATUS;
356 silc_server_command_pending_signal(cmd);
358 silc_server_command_reply_free(cmd);
360 return SILC_FSM_FINISH;
364 /********************************** MOTD ************************************/
366 SILC_FSM_STATE(silc_server_st_command_reply_motd)
368 SilcServerThread thread = fsm_context;
369 SilcServerCommand cmd = state_context;
370 SilcStatus status, error;
372 COMMAND_CHECK_STATUS;
375 silc_server_command_pending_signal(cmd);
377 silc_server_command_reply_free(cmd);
379 return SILC_FSM_FINISH;
383 /********************************** WATCH ***********************************/
385 SILC_FSM_STATE(silc_server_st_command_reply_watch)
387 SilcServerThread thread = fsm_context;
388 SilcServerCommand cmd = state_context;
389 SilcStatus status, error;
391 COMMAND_CHECK_STATUS;
394 silc_server_command_pending_signal(cmd);
396 silc_server_command_reply_free(cmd);
398 return SILC_FSM_FINISH;
402 /********************************** USERS ***********************************/
404 SILC_FSM_STATE(silc_server_st_command_reply_users)
406 SilcServerThread thread = fsm_context;
407 SilcServerCommand cmd = state_context;
408 SilcStatus status, error;
410 COMMAND_CHECK_STATUS;
413 silc_server_command_pending_signal(cmd);
415 silc_server_command_reply_free(cmd);
417 return SILC_FSM_FINISH;
421 /********************************** GETKEY **********************************/
423 SILC_FSM_STATE(silc_server_st_command_reply_getkey)
425 SilcServerThread thread = fsm_context;
426 SilcServer server = thread->server;
427 SilcServerCommand cmd = state_context;
428 SilcArgumentPayload args = silc_command_get_args(cmd->payload);
429 SilcStatus status, error;
432 SilcClientEntry client = NULL;
433 SilcServerEntry server_entry = NULL;
434 SilcIDPayload idp = NULL;
435 SilcClientID client_id;
436 SilcServerID server_id;
438 SilcPublicKey public_key = NULL;
440 COMMAND_CHECK_STATUS;
443 tmp = silc_argument_get_arg_type(args, 2, &len);
446 idp = silc_id_payload_parse(tmp, len);
450 /* Get the public key payload */
451 tmp = silc_argument_get_arg_type(args, 3, &len);
454 if (!silc_public_key_payload_decode(tmp, len, &public_key))
457 /* Store the public key */
458 id_type = silc_id_payload_get_type(idp);
459 if (id_type == SILC_ID_CLIENT) {
460 if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
463 client = silc_server_find_client_by_id(server, &client_id, TRUE, NULL);
467 if (!client->data.public_key) {
468 silc_skr_add_public_key_simple(server->repository, public_key,
469 SILC_SKR_USAGE_IDENTIFICATION, client);
470 client->data.public_key = public_key;
474 } else if (id_type == SILC_ID_SERVER) {
475 if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
478 server_entry = silc_server_find_server_by_id(server, &server_id,
483 server_entry->data.public_key = public_key;
488 silc_server_command_pending_signal(cmd);
490 silc_id_payload_free(idp);
492 silc_pkcs_public_key_free(public_key);
494 silc_server_command_reply_free(cmd);
496 return SILC_FSM_FINISH;
500 /******************************** SERVICE ***********************************/
502 SILC_FSM_STATE(silc_server_st_command_reply_service)
504 SilcServerThread thread = fsm_context;
505 SilcServerCommand cmd = state_context;
506 SilcStatus status, error;
508 COMMAND_CHECK_STATUS;
511 silc_server_command_pending_signal(cmd);
513 silc_server_command_reply_free(cmd);
515 return SILC_FSM_FINISH;