Merged c0ffee's patch.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 30 May 2002 13:54:42 +0000 (13:54 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 30 May 2002 13:54:42 +0000 (13:54 +0000)
CHANGES
apps/silcd/server.c
apps/silcd/server_backup.c
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h

diff --git a/CHANGES b/CHANGES
index f04510b2cdbf564d871fbd311b5b33f3f4226c2f..5f41b0b244171d209fb117f1e76048bb3848aa7d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Thu May 30 15:53:45 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Merged c0ffee's multiple interface support patch.
+         Affected files in silcd/.
+
 Wed May 29 18:08:15 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Cleanup keys properly.  Affected file is
index d971bd157527a4a1cb538c4efcb45ece2a93eb29..53fcb72efcc049c189497196d1d7c418cce21e67 100644 (file)
@@ -119,20 +119,76 @@ void silc_server_free(SilcServer server)
    XXX This function will become more general and will support multiple
    listening ports */
 
-static bool silc_server_listen(SilcServer server, int *sock)
+static bool silc_server_listen(SilcServer server, const char *server_ip,
+                               SilcUInt16 port, int *sock)
 {
-
-  *sock = silc_net_create_server(server->config->server_info->port,
-                               server->config->server_info->server_ip);
+  *sock = silc_net_create_server(port, server_ip);
   if (*sock < 0) {
     SILC_LOG_ERROR(("Could not create server listener: %s on %hu",
-                   server->config->server_info->server_ip,
-                   server->config->server_info->port));
+                       server_ip, port));
     return FALSE;
   }
   return TRUE;
 }
 
+/* Adds a secondary listener. */
+bool silc_server_init_secondary(SilcServer server)
+{
+  int sock=0, sock_list[server->config->param.connections_max];
+  SilcSocketConnection newsocket = NULL;
+  SilcServerConfigServerInfoInterface *interface;
+
+  for (interface = server->config->server_info->secondary; interface; 
+       interface = interface->next, sock++) {
+         
+    if (!silc_server_listen(server,
+       interface->server_ip, interface->port, &sock_list[sock]))
+      goto err;
+
+    /* Set socket to non-blocking mode */
+    silc_net_set_socket_nonblock(sock_list[sock]);
+
+    /* Add ourselves also to the socket table. The entry allocated above
+       is sent as argument for fast referencing in the future. */
+    silc_socket_alloc(sock_list[sock], 
+               SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
+    server->sockets[sock_list[sock]] = newsocket;
+
+    /* Perform name and address lookups to resolve the listenning address
+       and port. */
+    if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname,
+                           &newsocket->ip)) {
+      if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
+        !newsocket->ip) {
+        SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+                     newsocket->hostname ? newsocket->hostname :
+                     newsocket->ip ? newsocket->ip : ""));
+        server->stat.conn_failures++;
+        goto err;
+      }
+      if (!newsocket->hostname)
+        newsocket->hostname = strdup(newsocket->ip);
+    }
+    newsocket->port = silc_net_get_local_port(sock);
+    
+    newsocket->user_data = (void *)server->id_entry;
+    silc_schedule_task_add(server->schedule, sock_list[sock],
+                        silc_server_accept_new_connection,
+                        (void *)server, 0, 0,
+                        SILC_TASK_FD,
+                        SILC_TASK_PRI_NORMAL);
+
+  }
+
+  return TRUE;
+  
+err:
+
+  do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
+  return FALSE;
+
+}
+
 /* Initializes the entire SILC server. This is called always before running
    the server. This is called only once at the initialization of the program.
    This binds the server to its listenning port. After this function returns
@@ -218,7 +274,12 @@ bool silc_server_init(SilcServer server)
     goto err;
 
   /* Create a listening server */
-  if (!silc_server_listen(server, &sock))
+  if (!silc_server_listen(server,
+               server->config->server_info->primary == NULL ? NULL :
+                       server->config->server_info->primary->server_ip,
+               server->config->server_info->primary == NULL ? 0 :
+                       server->config->server_info->primary->port,
+               &sock))
     goto err;
 
   /* Set socket to non-blocking mode */
@@ -308,6 +369,10 @@ bool silc_server_init(SilcServer server)
                         (void *)server, 0, 0,
                         SILC_TASK_FD,
                         SILC_TASK_PRI_NORMAL);
