Added support for removing unconfigured client connections in
[silc.git] / apps / silcd / server_backup.c
1 /*
2
3   server_backup.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 2002 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; version 2 of the License.
12
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.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
25 static void silc_server_backup_connect_primary(SilcServer server,
26                                                SilcServerEntry server_entry,
27                                                void *context);
28
29 /* Backup router */
30 typedef struct {
31   SilcServerEntry server;
32   SilcIDIP ip;
33   SilcUInt16 port;
34   bool local;
35 } SilcServerBackupEntry;
36
37 /* Holds IP address and port of the primary router that was replaced
38    by backup router. */
39 typedef struct {
40   SilcIDIP ip;
41   SilcUInt16 port;
42   SilcServerEntry server;       /* Backup router that replaced the primary */
43 } SilcServerBackupReplaced;
44
45 /* Backup context */
46 struct SilcServerBackupStruct {
47   SilcServerBackupEntry *servers;
48   SilcUInt32 servers_count;
49   SilcServerBackupReplaced **replaced;
50   SilcUInt32 replaced_count;
51 };
52
53 typedef struct {
54   SilcUInt8 session;
55   bool connected;
56   SilcServerEntry server_entry;
57 } SilcServerBackupProtocolSession;
58
59 /* Backup resuming protocol context  */
60 typedef struct {
61   SilcServer server;
62   SilcSocketConnection sock;
63   bool responder;
64   SilcUInt8 type;
65   SilcUInt8 session;
66   SilcServerBackupProtocolSession *sessions;
67   SilcUInt32 sessions_count;
68   long start;
69 } *SilcServerBackupProtocolContext;
70
71 /* Adds the `backup_server' to be one of our backup router. This can be
72    called multiple times to set multiple backup routers. The `ip' and `port'
73    is the IP and port that the `backup_router' will replace if the `ip'
74    will become unresponsive. If `local' is TRUE then the `backup_server' is
75    in the local cell, if FALSE it is in some other cell. */
76
77 void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
78                             const char *ip, int port, bool local)
79 {
80   int i;
81
82   if (!ip)
83     return;
84
85   if (!server->backup) {
86     server->backup = silc_calloc(1, sizeof(*server->backup));
87     if (!server->backup)
88       return;
89   }
90
91   SILC_LOG_DEBUG(("Backup router %s will replace %s",
92                   ((SilcSocketConnection)backup_server->connection)->ip,
93                   ip, port));
94
95   for (i = 0; i < server->backup->servers_count; i++) {
96     if (!server->backup->servers[i].server) {
97       server->backup->servers[i].server = backup_server;
98       server->backup->servers[i].local = local;
99       memset(server->backup->servers[i].ip.data, 0,
100              sizeof(server->backup->servers[i].ip.data));
101       silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
102                         sizeof(server->backup->servers[i].ip.data));
103       return;
104     }
105   }
106
107   i = server->backup->servers_count;
108   server->backup->servers = silc_realloc(server->backup->servers,
109                                          sizeof(*server->backup->servers) *
110                                          (i + 1));
111   server->backup->servers[i].server = backup_server;
112   server->backup->servers[i].local = local;
113   memset(server->backup->servers[i].ip.data, 0,
114          sizeof(server->backup->servers[i].ip.data));
115   silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
116                     sizeof(server->backup->servers[i].ip.data));
117   server->backup->servers_count++;
118 }
119
120 /* Returns backup router for IP and port in `replacing' or NULL if there
121    does not exist backup router. */
122
123 SilcServerEntry silc_server_backup_get(SilcServer server, 
124                                        SilcServerID *server_id)
125 {
126   int i;
127
128   if (!server->backup)
129     return NULL;
130
131   for (i = 0; i < server->backup->servers_count; i++) {
132     if (server->backup->servers[i].server &&
133         !memcmp(&server->backup->servers[i].ip, &server_id->ip.data,
134                 sizeof(server_id->ip.data))) {
135       SILC_LOG_DEBUG(("Found backup router %s for %s",
136                       server->backup->servers[i].server->server_name,
137                       silc_id_render(server_id, SILC_ID_SERVER)));
138       return server->backup->servers[i].server;
139     }
140   }
141
142   return NULL;
143 }
144
145 /* Deletes the backup server `server_entry'. */
146
147 void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry)
148 {
149   int i;
150
151   if (!server->backup)
152     return;
153
154   for (i = 0; i < server->backup->servers_count; i++) {
155     if (server->backup->servers[i].server == server_entry) {
156       SILC_LOG_DEBUG(("Removing %s as backup router",
157                       silc_id_render(server->backup->servers[i].server->id,
158                                      SILC_ID_SERVER)));
159       server->backup->servers[i].server = NULL;
160       memset(server->backup->servers[i].ip.data, 0,
161              sizeof(server->backup->servers[i].ip.data));
162     }
163   }
164 }
165
166 /* Frees all data allocated for backup routers.  Call this after deleting
167    all backup routers and when new routers are added no more, for example
168    when shutting down the server. */
169
170 void silc_server_backup_free(SilcServer server)
171 {
172   int i;
173
174   if (!server->backup)
175     return;
176
177   /* Delete existing servers if caller didn't do it */
178   for (i = 0; i < server->backup->servers_count; i++) {
179     if (server->backup->servers[i].server)
180       silc_server_backup_del(server, server->backup->servers[i].server);
181   }
182
183   silc_free(server->backup->servers);
184   silc_free(server->backup);
185   server->backup = NULL;
186 }
187
188 /* Marks the IP address and port from the `server_id' as  being replaced
189    by backup router indicated by the `server'. If the router connects at
190    a later time we can check whether it has been replaced by an backup
191    router. */
192
193 void silc_server_backup_replaced_add(SilcServer server, 
194                                      SilcServerID *server_id,
195                                      SilcServerEntry server_entry)
196 {
197   int i;
198   SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
199
200   if (!server->backup)
201     server->backup = silc_calloc(1, sizeof(*server->backup));
202   if (!server->backup->replaced) {
203     server->backup->replaced = 
204       silc_calloc(1, sizeof(*server->backup->replaced));
205     server->backup->replaced_count = 1;
206   }
207
208   SILC_LOG_DEBUG(("Replacing router %s with %s",
209                   silc_id_render(server_id, SILC_ID_SERVER),
210                   server_entry->server_name));
211
212   memcpy(&r->ip, &server_id->ip, sizeof(server_id->ip));
213   r->server = server_entry;
214
215   for (i = 0; i < server->backup->replaced_count; i++) {
216     if (!server->backup->replaced[i]) {
217       server->backup->replaced[i] = r;
218       return;
219     }
220   }
221
222   i = server->backup->replaced_count;
223   server->backup->replaced = silc_realloc(server->backup->replaced,
224                                           sizeof(*server->backup->replaced) *
225                                           (i + 1));
226   server->backup->replaced[i] = r;
227   server->backup->replaced_count++;
228 }
229
230 /* Checks whether the IP address and port from the `server_id' has been
231    replaced by an backup router. If it has been then this returns TRUE
232    and the bacup router entry to the `server' pointer if non-NULL. Returns
233    FALSE if the router is not replaced by backup router. */
234
235 bool silc_server_backup_replaced_get(SilcServer server,
236                                      SilcServerID *server_id,
237                                      SilcServerEntry *server_entry)
238 {
239   int i;
240
241   if (!server->backup || !server->backup->replaced)
242     return FALSE;
243
244   for (i = 0; i < server->backup->replaced_count; i++) {
245     if (!server->backup->replaced[i])
246       continue;
247     if (!memcmp(&server->backup->replaced[i]->ip, &server_id->ip.data,
248                 sizeof(server_id->ip.data))) {
249       if (server_entry)
250         *server_entry = server->backup->replaced[i]->server;
251       SILC_LOG_DEBUG(("Router %s is replaced by %s",
252                       silc_id_render(server_id, SILC_ID_SERVER),
253                       server->backup->replaced[i]->server->server_name));
254       return TRUE;
255     }
256   }
257
258   SILC_LOG_DEBUG(("Router %s is not replaced by backup router",
259                   silc_id_render(server_id, SILC_ID_SERVER)));
260   return FALSE;
261 }
262
263 /* Deletes a replaced host by the set `server_entry. */
264
265 void silc_server_backup_replaced_del(SilcServer server,
266                                      SilcServerEntry server_entry)
267 {
268   int i;
269
270   if (!server->backup || !server->backup->replaced)
271     return;
272
273   for (i = 0; i < server->backup->replaced_count; i++) {
274     if (!server->backup->replaced[i])
275       continue;
276     if (server->backup->replaced[i]->server == server_entry) {
277       silc_free(server->backup->replaced[i]);
278       server->backup->replaced[i] = NULL;
279       return;
280     }
281   }
282 }
283
284 /* Broadcast the received packet indicated by `packet' to all of our backup 
285    routers. All router wide information is passed using broadcast packets. 
286    That is why all backup routers need to get this data too. It is expected
287    that the caller already knows that the `packet' is broadcast packet. */
288
289 void silc_server_backup_broadcast(SilcServer server, 
290                                   SilcSocketConnection sender,
291                                   SilcPacketContext *packet)
292 {
293   SilcServerEntry backup;
294   SilcSocketConnection sock;
295   SilcBuffer buffer;
296   const SilcBufferStruct p;
297   SilcIDListData idata;
298   int i;
299
300   if (!server->backup || server->server_type != SILC_ROUTER)
301     return;
302
303   SILC_LOG_DEBUG(("Broadcasting received packet to backup routers"));
304
305   buffer = packet->buffer;
306   silc_buffer_push(buffer, buffer->data - buffer->head);
307
308   for (i = 0; i < server->backup->servers_count; i++) {
309     backup = server->backup->servers[i].server;
310
311     if (!backup || backup->connection == sender || 
312         server->backup->servers[i].local == FALSE)
313       continue;
314     if (server->backup->servers[i].server == server->id_entry)
315       continue;
316
317     idata = (SilcIDListData)backup;
318     sock = backup->connection;
319
320     if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
321                                   (const SilcBuffer)&p)) {
322       SILC_LOG_ERROR(("Cannot send packet"));
323       return;
324     }
325     silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
326     silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, 
327                         (SilcBuffer)&p, p.len);
328
329     SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len);
330
331     /* Now actually send the packet */
332     silc_server_packet_send_real(server, sock, FALSE);
333   }
334 }
335
336 /* A generic routine to send data to all backup routers. If the `sender'
337    is provided it will indicate the original sender of the packet and the
338    packet won't be resent to that entity. The `data' is the data that will
339    be assembled to packet context before sending. The packet will be
340    encrypted this function. If the `force_send' is TRUE the data is sent
341    immediately and not put to queue. If `local' is TRUE then the packet
342    will be sent only to local backup routers inside the cell. If false the
343    packet can go from one cell to the other. This function has no effect
344    if there are no any backup routers. */
345
346 void silc_server_backup_send(SilcServer server,
347                              SilcServerEntry sender,
348                              SilcPacketType type,
349                              SilcPacketFlags flags,
350                              unsigned char *data,
351                              SilcUInt32 data_len,
352                              bool force_send,
353                              bool local)
354 {
355   SilcServerEntry backup;
356   SilcSocketConnection sock;
357   int i;
358
359   if (!server->backup || server->server_type != SILC_ROUTER)
360     return;
361
362   for (i = 0; i < server->backup->servers_count; i++) {
363     backup = server->backup->servers[i].server;
364     if (!backup || sender == backup)
365       continue;
366     if (local && server->backup->servers[i].local == FALSE)
367       continue;
368     if (server->backup->servers[i].server == server->id_entry)
369       continue;
370
371     sock = backup->connection;
372
373     SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
374                     silc_get_packet_name(type), sock->hostname, sock->ip));
375
376     silc_server_packet_send(server, backup->connection, type, flags, 
377                             data, data_len, force_send);
378   }
379 }
380
381 /* Same as silc_server_backup_send but sets a specific Destination ID to
382    the packet. The Destination ID is indicated by the `dst_id' and the
383    ID type `dst_id_type'. For example, packets destined to channels must
384    be sent using this function. */
385
386 void silc_server_backup_send_dest(SilcServer server,
387                                   SilcServerEntry sender,
388                                   SilcPacketType type,
389                                   SilcPacketFlags flags,
390                                   void *dst_id,
391                                   SilcIdType dst_id_type,
392                                   unsigned char *data,
393                                   SilcUInt32 data_len,
394                                   bool force_send,
395                                   bool local)
396 {
397   SilcServerEntry backup;
398   SilcSocketConnection sock;
399   int i;
400
401   if (!server->backup || server->server_type != SILC_ROUTER)
402     return;
403
404   for (i = 0; i < server->backup->servers_count; i++) {
405     backup = server->backup->servers[i].server;
406     if (!backup || sender == backup)
407       continue;
408     if (local && server->backup->servers[i].local == FALSE)
409       continue;
410     if (server->backup->servers[i].server == server->id_entry)
411       continue;
412
413     sock = backup->connection;
414
415     SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)",
416                     silc_get_packet_name(type), sock->hostname, sock->ip));
417
418     silc_server_packet_send_dest(server, backup->connection, type, flags, 
419                                  dst_id, dst_id_type, data, data_len, 
420                                  force_send);
421   }
422 }
423
424 /* Processes incoming RESUME_ROUTER packet. This can give the packet
425    for processing to the protocol handler or allocate new protocol if
426    start command is received. */
427
428 void silc_server_backup_resume_router(SilcServer server, 
429                                       SilcSocketConnection sock, 
430                                       SilcPacketContext *packet)
431 {
432   SilcUInt8 type, session;
433   SilcServerBackupProtocolContext ctx;
434   int i, ret;
435
436   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
437       sock->type == SILC_SOCKET_TYPE_UNKNOWN) {
438     SILC_LOG_DEBUG(("Bad packet received"));
439     return;
440   }
441
442   ret = silc_buffer_unformat(packet->buffer,
443                              SILC_STR_UI_CHAR(&type),
444                              SILC_STR_UI_CHAR(&session),
445                              SILC_STR_END);
446   if (ret < 0) {
447     SILC_LOG_DEBUG(("Malformed packet received"));
448     return;
449   }
450   
451   /* Activate the protocol for this socket if necessary */
452   if ((type == SILC_SERVER_BACKUP_RESUMED || 
453       type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
454       sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol && 
455       ((SilcIDListData)sock->user_data)->status & 
456       SILC_IDLIST_STATUS_DISABLED) {
457     SilcServerEntry backup_router;
458
459     if (silc_server_backup_replaced_get(server, 
460                                         ((SilcServerEntry)sock->
461                                          user_data)->id, 
462                                         &backup_router)) {
463       SilcSocketConnection bsock = 
464         (SilcSocketConnection)backup_router->connection;
465       if (bsock->protocol && bsock->protocol->protocol &&
466           bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
467         sock->protocol = bsock->protocol;
468         ctx = sock->protocol->context;
469         ctx->sock = sock;
470       }
471     }
472   }
473
474   /* If the backup resuming protocol is active then process the packet
475      in the protocol. */
476   if (sock->protocol && sock->protocol->protocol &&
477       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
478     ctx = sock->protocol->context;
479     ctx->type = type;
480
481     if (type != SILC_SERVER_BACKUP_RESUMED &&
482         type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
483       for (i = 0; i < ctx->sessions_count; i++) {
484         if (session == ctx->sessions[i].session) {
485           ctx->session = session;
486           silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
487           return;
488         }
489       }
490     } else {
491       silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
492       return;
493     }
494
495     SILC_LOG_DEBUG(("Bad resume router packet"));
496     return;
497   }
498
499   /* We don't have protocol active. If we are router and the packet is 
500      coming from our primary router then lets check whether it means we've
501      been replaced by an backup router in my cell. This is usually received
502      immediately after we've connected to our primary router. */
503
504   if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
505       sock && SILC_PRIMARY_ROUTE(server) == sock &&
506       type == SILC_SERVER_BACKUP_REPLACED) {
507     /* We have been replaced by an backup router in our cell. We must
508        mark our primary router connection disabled since we are not allowed
509        to use it at this moment. */
510     SilcIDListData idata = (SilcIDListData)sock->user_data;
511     SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
512                    "wait until backup resuming protocol is executed"));
513     idata->status |= SILC_IDLIST_STATUS_DISABLED;
514     return;
515   }
516
517   if (type == SILC_SERVER_BACKUP_START ||
518       type == SILC_SERVER_BACKUP_START_GLOBAL) {
519     /* We have received a start for resuming protocol. */
520     SilcServerBackupProtocolContext proto_ctx;
521
522     proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
523     proto_ctx->server = server;
524     proto_ctx->sock = sock;
525     proto_ctx->responder = TRUE;
526     proto_ctx->type = type;
527     proto_ctx->session = session;
528     proto_ctx->start = time(0);
529
530     SILC_LOG_DEBUG(("Starting backup resuming protocol as responder"));
531
532     /* Run the backup resuming protocol */
533     silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
534                         &sock->protocol, proto_ctx, 
535                         silc_server_protocol_backup_done);
536     silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
537   }
538 }
539
540 /* Timeout task callback to connect to remote router */
541
542 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
543 {
544   SilcServer server = app_context;
545   SilcServerConnection sconn = (SilcServerConnection)context;
546   int sock;
547   const char *server_ip;
548
549   SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
550                   sconn->remote_port));
551
552   /* Connect to remote host */
553   server_ip = server->config->server_info->primary == NULL ? NULL :
554     server->config->server_info->primary->server_ip;
555   sock = silc_net_create_connection(server_ip, sconn->remote_port,
556                                     sconn->remote_host);
557   if (sock < 0) {
558     silc_schedule_task_add(server->schedule, 0,
559                            silc_server_backup_connect_to_router,
560                            context, 5, 0, SILC_TASK_TIMEOUT, 
561                            SILC_TASK_PRI_NORMAL);
562     return;
563   }
564
565   /* Continue with key exchange protocol */
566   silc_server_start_key_exchange(server, sconn, sock);
567 }
568
569 /* Constantly tries to reconnect to a primary router indicated by the
570    `ip' and `port'. The `connected' callback will be called when the
571    connection is created. */
572
573 void silc_server_backup_reconnect(SilcServer server,
574                                   const char *ip, SilcUInt16 port,
575                                   SilcServerConnectRouterCallback callback,
576                                   void *context)
577 {
578   SilcServerConnection sconn;
579
580   sconn = silc_calloc(1, sizeof(*sconn));
581   sconn->remote_host = strdup(ip);
582   sconn->remote_port = port;
583   sconn->callback = callback;
584   sconn->callback_context = context;
585   sconn->no_reconnect = TRUE;
586   silc_schedule_task_add(server->schedule, 0, 
587                          silc_server_backup_connect_to_router,
588                          sconn, 1, 0, SILC_TASK_TIMEOUT,
589                          SILC_TASK_PRI_NORMAL);
590 }
591
592 /* Task that is called after backup router has connected back to
593    primary router and we are starting the resuming protocol */
594
595 SILC_TASK_CALLBACK(silc_server_backup_connected_later)
596 {
597   SilcServerBackupProtocolContext proto_ctx = 
598     (SilcServerBackupProtocolContext)context;
599   SilcServer server = proto_ctx->server;
600   SilcSocketConnection sock = proto_ctx->sock;
601
602   SILC_LOG_DEBUG(("Starting backup resuming protocol as initiator"));
603
604   /* Run the backup resuming protocol */
605   silc_protocol_alloc(SILC_PROTOCOL_SERVER_BACKUP,
606                       &sock->protocol, proto_ctx, 
607                       silc_server_protocol_backup_done);
608   silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
609 }
610
611 /* Called when we've established connection back to our primary router
612    when we've acting as backup router and have replaced the primary router
613    in the cell. This function will start the backup resuming protocol. */
614
615 void silc_server_backup_connected(SilcServer server,
616                                   SilcServerEntry server_entry,
617                                   void *context)
618 {
619   SilcServerBackupProtocolContext proto_ctx;
620   SilcSocketConnection sock;
621
622   if (!server_entry) {
623     /* Try again */
624     SilcServerConfigRouter *primary;
625     primary = silc_server_config_get_primary_router(server);
626     if (primary)
627       silc_server_backup_reconnect(server,
628                                    primary->host, primary->port,
629                                    silc_server_backup_connected,
630                                    context);
631     return;
632   }
633
634   sock = (SilcSocketConnection)server_entry->connection;
635   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
636   proto_ctx->server = server;
637   proto_ctx->sock = sock;
638   proto_ctx->responder = FALSE;
639   proto_ctx->type = SILC_SERVER_BACKUP_START;
640   proto_ctx->start = time(0);
641
642   /* Start through scheduler */
643   silc_schedule_task_add(server->schedule, 0,
644                          silc_server_backup_connected_later,
645                          proto_ctx, 0, 1,
646                          SILC_TASK_TIMEOUT,
647                          SILC_TASK_PRI_NORMAL);
648 }
649
650 /* Called when normal server has connected to its primary router after
651    backup router has sent the START packet in reusming protocol. We will
652    move the protocol context from the backup router connection to the
653    primary router. */
654
655 static void silc_server_backup_connect_primary(SilcServer server,
656                                                SilcServerEntry server_entry,
657                                                void *context)
658 {
659   SilcSocketConnection backup_router = (SilcSocketConnection)context;
660   SilcServerBackupProtocolContext ctx;
661   SilcSocketConnection sock;
662   SilcIDListData idata;
663   SilcBuffer buffer;
664
665   if (!server_entry) {
666     /* Try again */
667     SilcServerConfigRouter *primary;
668     primary = silc_server_config_get_primary_router(server);
669     if (primary)
670       silc_server_backup_reconnect(server,
671                                    primary->host, primary->port,
672                                    silc_server_backup_connect_primary,
673                                    context);
674     return;
675   }
676
677   ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
678   sock = (SilcSocketConnection)server_entry->connection;
679   idata = (SilcIDListData)server_entry;
680
681   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
682
683   /* Send the CONNECTED packet back to the backup router. */
684   buffer = silc_buffer_alloc(2);
685   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
686   silc_buffer_format(buffer,
687                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
688                      SILC_STR_UI_CHAR(ctx->session),
689                      SILC_STR_END);
690   silc_server_packet_send(server, backup_router, 
691                           SILC_PACKET_RESUME_ROUTER, 0, 
692                           buffer->data, buffer->len, FALSE);
693   silc_buffer_free(buffer);
694
695   /* The primary connection is disabled until it sends the RESUMED packet
696      to us. */
697   idata->status |= SILC_IDLIST_STATUS_DISABLED;
698
699   /* Move this protocol context from this backup router connection to
700      the primary router connection since it will send the subsequent
701      packets in this protocol. We don't talk with backup router 
702      anymore. */
703   sock->protocol = backup_router->protocol;
704   ctx->sock = (SilcSocketConnection)server_entry->connection;
705   backup_router->protocol = NULL;
706 }
707
708 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
709 {
710   SilcProtocol protocol = (SilcProtocol)context;
711   SilcServerBackupProtocolContext ctx = protocol->context;
712   SilcServer server = ctx->server;
713   SilcBuffer packet;
714   int i;
715
716   for (i = 0; i < ctx->sessions_count; i++)
717     if (ctx->sessions[i].server_entry == ctx->sock->user_data)
718       ctx->session = ctx->sessions[i].session;
719   
720   /* We've received all the CONNECTED packets and now we'll send the
721      ENDING packet to the new primary router. */
722   packet = silc_buffer_alloc(2);
723   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
724   silc_buffer_format(packet,
725                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
726                      SILC_STR_UI_CHAR(ctx->session),
727                      SILC_STR_END);
728   silc_server_packet_send(server, ctx->sock, 
729                           SILC_PACKET_RESUME_ROUTER, 0, 
730                           packet->data, packet->len, FALSE);
731   silc_buffer_free(packet);
732   
733   protocol->state = SILC_PROTOCOL_STATE_END;
734 }
735
736 /* Backup resuming protocol. This protocol is executed when the primary
737    router wants to resume its position as being primary router. */
738
739 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
740 {
741   SilcProtocol protocol = (SilcProtocol)context;
742   SilcServerBackupProtocolContext ctx = protocol->context;
743   SilcServer server = ctx->server;
744   SilcBuffer packet;
745   SilcIDCacheList list;
746   SilcIDCacheEntry id_cache;
747   SilcServerEntry server_entry;
748   int i;
749
750   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
751     protocol->state = SILC_PROTOCOL_STATE_START;
752
753   switch(protocol->state) {
754   case SILC_PROTOCOL_STATE_START:
755     if (ctx->responder == FALSE) {
756       /* Initiator of the protocol. We are backup router */
757
758       packet = silc_buffer_alloc(2);
759       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
760
761       /* Send the START packet to primary router and normal servers. */
762       if (silc_idcache_get_all(server->local_list->servers, &list)) {
763         if (silc_idcache_list_first(list, &id_cache)) {
764           while (id_cache) {
765             server_entry = (SilcServerEntry)id_cache->context;
766             if (!server_entry || (server_entry == server->id_entry) || 
767                 !server_entry->connection || !server_entry->data.send_key ||
768                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
769               if (!silc_idcache_list_next(list, &id_cache))
770                 break;
771               else
772                 continue;
773             }
774
775             ctx->sessions = silc_realloc(ctx->sessions,
776                                          sizeof(*ctx->sessions) *
777                                          (ctx->sessions_count + 1));
778             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
779             ctx->sessions[ctx->sessions_count].connected = FALSE;
780             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
781
782             SILC_LOG_DEBUG(("Sending START to %s (session %d)", 
783                             server_entry->server_name, ctx->sessions_count));
784
785             /* This connection is performing this protocol too now */
786             ((SilcSocketConnection)server_entry->connection)->protocol =
787               protocol;
788
789             if (server_entry->server_type == SILC_ROUTER)
790               packet->data[0] = SILC_SERVER_BACKUP_START;
791             else
792               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
793             packet->data[1] = ctx->sessions_count;
794             silc_server_packet_send(server, server_entry->connection,
795                                     SILC_PACKET_RESUME_ROUTER, 0, 
796                                     packet->data, packet->len, FALSE);
797             ctx->sessions_count++;
798
799             if (!silc_idcache_list_next(list, &id_cache))
800               break;
801           }
802         }
803
804         silc_idcache_list_free(list);
805       }
806
807       if (silc_idcache_get_all(server->global_list->servers, &list)) {
808         if (silc_idcache_list_first(list, &id_cache)) {
809           while (id_cache) {
810             server_entry = (SilcServerEntry)id_cache->context;
811             if (!server_entry || (server_entry == server->id_entry) || 
812                 !server_entry->connection || !server_entry->data.send_key ||
813                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
814               if (!silc_idcache_list_next(list, &id_cache))
815                 break;
816               else
817                 continue;
818             }
819
820             ctx->sessions = silc_realloc(ctx->sessions,
821                                          sizeof(*ctx->sessions) *
822                                          (ctx->sessions_count + 1));
823             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
824             ctx->sessions[ctx->sessions_count].connected = FALSE;
825             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
826
827             SILC_LOG_DEBUG(("Sending START to %s (session %d)", 
828                             server_entry->server_name, ctx->sessions_count));
829
830             /* This connection is performing this protocol too now */
831             ((SilcSocketConnection)server_entry->connection)->protocol =
832               protocol;
833
834             if (server_entry->server_type == SILC_ROUTER)
835               packet->data[0] = SILC_SERVER_BACKUP_START;
836             else
837               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
838             packet->data[1] = ctx->sessions_count;
839             silc_server_packet_send(server, server_entry->connection,
840                                     SILC_PACKET_RESUME_ROUTER, 0, 
841                                     packet->data, packet->len, FALSE);
842             ctx->sessions_count++;
843
844             if (!silc_idcache_list_next(list, &id_cache))
845               break;
846           }
847         }
848
849         silc_idcache_list_free(list);
850       }
851
852       silc_buffer_free(packet);
853
854       /* If we are not standalone and our primary is not the one we've
855          talking to now, then announce our information to it since we
856          haven't done that yet.  Standalone backup router announces
857          these during connecting to the primary. */
858       if (!server->standalone && SILC_PRIMARY_ROUTE(server) != ctx->sock) {
859         silc_server_announce_servers(server, TRUE, 0, ctx->sock);
860         silc_server_announce_clients(server, 0, ctx->sock);
861         silc_server_announce_channels(server, 0, ctx->sock);
862       }
863
864       protocol->state++;
865     } else {
866       /* Responder of the protocol. */
867       SilcServerConfigRouter *primary;
868
869       /* We should have received START or START_GLOBAL packet */
870       if (ctx->type != SILC_SERVER_BACKUP_START &&
871           ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
872         SILC_LOG_DEBUG(("Bad resume router packet"));
873         break;
874       }
875
876       /* Connect to the primary router that was down that is now supposed
877          to be back online. We send the CONNECTED packet after we've
878          established the connection to the primary router. */
879       primary = silc_server_config_get_primary_router(server);
880       if (primary && server->backup_primary) {
881         SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
882                         ctx->session));
883         silc_server_backup_reconnect(server,
884                                      primary->host, primary->port,
885                                      silc_server_backup_connect_primary,
886                                      ctx->sock);
887       } else {
888         /* Nowhere to connect just return the CONNECTED packet */
889         SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
890                         ctx->session));
891
892         /* Send the CONNECTED packet back to the backup router. */
893         packet = silc_buffer_alloc(2);
894         silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
895         silc_buffer_format(packet,
896                            SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
897                            SILC_STR_UI_CHAR(ctx->session),
898                            SILC_STR_END);
899         silc_server_packet_send(server, ctx->sock, 
900                                 SILC_PACKET_RESUME_ROUTER, 0, 
901                                 packet->data, packet->len, FALSE);
902         silc_buffer_free(packet);
903       }
904
905       if (server->server_type == SILC_ROUTER &&
906           (!server->router || 
907            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
908         protocol->state++;
909       else
910         protocol->state = SILC_PROTOCOL_STATE_END;
911
912       ctx->sessions = silc_realloc(ctx->sessions,
913                                    sizeof(*ctx->sessions) *
914                                    (ctx->sessions_count + 1));
915       ctx->sessions[ctx->sessions_count].session = ctx->session;
916       ctx->sessions_count++;
917     }
918     break;
919
920   case 2:
921     if (ctx->responder == FALSE) {
922       /* Initiator */
923
924       /* We should have received CONNECTED packet */
925       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
926         SILC_LOG_DEBUG(("Bad resume router packet"));
927         break;
928       }
929
930       SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
931
932       for (i = 0; i < ctx->sessions_count; i++) {
933         if (ctx->sessions[i].session == ctx->session) {
934           ctx->sessions[i].connected = TRUE;
935           break;
936         }
937       }
938
939       for (i = 0; i < ctx->sessions_count; i++) {
940         if (!ctx->sessions[i].connected)
941           return;
942       }
943
944       SILC_LOG_DEBUG(("All sessions has returned CONNECTED packets"));
945       SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
946
947       /* Send with a timeout */
948       silc_schedule_task_add(server->schedule, 0, 
949                              silc_server_backup_send_resumed,
950                              protocol, 1, 0, SILC_TASK_TIMEOUT,
951                              SILC_TASK_PRI_NORMAL);
952       return;
953     } else {
954       /* Responder */
955
956       /* We should have been received ENDING packet */
957       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
958         SILC_LOG_DEBUG(("Bad resume router packet"));
959         break;
960       }
961
962       SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
963
964       /* This state is received by the primary router but also servers
965          and perhaps other routers so check that if we are the primary
966          router of the cell then start sending RESUMED packets.  If we
967          are normal server or one of those other routers then procede
968          to next state. */
969       if (server->router &&
970           !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
971           silc_server_config_is_primary_route(server)) {
972         /* We'll wait for RESUMED packet */
973         protocol->state = SILC_PROTOCOL_STATE_END;
974         break;
975       }
976
977       /* Switch announced informations to our primary router of using the
978          backup router. */
979       silc_server_local_servers_toggle_enabled(server, TRUE);
980       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
981                                            server->router);
982       silc_server_update_clients_by_server(server, ctx->sock->user_data,
983                                            server->router, TRUE);
984       if (server->server_type == SILC_SERVER)
985         silc_server_update_channels_by_server(server, ctx->sock->user_data, 
986                                               server->router);
987
988       packet = silc_buffer_alloc(2);
989       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
990
991       /* We are the primary router, start sending RESUMED packets. */
992       if (silc_idcache_get_all(server->local_list->servers, &list)) {
993         if (silc_idcache_list_first(list, &id_cache)) {
994           while (id_cache) {
995             server_entry = (SilcServerEntry)id_cache->context;
996             if (!server_entry || (server_entry == server->id_entry) || 
997                 !server_entry->connection || !server_entry->data.send_key) {
998               if (!silc_idcache_list_next(list, &id_cache))
999                 break;
1000               else
1001                 continue;
1002             }
1003
1004             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1005                             server_entry->server_name));
1006
1007             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1008
1009             /* This connection is performing this protocol too now */
1010             ((SilcSocketConnection)server_entry->connection)->protocol =
1011               protocol;
1012
1013             if (server_entry->server_type == SILC_ROUTER)
1014               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1015             else
1016               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1017             silc_server_packet_send(server, server_entry->connection,
1018                                     SILC_PACKET_RESUME_ROUTER, 0, 
1019                                     packet->data, packet->len, FALSE);
1020
1021             if (!silc_idcache_list_next(list, &id_cache))
1022               break;
1023           }
1024         }
1025
1026         silc_idcache_list_free(list);
1027       }
1028
1029       if (silc_idcache_get_all(server->global_list->servers, &list)) {
1030         if (silc_idcache_list_first(list, &id_cache)) {
1031           while (id_cache) {
1032             server_entry = (SilcServerEntry)id_cache->context;
1033             if (!server_entry || (server_entry == server->id_entry) || 
1034                 !server_entry->connection || !server_entry->data.send_key) {
1035               if (!silc_idcache_list_next(list, &id_cache))
1036                 break;
1037               else
1038                 continue;
1039             }
1040
1041             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1042                             server_entry->server_name));
1043
1044             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1045
1046             /* This connection is performing this protocol too now */
1047             ((SilcSocketConnection)server_entry->connection)->protocol =
1048               protocol;
1049
1050             if (server_entry->server_type == SILC_ROUTER)
1051               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1052             else
1053               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1054             silc_server_packet_send(server, server_entry->connection,
1055                                     SILC_PACKET_RESUME_ROUTER, 0, 
1056                                     packet->data, packet->len, FALSE);
1057
1058             if (!silc_idcache_list_next(list, &id_cache))
1059               break;
1060           }
1061         }
1062
1063         silc_idcache_list_free(list);
1064       }
1065
1066       silc_buffer_free(packet);
1067
1068       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1069       server->wait_backup = FALSE;
1070
1071       /* For us this is the end of this protocol. */
1072       if (protocol->final_callback)
1073         silc_protocol_execute_final(protocol, server->schedule);
1074       else
1075         silc_protocol_free(protocol);
1076     }
1077     break;
1078
1079   case SILC_PROTOCOL_STATE_END:
1080     {
1081       SilcServerEntry router, backup_router;
1082
1083       /* We should have been received RESUMED packet from our primary
1084          router. */
1085       if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1086           ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1087         SILC_LOG_DEBUG(("Bad resume router packet"));
1088         break;
1089       }
1090
1091       SILC_LOG_DEBUG(("Received RESUMED from new primary router"));
1092
1093       if (server->backup_router)
1094         server->server_type = SILC_BACKUP_ROUTER;
1095
1096       /* We have now new primary router. All traffic goes there from now on. */
1097       router = (SilcServerEntry)ctx->sock->user_data;
1098       if (silc_server_backup_replaced_get(server, router->id, 
1099                                           &backup_router)) {
1100
1101         if (backup_router == server->router) {
1102           /* We have new primary router now */
1103           server->id_entry->router = router;
1104           server->router = router;
1105           SILC_LOG_INFO(("Switching back to primary router %s",
1106                          server->router->server_name));
1107         } else {
1108           /* We are connected to new primary and now continue using it */
1109           SILC_LOG_INFO(("Resuming the use of primary router %s",
1110                          router->server_name));
1111         }
1112
1113         /* Update the client entries of the backup router to the new 
1114            router */
1115         silc_server_local_servers_toggle_enabled(server, FALSE);
1116         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1117         silc_server_update_servers_by_server(server, backup_router, router);
1118         silc_server_update_clients_by_server(server, NULL, router, FALSE);
1119         if (server->server_type == SILC_SERVER)
1120           silc_server_update_channels_by_server(server, backup_router, router);
1121         silc_server_backup_replaced_del(server, backup_router);
1122
1123         /* Announce all of our information to the router. */
1124         if (server->server_type == SILC_ROUTER)
1125           silc_server_announce_servers(server, FALSE, ctx->start,
1126                                        router->connection);
1127
1128         /* Announce our clients and channels to the router */
1129         silc_server_announce_clients(server, ctx->start,
1130                                      router->connection);
1131         silc_server_announce_channels(server, ctx->start,
1132                                       router->connection);
1133       }
1134
1135       /* Send notify about primary router going down to local operators */
1136       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1137                              SILC_NOTIFY_TYPE_NONE,
1138                              ("%s resumed the use of primary router %s",
1139                               server->server_name,
1140                               server->router->server_name));
1141
1142       /* Protocol has ended, call the final callback */
1143       if (protocol->final_callback)
1144         silc_protocol_execute_final(protocol, server->schedule);
1145       else
1146         silc_protocol_free(protocol);
1147     }
1148     break;
1149
1150   case SILC_PROTOCOL_STATE_ERROR:
1151     /* Protocol has ended, call the final callback */
1152     if (protocol->final_callback)
1153       silc_protocol_execute_final(protocol, server->schedule);
1154     else
1155       silc_protocol_free(protocol);
1156     break;
1157
1158   case SILC_PROTOCOL_STATE_FAILURE:
1159     /* Protocol has ended, call the final callback */
1160     if (protocol->final_callback)
1161       silc_protocol_execute_final(protocol, server->schedule);
1162     else
1163       silc_protocol_free(protocol);
1164     break;
1165
1166   case SILC_PROTOCOL_STATE_UNKNOWN:
1167     break;
1168   }
1169 }
1170
1171 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1172 {
1173   SilcProtocol protocol = (SilcProtocol)context;
1174   SilcServerBackupProtocolContext ctx = protocol->context;
1175   SilcServer server = ctx->server;
1176   SilcServerEntry server_entry;
1177   SilcSocketConnection sock;
1178   SilcIDCacheList list;
1179   SilcIDCacheEntry id_cache;
1180
1181   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1182       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1183     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1184   }
1185
1186   /* Remove this protocol from all server entries that has it */
1187   if (silc_idcache_get_all(server->local_list->servers, &list)) {
1188     if (silc_idcache_list_first(list, &id_cache)) {
1189       while (id_cache) {
1190         server_entry = (SilcServerEntry)id_cache->context;
1191         sock = (SilcSocketConnection)server_entry->connection;
1192
1193         if (sock->protocol == protocol) {
1194           sock->protocol = NULL;
1195
1196           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1197             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1198         }
1199         
1200         if (!silc_idcache_list_next(list, &id_cache))
1201           break;
1202       }
1203     }
1204     silc_idcache_list_free(list);
1205   }
1206
1207   if (silc_idcache_get_all(server->global_list->servers, &list)) {
1208     if (silc_idcache_list_first(list, &id_cache)) {
1209       while (id_cache) {
1210         server_entry = (SilcServerEntry)id_cache->context;
1211         sock = (SilcSocketConnection)server_entry->connection;
1212
1213         if (sock->protocol == protocol) {
1214           sock->protocol = NULL;
1215
1216           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1217             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1218         }
1219         
1220         if (!silc_idcache_list_next(list, &id_cache))
1221           break;
1222       }
1223     }
1224     silc_idcache_list_free(list);
1225   }
1226
1227   SILC_LOG_DEBUG(("Backup resuming protocol has ended"));
1228
1229   if (ctx->sock->protocol)
1230     ctx->sock->protocol = NULL;
1231   silc_protocol_free(protocol);
1232   silc_free(ctx->sessions);
1233   silc_free(ctx);
1234 }