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