757f5177a17d0e812a64f01521870d0cc3ddf256
[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 = SILC_SWAB_16(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 = SILC_SWAB_16(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             SILC_LOG_INFO(("Sending RESUMED to %s",
1058                            server_entry->server_name));
1059
1060             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1061
1062             /* This connection is performing this protocol too now */
1063             ((SilcSocketConnection)server_entry->connection)->protocol =
1064               protocol;
1065
1066             if (server_entry->server_type == SILC_ROUTER)
1067               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1068             else
1069               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1070             silc_server_packet_send(server, server_entry->connection,
1071                                     SILC_PACKET_RESUME_ROUTER, 0, 
1072                                     packet->data, packet->len, FALSE);
1073
1074             if (!silc_idcache_list_next(list, &id_cache))
1075               break;
1076           }
1077         }
1078
1079         silc_idcache_list_free(list);
1080       }
1081
1082       if (silc_idcache_get_all(server->global_list->servers, &list)) {
1083         if (silc_idcache_list_first(list, &id_cache)) {
1084           while (id_cache) {
1085             server_entry = (SilcServerEntry)id_cache->context;
1086             if (!server_entry || (server_entry == server->id_entry) || 
1087                 !server_entry->connection || !server_entry->data.send_key) {
1088               if (!silc_idcache_list_next(list, &id_cache))
1089                 break;
1090               else
1091                 continue;
1092             }
1093
1094             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1095                             server_entry->server_name));
1096             SILC_LOG_INFO(("Sending RESUMED to %s",
1097                            server_entry->server_name));
1098
1099             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1100
1101             /* This connection is performing this protocol too now */
1102             ((SilcSocketConnection)server_entry->connection)->protocol =
1103               protocol;
1104
1105             if (server_entry->server_type == SILC_ROUTER)
1106               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1107             else
1108               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1109             silc_server_packet_send(server, server_entry->connection,
1110                                     SILC_PACKET_RESUME_ROUTER, 0, 
1111                                     packet->data, packet->len, FALSE);
1112
1113             if (!silc_idcache_list_next(list, &id_cache))
1114               break;
1115           }
1116         }
1117
1118         silc_idcache_list_free(list);
1119       }
1120
1121       silc_buffer_free(packet);
1122
1123       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1124       server->wait_backup = FALSE;
1125
1126       /* For us this is the end of this protocol. */
1127       if (protocol->final_callback)
1128         silc_protocol_execute_final(protocol, server->schedule);
1129       else
1130         silc_protocol_free(protocol);
1131     }
1132     break;
1133
1134   case SILC_PROTOCOL_STATE_END:
1135     {
1136       SilcServerEntry router, backup_router;
1137
1138       /* We should have been received RESUMED packet from our primary
1139          router. */
1140       if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1141           ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1142         SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1143         break;
1144       }
1145
1146       SILC_LOG_INFO(("Received RESUMED from new primary router"));
1147
1148       if (server->backup_router)
1149         server->server_type = SILC_BACKUP_ROUTER;
1150
1151       /* We have now new primary router. All traffic goes there from now on. */
1152       router = (SilcServerEntry)ctx->sock->user_data;
1153       if (silc_server_backup_replaced_get(server, router->id, 
1154                                           &backup_router)) {
1155
1156         if (backup_router == server->router) {
1157           /* We have new primary router now */
1158           server->id_entry->router = router;
1159           server->router = router;
1160           SILC_LOG_INFO(("Switching back to primary router %s",
1161                          server->router->server_name));
1162         } else {
1163           /* We are connected to new primary and now continue using it */
1164           SILC_LOG_INFO(("Resuming the use of primary router %s",
1165                          router->server_name));
1166         }
1167         server->backup_primary = FALSE;
1168
1169         /* Update the client entries of the backup router to the new 
1170            router */
1171         silc_server_local_servers_toggle_enabled(server, FALSE);
1172         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1173         silc_server_update_servers_by_server(server, backup_router, router);
1174         silc_server_update_clients_by_server(server, NULL, router, FALSE);
1175         if (server->server_type == SILC_SERVER)
1176           silc_server_update_channels_by_server(server, backup_router, router);
1177         silc_server_backup_replaced_del(server, backup_router);
1178
1179         /* Announce all of our information to the router. */
1180         if (server->server_type == SILC_ROUTER)
1181           silc_server_announce_servers(server, FALSE, ctx->start,
1182                                        router->connection);
1183
1184         /* Announce our clients and channels to the router */
1185         silc_server_announce_clients(server, ctx->start,
1186                                      router->connection);
1187         silc_server_announce_channels(server, ctx->start,
1188                                       router->connection);
1189       }
1190
1191       /* Send notify about primary router going down to local operators */
1192       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1193                              SILC_NOTIFY_TYPE_NONE,
1194                              ("%s resumed the use of primary router %s",
1195                               server->server_name,
1196                               server->router->server_name));
1197
1198       /* Protocol has ended, call the final callback */
1199       if (protocol->final_callback)
1200         silc_protocol_execute_final(protocol, server->schedule);
1201       else
1202         silc_protocol_free(protocol);
1203     }
1204     break;
1205
1206   case SILC_PROTOCOL_STATE_ERROR:
1207     /* Protocol has ended, call the final callback */
1208     if (protocol->final_callback)
1209       silc_protocol_execute_final(protocol, server->schedule);
1210     else
1211       silc_protocol_free(protocol);
1212     break;
1213
1214   case SILC_PROTOCOL_STATE_FAILURE:
1215     /* Protocol has ended, call the final callback */
1216     SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1217     if (protocol->final_callback)
1218       silc_protocol_execute_final(protocol, server->schedule);
1219     else
1220       silc_protocol_free(protocol);
1221     break;
1222
1223   case SILC_PROTOCOL_STATE_UNKNOWN:
1224     break;
1225   }
1226 }
1227
1228 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1229 {
1230   SilcProtocol protocol = (SilcProtocol)context;
1231   SilcServerBackupProtocolContext ctx = protocol->context;
1232   SilcServer server = ctx->server;
1233   SilcServerEntry server_entry;
1234   SilcSocketConnection sock;
1235   SilcIDCacheList list;
1236   SilcIDCacheEntry id_cache;
1237
1238   silc_schedule_task_del_by_context(server->schedule, protocol);
1239
1240   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1241       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1242     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1243   }
1244
1245   if (server->server_shutdown)
1246     return;
1247
1248   /* Remove this protocol from all server entries that has it */
1249   if (silc_idcache_get_all(server->local_list->servers, &list)) {
1250     if (silc_idcache_list_first(list, &id_cache)) {
1251       while (id_cache) {
1252         server_entry = (SilcServerEntry)id_cache->context;
1253         sock = (SilcSocketConnection)server_entry->connection;
1254
1255         if (sock->protocol == protocol) {
1256           sock->protocol = NULL;
1257
1258           /* Backup closes connection and reconnects if error occurred */
1259           if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1260             if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1261                 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1262               server->backup_noswitch = TRUE;
1263               server->server_type = SILC_BACKUP_ROUTER;
1264               if (ctx->sock == sock)
1265                 ctx->sock = NULL;
1266
1267               if (sock->user_data)
1268                 silc_server_free_sock_user_data(server, sock, NULL);
1269               silc_server_close_connection(server, sock);
1270               silc_server_create_connections(server);
1271
1272               if (!silc_idcache_list_next(list, &id_cache))
1273                 break;
1274               continue;
1275             }
1276           }
1277
1278           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1279             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1280         }
1281         
1282         if (!silc_idcache_list_next(list, &id_cache))
1283           break;
1284       }
1285     }
1286     silc_idcache_list_free(list);
1287   }
1288
1289   if (silc_idcache_get_all(server->global_list->servers, &list)) {
1290     if (silc_idcache_list_first(list, &id_cache)) {
1291       while (id_cache) {
1292         server_entry = (SilcServerEntry)id_cache->context;
1293         sock = (SilcSocketConnection)server_entry->connection;
1294
1295         if (sock->protocol == protocol) {
1296           sock->protocol = NULL;
1297
1298           /* Backup closes connection and reconnects if error occurred */
1299           if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1300             if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1301                 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1302               server->backup_noswitch = TRUE;
1303               server->server_type = SILC_BACKUP_ROUTER;
1304               if (ctx->sock == sock)
1305                 ctx->sock = NULL;
1306
1307               if (sock->user_data)
1308                 silc_server_free_sock_user_data(server, sock, NULL);
1309               silc_server_close_connection(server, sock);
1310               silc_server_create_connections(server);
1311
1312               if (!silc_idcache_list_next(list, &id_cache))
1313                 break;
1314               continue;
1315             }
1316           }
1317
1318           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1319             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1320         }
1321         
1322         if (!silc_idcache_list_next(list, &id_cache))
1323           break;
1324       }
1325     }
1326     silc_idcache_list_free(list);
1327   }
1328
1329   if (protocol->state != SILC_PROTOCOL_STATE_ERROR &&
1330       protocol->state != SILC_PROTOCOL_STATE_FAILURE)
1331     SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
1332
1333   if (ctx->sock && ctx->sock->protocol)
1334     ctx->sock->protocol = NULL;
1335   silc_protocol_free(protocol);
1336   silc_free(ctx->sessions);
1337   silc_free(ctx);
1338 }