- return strdup(buf);
-}
-
-/* Renders ID to suitable to print for example to log file. */
-
-static char rid[256];
-#define _PUT_STRING(__d__, __s__) \
-do { \
- int __sp = sizeof(__d__) - 1 - strlen(__d__); \
- if (__sp < strlen(__s__)) { \
- if (__sp) \
- strncat(__d__, __s__, (sizeof(__d__) - 1) - strlen(__d__)); \
- } else { \
- strncat(__d__, __s__, strlen(__s__)); \
- } \
-} while(0)
-
-char *silc_id_render(void *id, SilcUInt16 type)
-{
- char tmp[100];
- unsigned char tmps[2];
- char *cp;
-
- memset(rid, 0, sizeof(rid));
- switch(type) {
- case SILC_ID_SERVER:
- {
- SilcServerID *server_id = (SilcServerID *)id;
- if (server_id->ip.data_len > 4) {
-#ifdef HAVE_IPV6
- struct sockaddr_in6 ipv6;
- memset(&ipv6, 0, sizeof(ipv6));
- ipv6.sin6_family = AF_INET6;
- memmove(&ipv6.sin6_addr, server_id->ip.data, sizeof(ipv6.sin6_addr));
- if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
- tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
- _PUT_STRING(rid, tmp);
-#endif
- } else {
- struct in_addr ipv4;
- memmove(&ipv4.s_addr, server_id->ip.data, 4);
- cp = inet_ntoa(ipv4);
- if (cp)
- _PUT_STRING(rid, cp);
- }
-
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(server_id->port));
- _PUT_STRING(rid, tmp);
- SILC_PUT16_MSB(server_id->rnd, tmps);
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
- _PUT_STRING(rid, tmp);
- }
- break;
- case SILC_ID_CLIENT:
- {
- SilcClientID *client_id = (SilcClientID *)id;
- if (client_id->ip.data_len > 4) {
-#ifdef HAVE_IPV6
- struct sockaddr_in6 ipv6;
- memset(&ipv6, 0, sizeof(ipv6));
- ipv6.sin6_family = AF_INET6;
- memmove(&ipv6.sin6_addr, client_id->ip.data, sizeof(ipv6.sin6_addr));
- if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
- tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
- _PUT_STRING(rid, tmp);
-#endif
- } else {
- struct in_addr ipv4;
- memmove(&ipv4.s_addr, client_id->ip.data, 4);
- cp = inet_ntoa(ipv4);
- if (cp)
- _PUT_STRING(rid, cp);
- }
-
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, ",%02x,", client_id->rnd);
- _PUT_STRING(rid, tmp);
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x %02x %02x...]",
- client_id->hash[0], client_id->hash[1],
- client_id->hash[2], client_id->hash[3]);
- _PUT_STRING(rid, tmp);
- }
- break;
- case SILC_ID_CHANNEL:
- {
- SilcChannelID *channel_id = (SilcChannelID *)id;
- if (channel_id->ip.data_len > 4) {
-#ifdef HAVE_IPV6
- struct sockaddr_in6 ipv6;
- memset(&ipv6, 0, sizeof(ipv6));
- ipv6.sin6_family = AF_INET6;
- memmove(&ipv6.sin6_addr, channel_id->ip.data, sizeof(ipv6.sin6_addr));
- if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
- tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
- _PUT_STRING(rid, tmp);
-#endif
- } else {
- struct in_addr ipv4;
- memmove(&ipv4.s_addr, channel_id->ip.data, 4);
- cp = inet_ntoa(ipv4);
- if (cp)
- _PUT_STRING(rid, cp);
- }
-
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(channel_id->port));
- _PUT_STRING(rid, tmp);
- SILC_PUT16_MSB(channel_id->rnd, tmps);
- memset(tmp, 0, sizeof(tmp));
- snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
- _PUT_STRING(rid, tmp);
- }
- break;
- }
-
- return rid;
-}
-#undef _PUT_STRING
-
-/* Compares two strings. Strings may include wildcards '*' and '?'.
- Returns TRUE if strings match. */
-
-int silc_string_compare(char *string1, char *string2)
-{
- int i;
- int slen1;
- int slen2;
- char *tmpstr1, *tmpstr2;
-
- if (!string1 || !string2)
- return FALSE;
-
- slen1 = strlen(string1);
- slen2 = strlen(string2);
-
- /* See if they are same already */
- if (!strncmp(string1, string2, slen2) && slen2 == slen1)
- return TRUE;
-
- if (slen2 < slen1)
- if (!strchr(string1, '*'))
- return FALSE;
-
- /* Take copies of the original strings as we will change them */
- tmpstr1 = silc_calloc(slen1 + 1, sizeof(char));
- memcpy(tmpstr1, string1, slen1);
- tmpstr2 = silc_calloc(slen2 + 1, sizeof(char));
- memcpy(tmpstr2, string2, slen2);
-
- for (i = 0; i < slen1; i++) {
-
- /* * wildcard. Only one * wildcard is possible. */
- if (tmpstr1[i] == '*')
- if (!strncmp(tmpstr1, tmpstr2, i)) {
- memset(tmpstr2, 0, slen2);
- strncpy(tmpstr2, tmpstr1, i);
- break;
- }
-
- /* ? wildcard */
- if (tmpstr1[i] == '?') {
- if (!strncmp(tmpstr1, tmpstr2, i)) {
- if (!(slen1 < i + 1))
- if (tmpstr1[i + 1] != '?' &&
- tmpstr1[i + 1] != tmpstr2[i + 1])
- continue;
-
- if (!(slen1 < slen2))
- tmpstr2[i] = '?';
- }
- }
- }
-
- /* if using *, remove it */
- if (strchr(tmpstr1, '*'))
- *strchr(tmpstr1, '*') = 0;
-
- if (!strcmp(tmpstr1, tmpstr2)) {
- memset(tmpstr1, 0, slen1);
- memset(tmpstr2, 0, slen2);
- silc_free(tmpstr1);
- silc_free(tmpstr2);
- return TRUE;
- }
-
- memset(tmpstr1, 0, slen1);
- memset(tmpstr2, 0, slen2);
- silc_free(tmpstr1);
- silc_free(tmpstr2);
- return FALSE;
-}
-
-/* Basic has function to hash strings. May be used with the SilcHashTable.
- Note that this lowers the characters of the string (with tolower()) so
- this is used usually with nicknames, channel and server names to provide
- case insensitive keys. */
-
-SilcUInt32 silc_hash_string(void *key, void *user_context)
-{
- char *s = (char *)key;
- SilcUInt32 h = 0, g;
-
- while (*s != '\0') {
- h = (h << 4) + tolower(*s);
- if ((g = h & 0xf0000000)) {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
- s++;
- }
-
- return h;
-}
-
-/* Basic hash function to hash integers. May be used with the SilcHashTable. */
-
-SilcUInt32 silc_hash_uint(void *key, void *user_context)
-{
- return *(SilcUInt32 *)key;
-}
-
-/* Basic hash funtion to hash pointers. May be used with the SilcHashTable. */
-
-SilcUInt32 silc_hash_ptr(void *key, void *user_context)
-{
- return (SilcUInt32)key;
-}
-
-/* Hash a ID. The `user_context' is the ID type. */
-
-SilcUInt32 silc_hash_id(void *key, void *user_context)
-{
- SilcIdType id_type = (SilcIdType)(SilcUInt32)user_context;
- SilcUInt32 h = 0;
- int i;
-
- switch (id_type) {
- case SILC_ID_CLIENT:
- {
- SilcClientID *id = (SilcClientID *)key;
-
- /* The client ID is hashed by hashing the hash of the ID
- (which is a truncated MD5 hash of the nickname) so that we
- can access the entry from the cache with both Client ID but
- with just a hash from the ID as well. */
- return silc_hash_client_id_hash(id->hash, NULL);
- }
- break;
- case SILC_ID_SERVER:
- {
- SilcServerID *id = (SilcServerID *)key;
-
- h = id->port * id->rnd;
- for (i = 0; i < id->ip.data_len; i++)
- h ^= id->ip.data[i];
-
- return h;
- }
- break;
- case SILC_ID_CHANNEL:
- {
- SilcChannelID *id = (SilcChannelID *)key;
-
- h = id->port * id->rnd;
- for (i = 0; i < id->ip.data_len; i++)
- h ^= id->ip.data[i];
-
- return h;
- }
- break;
- default:
- break;
- }
-
- return h;
-}
-
-/* Hash Client ID's hash. */
-
-SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context)
-{
- int i;
- unsigned char *hash = key;
- SilcUInt32 h = 0, g;
-
- for (i = 0; i < CLIENTID_HASH_LEN; i++) {
- h = (h << 4) + hash[i];
- if ((g = h & 0xf0000000)) {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
- }
-
- return h;
-}
-
-/* Hash binary data. The `user_context' is the data length. */
-
-SilcUInt32 silc_hash_data(void *key, void *user_context)
-{
- SilcUInt32 len = (SilcUInt32)user_context, h = 0;
- unsigned char *data = (unsigned char *)key;
- int i;
-
- h = (data[0] * data[len - 1] + 1) * len;
- for (i = 0; i < len; i++)
- h ^= data[i];
-
- return h;
-}
-
-/* Hashed SILC Public key. */
-
-SilcUInt32 silc_hash_public_key(void *key, void *user_context)
-{
- SilcPublicKey pk = (SilcPublicKey)key;
- return (pk->len + silc_hash_string(pk->name, NULL) +
- silc_hash_string(pk->identifier, NULL) +
- silc_hash_data(pk->pk, (void *)pk->pk_len));
-}
-
-/* Compares two strings. It may be used as SilcHashTable comparison
- function. */
-
-bool silc_hash_string_compare(void *key1, void *key2, void *user_context)
-{
- return !strcasecmp((char *)key1, (char *)key2);
-}
-
-/* Compares two ID's. May be used as SilcHashTable comparison function.
- The Client ID's compares only the hash of the Client ID not any other
- part of the Client ID. Other ID's are fully compared. */
-
-bool silc_hash_id_compare(void *key1, void *key2, void *user_context)
-{
- SilcIdType id_type = (SilcIdType)(SilcUInt32)user_context;
- return (id_type == SILC_ID_CLIENT ?
- SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
- SILC_ID_COMPARE_TYPE(key1, key2, id_type));
-}
-
-/* Compare two Client ID's entirely and not just the hash from the ID. */
-
-bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context)
-{
- return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
-}
-
-/* Compares binary data. May be used as SilcHashTable comparison function. */
-
-bool silc_hash_data_compare(void *key1, void *key2, void *user_context)
-{
- SilcUInt32 len = (SilcUInt32)user_context;
- return !memcmp(key1, key2, len);