+
+  if (silc_server_init_secondary(server) == FALSE)
+    goto err;
+  
   server->listenning = TRUE;
 
   /* If server connections has been configured then we must be router as
@@ -659,9 +724,10 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(server->config->server_info->server_ip,
-                                   sconn->remote_port,
-                                   sconn->remote_host);
+  sock = silc_net_create_connection(server->config->server_info->primary == NULL ? NULL :
+                server->config->server_info->primary->server_ip,
+                sconn->remote_port,
+                sconn->remote_host);
   if (sock < 0) {
     SILC_LOG_ERROR(("Could not connect to router %s:%d",
                    sconn->remote_host, sconn->remote_port));
@@ -1094,14 +1160,16 @@ static void
 silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                                         void *context)
 {
-  SilcServer server = (SilcServer)context;
-  SilcServerKEInternalContext *proto_ctx;
+  SilcServerKEInternalContext *proto_ctx = (SilcServerKEInternalContext *)context;
+  SilcServer server = (SilcServer)proto_ctx->server;
   SilcServerConfigClient *cconfig = NULL;
   SilcServerConfigServer *sconfig = NULL;
   SilcServerConfigRouter *rconfig = NULL;
   SilcServerConfigDeny *deny;
   int port;
 
+  context = (void *)server;
+
   SILC_LOG_DEBUG(("Start"));
 
   /* Check whether we could resolve both IP and FQDN. */
@@ -1114,6 +1182,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
                                  "Unknown host or IP");
+    silc_free(proto_ctx);
     return;
   }
 
@@ -1128,7 +1197,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   SILC_LOG_INFO(("Incoming connection %s (%s)", sock->hostname,
                 sock->ip));
 
-  port = server->sockets[server->sock]->port; /* Listenning port */
+  port = server->sockets[(SilcUInt32)proto_ctx->context]->port; /* Listenning port */
 
   /* Check whether this connection is denied to connect to us. */
   deny = silc_server_config_find_denied(server, sock->ip);
@@ -1142,6 +1211,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                  deny->reason);
     server->stat.conn_failures++;
+    silc_free(proto_ctx);
     return;
   }
 
