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_ne(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_ne(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, 
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 /* Resume protocol with RESUME_ROUTER packet: 
654
655    SILC_PACKET_RESUME_ROUTER:
656
657    <uint8 type> <uint8 Session ID>
658
659    <type>          = the protocol opcode
660    <Session ID>    = Identifier for this packet and any subsequent reply
661                      packets must include this identifier.
662
663    Types:
664
665      1    = To router: Comensing backup resuming protocol. This will
666             indicate that the sender is backup router acting as primary
667             and the receiver is primary router that has been replaced by
668             the backup router.
669
670             To server. Comensing backup resuming protocol. This will
671             indicate that the sender is backup router and the receiver
672             must reconnect to the real primary router of the cell.
673
674      2    = To Router: Comesning backup resuming protocol in another
675             cell.  The receiver will connect to its primary router 
676             (the router that is now online again) but will not use
677             the link.  If the receiver is not configured to connect
678             to any router it does as locally configured.  The sender
679             is always backup router.
680
681             To server: this is never sent to server.
682
683      3    = To backup router: Sender is normal server or router and it
684             tells to backup router that they have connected to the
685             primary router.  Backup router never sends this type.
686
687      4    = To router: Ending backup resuming protocol. This is sent
688             to the real primary router to tell that it can take over
689             the task as being primary router.
690
691             To server: same as sending for router.
692
693             Backup router sends this also to the primary route but only
694             after it has sent them to normal servers and has purged all
695             traffic coming from normal servers.
696
697      5    = To router: Sender is the real primary router after it has
698             received type 4 from backup router. To tell that it is again
699             primary router of the cell.
700
701      20   = To router: This is sent only when router is connecting to
702             another router and has been replaced by an backup router.
703             The sender knows that the connectee has been replaced.
704
705  */
706
707 /* Backup resuming protocol. This protocol is executed when the primary
708    router wants to resume its position as being primary router. */
709
710 SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
711 {
712   SilcProtocol protocol = (SilcProtocol)context;
713   SilcServerBackupProtocolContext ctx = protocol->context;
714   SilcServer server = ctx->server;
715   SilcBuffer packet;
716   SilcIDCacheList list;
717   SilcIDCacheEntry id_cache;
718   SilcServerEntry server_entry;
719   int i;
720
721   SILC_LOG_DEBUG(("Start"));
722
723   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
724     protocol->state = SILC_PROTOCOL_STATE_START;
725
726   SILC_LOG_DEBUG(("State=%d", protocol->state));
727
728   switch(protocol->state) {
729   case SILC_PROTOCOL_STATE_START:
730     if (ctx->responder == FALSE) {
731       /* Initiator of the protocol. We are backup router */
732
733       packet = silc_buffer_alloc(2);
734       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
735
736       SILC_LOG_DEBUG(("********************************"));
737       SILC_LOG_DEBUG(("Sending START packets"));
738
739       /* Send the START packet to primary router and normal servers. */
740       if (silc_idcache_get_all(server->local_list->servers, &list)) {
741         if (silc_idcache_list_first(list, &id_cache)) {
742           while (id_cache) {
743             server_entry = (SilcServerEntry)id_cache->context;
744             if (!server_entry || (server_entry == server->id_entry) || 
745                 !server_entry->connection || !server_entry->data.send_key ||
746                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
747               if (!silc_idcache_list_next(list, &id_cache))
748                 break;
749               else
750                 continue;
751             }
752
753             ctx->sessions = silc_realloc(ctx->sessions,
754                                          sizeof(*ctx->sessions) *
755                                          (ctx->sessions_count + 1));
756             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
757             ctx->sessions[ctx->sessions_count].connected = FALSE;
758             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
759
760             SILC_LOG_DEBUG(("********************************"));
761             SILC_LOG_DEBUG(("START (local) for session %d", 
762                             ctx->sessions_count));
763
764             /* This connection is performing this protocol too now */
765             ((SilcSocketConnection)server_entry->connection)->protocol =
766               protocol;
767
768             if (server_entry->server_type == SILC_ROUTER)
769               packet->data[0] = SILC_SERVER_BACKUP_START;
770             else
771               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
772             packet->data[1] = ctx->sessions_count;
773             silc_server_packet_send(server, server_entry->connection,
774                                     SILC_PACKET_RESUME_ROUTER, 0, 
775                                     packet->data, packet->len, FALSE);
776             ctx->sessions_count++;
777
778             if (!silc_idcache_list_next(list, &id_cache))
779               break;
780           }
781         }
782
783         silc_idcache_list_free(list);
784       }
785
786       if (silc_idcache_get_all(server->global_list->servers, &list)) {
787         if (silc_idcache_list_first(list, &id_cache)) {
788           while (id_cache) {
789             server_entry = (SilcServerEntry)id_cache->context;
790             if (!server_entry || (server_entry == server->id_entry) || 
791                 !server_entry->connection || !server_entry->data.send_key ||
792                 (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
793               if (!silc_idcache_list_next(list, &id_cache))
794                 break;
795               else
796                 continue;
797             }
798
799             ctx->sessions = silc_realloc(ctx->sessions,
800                                          sizeof(*ctx->sessions) *
801                                          (ctx->sessions_count + 1));
802             ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
803             ctx->sessions[ctx->sessions_count].connected = FALSE;
804             ctx->sessions[ctx->sessions_count].server_entry = server_entry;
805
806             SILC_LOG_DEBUG(("********************************"));
807             SILC_LOG_DEBUG(("START (global) for session %d", 
808                             ctx->sessions_count));
809
810             /* This connection is performing this protocol too now */
811             ((SilcSocketConnection)server_entry->connection)->protocol =
812               protocol;
813
814             if (server_entry->server_type == SILC_ROUTER)
815               packet->data[0] = SILC_SERVER_BACKUP_START;
816             else
817               packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
818             packet->data[1] = ctx->sessions_count;
819             silc_server_packet_send(server, server_entry->connection,
820                                     SILC_PACKET_RESUME_ROUTER, 0, 
821                                     packet->data, packet->len, FALSE);
822             ctx->sessions_count++;
823
824             if (!silc_idcache_list_next(list, &id_cache))
825               break;
826           }
827         }
828
829         silc_idcache_list_free(list);
830       }
831
832       silc_buffer_free(packet);
833
834       /* Announce all of our information */
835       silc_server_announce_servers(server, TRUE, 0, ctx->sock);
836       silc_server_announce_clients(server, 0, ctx->sock);
837       silc_server_announce_channels(server, 0, ctx->sock);
838
839       protocol->state++;
840     } else {
841       /* Responder of the protocol. */
842       SilcServerConfigSectionServerConnection *primary;
843
844       /* We should have received START or START_GLOBAL packet */
845       if (ctx->type != SILC_SERVER_BACKUP_START &&
846           ctx->type != SILC_SERVER_BACKUP_START_GLOBAL) {
847         SILC_LOG_DEBUG(("Bad resume router packet"));
848         break;
849       }
850
851       SILC_LOG_DEBUG(("********************************"));
852       SILC_LOG_DEBUG(("Received START packet, reconnecting to router"));
853
854       /* Connect to the primary router that was down that is now supposed
855          to be back online. We send the CONNECTED packet after we've
856          established the connection to the primary router. */
857       primary = silc_server_config_get_primary_router(server->config);
858       if (primary && server->backup_primary) {
859         silc_server_backup_reconnect(server,
860                                      primary->host, primary->port,
861                                      silc_server_backup_connect_primary,
862                                      ctx->sock);
863       } else {
864         /* Nowhere to connect just return the CONNECTED packet */
865
866         SILC_LOG_DEBUG(("********************************"));
867         SILC_LOG_DEBUG(("Sending CONNECTED packet, session %d", ctx->session));
868         
869         /* Send the CONNECTED packet back to the backup router. */
870         packet = silc_buffer_alloc(2);
871         silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
872         silc_buffer_format(packet,
873                            SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_CONNECTED),
874                            SILC_STR_UI_CHAR(ctx->session),
875                            SILC_STR_END);
876         silc_server_packet_send(server, ctx->sock, 
877                                 SILC_PACKET_RESUME_ROUTER, 0, 
878                                 packet->data, packet->len, FALSE);
879         silc_buffer_free(packet);
880       }
881
882       if (server->server_type == SILC_ROUTER &&
883           (!server->router || 
884            server->router->data.status & SILC_IDLIST_STATUS_DISABLED))
885         protocol->state++;
886       else
887         protocol->state = SILC_PROTOCOL_STATE_END;
888
889       ctx->sessions = silc_realloc(ctx->sessions,
890                                    sizeof(*ctx->sessions) *
891                                    (ctx->sessions_count + 1));
892       ctx->sessions[ctx->sessions_count].session = ctx->session;
893       ctx->sessions_count++;
894     }
895     break;
896
897   case 2:
898     if (ctx->responder == FALSE) {
899       /* Initiator */
900
901       /* We should have received CONNECTED packet */
902       if (ctx->type != SILC_SERVER_BACKUP_CONNECTED) {
903         SILC_LOG_DEBUG(("Bad resume router packet"));
904         break;
905       }
906
907       SILC_LOG_DEBUG(("********************************"));
908       SILC_LOG_DEBUG(("Received CONNECTED packet, session %d", ctx->session));
909
910       for (i = 0; i < ctx->sessions_count; i++) {
911         if (ctx->sessions[i].session == ctx->session) {
912           ctx->sessions[i].connected = TRUE;
913           break;
914         }
915       }
916
917       for (i = 0; i < ctx->sessions_count; i++) {
918         if (!ctx->sessions[i].connected)
919           return;
920       }
921
922       SILC_LOG_DEBUG(("********************************"));
923       SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
924
925       for (i = 0; i < ctx->sessions_count; i++)
926         if (ctx->sessions[i].server_entry == ctx->sock->user_data)
927           ctx->session = ctx->sessions[i].session;
928
929       /* We've received all the CONNECTED packets and now we'll send the
930          ENDING packet to the new primary router. */
931       packet = silc_buffer_alloc(2);
932       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
933       silc_buffer_format(packet,
934                          SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
935                          SILC_STR_UI_CHAR(ctx->session),
936                          SILC_STR_END);
937       silc_server_packet_send(server, ctx->sock, 
938                               SILC_PACKET_RESUME_ROUTER, 0, 
939                               packet->data, packet->len, FALSE);
940       silc_buffer_free(packet);
941
942       protocol->state = SILC_PROTOCOL_STATE_END;
943     } else {
944       /* Responder */
945
946       /* We should have been received ENDING packet */
947       if (ctx->type != SILC_SERVER_BACKUP_ENDING) {
948         SILC_LOG_DEBUG(("Bad resume router packet"));
949         break;
950       }
951
952       SILC_LOG_DEBUG(("********************************"));
953       SILC_LOG_DEBUG(("Received ENDING packet, sending RESUMED packets"));
954
955       /* This state is received by the primary router but also servers
956          and perhaps other routers so check that if we are the primary
957          router of the cell then start sending RESUMED packets.  If we
958          are normal server or one of those other routers then procede
959          to next state. */
960       if (server->router &&
961           !(server->router->data.status & SILC_IDLIST_STATUS_DISABLED) &&
962           silc_server_config_is_primary_route(server->config)) {
963         /* We'll wait for RESUMED packet */
964         protocol->state = SILC_PROTOCOL_STATE_END;
965         break;
966       }
967
968       /* Switch announced informations to our primary router of using the
969          backup router. */
970       silc_server_update_clients_by_server(server, ctx->sock->user_data,
971                                            server->router, TRUE, FALSE);
972
973       packet = silc_buffer_alloc(2);
974       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
975
976       /* We are the primary router, start sending RESUMED packets. */
977       if (silc_idcache_get_all(server->local_list->servers, &list)) {
978         if (silc_idcache_list_first(list, &id_cache)) {
979           while (id_cache) {
980             server_entry = (SilcServerEntry)id_cache->context;
981             if (!server_entry || (server_entry == server->id_entry) || 
982                 !server_entry->connection || !server_entry->data.send_key) {
983               if (!silc_idcache_list_next(list, &id_cache))
984                 break;
985               else
986                 continue;
987             }
988
989             SILC_LOG_DEBUG(("********************************"));
990             SILC_LOG_DEBUG(("RESUMED packet (local)"));
991
992             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
993
994             /* This connection is performing this protocol too now */
995             ((SilcSocketConnection)server_entry->connection)->protocol =
996               protocol;
997
998             if (server_entry->server_type == SILC_ROUTER)
999               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1000             else
1001               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1002             silc_server_packet_send(server, server_entry->connection,
1003                                     SILC_PACKET_RESUME_ROUTER, 0, 
1004                                     packet->data, packet->len, FALSE);
1005
1006             if (!silc_idcache_list_next(list, &id_cache))
1007               break;
1008           }
1009         }
1010
1011         silc_idcache_list_free(list);
1012       }
1013
1014       if (silc_idcache_get_all(server->global_list->servers, &list)) {
1015         if (silc_idcache_list_first(list, &id_cache)) {
1016           while (id_cache) {
1017             server_entry = (SilcServerEntry)id_cache->context;
1018             if (!server_entry || (server_entry == server->id_entry) || 
1019                 !server_entry->connection || !server_entry->data.send_key) {
1020               if (!silc_idcache_list_next(list, &id_cache))
1021                 break;
1022               else
1023                 continue;
1024             }
1025
1026             SILC_LOG_DEBUG(("********************************"));
1027             SILC_LOG_DEBUG(("RESUMED packet (global)"));
1028
1029             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1030
1031             /* This connection is performing this protocol too now */
1032             ((SilcSocketConnection)server_entry->connection)->protocol =
1033               protocol;
1034
1035             if (server_entry->server_type == SILC_ROUTER)
1036               packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
1037             else
1038               packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
1039             silc_server_packet_send(server, server_entry->connection,
1040                                     SILC_PACKET_RESUME_ROUTER, 0, 
1041                                     packet->data, packet->len, FALSE);
1042
1043             if (!silc_idcache_list_next(list, &id_cache))
1044               break;
1045           }
1046         }
1047
1048         silc_idcache_list_free(list);
1049       }
1050
1051       silc_buffer_free(packet);
1052
1053       SILC_LOG_INFO(("We are now the primary router of our cell again"));
1054
1055       /* For us this is the end of this protocol. */
1056       if (protocol->final_callback)
1057         silc_protocol_execute_final(protocol, server->schedule);
1058       else
1059         silc_protocol_free(protocol);
1060     }
1061     break;
1062
1063   case SILC_PROTOCOL_STATE_END:
1064     {
1065       SilcIDListData idata;
1066       SilcServerEntry router, backup_router;
1067
1068       /* We should have been received RESUMED packet from our primary
1069          router. */
1070       if (ctx->type != SILC_SERVER_BACKUP_RESUMED &&
1071           ctx->type != SILC_SERVER_BACKUP_RESUMED_GLOBAL) {
1072         SILC_LOG_DEBUG(("Bad resume router packet"));
1073         break;
1074       }
1075
1076       SILC_LOG_DEBUG(("********************************"));
1077       SILC_LOG_DEBUG(("Received RESUMED packet"));
1078
1079       /* We have now new primary router. All traffic goes there from now on. */
1080       if (server->backup_router)
1081         server->server_type = SILC_BACKUP_ROUTER;
1082
1083       router = (SilcServerEntry)ctx->sock->user_data;
1084       if (silc_server_backup_replaced_get(server, router->id, 
1085                                           &backup_router)) {
1086
1087         if (backup_router == server->router) {
1088           server->id_entry->router = router;
1089           server->router = router;
1090           SILC_LOG_INFO(("Switching back to primary router %s",
1091                          server->router->server_name));
1092           SILC_LOG_DEBUG(("Switching back to primary router %s",
1093                           server->router->server_name));
1094           idata = (SilcIDListData)server->router;
1095           idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1096         } else {
1097           SILC_LOG_INFO(("Resuming the use of router %s",
1098                          router->server_name));
1099           SILC_LOG_DEBUG(("Resuming the use of router %s",
1100                           router->server_name));
1101           idata = (SilcIDListData)router;
1102           idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
1103         }
1104
1105         /* Update the client entries of the backup router to the new 
1106            router */
1107         silc_server_update_clients_by_server(server, backup_router,
1108                                              router, TRUE, FALSE);
1109         silc_server_backup_replaced_del(server, backup_router);
1110         silc_server_backup_add(server, backup_router, 
1111                                ctx->sock->ip, ctx->sock->port,
1112                                backup_router->server_type != SILC_ROUTER ?
1113                                TRUE : FALSE);
1114
1115         /* Announce all of our information to the router. */
1116         if (server->server_type == SILC_ROUTER)
1117           silc_server_announce_servers(server, FALSE, 0, router->connection);
1118
1119         /* Announce our clients and channels to the router */
1120         silc_server_announce_clients(server, 0, router->connection);
1121         silc_server_announce_channels(server, 0, router->connection);
1122       }
1123
1124       /* Protocol has ended, call the final callback */
1125       if (protocol->final_callback)
1126         silc_protocol_execute_final(protocol, server->schedule);
1127       else
1128         silc_protocol_free(protocol);
1129     }
1130     break;
1131
1132   case SILC_PROTOCOL_STATE_ERROR:
1133     /* Protocol has ended, call the final callback */
1134     if (protocol->final_callback)
1135       silc_protocol_execute_final(protocol, server->schedule);
1136     else
1137       silc_protocol_free(protocol);
1138     break;
1139
1140   case SILC_PROTOCOL_STATE_FAILURE:
1141     /* Protocol has ended, call the final callback */
1142     if (protocol->final_callback)
1143       silc_protocol_execute_final(protocol, server->schedule);
1144     else
1145       silc_protocol_free(protocol);
1146     break;
1147
1148   case SILC_PROTOCOL_STATE_UNKNOWN:
1149     break;
1150   }
1151 }
1152
1153 SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
1154 {
1155   SilcProtocol protocol = (SilcProtocol)context;
1156   SilcServerBackupProtocolContext ctx = protocol->context;
1157   SilcServer server = ctx->server;
1158   SilcServerEntry server_entry;
1159   SilcSocketConnection sock;
1160   SilcIDCacheList list;
1161   SilcIDCacheEntry id_cache;
1162
1163   SILC_LOG_DEBUG(("Start"));
1164
1165   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1166       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1167     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
1168   }
1169
1170   /* Remove this protocol from all server entries that has it */
1171   if (silc_idcache_get_all(server->local_list->servers, &list)) {
1172     if (silc_idcache_list_first(list, &id_cache)) {
1173       while (id_cache) {
1174         server_entry = (SilcServerEntry)id_cache->context;
1175         sock = (SilcSocketConnection)server_entry->connection;
1176
1177         if (sock->protocol == protocol) {
1178           sock->protocol = NULL;
1179
1180           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1181             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1182         }
1183         
1184         if (!silc_idcache_list_next(list, &id_cache))
1185           break;
1186       }
1187     }
1188     silc_idcache_list_free(list);
1189   }
1190
1191   if (silc_idcache_get_all(server->global_list->servers, &list)) {
1192     if (silc_idcache_list_first(list, &id_cache)) {
1193       while (id_cache) {
1194         server_entry = (SilcServerEntry)id_cache->context;
1195         sock = (SilcSocketConnection)server_entry->connection;
1196
1197         if (sock->protocol == protocol) {
1198           sock->protocol = NULL;
1199
1200           if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
1201             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
1202         }
1203         
1204         if (!silc_idcache_list_next(list, &id_cache))
1205           break;
1206       }
1207     }
1208     silc_idcache_list_free(list);
1209   }
1210
1211   if (ctx->sock->protocol)
1212     ctx->sock->protocol = NULL;
1213   silc_protocol_free(protocol);
1214   silc_free(ctx->sessions);
1215   silc_free(ctx);
1216 }