Static analyzer bug fixes
[silc.git] / apps / silcd / server_backup.c
index db4725eeb3cb96979bba99454cfe733e9c8d9c8f..4ae58843afe27de16bef023d29daeea86f0dae93 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2007 Pekka Riikonen
+  Copyright (C) 2001 - 2014 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -108,7 +108,8 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
   }
 
   SILC_LOG_DEBUG(("Backup router %s will replace %s",
-                 backup_server->data.sconn->remote_host, ip, port));
+                 backup_server->data.sconn ?
+                 backup_server->data.sconn->remote_host : "(me)", ip));
 
   for (i = 0; i < server->backup->servers_count; i++) {
     if (!server->backup->servers[i].server) {
@@ -218,13 +219,19 @@ void silc_server_backup_replaced_add(SilcServer server,
   int i;
   SilcServerBackupReplaced *r = silc_calloc(1, sizeof(*r));;
 
+  if (!r)
+    return;
   if (!server->backup)
     server->backup = silc_calloc(1, sizeof(*server->backup));
+  if (!server->backup)
+    return;
   if (!server->backup->replaced) {
     server->backup->replaced =
       silc_calloc(1, sizeof(*server->backup->replaced));
     server->backup->replaced_count = 1;
   }
+  if (!server->backup->replaced)
+    return;
 
   SILC_LOG_DEBUG(("Replacing router %s with %s",
                  silc_id_render(server_id, SILC_ID_SERVER),
@@ -353,7 +360,6 @@ void silc_server_backup_send(SilcServer server,
                             SilcBool local)
 {
   SilcServerEntry backup;
-  SilcPacketStream sock;
   int i;
 
   if (!server->backup || server->server_type != SILC_ROUTER)
@@ -368,8 +374,6 @@ void silc_server_backup_send(SilcServer server,
     if (server->backup->servers[i].server == server->id_entry)
       continue;
 
-    sock = backup->connection;
-
     silc_server_packet_send(server, backup->connection, type, flags,
                            data, data_len);
   }
@@ -392,7 +396,6 @@ void silc_server_backup_send_dest(SilcServer server,
                                  SilcBool local)
 {
   SilcServerEntry backup;
-  SilcPacketStream sock;
   int i;
 
   if (!server->backup || server->server_type != SILC_ROUTER)
@@ -407,8 +410,6 @@ void silc_server_backup_send_dest(SilcServer server,
     if (server->backup->servers[i].server == server->id_entry)
       continue;
 
-    sock = backup->connection;
-
     silc_server_packet_send_dest(server, backup->connection, type, flags,
                                 dst_id, dst_id_type, data, data_len);
   }
@@ -551,10 +552,10 @@ void silc_server_backup_ping_reply(void *context, void *reply)
     /* The primary is not down, refuse to serve the server as primary */
     SILC_LOG_DEBUG(("PING received, primary is up"));
     silc_server_backup_send_start_use(pc->server, pc->sock, TRUE);
+    silc_packet_free(pc->packet);
   }
 
   silc_packet_stream_unref(pc->sock);
-  silc_packet_free(pc->packet);
   silc_free(pc);
 }
 
@@ -636,6 +637,11 @@ void silc_server_backup_resume_router(SilcServer server,
 
     /* Reprocess this packet after received reply from router */
     pc = silc_calloc(1, sizeof(*pc));
+    if (!pc) {
+      silc_server_backup_send_start_use(server, sock, FALSE);
+      silc_packet_free(packet);
+      return;
+    }
     pc->server = server;
     pc->sock = sock;
     pc->packet = packet;
@@ -651,12 +657,12 @@ void silc_server_backup_resume_router(SilcServer server,
     /* We have received a start for resuming protocol.  We are either
        primary router that came back online or normal server. */
     SilcServerBackupProtocolContext proto_ctx;
+    unsigned char data[4];
 
     /* If backup had closed the connection earlier we won't allow resuming
        since we (primary router) have never gone away. */
     if (server->server_type == SILC_ROUTER && !server->backup_router &&
        server->backup_closed) {
-      unsigned char data[4];
       SILC_LOG_DEBUG(("Backup resuming not allowed since we are still "
                      "primary router"));
       SILC_LOG_INFO(("Backup resuming not allowed since we are still "
@@ -670,6 +676,14 @@ void silc_server_backup_resume_router(SilcServer server,
     }
 
     proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+    if (!proto_ctx) {
+      SILC_PUT32_MSB(SILC_SERVER_BACKUP_START, data);
+      silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
+                             data, 4);
+      server->backup_closed = FALSE;
+      silc_packet_free(packet);
+      return;
+    }
     proto_ctx->server = server;
     proto_ctx->sock = sock;
     proto_ctx->responder = TRUE;
@@ -711,8 +725,17 @@ void silc_server_backup_resume_router(SilcServer server,
   if (type == SILC_SERVER_BACKUP_RESUMED &&
       idata->conn_type == SILC_CONN_ROUTER && !router->backup &&
       idata->status & SILC_IDLIST_STATUS_DISABLED) {
-    if (silc_server_backup_replaced_get(server, router->id, NULL))
+    SilcServerEntry backup_router;
+
+    if (silc_server_backup_replaced_get(server, router->id, &backup_router)) {
+      ctx = backup_router->backup_proto;
+      if (ctx->sock)
+       silc_packet_stream_unref(ctx->sock);
       router->backup = TRUE;
+      router->backup_proto = ctx;
+      ctx->sock = sock;
+      silc_packet_stream_ref(sock);
+    }
   }
 
   /* Call the resuming protocol if the protocol is active. */
@@ -776,11 +799,16 @@ SILC_TASK_CALLBACK(silc_server_backup_connected_again)
   SilcServer server = app_context;
   SilcServerConfigRouter *primary;
 
+  SILC_LOG_DEBUG(("Reconnecting"));
+
+  if (server->server_shutdown)
+    return;
+
   primary = silc_server_config_get_primary_router(server);
   if (primary) {
     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
                                         primary->host, primary->port))
-      silc_server_create_connection(server, FALSE, FALSE,
+      silc_server_create_connection(server, TRUE, FALSE,
                                    primary->host, primary->port,
                                    silc_server_backup_connected,
                                    context);
@@ -800,14 +828,17 @@ void silc_server_backup_connected(SilcServer server,
 
   if (!server_entry) {
     /* Try again */
+    SILC_LOG_DEBUG(("Connecting failed"));
     silc_schedule_task_add_timeout(server->schedule,
                                   silc_server_backup_connected_again,
-                                  context, 0, 1);
+                                  context, 5, 0);
     return;
   }
 
   sock = server_entry->connection;
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+  if (!proto_ctx)
+    return;
   proto_ctx->server = server;
   proto_ctx->sock = sock;
   proto_ctx->responder = FALSE;
@@ -830,7 +861,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_primary_again)
   if (primary) {
     if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER,
                                         primary->host, primary->port))
-      silc_server_create_connection(server, FALSE, FALSE,
+      silc_server_create_connection(server, TRUE, FALSE,
                                    primary->host, primary->port,
                                    silc_server_backup_connect_primary,
                                    context);
@@ -861,13 +892,10 @@ static void silc_server_backup_connect_primary(SilcServer server,
     return;
   }
 
-  /* Unref */
-  silc_packet_stream_unref(backup_router);
-
-  if (!router->backup)
-    return;
-  if (!server_entry->connection)
+  if (!router->backup || !server_entry->connection) {
+    silc_packet_stream_unref(backup_router);
     return;
+  }
 
   ctx = router->backup_proto;
   sock = server_entry->connection;
@@ -891,10 +919,17 @@ static void silc_server_backup_connect_primary(SilcServer server,
      the primary router connection since it will send the subsequent
      packets in this protocol. We don't talk with backup router
      anymore. */
+  if (ctx->sock)
+    silc_packet_stream_unref(ctx->sock);
+  ctx->sock = sock;
+  silc_packet_stream_ref(sock);
   server_entry->backup = TRUE;
   server_entry->backup_proto = ctx;
   router->backup = FALSE;
   router->backup_proto = NULL;
+
+  /* Unref */
+  silc_packet_stream_unref(backup_router);
 }
 
 /* Timeout callback used by the backup router to send the ENDING packet
@@ -1026,7 +1061,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
        SILC_LOG_DEBUG(("Received START (session %d), reconnect to router",
                        ctx->session));
        silc_packet_stream_ref(ctx->sock);
-       silc_server_create_connection(server, FALSE, FALSE,
+       silc_server_create_connection(server, TRUE, FALSE,
                                      primary->host, primary->port,
                                      silc_server_backup_connect_primary,
                                      ctx->sock);
@@ -1146,7 +1181,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
        if (sock == ctx->sock)
          continue;
 
-      send_to_backup:
+       server_entry = silc_packet_get_context(sock);
        server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
 
        SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
@@ -1161,14 +1196,27 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
        silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
                                data, sizeof(data));
       }
-      silc_packet_engine_free_streams_list(list);
 
       /* Now send the same packet to backup */
       if (sock != ctx->sock) {
        sleep(1);
        sock = ctx->sock;
-       goto send_to_backup;
+       server_entry = silc_packet_get_context(sock);
+       server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+
+       SILC_LOG_DEBUG(("Sending RESUMED to %s", server_entry->server_name));
+       SILC_LOG_INFO(("Sending RESUMED to %s", server_entry->server_name));
+
+       /* This connection is performing this protocol too now */
+       server_entry->backup = TRUE;
+       server_entry->backup_proto = ctx;
+
+       data[0] = SILC_SERVER_BACKUP_RESUMED;
+       data[1] = 0;
+       silc_server_packet_send(server, sock, SILC_PACKET_RESUME_ROUTER, 0,
+                               data, sizeof(data));
       }
+      silc_packet_engine_free_streams_list(list);
 
       /* We are now resumed and are back as primary router in the cell. */
       SILC_LOG_INFO(("We are now the primary router of our cell again"));
@@ -1183,7 +1231,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
       /* For us this is the end of this protocol. */
       silc_schedule_task_add_timeout(server->schedule,
                                     silc_server_protocol_backup_done,
-                                    ctx->sock, 0, 1);
+                                    ctx, 0, 1);
     }
     break;
 
@@ -1249,7 +1297,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
       /* Protocol has ended, call the final callback */
       silc_schedule_task_add_timeout(server->schedule,
                                     silc_server_protocol_backup_done,
-                                    ctx->sock, 0, 1);
+                                    ctx, 0, 1);
     }
     break;
 
@@ -1257,7 +1305,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
     /* Protocol has ended, call the final callback */
     silc_schedule_task_add_timeout(server->schedule,
                                   silc_server_protocol_backup_done,
-                                  ctx->sock, 0, 1);
+                                  ctx, 0, 1);
     break;
 
   case 252:
@@ -1266,7 +1314,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup)
     ctx->received_failure = TRUE;
     silc_schedule_task_add_timeout(server->schedule,
                                   silc_server_protocol_backup_done,
-                                  ctx->sock, 0, 1);
+                                  ctx, 0, 1);
     break;
 
   default:
@@ -1284,7 +1332,6 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
   SilcServerEntry server_entry;
   SilcPacketStream sock;
   SilcBool error;
-  int i;
 
   silc_schedule_task_del_by_context(server->schedule, ctx);
 
@@ -1335,12 +1382,15 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
 
            /* Restart the protocol. */
            proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+           if (!proto_ctx)
+             continue;
            proto_ctx->server = server;
            proto_ctx->sock = sock;
            proto_ctx->responder = FALSE;
            proto_ctx->type = SILC_SERVER_BACKUP_START;
            proto_ctx->start = time(0);
            proto_ctx->initiator_restart = ctx->initiator_restart + 1;
+           silc_packet_stream_ref(sock);
 
            /* Start through scheduler */
            silc_schedule_task_add_timeout(server->schedule,
@@ -1364,6 +1414,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
            silc_server_announce_channels(server, 0, sock);
 
            /* Announce WATCH list a little later */
+           silc_packet_stream_ref(sock);
            silc_schedule_task_add_timeout(server->schedule,
                                           silc_server_backup_announce_watches,
                                           sock, 5, 0);
@@ -1392,6 +1443,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
       silc_server_announce_channels(server, 0, server->router->connection);
 
       /* Announce WATCH list a little later */
+      silc_packet_stream_ref(server->router->connection);
       silc_schedule_task_add_timeout(server->schedule,
                                     silc_server_backup_announce_watches,
                                     server->router->connection, 4, 0);
@@ -1409,14 +1461,17 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
                                          FALSE);
 
        /* Check couple of times same START_USE just in case. */
+       silc_packet_stream_ref(server->router->connection);
        silc_schedule_task_add_timeout(server->schedule,
                                       silc_server_backup_check_status,
                                       server->router->connection,
                                       5, 1);
+       silc_packet_stream_ref(server->router->connection);
        silc_schedule_task_add_timeout(server->schedule,
                                       silc_server_backup_check_status,
                                       server->router->connection,
                                       20, 1);
+       silc_packet_stream_ref(server->router->connection);
        silc_schedule_task_add_timeout(server->schedule,
                                       silc_server_backup_check_status,
                                       server->router->connection,
@@ -1425,8 +1480,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
     }
   }
 
-  if (ctx->sock)
+  if (ctx->sock) {
+    SilcServerEntry r = silc_packet_get_context(ctx->sock);
+    if (r) {
+      r->backup = FALSE;
+      r->backup_proto = NULL;
+    }
     silc_packet_stream_unref(ctx->sock);
+  }
   silc_free(ctx->sessions);
   silc_free(ctx);
 }