/* server_util.c Author: Pekka Riikonen Copyright (C) 1997 - 2006 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 the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /* $Id$ */ #include "silc.h" #include "silcserver.h" #include "server_internal.h" /* Return next available command identifier. */ SilcUInt16 silc_server_cmd_ident(SilcServer server) { SilcUInt16 cmd_ident; silc_mutex_lock(server->lock); cmd_ident = ++server->cmd_ident; silc_mutex_unlock(server->lock); return cmd_ident; } /* XXX locking */ SilcBool silc_server_check_watcher_list(SilcServer server, SilcClientEntry client, const char *new_nick, SilcNotifyType notify) { return TRUE; } /* This function is used to send the notify packets and motd to the incoming client connection. */ void silc_server_send_welcome(SilcServerAccept ac, SilcClientEntry client) { SilcServer server = ac->thread->server; SilcPacketStream stream = client->stream; SILC_LOG_DEBUG(("Send welcome notifys")); /* Send some nice info to the client */ SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("Welcome to the SILC Network %s", client->username)); SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("Your host is %s, running version %s", server->server_name, SILC_DIST_VERSION_STRING)); if (server->server_type == SILC_ROUTER) { SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("There are %d clients, %d servers and %d " "routers in SILC Network", server->stat.clients, server->stat.servers, server->stat.routers)); } else { if (server->stat.clients && server->stat.servers + 1) SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("There are %d clients, %d servers and %d " "routers in SILC Network", server->stat.clients, server->stat.servers, (server->standalone ? 0 : !server->stat.routers ? 1 : server->stat.routers))); } if (server->stat.cell_clients && server->stat.cell_servers + 1) SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("There are %d clients on %d servers in our cell", server->stat.cell_clients, server->stat.cell_servers)); if (server->server_type == SILC_ROUTER) { SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("I have %d clients, %d channels, %d servers and " "%d routers", server->stat.my_clients, server->stat.my_channels, server->stat.my_servers, server->stat.my_routers)); } else { SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("I have %d clients and %d channels formed", server->stat.my_clients, server->stat.my_channels)); } if (server->stat.server_ops || server->stat.router_ops) SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("There are %d server operators and %d router " "operators online", server->stat.server_ops, server->stat.router_ops)); if (server->stat.my_router_ops + server->stat.my_server_ops) SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("I have %d operators online", server->stat.my_router_ops + server->stat.my_server_ops)); SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("Your connection is secured with %s cipher, " "key length %d bits", silc_cipher_get_name(ac->prop->cipher), silc_cipher_get_key_len(ac->prop->cipher))); SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE, ("Your current nickname is %s", client->nickname)); /* Send motd */ silc_server_send_motd(server, stream); } /* Creates new Client ID. */ SilcBool silc_server_create_client_id(SilcServer server, char *nickname, SilcClientID *new_id) { unsigned char hash[16]; SilcBool finding = FALSE; SILC_LOG_DEBUG(("Creating new Client ID")); /* Create hash of the nickname (it's already checked as valid identifier string). */ silc_hash_make(server->md5hash, nickname, strlen(nickname), hash); /* Create the ID */ memset(new_id, 0, sizeof(*new_id)); memcpy(new_id->ip.data, server->id.ip.data, server->id.ip.data_len); new_id->ip.data_len = server->id.ip.data_len; new_id->rnd = silc_rng_get_byte(server->rng); memcpy(new_id->hash, hash, CLIENTID_HASH_LEN); /* Assure that the ID does not exist already */ while (1) { if (!silc_server_find_client_by_id(server, new_id, FALSE, NULL)) break; /* The ID exists, start increasing the rnd from 0 until we find a ID that does not exist. If we wrap and it still exists then we will return FALSE and the caller must send some other nickname since this cannot be used anymore. */ new_id->rnd++; if (finding && new_id->rnd == 0) return FALSE; if (!finding) { new_id->rnd = 0; finding = TRUE; } } SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_CLIENT))); return TRUE; } /* Creates a Server ID. */ SilcBool silc_server_create_server_id(SilcServer server, const char *ip, SilcUInt16 port, SilcServerID *new_id) { SILC_LOG_DEBUG(("Creating new Server ID")); if (!new_id) return FALSE; /* Create the ID */ if (!silc_net_addr2bin(ip, new_id->ip.data, sizeof(new_id->ip.data))) return FALSE; new_id->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16; new_id->port = SILC_SWAB_16(port); new_id->rnd = silc_rng_get_rn16(server->rng); SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_SERVER))); return TRUE; } /* Checks whether the `server_id' is valid. It must be based to the IP address provided in the `remote' socket connection. */ SilcBool silc_server_check_server_id(const char *ip_address, SilcServerID *server_id) { unsigned char ip[16]; if (!silc_net_addr2bin(ip_address, ip, sizeof(ip))) return FALSE; if (silc_net_is_ip4(ip_address)) { if (!memcmp(server_id->ip.data, ip, 4)) return TRUE; } else { if (!memcmp(server_id->ip.data, ip, 16)) return TRUE; } return FALSE; }