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