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