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