548875f057d64781562673384faa561ee156f4e4
[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
716   /* Send the CONNECTED packet back to the backup router. */
717   buffer = silc_buffer_alloc(2);
718   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
719   silc_buffer_format(buffer,
720                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
721                      SILC_STR_UI_CHAR(ctx->session),
722                      SILC_STR_END);
723   silc_server_packet_send(server, backup_router, 
724                           SILC_PACKET_RESUME_ROUTER, 0, 
725                           buffer->data, buffer->len, FALSE);
726   silc_buffer_free(buffer);
727
728   /* The primary connection is disabled until it sends the RESUMED packet
729      to us. */
730   idata->status |= SILC_IDLIST_STATUS_DISABLED;
731
732   /* Move this protocol context from this backup router connection to
733      the primary router connection since it will send the subsequent
734      packets in this protocol. We don't talk with backup router 
735      anymore. */
736   sock->protocol = backup_router->protocol;
737   ctx->sock = (SilcSocketConnection)server_entry->connection;
738   backup_router->protocol = NULL;
739 }
740
741 SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
742 {
743   SilcProtocol protocol = (SilcProtocol)context;
744   SilcServerBackupProtocolContext ctx = protocol->context;
745   SilcServer server = ctx->server;
746   SilcBuffer packet;
747   int i;
748
749   for (i = 0; i < ctx->sessions_count; i++)
750     if (ctx->sessions[i].server_entry == ctx->sock->user_data)
751       ctx->session = ctx->sessions[i].session;
752   
753   /* We've received all the CONNECTED packets and now we'll send the
754      ENDING packet to the new primary router. */
755   packet = silc_buffer_alloc(2);
756   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
757   silc_buffer_format(packet,
758                      SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
759                      SILC_STR_UI_CHAR(ctx->session),
760                      SILC_STR_END);
761   silc_server_packet_send(server, ctx->sock, 
762                           SILC_PACKET_RESUME_ROUTER, 0, 
763                           packet->data, packet->len, FALSE);
764   silc_buffer_free(packet);
765   
766   protocol->state = SILC_PROTOCOL_STATE_END;
767 }
768
769 /* Backup resuming protocol. This protocol is executed when the primary
770    router wants to resume its position as being primary router. */
771
772 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
773 {
774   SilcProtocol protocol = (SilcProtocol)context;
775   SilcServerBackupProtocolContext ctx = protocol->context;
776   SilcServer server = ctx->server;
777   SilcBuffer packet;
778   SilcIDCacheList list;
779   SilcIDCacheEntry id_cache;
780   SilcServerEntry server_entry;
781   int i;
782
783   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
784     protocol->state = SILC_PROTOCOL_STATE_START;
785
786   switch(protocol->state) {
787   case SILC_PROTOCOL_STATE_START:
788     if (ctx->responder == FALSE) {
789       /* Initiator of the protocol. We are backup router */
790
791       packet = silc_buffer_alloc(2);
792       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
793
794       /* Send the START packet to primary router and normal servers. */
795       if (silc_idcache_get_all(server->local_list->servers, &list)) {
796         if (silc_idcache_list_first(list, &id_cache)) {
797           while (id_cache) {
798             server_entry = (SilcServerEntry)id_cache->context;
799             if (!server_entry || (server_entry == server->id_entry) || 
800                 !server_entry->connection || !server_entry->data.send_key ||
801                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
802               if (!silc_idcache_list_next(list, &id_cache))
803                 break;
804               else
805                 continue;
806             }
807
808             ctx->sessions = silc_realloc(ctx->sessions,
809                                          sizeof(*ctx->sessions) *
810                                          (ctx->sessions_count + 1));
811             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
812             ctx->sessions[ctx->sessions_count].connected = FALSE;
813             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
814
815             SILC_LOG_DEBUG(("Sending START to %s (session %d)",
816                             server_entry->server_name, ctx->sessions_count));
817             SILC_LOG_INFO(("Expecting CONNECTED from %s (session %d)",
818                             server_entry->server_name, ctx->sessions_count));
819
820             /* This connection is performing this protocol too now */
821             ((SilcSocketConnection)server_entry->connection)->protocol =
822               protocol;
823
824             if (server_entry->server_type == SILC_ROUTER)
825               packet->data[0] = SILC_SERVER_BACKUP_START;
826             else
827               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
828             packet->data[1] = ctx->sessions_count;
829             silc_server_packet_send(server, server_entry->connection,
830                                     SILC_PACKET_RESUME_ROUTER, 0, 
831                                     packet->data, packet->len, FALSE);
832             ctx->sessions_count++;
833
834             if (!silc_idcache_list_next(list, &id_cache))
835               break;
836           }
837         }
838
839         silc_idcache_list_free(list);
840       }
841
842       if (silc_idcache_get_all(server->global_list->servers, &list)) {
843         if (silc_idcache_list_first(list, &id_cache)) {
844           while (id_cache) {
845             server_entry = (SilcServerEntry)id_cache->context;
846             if (!server_entry || (server_entry == server->id_entry) || 
847                 !server_entry->connection || !server_entry->data.send_key ||
848                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
849               if (!silc_idcache_list_next(list, &id_cache))
850                 break;
851               else
852                 continue;
853             }
854
855             ctx->sessions = silc_realloc(ctx->sessions,
856                                          sizeof(*ctx->sessions) *
857                                          (ctx->sessions_count + 1));
858             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
859             ctx->sessions[ctx->sessions_count].connected = FALSE;
860             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
861
862             SILC_LOG_DEBUG(("Sending START to %s (session %d)", 
863                             server_entry->server_name, ctx->sessions_count));
864             SILC_LOG_INFO(("Expecting CONNECTED from %s (session %d)",
865                             server_entry->server_name, ctx->sessions_count));
866
867             /* This connection is performing this protocol too now */
868             ((SilcSocketConnection)server_entry->connection)->protocol =
869               protocol;
870
871             if (server_entry->server_type == SILC_ROUTER)
872               packet->data[0] = SILC_SERVER_BACKUP_START;
873             else
874               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
875             packet->data[1] = ctx->sessions_count;
876             silc_server_packet_send(server, server_entry->connection,
877                                     SILC_PACKET_RESUME_ROUTER, 0, 
878                                     packet->data, packet->len, FALSE);
879             ctx->sessions_count++;
880
881             if (!silc_idcache_list_next(list, &id_cache))
882               break;
883           }
884         }
885
886         silc_idcache_list_free(list);
887       }
888
889       silc_buffer_free(packet);
890
891       /* If we are not standalone and our primary is not the one we've
892          talking to now, then announce our information to it since we
893          haven't done that yet.  Standalone backup router announces
894          these during connecting to the primary. */
895       if (!server->standalone && SILC_PRIMARY_ROUTE(server) != ctx->sock) {
896         silc_server_announce_servers(server, TRUE, 0, ctx->sock);
897         silc_server_announce_clients(server, 0, ctx->sock);
898         silc_server_announce_channels(server, 0, ctx->sock);
899       }
900
901       protocol->state++;
902     } else {
903       /* Responder of the protocol. */
904       SilcServerConfigRouter *primary;
905
906       /* We should have received START or START_GLOBAL packet */
907       if (ctx->type != SILC_SERVER_BACKUP_START &&
908           ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
909         SILC_LOG_ERROR(("Bad resume router packet START %d", ctx->type));
910         break;
911       }
912
913       /* Connect to the primary router that was down that is now supposed
914          to be back online. We send the CONNECTED packet after we've
915          established the connection to the primary router. */
916       primary = silc_server_config_get_primary_router(server);
917       if (primary && server->backup_primary) {
918         SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
919                         ctx->session));
920         silc_server_backup_reconnect(server,
921                                      primary->host, primary->port,
922                                      silc_server_backup_connect_primary,
923                                      ctx->sock);
924       } else {
925         /* Nowhere to connect just return the CONNECTED packet */
926         SILC_LOG_DEBUG(("Received START (session %d), send CONNECTED back",
927                         ctx->session));
928
929         /* Send the CONNECTED packet back to the backup router. */
930         packet = silc_buffer_alloc(2);
931         silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
932         silc_buffer_format(packet,
933                            SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
934                            SILC_STR_UI_CHAR(ctx->session),
935                            SILC_STR_END);
936         silc_server_packet_send(server, ctx->sock, 
937                                 SILC_PACKET_RESUME_ROUTER, 0, 
938                                 packet->data, packet->len, FALSE);
939         silc_buffer_free(packet);
940       }
941
942       if (server->server_type == SILC_ROUTER &&
943           (!server->router || 
944            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
945         protocol->state++;
946       else
947         protocol->state = SILC_PROTOCOL_STATE_END;
948
949       ctx->sessions = silc_realloc(ctx->sessions,
950                                    sizeof(*ctx->sessions) *
951                                    (ctx->sessions_count + 1));
952       ctx->sessions[ctx->sessions_count].session = ctx->session;
953       ctx->sessions_count++;
954     }
955     break;
956
957   case 2:
958     if (ctx->responder == FALSE) {
959       /* Initiator */
960
961       /* We should have received CONNECTED packet */
962       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
963         SILC_LOG_ERROR(("Bad resume router packet CONNECTED %d", ctx->type));
964         break;
965       }
966
967       for (i = 0; i < ctx->sessions_count; i++) {
968         if (ctx->sessions[i].session == ctx->session) {
969           ctx->sessions[i].connected = TRUE;
970           SILC_LOG_INFO(("Received CONNECTED from %s (session %d)",
971                          ctx->sessions[i].server_entry->server_name,
972                          ctx->session));
973           SILC_LOG_DEBUG(("Received CONNECTED (session %d)", ctx->session));
974           break;
975         }
976       }
977
978       for (i = 0; i < ctx->sessions_count; i++) {
979         if (!ctx->sessions[i].connected)
980           return;
981       }
982
983       SILC_LOG_INFO(("All sessions have returned CONNECTED packets, "
984                      "continuing"));
985       SILC_LOG_DEBUG(("Sending ENDING packet to primary router"));
986
987       /* Send with a timeout */
988       silc_schedule_task_add(server->schedule, 0, 
989                              silc_server_backup_send_resumed,
990                              protocol, 1, 0, SILC_TASK_TIMEOUT,
991                              SILC_TASK_PRI_NORMAL);
992       return;
993     } else {
994       /* Responder */
995
996       /* We should have been received ENDING packet */
997       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
998         SILC_LOG_ERROR(("Bad resume router packet ENDING %d", ctx->type));
999         break;
1000       }
1001
1002       SILC_LOG_DEBUG(("Received ENDING packet, we are going to resume now"));
1003
1004       /* This state is received by the primary router but also servers
1005          and perhaps other routers so check that if we are the primary
1006          router of the cell then start sending RESUMED packets.  If we
1007          are normal server or one of those other routers then procede
1008          to next state. */
1009       if (server->router &&
1010           !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
1011           silc_server_config_is_primary_route(server)) {
1012         /* We'll wait for RESUMED packet */
1013         protocol->state = SILC_PROTOCOL_STATE_END;
1014         break;
1015       }
1016
1017       /* Switch announced informations to our primary router of using the
1018          backup router. */
1019       silc_server_local_servers_toggle_enabled(server, TRUE);
1020       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
1021                                            server->router);
1022       silc_server_update_clients_by_server(server, ctx->sock->user_data,
1023                                            server->router, TRUE);
1024       if (server->server_type == SILC_SERVER)
1025         silc_server_update_channels_by_server(server, ctx->sock->user_data, 
1026                                               server->router);
1027
1028       packet = silc_buffer_alloc(2);
1029       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1030
1031       /* We are the primary router, start sending RESUMED packets. */
1032       if (silc_idcache_get_all(server->local_list->servers, &list)) {
1033         if (silc_idcache_list_first(list, &id_cache)) {
1034           while (id_cache) {
1035             server_entry = (SilcServerEntry)id_cache->context;
1036             if (!server_entry || (server_entry == server->id_entry) || 
1037                 !server_entry->connection || !server_entry->data.send_key) {
1038               if (!silc_idcache_list_next(list, &id_cache))
1039                 break;
1040               else
1041                 continue;
1042             }
1043
1044             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1045                             server_entry->server_name));
1046
1047             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1048
1049             /* This connection is performing this protocol too now */
1050             ((SilcSocketConnection)server_entry->connection)->protocol =
1051               protocol;
1052
1053             if (server_entry->server_type == SILC_ROUTER)
1054               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1055             else
1056               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1057             silc_server_packet_send(server, server_entry->connection,
1058                                     SILC_PACKET_RESUME_ROUTER, 0, 
1059                                     packet->data, packet->len, FALSE);
1060
1061             if (!silc_idcache_list_next(list, &id_cache))
1062               break;
1063           }
1064         }
1065
1066         silc_idcache_list_free(list);
1067       }
1068
1069       if (silc_idcache_get_all(server->global_list->servers, &list)) {
1070         if (silc_idcache_list_first(list, &id_cache)) {
1071           while (id_cache) {
1072             server_entry = (SilcServerEntry)id_cache->context;
1073             if (!server_entry || (server_entry == server->id_entry) || 
1074                 !server_entry->connection || !server_entry->data.send_key) {
1075               if (!silc_idcache_list_next(list, &id_cache))
1076                 break;
1077               else
1078                 continue;
1079             }
1080
1081             SILC_LOG_DEBUG(("Sending RESUMED to %s",
1082                             server_entry->server_name));
1083
1084             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1085
1086             /* This connection is performing this protocol too now */
1087             ((SilcSocketConnection)server_entry->connection)->protocol =
1088               protocol;
1089
1090             if (server_entry->server_type == SILC_ROUTER)
1091               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1092             else
1093               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1094             silc_server_packet_send(server, server_entry->connection,
1095                                     SILC_PACKET_RESUME_ROUTER, 0, 
1096                                     packet->data, packet->len, FALSE);
1097
1098             if (!silc_idcache_list_next(list, &id_cache))
1099               break;
1100           }
1101         }
1102
1103         silc_idcache_list_free(list);
1104       }
1105
1106       silc_buffer_free(packet);
1107
1108       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1109       server->wait_backup = FALSE;
1110
1111       /* For us this is the end of this protocol. */
1112       if (protocol->final_callback)
1113         silc_protocol_execute_final(protocol, server->schedule);
1114       else
1115         silc_protocol_free(protocol);
1116     }
1117     break;
1118
1119   case SILC_PROTOCOL_STATE_END:
1120     {
1121       SilcServerEntry router, backup_router;
1122
1123       /* We should have been received RESUMED packet from our primary
1124          router. */
1125       if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1126           ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1127         SILC_LOG_ERROR(("Bad resume router packet RESUMED %d", ctx->type));
1128         break;
1129       }
1130
1131       SILC_LOG_INFO(("Received RESUMED from new primary router"));
1132
1133       if (server->backup_router)
1134         server->server_type = SILC_BACKUP_ROUTER;
1135
1136       /* We have now new primary router. All traffic goes there from now on. */
1137       router = (SilcServerEntry)ctx->sock->user_data;
1138       if (silc_server_backup_replaced_get(server, router->id, 
1139                                           &backup_router)) {
1140
1141         if (backup_router == server->router) {
1142           /* We have new primary router now */
1143           server->id_entry->router = router;
1144           server->router = router;
1145           SILC_LOG_INFO(("Switching back to primary router %s",
1146                          server->router->server_name));
1147         } else {
1148           /* We are connected to new primary and now continue using it */
1149           SILC_LOG_INFO(("Resuming the use of primary router %s",
1150                          router->server_name));
1151         }
1152
1153         /* Update the client entries of the backup router to the new 
1154            router */
1155         silc_server_local_servers_toggle_enabled(server, FALSE);
1156         router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1157         silc_server_update_servers_by_server(server, backup_router, router);
1158         silc_server_update_clients_by_server(server, NULL, router, FALSE);
1159         if (server->server_type == SILC_SERVER)
1160           silc_server_update_channels_by_server(server, backup_router, router);
1161         silc_server_backup_replaced_del(server, backup_router);
1162
1163         /* Announce all of our information to the router. */
1164         if (server->server_type == SILC_ROUTER)
1165           silc_server_announce_servers(server, FALSE, ctx->start,
1166                                        router->connection);
1167
1168         /* Announce our clients and channels to the router */
1169         silc_server_announce_clients(server, ctx->start,
1170                                      router->connection);
1171         silc_server_announce_channels(server, ctx->start,
1172                                       router->connection);
1173       }
1174
1175       /* Send notify about primary router going down to local operators */
1176       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
1177                              SILC_NOTIFY_TYPE_NONE,
1178                              ("%s resumed the use of primary router %s",
1179                               server->server_name,
1180                               server->router->server_name));
1181
1182       /* Protocol has ended, call the final callback */
1183       if (protocol->final_callback)
1184         silc_protocol_execute_final(protocol, server->schedule);
1185       else
1186         silc_protocol_free(protocol);
1187     }
1188     break;
1189
1190   case SILC_PROTOCOL_STATE_ERROR:
1191     /* Protocol has ended, call the final callback */
1192     if (protocol->final_callback)
1193       silc_protocol_execute_final(protocol, server->schedule);
1194     else
1195       silc_protocol_free(protocol);
1196     break;
1197
1198   case SILC_PROTOCOL_STATE_FAILURE:
1199     /* Protocol has ended, call the final callback */
1200     SILC_LOG_ERROR(("Error during backup resume: received Failure"));
1201     if (protocol->final_callback)
1202       silc_protocol_execute_final(protocol, server->schedule);
1203     else
1204       silc_protocol_free(protocol);
1205     break;
1206
1207   case SILC_PROTOCOL_STATE_UNKNOWN:
1208     break;
1209   }
1210 }
1211
1212 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1213 {
1214   SilcProtocol protocol = (SilcProtocol)context;
1215   SilcServerBackupProtocolContext ctx = protocol->context;
1216   SilcServer server = ctx->server;
1217   SilcServerEntry server_entry;
1218   SilcSocketConnection sock;
1219   SilcIDCacheList list;
1220   SilcIDCacheEntry id_cache;
1221
1222   silc_schedule_task_del_by_context(server->schedule, protocol);
1223
1224   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1225       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1226     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1227   }
1228
1229   if (server->server_shutdown)
1230     return;
1231
1232   /* Remove this protocol from all server entries that has it */
1233   if (silc_idcache_get_all(server->local_list->servers, &list)) {
1234     if (silc_idcache_list_first(list, &id_cache)) {
1235       while (id_cache) {
1236         server_entry = (SilcServerEntry)id_cache->context;
1237         sock = (SilcSocketConnection)server_entry->connection;
1238
1239         if (sock->protocol == protocol) {
1240           sock->protocol = NULL;
1241
1242           /* Backup closes connection and reconnects if error occurred */
1243           if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1244             if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1245                 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1246               server->backup_noswitch = TRUE;
1247               server->server_type = SILC_BACKUP_ROUTER;
1248
1249               if (sock->user_data)
1250                 silc_server_free_sock_user_data(server, sock, NULL);
1251               silc_server_close_connection(server, sock);
1252
1253               silc_schedule_task_add(server->schedule, 0,
1254                                      silc_server_connect_to_router,
1255                                      server, 1, 0,
1256                                      SILC_TASK_TIMEOUT,
1257                                      SILC_TASK_PRI_NORMAL);
1258
1259               if (!silc_idcache_list_next(list, &id_cache))
1260                 break;
1261               continue;
1262             }
1263           }
1264
1265           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1266             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1267         }
1268         
1269         if (!silc_idcache_list_next(list, &id_cache))
1270           break;
1271       }
1272     }
1273     silc_idcache_list_free(list);
1274   }
1275
1276   if (silc_idcache_get_all(server->global_list->servers, &list)) {
1277     if (silc_idcache_list_first(list, &id_cache)) {
1278       while (id_cache) {
1279         server_entry = (SilcServerEntry)id_cache->context;
1280         sock = (SilcSocketConnection)server_entry->connection;
1281
1282         if (sock->protocol == protocol) {
1283           sock->protocol = NULL;
1284
1285           /* Backup closes connection and reconnects if error occurred */
1286           if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router) {
1287             if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1288                 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1289               server->backup_noswitch = TRUE;
1290               server->server_type = SILC_BACKUP_ROUTER;
1291
1292               if (sock->user_data)
1293                 silc_server_free_sock_user_data(server, sock, NULL);
1294               silc_server_close_connection(server, sock);
1295
1296               silc_schedule_task_add(server->schedule, 0,
1297                                      silc_server_connect_to_router,
1298                                      server, 1, 0,
1299                                      SILC_TASK_TIMEOUT,
1300                                      SILC_TASK_PRI_NORMAL);
1301
1302               if (!silc_idcache_list_next(list, &id_cache))
1303                 break;
1304               continue;
1305             }
1306           }
1307
1308           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1309             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1310         }
1311         
1312         if (!silc_idcache_list_next(list, &id_cache))
1313           break;
1314       }
1315     }
1316     silc_idcache_list_free(list);
1317   }
1318
1319   if (protocol->state != SILC_PROTOCOL_STATE_ERROR &&
1320       protocol->state != SILC_PROTOCOL_STATE_FAILURE)
1321     SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
1322
1323   if (ctx->sock->protocol)
1324     ctx->sock->protocol = NULL;
1325   silc_protocol_free(protocol);
1326   silc_free(ctx->sessions);
1327   silc_free(ctx);
1328 }