@@ -1154,9 +1224,9 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
     sconfig = silc_server_config_find_server_conn(server, sock->hostname);
   if (server->server_type == SILC_ROUTER) {
     if (!(rconfig = silc_server_config_find_router_conn(server,
-                                                       sock->ip, port)))
+                                                       sock->ip, sock->port)))
       rconfig = silc_server_config_find_router_conn(server, sock->hostname,
-                                                   port);
+                                                   sock->port);
   }
   if (!cconfig && !sconfig && !rconfig) {
     SILC_LOG_INFO(("Connection %s (%s) is not allowed", sock->hostname,
@@ -1164,15 +1234,14 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER);
     server->stat.conn_failures++;
+    silc_free(proto_ctx);
     return;
   }
 
   /* The connection is allowed */
 
-  /* Allocate internal context for key exchange protocol. This is
+  /* Set internal context for key exchange protocol. This is
      sent as context for the protocol. */
-  proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
-  proto_ctx->server = context;
   proto_ctx->sock = sock;
   proto_ctx->rng = server->rng;
   proto_ctx->responder = TRUE;
@@ -1204,7 +1273,8 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   proto_ctx->timeout_task =
     silc_schedule_task_add(server->schedule, sock->sock,
                           silc_server_timeout_remote,
-                          context, server->config->key_exchange_timeout, 0,
+                          (void *)server,
+                          server->config->key_exchange_timeout, 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 }
@@ -1216,13 +1286,14 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
 {
   SilcServer server = (SilcServer)context;
   SilcSocketConnection newsocket;
+  SilcServerKEInternalContext *proto_ctx;
   int sock;
 
   SILC_LOG_DEBUG(("Accepting new connection"));
 
   server->stat.conn_attempts++;
 
-  sock = silc_net_accept_connection(server->sock);
+  sock = silc_net_accept_connection(fd);
   if (sock < 0) {
     SILC_LOG_ERROR(("Could not accept new connection: %s", strerror(errno)));
     server->stat.conn_failures++;
@@ -1249,9 +1320,12 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
   /* Perform asynchronous host lookup. This will lookup the IP and the
      FQDN of the remote connection. After the lookup is done the connection
      is accepted further. */
+  proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+  proto_ctx->server = server;
+  proto_ctx->context = (void *)fd;
   silc_socket_host_lookup(newsocket, TRUE,
-                         silc_server_accept_new_connection_lookup, context,
-                         server->schedule);
+                         silc_server_accept_new_connection_lookup,
+                         (void *)proto_ctx, server->schedule);
 }
 
 /* Second part of accepting new connection. Key exchange protocol has been
index 6d12da6f741aaed808effdb7f43f1f1a6e923a05..70322dd93b4ebfff4de2af22809369cf73f82cd1 100644 (file)
@@ -523,13 +523,15 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
   SilcServerConnection sconn = (SilcServerConnection)context;
   SilcServer server = sconn->server;
   int sock;
+  const char *server_ip;
 
   SILC_LOG_DEBUG(("Connecting to router %s:%d", sconn->remote_host,
                  sconn->remote_port));
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(server->config->server_info->server_ip,
-                                   sconn->remote_port,
+  server_ip = server->config->server_info->primary == NULL ? NULL :
+               server->config->server_info->primary->server_ip;
+  sock = silc_net_create_connection(server_ip, sconn->remote_port,
                                    sconn->remote_host);
   if (sock < 0) {
     silc_schedule_task_add(server->schedule, 0,
index 6252325bbf45f707db7633fe253980e5c8b1b742..3a8005324a44bce23b9e62630df7343475d0005c 100644 (file)
@@ -423,9 +423,8 @@ SILC_CONFIG_CALLBACK(fetch_pkcs)
 
 SILC_CONFIG_CALLBACK(fetch_serverinfo)
 {
-  SilcServerConfig config = (SilcServerConfig) context;
+  SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
   SilcServerConfigServerInfo *server_info = config->server_info;
-  int got_errno = 0;
 
   /* if there isn't the struct alloc it */
   if (!server_info)
@@ -433,8 +432,20 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
                silc_calloc(1, sizeof(*server_info));
 
   if (type == SILC_CONFIG_ARG_BLOCK) {
-    /* check for mandatory inputs */
-    if (!server_info->public_key || !server_info->private_key) {
+    if (!strcmp(name, "primary")) {
+      CONFIG_IS_DOUBLE(server_info->primary);
+      if (!tmp)
+       return SILC_CONFIG_OK;
+      server_info->primary = tmp;
+      config->tmp = NULL;
+      return SILC_CONFIG_OK;
+    } else if (!strcmp(name, "secondary")) {
+      if (!tmp)
+       return SILC_CONFIG_OK;
+      SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
+      config->tmp = NULL;
+      return SILC_CONFIG_OK;
+    } else if (!server_info->public_key || !server_info->private_key) {
       got_errno = SILC_CONFIG_EMISSFIELDS;
       goto got_err;
     }
@@ -445,18 +456,20 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
     server_info->server_name = strdup((char *) val);
   }
   else if (!strcmp(name, "ip")) {
-    CONFIG_IS_DOUBLE(server_info->server_ip);
-    server_info->server_ip = strdup((char *) val);
+    SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
+    CONFIG_IS_DOUBLE(tmp->server_ip);
+    tmp->server_ip = strdup((char *) val);
   }
   else if (!strcmp(name, "port")) {
     int port = *(int *)val;
+    SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
     if ((port <= 0) || (port > 65535)) {
       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
                             "Invalid port number!\n"));
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
-    server_info->port = (SilcUInt16) port;
+    tmp->port = (SilcUInt16) port;
   }
   else if (!strcmp(name, "servertype")) {
     CONFIG_IS_DOUBLE(server_info->server_type);
@@ -521,6 +534,9 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   return SILC_CONFIG_OK;
 
  got_err:
+  silc_free(tmp);
+  silc_free(config->tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
@@ -1032,10 +1048,16 @@ static const SilcConfigTable table_pkcs[] = {
   { 0, 0, 0, 0 }
 };
 
-static const SilcConfigTable table_serverinfo[] = {
-  { "hostname",                SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
+static const SilcConfigTable table_serverinfo_c[] = {
   { "ip",              SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
   { "port",            SILC_CONFIG_ARG_INT,    fetch_serverinfo, NULL},
+  { 0, 0, 0, 0 }
+};
+
+static const SilcConfigTable table_serverinfo[] = {
+  { "hostname",                SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
+  { "primary",         SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
+  { "secondary",       SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
   { "servertype",      SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
   { "location",                SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
   { "admin",           SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
@@ -1298,7 +1320,15 @@ void silc_server_config_destroy(SilcServerConfig config)
   if (config->server_info) {
     register SilcServerConfigServerInfo *si = config->server_info;
     silc_free(si->server_name);
-    silc_free(si->server_ip);
+    if (si->primary) {
+      silc_free(si->primary->server_ip);
+      silc_free(si->primary);
+    }
+    SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
+                                 si->secondary)
+      silc_free(di->server_ip);
+      silc_free(di);
+    }
     silc_free(si->server_type);
     silc_free(si->location);
     silc_free(si->admin);
index 91b749d1d7859ab3a5e6d89f463474621c0be6bc..70674b81cb1630974407be26cf1e5c62e94706e4 100644 (file)
@@ -49,10 +49,16 @@ typedef struct SilcServerConfigPkcsStruct {
   struct SilcServerConfigPkcsStruct *next;
 } SilcServerConfigPkcs;
 
-typedef struct SilcServerConfigServerInfoStruct {
-  char *server_name;
+typedef struct SilcServerConfigServerInfoInterfaceStruct {
   char *server_ip;
   SilcUInt16 port;
+  struct SilcServerConfigServerInfoInterfaceStruct *next;
+} SilcServerConfigServerInfoInterface;
+
+typedef struct SilcServerConfigServerInfoStruct {
+  char *server_name;
+  SilcServerConfigServerInfoInterface *primary;
+  SilcServerConfigServerInfoInterface *secondary;
   char *server_type;   /* E.g. "Test Server" */
   char *location;      /* geographic location */
   char *admin;         /* admin full name */