/*
serverid.c
Author: Pekka Riikonen <priikone@silcnet.org>
Copyright (C) 1997 - 2005 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; either version 2 of the License, or
(at your option) any later version.
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: serverid.c,v 1.13.2.3 2005/03/30 12:24:54 priikone Exp $ */
#include "serverincludes.h"
#include "server_internal.h"
/* Creates a Server ID. Newly created Server ID is returned to the
new_id argument. */
void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
SilcServerID **new_id)
{
SILC_LOG_DEBUG(("Creating new Server ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
/* Create the ID */
if (!silc_net_addr2bin(ip, (*new_id)->ip.data,
sizeof((*new_id)->ip.data))) {
silc_free(*new_id);
*new_id = NULL;
return;
}
(*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(rng);
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
}
/* Creates Client ID. This assures that there are no collisions in the
created Client IDs. If the collision would occur (meaning that there
are 2^8 occurences of the `nickname' this will return FALSE, and the
caller must recall the function with different nickname. If this returns
TRUE the new ID was created successfully. */
bool silc_id_create_client_id(SilcServer server,
SilcServerID *server_id, SilcRng rng,
SilcHash md5hash,
unsigned char *nickname, SilcUInt32 nick_len,
SilcClientID **new_id)
{
unsigned char hash[16];
bool finding = FALSE;
SILC_LOG_DEBUG(("Creating new Client ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
/* Create hash of the nickname (it's already checked as valid identifier
string). */
silc_hash_make(md5hash, nickname, nick_len, hash);
/* Create the 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(rng);
memcpy((*new_id)->hash, hash, CLIENTID_HASH_LEN);
/* Assure that the ID does not exist already */
while (1) {
if (!silc_idlist_find_client_by_id(server->local_list,
*new_id, FALSE, NULL))
if (!silc_idlist_find_client_by_id(server->global_list,
*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 Channel ID */
bool silc_id_create_channel_id(SilcServer server,
SilcServerID *router_id, SilcRng rng,
SilcChannelID **new_id)
{
bool finding = TRUE;
SILC_LOG_DEBUG(("Creating new Channel ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
/* Create the ID */
memcpy((*new_id)->ip.data, router_id->ip.data, router_id->ip.data_len);
(*new_id)->ip.data_len = router_id->ip.data_len;
(*new_id)->port = router_id->port;
(*new_id)->rnd = silc_rng_get_rn16(rng);
/* Assure that the ID does not exist already */
while (1) {
if (!silc_idlist_find_channel_by_id(server->local_list,
*new_id, NULL))
break;
(*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_CHANNEL)));
return TRUE;
}
/* Checks whether the `server_id' is valid. It must be based to the
IP address provided in the `remote' socket connection. */
bool silc_id_is_valid_server_id(SilcServer server,
SilcServerID *server_id,
SilcSocketConnection remote)
{
unsigned char ip[16];
if (!silc_net_addr2bin(remote->ip, ip, sizeof(ip)))
return FALSE;
if (silc_net_is_ip4(remote->ip)) {
if (!memcmp(server_id->ip.data, ip, 4))
return TRUE;
} else {
if (!memcmp(server_id->ip.data, ip, 16))
return TRUE;
}
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1