Code auditing weekend results and fixes committing.
[silc.git] / apps / silcd / packet_receive.c
1 /*
2
3   packet_receive.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /*
21  * Server packet routines to handle received packets.
22  */
23 /* $Id$ */
24
25 #include "serverincludes.h"
26 #include "server_internal.h"
27
28 extern char *server_version;
29
30 /* Received private message. This resolves the destination of the message 
31    and sends the packet. This is used by both server and router.  If the
32    destination is our locally connected client this sends the packet to
33    the client. This may also send the message for further routing if
34    the destination is not in our server (or router). */
35
36 void silc_server_private_message(SilcServer server,
37                                  SilcSocketConnection sock,
38                                  SilcPacketContext *packet)
39 {
40   SilcClientID *id;
41   SilcServerEntry router;
42   SilcSocketConnection dst_sock;
43   SilcClientEntry client;
44   SilcIDListData idata;
45
46   SILC_LOG_DEBUG(("Start"));
47
48   if (!packet->dst_id)
49     goto err;
50
51   /* Decode destination Client ID */
52   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
53   if (!id) {
54     SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
55     goto err;
56   }
57
58   /* If the destination belongs to our server we don't have to route
59      the message anywhere but to send it to the local destination. */
60   client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
61   if (client) {
62     /* It exists, now deliver the message to the destination */
63     dst_sock = (SilcSocketConnection)client->connection;
64
65     /* If we are router and the client has router then the client is in
66        our cell but not directly connected to us. */
67     if (server->server_type == SILC_ROUTER && client->router) {
68       /* We are of course in this case the client's router thus the real
69          "router" of the client is the server who owns the client. Thus
70          we will send the packet to that server. */
71       router = (SilcServerEntry)dst_sock->user_data;
72       idata = (SilcIDListData)router;
73
74       silc_server_send_private_message(server, dst_sock,
75                                        idata->send_key,
76                                        idata->hmac,
77                                        packet);
78       return;
79     }
80
81     /* Seems that client really is directly connected to us */
82     idata = (SilcIDListData)client;
83     silc_server_send_private_message(server, dst_sock, 
84                                      idata->send_key,
85                                      idata->hmac, packet);
86     return;
87   }
88
89   /* Destination belongs to someone not in this server. If we are normal
90      server our action is to send the packet to our router. */
91   if (server->server_type == SILC_SERVER && !server->standalone) {
92     router = server->router;
93
94     /* Send to primary route */
95     if (router) {
96       dst_sock = (SilcSocketConnection)router->connection;
97       idata = (SilcIDListData)router;
98       silc_server_send_private_message(server, dst_sock, 
99                                        idata->send_key,
100                                        idata->hmac, packet);
101     }
102     return;
103   }
104
105   /* We are router and we will perform route lookup for the destination 
106      and send the message to fastest route. */
107   if (server->server_type == SILC_ROUTER && !server->standalone) {
108     /* Check first that the ID is valid */
109     client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
110     if (client) {
111       dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
112       router = (SilcServerEntry)dst_sock->user_data;
113       idata = (SilcIDListData)router;
114
115       /* Get fastest route and send packet. */
116       if (router)
117         silc_server_send_private_message(server, dst_sock, 
118                                          idata->send_key,
119                                          idata->hmac, packet);
120       return;
121     }
122   }
123
124  err:
125   silc_server_send_error(server, sock, 
126                          "No such nickname: Private message not sent");
127 }
128
129 /* Processes incoming command reply packet. The command reply packet may
130    be destined to one of our clients or it may directly for us. We will 
131    call the command reply routine after processing the packet. */
132
133 void silc_server_command_reply(SilcServer server,
134                                SilcSocketConnection sock,
135                                SilcPacketContext *packet)
136 {
137   SilcBuffer buffer = packet->buffer;
138   SilcClientEntry client = NULL;
139   SilcSocketConnection dst_sock;
140   SilcIDListData idata;
141   SilcClientID *id = NULL;
142
143   SILC_LOG_DEBUG(("Start"));
144
145   /* Source must be server or router */
146   if (packet->src_id_type != SILC_ID_SERVER &&
147       sock->type != SILC_SOCKET_TYPE_ROUTER)
148     return;
149
150   if (packet->dst_id_type == SILC_ID_CHANNEL)
151     return;
152
153   if (packet->dst_id_type == SILC_ID_CLIENT) {
154     /* Destination must be one of ours */
155     id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
156     if (!id)
157       return;
158     client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
159     if (!client) {
160       SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
161       silc_free(id);
162       return;
163     }
164   }
165
166   if (packet->dst_id_type == SILC_ID_SERVER) {
167     /* For now this must be for us */
168     if (SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
169       SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
170       return;
171     }
172   }
173
174   /* Execute command reply locally for the command */
175   silc_server_command_reply_process(server, sock, buffer);
176
177   if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
178     /* Relay the packet to the client */
179     
180     dst_sock = (SilcSocketConnection)client->connection;
181     silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
182                      + packet->dst_id_len + packet->padlen);
183     
184     silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
185     silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
186     
187     idata = (SilcIDListData)client;
188     
189     /* Encrypt packet */
190     silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf, 
191                         buffer->len);
192     
193     /* Send the packet */
194     silc_server_packet_send_real(server, dst_sock, TRUE);
195
196     silc_free(id);
197   }
198 }
199
200 /* Process received channel message. The message can be originated from
201    client or server. */
202
203 void silc_server_channel_message(SilcServer server,
204                                  SilcSocketConnection sock,
205                                  SilcPacketContext *packet)
206 {
207   SilcChannelEntry channel = NULL;
208   SilcChannelClientEntry chl;
209   SilcChannelID *id = NULL;
210   void *sender = NULL;
211
212   SILC_LOG_DEBUG(("Processing channel message"));
213
214   /* Sanity checks */
215   if (packet->dst_id_type != SILC_ID_CHANNEL) {
216     SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
217     goto out;
218   }
219
220   /* Find channel entry */
221   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
222   if (!id)
223     goto out;
224   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
225   if (!channel) {
226     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
227     if (!channel) {
228       SILC_LOG_DEBUG(("Could not find channel"));
229       goto out;
230     }
231   }
232
233   /* See that this client is on the channel. If the message is coming
234      from router we won't do the check as the message is from client that
235      we don't know about. Also, if the original sender is not client
236      (as it can be server as well) we don't do the check. */
237   sender = silc_id_str2id(packet->src_id, packet->src_id_len, 
238                           packet->src_id_type);
239   if (!sender)
240     goto out;
241   if (sock->type != SILC_SOCKET_TYPE_ROUTER && 
242       packet->src_id_type == SILC_ID_CLIENT) {
243     silc_list_start(channel->user_list);
244     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
245       if (chl->client && !SILC_ID_CLIENT_COMPARE(chl->client->id, sender))
246         break;
247     }
248     if (chl == SILC_LIST_END)
249       goto out;
250   }
251
252   /* Distribute the packet to our local clients. This will send the
253      packet for further routing as well, if needed. */
254   silc_server_packet_relay_to_channel(server, sock, channel, sender,
255                                       packet->src_id_type,
256                                       packet->buffer->data,
257                                       packet->buffer->len, FALSE);
258
259  out:
260   if (sender)
261     silc_free(sender);
262   if (id)
263     silc_free(id);
264 }
265
266 /* Received channel key packet. We distribute the key to all of our locally
267    connected clients on the channel. */
268
269 void silc_server_channel_key(SilcServer server,
270                              SilcSocketConnection sock,
271                              SilcPacketContext *packet)
272 {
273   SilcBuffer buffer = packet->buffer;
274   SilcChannelEntry channel;
275
276   if (packet->src_id_type != SILC_ID_SERVER)
277     return;
278
279   /* Save the channel key */
280   channel = silc_server_save_channel_key(server, buffer, NULL);
281   if (!channel)
282     return;
283
284   /* Distribute the key to everybody who is on the channel. If we are router
285      we will also send it to locally connected servers. */
286   silc_server_send_channel_key(server, sock, channel, FALSE);
287 }
288
289 /* Received packet to replace a ID. This checks that the requested ID
290    exists and replaces it with the new one. */
291
292 void silc_server_replace_id(SilcServer server,
293                             SilcSocketConnection sock,
294                             SilcPacketContext *packet)
295 {
296   SilcBuffer buffer = packet->buffer;
297   unsigned char *old_id = NULL, *new_id = NULL;
298   SilcIdType old_id_type, new_id_type;
299   unsigned short old_id_len, new_id_len;
300   void *id = NULL, *id2 = NULL;
301   int ret;
302
303   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
304       packet->src_id_type == SILC_ID_CLIENT)
305     return;
306
307   SILC_LOG_DEBUG(("Replacing ID"));
308
309   ret = silc_buffer_unformat(buffer,
310                              SILC_STR_UI_SHORT(&old_id_type),
311                              SILC_STR_UI16_NSTRING_ALLOC(&old_id, &old_id_len),
312                              SILC_STR_UI_SHORT(&new_id_type),
313                              SILC_STR_UI16_NSTRING_ALLOC(&new_id, &new_id_len),
314                              SILC_STR_END);
315   if (ret == -1)
316     goto out;
317
318   if (old_id_type != new_id_type)
319     goto out;
320
321   if (old_id_len != silc_id_get_len(old_id_type) ||
322       new_id_len != silc_id_get_len(new_id_type))
323     goto out;
324
325   id = silc_id_str2id(old_id, old_id_len, old_id_type);
326   if (!id)
327     goto out;
328
329   id2 = silc_id_str2id(new_id, new_id_len, new_id_type);
330   if (!id2)
331     goto out;
332
333   /* If we are router and this packet is not already broadcast packet
334      we will broadcast it. The sending socket really cannot be router or
335      the router is buggy. If this packet is coming from router then it must
336      have the broadcast flag set already and we won't do anything. */
337   if (!server->standalone && server->server_type == SILC_ROUTER &&
338       sock->type == SILC_SOCKET_TYPE_SERVER &&
339       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
340     SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
341     silc_server_packet_send(server, server->router->connection, packet->type,
342                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
343                             buffer->data, buffer->len, FALSE);
344   }
345
346   /* Replace the old ID */
347   switch(old_id_type) {
348   case SILC_ID_CLIENT:
349     {
350       SilcBuffer nidp, oidp;
351       SilcClientEntry client = NULL;
352
353       SILC_LOG_DEBUG(("Old Client ID id(%s)", 
354                       silc_id_render(id, SILC_ID_CLIENT)));
355       SILC_LOG_DEBUG(("New Client ID id(%s)", 
356                       silc_id_render(id2, SILC_ID_CLIENT)));
357
358       if ((client = silc_idlist_replace_client_id(server->local_list, 
359                                                   id, id2)) == NULL)
360         if (server->server_type == SILC_ROUTER)
361           client = silc_idlist_replace_client_id(server->global_list, id, id2);
362       
363       if (client) {
364         oidp = silc_id_payload_encode(id, SILC_ID_CLIENT);
365         nidp = silc_id_payload_encode(id2, SILC_ID_CLIENT);
366
367         /* Send the NICK_CHANGE notify type to local clients on the channels
368            this client is joined to. */
369         silc_server_send_notify_on_channels(server, client, 
370                                             SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
371                                             oidp->data, oidp->len, 
372                                             nidp->data, nidp->len);
373         
374         silc_buffer_free(nidp);
375         silc_buffer_free(oidp);
376       }
377       break;
378     }
379
380   case SILC_ID_SERVER:
381     SILC_LOG_DEBUG(("Old Server ID id(%s)", 
382                     silc_id_render(id, SILC_ID_CLIENT)));
383     SILC_LOG_DEBUG(("New Server ID id(%s)", 
384                     silc_id_render(id2, SILC_ID_CLIENT)));
385     if (silc_idlist_replace_server_id(server->local_list, id, id2) == NULL)
386       if (server->server_type == SILC_ROUTER)
387         silc_idlist_replace_server_id(server->global_list, id, id2);
388     break;
389
390   case SILC_ID_CHANNEL:
391     /* XXX Hmm... Basically this cannot occur. Channel ID's cannot be
392        re-generated. */
393     silc_free(id2);
394     break;
395
396   default:
397     silc_free(id2);
398     break;
399   }
400
401  out:
402   if (id)
403     silc_free(id);
404   if (old_id)
405     silc_free(old_id);
406   if (new_id)
407     silc_free(new_id);
408 }
409
410
411 /* Received New Client packet and processes it.  Creates Client ID for the
412    client. Client becomes registered after calling this functions. */
413
414 SilcClientEntry silc_server_new_client(SilcServer server,
415                                        SilcSocketConnection sock,
416                                        SilcPacketContext *packet)
417 {
418   SilcBuffer buffer = packet->buffer;
419   SilcClientEntry client;
420   SilcIDCacheEntry cache;
421   SilcClientID *client_id;
422   SilcBuffer reply;
423   SilcIDListData idata;
424   char *username = NULL, *realname = NULL, *id_string;
425   int ret;
426
427   SILC_LOG_DEBUG(("Creating new client"));
428
429   if (sock->type != SILC_SOCKET_TYPE_CLIENT)
430     return NULL;
431
432   /* Take client entry */
433   client = (SilcClientEntry)sock->user_data;
434   idata = (SilcIDListData)client;
435
436   /* Fetch the old client cache entry so that we can update it. */
437   if (!silc_idcache_find_by_context(server->local_list->clients,
438                                     sock->user_data, &cache)) {
439     SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
440     return NULL;
441   }
442
443   /* Parse incoming packet */
444   ret = silc_buffer_unformat(buffer,
445                              SILC_STR_UI16_STRING_ALLOC(&username),
446                              SILC_STR_UI16_STRING_ALLOC(&realname),
447                              SILC_STR_END);
448   if (ret == -1) {
449     if (username)
450       silc_free(username);
451     if (realname)
452       silc_free(realname);
453     return NULL;
454   }
455
456   /* Create Client ID */
457   silc_id_create_client_id(server->id, server->rng, server->md5hash,
458                            username, &client_id);
459
460   /* Update client entry */
461   idata->registered = TRUE;
462   client->nickname = strdup(username);
463   client->username = username;
464   client->userinfo = realname;
465   client->id = client_id;
466
467   /* Update the cache entry */
468   cache->id = (void *)client_id;
469   cache->type = SILC_ID_CLIENT;
470   cache->data = username;
471   silc_idcache_sort_by_data(server->local_list->clients);
472
473   /* Notify our router about new client on the SILC network */
474   if (!server->standalone)
475     silc_server_send_new_id(server, (SilcSocketConnection) 
476                             server->router->connection, 
477                             server->server_type == SILC_ROUTER ? TRUE : FALSE,
478                             client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
479   
480   /* Send the new client ID to the client. */
481   id_string = silc_id_id2str(client->id, SILC_ID_CLIENT);
482   reply = silc_buffer_alloc(2 + 2 + SILC_ID_CLIENT_LEN);
483   silc_buffer_pull_tail(reply, SILC_BUFFER_END(reply));
484   silc_buffer_format(reply,
485                      SILC_STR_UI_SHORT(SILC_ID_CLIENT),
486                      SILC_STR_UI_SHORT(SILC_ID_CLIENT_LEN),
487                      SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
488                      SILC_STR_END);
489   silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, 
490                           reply->data, reply->len, FALSE);
491   silc_free(id_string);
492   silc_buffer_free(reply);
493
494   /* Send some nice info to the client */
495   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
496                           ("Welcome to the SILC Network %s@%s",
497                            username, sock->hostname));
498   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
499                           ("Your host is %s, running version %s",
500                            server->config->server_info->server_name,
501                            server_version));
502   if (server->server_type == SILC_ROUTER) {
503     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
504                             ("There are %d clients on %d servers in SILC "
505                              "Network", server->stat.clients,
506                              server->stat.servers + 1));
507     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
508                             ("There are %d clients on %d server in our cell",
509                              server->stat.cell_clients,
510                              server->stat.cell_servers));
511     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
512                             ("I have %d clients, %d channels, %d servers and "
513                              "%d routers",
514                              server->stat.my_clients, 
515                              server->stat.my_channels,
516                              server->stat.my_servers,
517                              server->stat.my_routers));
518     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
519                             ("%d server operators and %d router operators "
520                              "online",
521                              server->stat.my_server_ops,
522                              server->stat.my_router_ops));
523   } else {
524     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
525                             ("I have %d clients and %d channels formed",
526                              server->stat.my_clients,
527                              server->stat.my_channels));
528     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
529                             ("%d operators online",
530                              server->stat.my_server_ops));
531   }
532   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
533                           ("Your connection is secured with %s cipher, "
534                            "key length %d bits",
535                            idata->send_key->cipher->name,
536                            idata->send_key->cipher->key_len));
537   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
538                           ("Your current nickname is %s",
539                            client->nickname));
540
541   /* Send motd */
542   silc_server_send_motd(server, sock);
543
544   return client;
545 }
546
547 /* Create new server. This processes received New Server packet and
548    saves the received Server ID. The server is our locally connected
549    server thus we save all the information and save it to local list. 
550    This funtion can be used by both normal server and router server.
551    If normal server uses this it means that its router has connected
552    to the server. If router uses this it means that one of the cell's
553    servers is connected to the router. */
554
555 SilcServerEntry silc_server_new_server(SilcServer server,
556                                        SilcSocketConnection sock,
557                                        SilcPacketContext *packet)
558 {
559   SilcBuffer buffer = packet->buffer;
560   SilcServerEntry new_server;
561   SilcIDCacheEntry cache;
562   SilcServerID *server_id;
563   SilcIDListData idata;
564   unsigned char *server_name, *id_string;
565   unsigned short id_len;
566   int ret;
567
568   SILC_LOG_DEBUG(("Creating new server"));
569
570   if (sock->type != SILC_SOCKET_TYPE_SERVER &&
571       sock->type != SILC_SOCKET_TYPE_ROUTER)
572     return NULL;
573
574   /* Take server entry */
575   new_server = (SilcServerEntry)sock->user_data;
576   idata = (SilcIDListData)new_server;
577
578   /* Fetch the old server cache entry so that we can update it. */
579   if (!silc_idcache_find_by_context(server->local_list->servers,
580                                     sock->user_data, &cache)) {
581     SILC_LOG_ERROR(("Lost server's cache entry - bad thing"));
582     return NULL;
583   }
584
585   /* Parse the incoming packet */
586   ret = silc_buffer_unformat(buffer,
587                              SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
588                              SILC_STR_UI16_STRING_ALLOC(&server_name),
589                              SILC_STR_END);
590   if (ret == -1) {
591     if (id_string)
592       silc_free(id_string);
593     if (server_name)
594       silc_free(server_name);
595     return NULL;
596   }
597
598   if (id_len > buffer->len) {
599     silc_free(id_string);
600     silc_free(server_name);
601     return NULL;
602   }
603
604   /* Get Server ID */
605   server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
606   if (!server_id) {
607     silc_free(id_string);
608     silc_free(server_name);
609     return NULL;
610   }
611   silc_free(id_string);
612
613   /* Update client entry */
614   idata->registered = TRUE;
615   new_server->server_name = server_name;
616   new_server->id = server_id;
617
618   /* Update the cache entry */
619   cache->id = (void *)server_id;
620   cache->type = SILC_ID_SERVER;
621   cache->data = server_name;
622   silc_idcache_sort_by_data(server->local_list->servers);
623
624   /* Distribute the information about new server in the SILC network
625      to our router. If we are normal server we won't send anything
626      since this connection must be our router connection. */
627   if (server->server_type == SILC_ROUTER && !server->standalone &&
628       server->router->connection != sock)
629     silc_server_send_new_id(server, server->router->connection,
630                             TRUE, new_server->id, SILC_ID_SERVER, 
631                             SILC_ID_SERVER_LEN);
632
633   if (server->server_type == SILC_ROUTER)
634     server->stat.cell_servers++;
635
636   return new_server;
637 }
638
639 /* Processes incoming New ID packet. New ID Payload is used to distribute
640    information about newly registered clients and servers. */
641
642 void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
643                         SilcPacketContext *packet)
644 {
645   SilcBuffer buffer = packet->buffer;
646   SilcIDList id_list;
647   SilcServerEntry router;
648   SilcSocketConnection router_sock;
649   SilcIDPayload idp;
650   SilcIdType id_type;
651   unsigned char *hash = NULL;
652   void *id;
653
654   SILC_LOG_DEBUG(("Processing new ID"));
655
656   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
657       server->server_type == SILC_SERVER ||
658       packet->src_id_type != SILC_ID_SERVER)
659     return;
660
661   idp = silc_id_payload_parse(buffer);
662   if (!idp)
663     return;
664
665   id_type = silc_id_payload_get_type(idp);
666
667   /* Normal server cannot have other normal server connections */
668   if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER)
669     goto out;
670
671   id = silc_id_payload_get_id(idp);
672   if (!id)
673     goto out;
674
675   /* If the sender of this packet is server and we are router we need to
676      broadcast this packet to other routers in the network. */
677   if (!server->standalone && server->server_type == SILC_ROUTER &&
678       sock->type == SILC_SOCKET_TYPE_SERVER &&
679       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
680     SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
681     silc_server_packet_send(server, server->router->connection,
682                             packet->type, 
683                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
684                             buffer->data, buffer->len, FALSE);
685   }
686
687   if (sock->type == SILC_SOCKET_TYPE_SERVER)
688     id_list = server->local_list;
689   else
690     id_list = server->global_list;
691
692   router_sock = sock;
693   router = sock->user_data;
694
695   switch(id_type) {
696   case SILC_ID_CLIENT:
697     {
698       SilcClientEntry entry;
699
700       SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
701                       silc_id_render(id, SILC_ID_CLIENT),
702                       sock->type == SILC_SOCKET_TYPE_SERVER ?
703                       "Server" : "Router", sock->hostname));
704     
705       /* As a router we keep information of all global information in our
706          global list. Cell wide information however is kept in the local
707          list. The client is put to global list and we will take the hash
708          value of the Client ID and save it to the ID Cache system for fast
709          searching in the future. */
710       hash = silc_calloc(sizeof(((SilcClientID *)id)->hash), 
711                          sizeof(unsigned char));
712       memcpy(hash, ((SilcClientID *)id)->hash, 
713              sizeof(((SilcClientID *)id)->hash));
714       entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id, 
715                                      router, router_sock);
716       entry->nickname = NULL;
717
718       if (sock->type == SILC_SOCKET_TYPE_SERVER)
719         server->stat.cell_clients++;
720       server->stat.clients++;
721
722 #if 0
723       /* XXX Adding two ID's with same IP number replaces the old entry thus
724          gives wrong route. Thus, now disabled until figured out a better way
725          to do this or when removed the whole thing. This could be removed
726          because entry->router->connection gives always the most optimal route
727          for the ID anyway (unless new routes (faster perhaps) are established
728          after receiving this ID, this we don't know however). */
729       /* Add route cache for this ID */
730       silc_server_route_add(silc_server_route_hash(
731                             ((SilcClientID *)id)->ip.s_addr,
732                             server->id->port), ((SilcClientID *)id)->ip.s_addr,
733                             router);
734 #endif
735     }
736     break;
737
738   case SILC_ID_SERVER:
739     SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
740                     silc_id_render(id, SILC_ID_SERVER),
741                     sock->type == SILC_SOCKET_TYPE_SERVER ?
742                     "Server" : "Router", sock->hostname));
743     
744     /* As a router we keep information of all global information in our global
745        list. Cell wide information however is kept in the local list. */
746     silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
747
748     if (sock->type == SILC_SOCKET_TYPE_SERVER)
749       server->stat.cell_servers++;
750     server->stat.servers++;
751
752 #if 0
753     /* Add route cache for this ID */
754     silc_server_route_add(silc_server_route_hash(
755                           ((SilcServerID *)id)->ip.s_addr,
756                           ((SilcServerID *)id)->port), 
757                           ((SilcServerID *)id)->ip.s_addr,
758                           router);
759 #endif
760     break;
761
762   case SILC_ID_CHANNEL:
763     SILC_LOG_ERROR(("Channel cannot be registered with NEW_ID packet"));
764     break;
765
766   default:
767     break;
768   }
769
770  out:
771   silc_id_payload_free(idp);
772 }
773
774 /* Received Remove Channel User packet to remove a user from a channel. 
775    Routers notify other routers that user has left a channel. Client must
776    not send this packet. Normal server may send this packet but must not
777    receive it. */
778
779 void silc_server_remove_channel_user(SilcServer server,
780                                      SilcSocketConnection sock,
781                                      SilcPacketContext *packet)
782 {
783   SilcBuffer buffer = packet->buffer;
784   unsigned char *tmp1 = NULL, *tmp2 = NULL;
785   unsigned int tmp1_len, tmp2_len;
786   SilcClientID *client_id = NULL;
787   SilcChannelID *channel_id = NULL;
788   SilcChannelEntry channel;
789   SilcClientEntry client;
790   int ret;
791
792   SILC_LOG_DEBUG(("Removing user from channel"));
793
794   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
795       server->server_type == SILC_SERVER)
796     return;
797
798   ret = silc_buffer_unformat(buffer,
799                              SILC_STR_UI16_NSTRING_ALLOC(&tmp1, &tmp1_len),
800                              SILC_STR_UI16_NSTRING_ALLOC(&tmp2, &tmp2_len),
801                              SILC_STR_END);
802   if (ret == -1)
803     goto out;
804
805   client_id = silc_id_str2id(tmp1, tmp1_len, SILC_ID_CLIENT);
806   channel_id = silc_id_str2id(tmp2, tmp2_len, SILC_ID_CHANNEL);
807   if (!client_id || !channel_id)
808     goto out;
809
810   /* If we are router and this packet is not already broadcast packet
811      we will broadcast it. The sending socket really cannot be router or
812      the router is buggy. If this packet is coming from router then it must
813      have the broadcast flag set already and we won't do anything. */
814   if (!server->standalone && server->server_type == SILC_ROUTER &&
815       sock->type == SILC_SOCKET_TYPE_SERVER &&
816       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
817     SILC_LOG_DEBUG(("Broadcasting received Remove Channel User packet"));
818     silc_server_packet_send(server, server->router->connection, packet->type,
819                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
820                             buffer->data, buffer->len, FALSE);
821   }
822
823   /* Get channel entry */
824   channel = silc_idlist_find_channel_by_id(server->local_list, 
825                                            channel_id, NULL);
826   if (!channel) {
827     channel = silc_idlist_find_channel_by_id(server->global_list, 
828                                              channel_id, NULL);
829     if (!channel)
830       goto out;
831   }
832
833   /* Get client entry */
834   client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
835   if (!client) {
836     client = silc_idlist_find_client_by_id(server->global_list, 
837                                            client_id, NULL);
838     if (!client)
839       goto out;
840   }
841
842   /* Remove user from channel */
843   silc_server_remove_from_one_channel(server, sock, channel, client, TRUE);
844
845  out:
846   if (tmp1)
847     silc_free(tmp1);
848   if (tmp2)
849     silc_free(tmp2);
850   if (client_id)
851     silc_free(client_id);
852   if (channel_id)
853     silc_free(channel_id);
854 }
855
856 /* Received New Channel packet. Information about new channels in the 
857    network are distributed using this packet. Save the information about
858    the new channel. */
859
860 void silc_server_new_channel(SilcServer server,
861                              SilcSocketConnection sock,
862                              SilcPacketContext *packet)
863 {
864   unsigned char *id;
865   SilcChannelID *channel_id;
866   unsigned short channel_id_len;
867   char *channel_name;
868   int ret;
869
870   SILC_LOG_DEBUG(("Processing New Channel"));
871
872   if (sock->type != SILC_SOCKET_TYPE_ROUTER ||
873       server->server_type == SILC_SERVER ||
874       packet->src_id_type != SILC_ID_SERVER)
875     return;
876
877   /* Parse payload */
878   ret = silc_buffer_unformat(packet->buffer, 
879                              SILC_STR_UI16_STRING_ALLOC(&channel_name),
880                              SILC_STR_UI16_NSTRING_ALLOC(&id, &channel_id_len),
881                              SILC_STR_END);
882   if (ret == -1) {
883     if (channel_name)
884       silc_free(channel_name);
885     if (id)
886       silc_free(id);
887     return;
888   }
889     
890   /* Decode the channel ID */
891   channel_id = silc_id_str2id(id, channel_id_len, SILC_ID_CHANNEL);
892   if (!channel_id)
893     return;
894   silc_free(id);
895
896   SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
897                   silc_id_render(channel_id, SILC_ID_CHANNEL), 
898                   sock->hostname));
899
900   /* Add the new channel. Add it always to global list since if we receive
901      this packet then it cannot be created by ourselves but some other 
902      router hence global channel. */
903   silc_idlist_add_channel(server->global_list, channel_name, 0, channel_id, 
904                           server->router->connection, NULL);
905
906   server->stat.channels++;
907 }
908
909 /* Received notify packet. Server can receive notify packets from router. 
910    Server then relays the notify messages to clients if needed. */
911
912 void silc_server_notify(SilcServer server,
913                         SilcSocketConnection sock,
914                         SilcPacketContext *packet)
915 {
916   SilcNotifyPayload payload;
917   SilcNotifyType type;
918   SilcArgumentPayload args;
919   SilcChannelID *channel_id;
920   SilcClientID *client_id, *client_id2;
921   SilcChannelEntry channel;
922   SilcClientEntry client;
923   unsigned char *tmp;
924   unsigned int tmp_len;
925
926   SILC_LOG_DEBUG(("Start"));
927
928   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
929       packet->src_id_type != SILC_ID_SERVER)
930     return;
931
932   /* XXX: For now we expect that the we are normal server and that the
933      sender is router. Server could send (protocol allows it) notify to
934      router but we don't support it yet. */
935   if (server->server_type != SILC_SERVER &&
936       sock->type != SILC_SOCKET_TYPE_ROUTER)
937     return;
938
939   payload = silc_notify_payload_parse(packet->buffer);
940   if (!payload)
941     return;
942
943   type = silc_notify_get_type(payload);
944   args = silc_notify_get_args(payload);
945   if (!args)
946     goto out;
947
948   switch(type) {
949   case SILC_NOTIFY_TYPE_JOIN:
950     /* 
951      * Distribute the notify to local clients on the channel
952      */
953     SILC_LOG_DEBUG(("JOIN notify"));
954
955     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
956                                 packet->dst_id_type);
957     if (!channel_id)
958       goto out;
959
960     /* Get channel entry */
961     channel = silc_idlist_find_channel_by_id(server->local_list, 
962                                              channel_id, NULL);
963     if (!channel) {
964       silc_free(channel_id);
965       goto out;
966     }
967
968     /* Get client ID */
969     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
970     if (!tmp) {
971       silc_free(channel_id);
972       goto out;
973     }
974     client_id = silc_id_payload_parse_id(tmp, tmp_len);
975     if (!client_id) {
976       silc_free(channel_id);
977       goto out;
978     }
979
980     /* Send to channel */
981     silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
982                                        FALSE, packet->buffer->data, 
983                                        packet->buffer->len, FALSE);
984
985     /* If the the client is not in local list we check global list (ie. the
986        channel will be global channel) and if it does not exist then create
987        entry for the client. */
988     client = silc_idlist_find_client_by_id(server->local_list, 
989                                            client_id, NULL);
990     if (!client) {
991       SilcChannelClientEntry chl;
992
993       client = silc_idlist_find_client_by_id(server->global_list, 
994                                              client_id, NULL);
995       if (!client) {
996         client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
997                                         client_id, sock->user_data, sock);
998         if (!client) {
999           silc_free(channel_id);
1000           silc_free(client_id);
1001           goto out;
1002         }
1003       }
1004
1005       /* The channel is global now */
1006       channel->global_users = TRUE;
1007
1008       /* Now actually JOIN the global client to the channel */
1009       chl = silc_calloc(1, sizeof(*chl));
1010       chl->client = client;
1011       chl->channel = channel;
1012       silc_list_add(channel->user_list, chl);
1013       silc_list_add(client->channels, chl);
1014     } else {
1015       silc_free(client_id);
1016     }
1017     break;
1018
1019   case SILC_NOTIFY_TYPE_LEAVE:
1020     /* 
1021      * Distribute the notify to local clients on the channel
1022      */
1023     SILC_LOG_DEBUG(("LEAVE notify"));
1024
1025     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1026                                 packet->dst_id_type);
1027     if (!channel_id)
1028       goto out;
1029
1030     /* Get channel entry */
1031     channel = silc_idlist_find_channel_by_id(server->local_list, 
1032                                              channel_id, NULL);
1033     if (!channel) { 
1034       silc_free(channel_id);
1035       goto out;
1036     }
1037
1038     /* Get client ID */
1039     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1040     if (!tmp) {
1041       silc_free(channel_id);
1042       goto out;
1043     }
1044     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1045     if (!client_id) {
1046       silc_free(channel_id);
1047       goto out;
1048     }
1049
1050     /* Send to channel */
1051     silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
1052                                        FALSE, packet->buffer->data, 
1053                                        packet->buffer->len, FALSE);
1054
1055     /* Get client entry */
1056     client = silc_idlist_find_client_by_id(server->global_list, 
1057                                            client_id, NULL);
1058     if (!client) {
1059       client = silc_idlist_find_client_by_id(server->local_list, 
1060                                              client_id, NULL);
1061       if (!client) {
1062         silc_free(client_id);
1063         silc_free(channel_id);
1064         goto out;
1065       }
1066     }
1067     silc_free(client_id);
1068
1069     /* Remove the user from channel */
1070     silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
1071     break;
1072
1073   case SILC_NOTIFY_TYPE_SIGNOFF:
1074     /* 
1075      * Distribute the notify to local clients on the channel
1076      */
1077     SILC_LOG_DEBUG(("SIGNOFF notify"));
1078
1079     /* Get client ID */
1080     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1081     if (!tmp)
1082       goto out;
1083     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1084     if (!client_id)
1085       goto out;
1086
1087     /* Get client entry */
1088     client = silc_idlist_find_client_by_id(server->global_list, 
1089                                            client_id, NULL);
1090     if (!client) {
1091       client = silc_idlist_find_client_by_id(server->local_list, 
1092                                              client_id, NULL);
1093       if (!client) {
1094         silc_free(client_id);
1095         goto out;
1096       }
1097     }
1098     silc_free(client_id);
1099
1100     /* Remove the client from all channels */
1101     silc_server_remove_from_channels(server, NULL, client);
1102
1103     /* Remove the client entry */
1104     silc_idlist_del_client(server->global_list, client);
1105     break;
1106
1107   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1108     {
1109       /* 
1110        * Distribute the notify to local clients on the channel
1111        */
1112       unsigned char *id, *id2;
1113
1114       SILC_LOG_DEBUG(("NICK CHANGE notify"));
1115       
1116       /* Get old client ID */
1117       id = silc_argument_get_arg_type(args, 1, &tmp_len);
1118       if (!id)
1119         goto out;
1120       client_id = silc_id_payload_parse_id(id, tmp_len);
1121       if (!client_id)
1122         goto out;
1123       
1124       /* Get new client ID */
1125       id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
1126       if (!id2)
1127         goto out;
1128       client_id2 = silc_id_payload_parse_id(id2, tmp_len);
1129       if (!client_id2)
1130         goto out;
1131       
1132       SILC_LOG_DEBUG(("Old Client ID id(%s)", 
1133                       silc_id_render(client_id, SILC_ID_CLIENT)));
1134       SILC_LOG_DEBUG(("New Client ID id(%s)", 
1135                       silc_id_render(client_id2, SILC_ID_CLIENT)));
1136
1137       /* Replace the Client ID */
1138       client = silc_idlist_replace_client_id(server->global_list, client_id,
1139                                              client_id2);
1140       if (!client)
1141         client = silc_idlist_replace_client_id(server->local_list, client_id, 
1142                                                client_id2);
1143
1144       if (client)
1145         /* Send the NICK_CHANGE notify type to local clients on the channels
1146            this client is joined to. */
1147         silc_server_send_notify_on_channels(server, client, 
1148                                             SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1149                                             id, tmp_len, 
1150                                             id2, tmp_len);
1151
1152       silc_free(client_id);
1153       if (!client)
1154         silc_free(client_id2);
1155       break;
1156     }
1157   case SILC_NOTIFY_TYPE_TOPIC_SET:
1158     /* 
1159      * Distribute the notify to local clients on the channel
1160      */
1161     SILC_LOG_DEBUG(("TOPIC SET notify (not-impl XXX)"));
1162     break;
1163
1164   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1165     /* 
1166      * Distribute the notify to local clients on the channel
1167      */
1168     SILC_LOG_DEBUG(("CMODE CHANGE notify (not-impl XXX)"));
1169     break;
1170
1171   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1172     /* 
1173      * Distribute the notify to local clients on the channel
1174      */
1175     SILC_LOG_DEBUG(("CUMODE CHANGE notify (not-impl XXX)"));
1176     break;
1177
1178     /* Ignore rest notify types for now */
1179   case SILC_NOTIFY_TYPE_NONE:
1180   case SILC_NOTIFY_TYPE_INVITE:
1181   case SILC_NOTIFY_TYPE_MOTD:
1182   default:
1183     break;
1184   }
1185
1186  out:
1187   silc_notify_payload_free(payload);
1188 }
1189
1190 /* Received new channel user packet. Information about new users on a
1191    channel are distributed between routers using this packet.  The
1192    router receiving this will redistribute it and also sent JOIN notify
1193    to local clients on the same channel. Normal server sends JOIN notify
1194    to its local clients on the channel. */
1195
1196 void silc_server_new_channel_user(SilcServer server,
1197                                   SilcSocketConnection sock,
1198                                   SilcPacketContext *packet)
1199 {
1200   unsigned char *tmpid1, *tmpid2;
1201   SilcClientID *client_id = NULL;
1202   SilcChannelID *channel_id = NULL;
1203   unsigned short channel_id_len;
1204   unsigned short client_id_len;
1205   SilcClientEntry client;
1206   SilcChannelEntry channel;
1207   SilcChannelClientEntry chl;
1208   SilcBuffer clidp;
1209   int ret;
1210
1211   SILC_LOG_DEBUG(("Start"));
1212
1213   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
1214       server->server_type != SILC_ROUTER ||
1215       packet->src_id_type != SILC_ID_SERVER)
1216     return;
1217
1218   /* Parse payload */
1219   ret = silc_buffer_unformat(packet->buffer, 
1220                              SILC_STR_UI16_NSTRING_ALLOC(&tmpid1, 
1221                                                          &channel_id_len),
1222                              SILC_STR_UI16_NSTRING_ALLOC(&tmpid2, 
1223                                                          &client_id_len),
1224                              SILC_STR_END);
1225   if (ret == -1) {
1226     if (tmpid1)
1227       silc_free(tmpid1);
1228     if (tmpid2)
1229       silc_free(tmpid2);
1230     return;
1231   }
1232
1233   /* Decode the channel ID */
1234   channel_id = silc_id_str2id(tmpid1, channel_id_len, SILC_ID_CHANNEL);
1235   if (!channel_id)
1236     goto out;
1237
1238   /* Decode the client ID */
1239   client_id = silc_id_str2id(tmpid2, client_id_len, SILC_ID_CLIENT);
1240   if (!client_id)
1241     goto out;
1242
1243   /* Find the channel */
1244   channel = silc_idlist_find_channel_by_id(server->local_list, 
1245                                            channel_id, NULL);
1246   if (!channel) {
1247     channel = silc_idlist_find_channel_by_id(server->global_list, 
1248                                              channel_id, NULL);
1249     if (!channel)
1250       goto out;
1251   }
1252
1253   /* If we are router and this packet is not already broadcast packet
1254      we will broadcast it. */
1255   if (!server->standalone && server->server_type == SILC_ROUTER &&
1256       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
1257     SILC_LOG_DEBUG(("Broadcasting received New Channel User packet"));
1258     silc_server_packet_send(server, server->router->connection, packet->type,
1259                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
1260                             packet->buffer->data, packet->buffer->len, FALSE);
1261   }
1262
1263   /* Get client entry */
1264   client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
1265   if (!client) {
1266     client = silc_idlist_find_client_by_id(server->global_list, 
1267                                            client_id, NULL);
1268     if (!client)
1269       goto out;
1270   }
1271
1272   /* Join the client to the channel by adding it to channel's user list.
1273      Add also the channel to client entry's channels list for fast cross-
1274      referencing. */
1275   chl = silc_calloc(1, sizeof(*chl));
1276   chl->client = client;
1277   chl->channel = channel;
1278   silc_list_add(channel->user_list, chl);
1279   silc_list_add(client->channels, chl);
1280
1281   server->stat.chanclients++;
1282
1283   /* Send JOIN notify to local clients on the channel. As we are router
1284      it is assured that this is sent only to our local clients and locally
1285      connected servers if needed. */
1286   clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1287   silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1288                                      SILC_NOTIFY_TYPE_JOIN, 
1289                                      1, clidp->data, clidp->len);
1290   silc_buffer_free(clidp);
1291
1292   client_id = NULL;
1293
1294  out:
1295   if (client_id)
1296     silc_free(client_id);
1297   if (channel_id)
1298     silc_free(channel_id);
1299   silc_free(tmpid1);
1300   silc_free(tmpid2);
1301 }
1302
1303 /* Processes incoming REMOVE_ID packet. The packet is used to notify routers
1304    that certain ID should be removed. After that the ID will become invalid. */
1305
1306 void silc_server_remove_id(SilcServer server,
1307                            SilcSocketConnection sock,
1308                            SilcPacketContext *packet)
1309 {
1310   SilcIDList id_list;
1311   SilcIDPayload idp;
1312   SilcIdType id_type;
1313   void *id, *id_entry;
1314
1315   SILC_LOG_DEBUG(("Start"));
1316
1317   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
1318       server->server_type == SILC_SERVER ||
1319       packet->src_id_type != SILC_ID_SERVER)
1320     return;
1321
1322   idp = silc_id_payload_parse(packet->buffer);
1323   if (!idp)
1324     return;
1325
1326   id_type = silc_id_payload_get_type(idp);
1327
1328   id = silc_id_payload_get_id(idp);
1329   if (!id)
1330     goto out;
1331
1332   /* If the sender of this packet is server and we are router we need to
1333      broadcast this packet to other routers in the network. */
1334   if (!server->standalone && server->server_type == SILC_ROUTER &&
1335       sock->type == SILC_SOCKET_TYPE_SERVER &&
1336       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
1337     SILC_LOG_DEBUG(("Broadcasting received Remove ID packet"));
1338     silc_server_packet_send(server, server->router->connection,
1339                             packet->type, 
1340                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
1341                             packet->buffer->data, packet->buffer->len, FALSE);
1342   }
1343
1344   if (sock->type == SILC_SOCKET_TYPE_SERVER)
1345     id_list = server->local_list;
1346   else
1347     id_list = server->global_list;
1348
1349   /* Remove the ID */
1350   switch (id_type) {
1351   case SILC_ID_CLIENT:
1352     id_entry = silc_idlist_find_client_by_id(id_list, (SilcClientID *)id, 
1353                                              NULL);
1354     if (id_entry) {
1355       /* Remove from channels */
1356       silc_server_remove_from_channels(server, NULL, id_entry);
1357
1358       /* Remove the client entry */
1359       silc_idlist_del_client(id_list, (SilcClientEntry)id_entry);
1360       server->stat.clients--;
1361
1362       SILC_LOG_DEBUG(("Removed client id(%s) from [%s] %s",
1363                       silc_id_render(id, SILC_ID_CLIENT),
1364                       sock->type == SILC_SOCKET_TYPE_SERVER ?
1365                       "Server" : "Router", sock->hostname));
1366     }
1367     break;
1368
1369   case SILC_ID_SERVER:
1370     id_entry = silc_idlist_find_server_by_id(id_list, (SilcServerID *)id,
1371                                              NULL);
1372     if (id_entry) {
1373       silc_idlist_del_server(id_list, (SilcServerEntry)id_entry);
1374       server->stat.servers--;
1375
1376       SILC_LOG_DEBUG(("Removed server id(%s) from [%s] %s",
1377                       silc_id_render(id, SILC_ID_SERVER),
1378                       sock->type == SILC_SOCKET_TYPE_SERVER ?
1379                       "Server" : "Router", sock->hostname));
1380     }
1381     break;
1382
1383   case SILC_ID_CHANNEL:
1384     id_entry = silc_idlist_find_channel_by_id(id_list, (SilcChannelID *)id,
1385                                               NULL);
1386     if (id_entry) {
1387       silc_idlist_del_channel(id_list, (SilcChannelEntry)id_entry);
1388       server->stat.channels--;
1389
1390       SILC_LOG_DEBUG(("Removed channel id(%s) from [%s] %s",
1391                       silc_id_render(id, SILC_ID_CHANNEL),
1392                       sock->type == SILC_SOCKET_TYPE_SERVER ?
1393                       "Server" : "Router", sock->hostname));
1394     }
1395     break;
1396
1397   default:
1398     break;
1399   }
1400
1401  out:
1402   silc_id_payload_free(idp);
1403 }
1404
1405 /* Processes received SET_MODE packet. The packet is used to distribute
1406    the information about changed channel's or client's channel modes. */
1407
1408 void silc_server_set_mode(SilcServer server,
1409                           SilcSocketConnection sock,
1410                           SilcPacketContext *packet)
1411 {
1412   SilcSetModePayload payload = NULL;
1413   SilcArgumentPayload args = NULL;
1414   unsigned short mode_type;
1415   unsigned int mode_mask;
1416   unsigned char *tmp, *tmp2;
1417   unsigned int tmp_len, tmp_len2;
1418   unsigned char mode[4];
1419   SilcClientID *client_id;
1420   SilcChannelID *channel_id = NULL;
1421   SilcClientEntry client;
1422   SilcChannelEntry channel;
1423   SilcChannelClientEntry chl;
1424
1425   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
1426       packet->src_id_type == SILC_ID_CLIENT)
1427     return;
1428
1429   SILC_LOG_DEBUG(("Start"));
1430
1431   /* If we are router and this packet is not already broadcast packet
1432      we will broadcast it. The sending socket really cannot be router or
1433      the router is buggy. If this packet is coming from router then it must
1434      have the broadcast flag set already and we won't do anything. */
1435   if (!server->standalone && server->server_type == SILC_ROUTER &&
1436       sock->type == SILC_SOCKET_TYPE_SERVER &&
1437       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
1438     SILC_LOG_DEBUG(("Broadcasting received Set Mode packet"));
1439     silc_server_packet_send(server, server->router->connection, packet->type,
1440                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
1441                             packet->buffer->data, packet->buffer->len, FALSE);
1442   }
1443
1444   /* Parse Set Mode payload */
1445   payload = silc_set_mode_payload_parse(packet->buffer);
1446   if (!payload)
1447     return;
1448
1449   mode_type = silc_set_mode_get_type(payload);
1450   args = silc_set_mode_get_args(payload);
1451   if (!args)
1452     goto out;
1453
1454   mode_mask = silc_set_mode_get_mode(payload);
1455   SILC_PUT32_MSB(mode_mask, mode);
1456
1457   switch (mode_type) {
1458   case SILC_MODE_TYPE_CHANNEL:
1459     /* Get Channel ID */
1460     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1461     if (!tmp)
1462       goto out;
1463     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1464     if (!channel_id)
1465       goto out;
1466
1467     /* Get channel entry */
1468     channel = silc_idlist_find_channel_by_id(server->local_list, 
1469                                              channel_id, NULL);
1470     if (!channel) {
1471       channel = silc_idlist_find_channel_by_id(server->global_list, 
1472                                                channel_id, NULL);
1473       if (!channel)
1474         goto out;
1475     }
1476
1477     /* Get Client ID payload */
1478     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1479     if (!tmp)
1480       goto out;
1481
1482     /* Send CMODE_CHANGE notify to local channel */
1483     silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1484                                        SILC_NOTIFY_TYPE_CMODE_CHANGE, 
1485                                        2, tmp, tmp_len,
1486                                        mode, sizeof(mode));
1487
1488     /* Change the mode */
1489     channel->mode = mode_mask;
1490     break;
1491
1492   case SILC_MODE_TYPE_UCHANNEL:
1493     /* Get Channel ID */
1494     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1495     if (!tmp)
1496       goto out;
1497     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1498     if (!channel_id)
1499       goto out;
1500
1501     /* Get channel entry */
1502     channel = silc_idlist_find_channel_by_id(server->local_list, 
1503                                              channel_id, NULL);
1504     if (!channel) {
1505       channel = silc_idlist_find_channel_by_id(server->global_list, 
1506                                                channel_id, NULL);
1507       if (!channel)
1508         goto out;
1509     }
1510
1511     /* Get Client ID payload */
1512     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1513     if (!tmp)
1514       goto out;
1515
1516     /* Get target Client ID */
1517     tmp2 = silc_argument_get_arg_type(args, 3, &tmp_len2);
1518     if (!tmp2)
1519       goto out;
1520     client_id = silc_id_payload_parse_id(tmp2, tmp_len2);
1521     if (!client_id)
1522       goto out;
1523
1524     /* Get target client entry */
1525     client = silc_idlist_find_client_by_id(server->global_list, 
1526                                            client_id, NULL);
1527     if (!client) {
1528       client = silc_idlist_find_client_by_id(server->local_list, 
1529                                              client_id, NULL);
1530       if (!client) {
1531         silc_free(client_id);
1532         goto out;
1533       }
1534     }
1535     silc_free(client_id);
1536
1537     /* Send CUMODE_CHANGE notify to local channel */
1538     silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1539                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 2, 
1540                                        tmp, tmp_len,
1541                                        mode, sizeof(mode),
1542                                        tmp2, tmp_len2);
1543
1544     /* Get entry to the channel user list */
1545     silc_list_start(channel->user_list);
1546     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1547       if (chl->client == client) {
1548         /* Change the mode */
1549         chl->mode = mode_mask;
1550         break;
1551       }
1552
1553     break;
1554
1555   default:
1556     break;
1557   }
1558
1559  out:
1560   if (channel_id)
1561     silc_free(channel_id);
1562   if (args)
1563     silc_argument_payload_free(args);
1564   if (payload)
1565     silc_set_mode_payload_free(payload);
1566 }