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