5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
23 static char *silc_create_pk_identifier(void)
25 char *username = NULL, *realname = NULL;
26 char *hostname, email[256];
30 realname = silc_get_real_name();
33 hostname = silc_net_localhost();
35 fprintf(stderr, "Could not resolve local hostname/IP address");
39 /* Get username (mandatory) */
40 username = silc_get_username();
42 fprintf(stderr, "Could not determine username");
46 /* Create default email address, whether it is right or not */
47 silc_snprintf(email, sizeof(email), "%s@%s", username, hostname);
49 ident = silc_pkcs_silc_encode_identifier(NULL, username, hostname, realname,
50 email, NULL, NULL, NULL);
59 /* Generate key pair */
61 SilcBool silc_create_key_pair(const char *pkcs_name,
62 SilcUInt32 key_len_bits,
63 const char *pub_filename,
64 const char *prv_filename,
65 const char *pub_identifier,
66 const char *passphrase,
67 SilcPublicKey *return_public_key,
68 SilcPrivateKey *return_private_key,
73 char *pkfile = pub_filename ? strdup(pub_filename) : NULL;
74 char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
75 char *alg = pkcs_name ? strdup(pkcs_name) : NULL;
76 char *identifier = pub_identifier ? strdup(pub_identifier) : NULL;
77 char *pass = passphrase ? strdup(passphrase) : NULL;
78 SilcPublicKey public_key;
79 SilcPrivateKey private_key;
81 if (interactive && (!alg || !pub_filename || !prv_filename))
83 New pair of keys will be created. Please, answer to following questions.\n\
89 alg = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
93 if (*alg == 'l' || *alg == 'L') {
94 char *list = silc_pkcs_get_supported();
106 if (!silc_pkcs_find_algorithm(alg, NULL)) {
107 fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library"
108 "is not initialized", alg);
115 length = silc_get_input("Key length in key_len_bits [2048]: ", FALSE);
117 key_len_bits = atoi(length);
125 char *def = silc_create_pk_identifier();
128 memset(line, 0, sizeof(line));
130 silc_snprintf(line, sizeof(line), "Identifier [%s]: ", def);
132 silc_snprintf(line, sizeof(line),
133 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
134 "RN=Jon Johnson, E=jon@dummy.com): ");
136 while (!identifier) {
137 identifier = silc_get_input(line, FALSE);
138 if (!identifier && def)
139 identifier = strdup(def);
143 fprintf(stderr, "Could not create public key identifier\n");
146 identifier = strdup(def);
152 if (!strstr(identifier, "UN=") || !strstr(identifier, "HN=")) {
153 fprintf(stderr, "Invalid public key identifier. You must specify both "
158 rng = silc_rng_alloc();
160 silc_rng_global_init(rng);
164 memset(line, 0, sizeof(line));
165 silc_snprintf(line, sizeof(line), "Public key filename [public_key.pub]: ");
166 pkfile = silc_get_input(line, FALSE);
169 pkfile = strdup("public_key.pub");
174 memset(line, 0, sizeof(line));
175 silc_snprintf(line, sizeof(line), "Private key filename [private_key.prv]: ");
176 prvfile = silc_get_input(line, FALSE);
179 prvfile = strdup("private_key.prv");
185 pass = silc_get_input("Private key passphrase: ", TRUE);
192 pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
195 match = !strcmp(pass, pass2);
199 fprintf(stderr, "\nPassphrases do not match\n\n");
205 printf("\nGenerating the key pair...\n");
208 if (!silc_pkcs_silc_generate_key(alg, key_len_bits,
209 identifier, rng, &public_key,
213 /* Save public key into file */
214 if (!silc_pkcs_save_public_key(pkfile, public_key, SILC_PKCS_FILE_BASE64))
217 /* Save private key into file */
218 if (!silc_pkcs_save_private_key(prvfile, private_key,
219 (const unsigned char *)pass, strlen(pass),
220 SILC_PKCS_FILE_BIN, rng))
223 if (return_public_key)
224 *return_public_key = public_key;
226 silc_pkcs_public_key_free(public_key);
228 if (return_private_key)
229 *return_private_key = private_key;
231 silc_pkcs_private_key_free(private_key);
233 printf("Public key has been saved into `%s'.\n", pkfile);
234 printf("Private key has been saved into `%s'.\n", prvfile);
236 printf("Press <Enter> to continue...\n");
244 silc_free(identifier);
245 memset(pass, 0, strlen(pass));
253 SilcBool silc_load_key_pair(const char *pub_filename,
254 const char *prv_filename,
255 const char *passphrase,
256 SilcPublicKey *return_public_key,
257 SilcPrivateKey *return_private_key)
259 char *pass = passphrase ? strdup(passphrase) : NULL;
261 SILC_LOG_DEBUG(("Loading public and private keys"));
263 if (!silc_pkcs_load_public_key(pub_filename,
264 SILC_PKCS_ANY, return_public_key)) {
266 memset(pass, 0, strlen(pass));
272 pass = silc_get_input("Private key passphrase: ", TRUE);
277 if (!silc_pkcs_load_private_key(prv_filename,
278 (const unsigned char *)pass, strlen(pass),
280 return_private_key)) {
281 silc_pkcs_public_key_free(*return_public_key);
282 *return_public_key = NULL;
283 memset(pass, 0, strlen(pass));
288 memset(pass, 0, strlen(pass));
293 /* Dump public key into stdout */
295 SilcBool silc_show_public_key(SilcPublicKey public_key)
297 SilcSILCPublicKey silc_pubkey;
298 SilcPublicKeyIdentifier ident;
299 char *fingerprint, *babbleprint;
302 SilcUInt32 key_len = 0;
304 silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
308 ident = &silc_pubkey->identifier;
309 key_len = silc_pkcs_public_key_get_len(public_key);
310 pk = silc_pkcs_public_key_encode(NULL, public_key, &pk_len);
313 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
314 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
316 printf("Algorithm : %s\n", silc_pkcs_get_name(public_key));
318 printf("Key length (bits) : %d\n", (unsigned int)key_len);
320 printf("Version : %s\n", ident->version);
322 printf("Real name : %s\n", ident->realname);
324 printf("Username : %s\n", ident->username);
326 printf("Hostname : %s\n", ident->host);
328 printf("Email : %s\n", ident->email);
330 printf("Organization : %s\n", ident->org);
332 printf("Country : %s\n", ident->country);
333 printf("Fingerprint (SHA1) : %s\n", fingerprint);
334 printf("Babbleprint (SHA1) : %s\n", babbleprint);
338 silc_free(fingerprint);
339 silc_free(babbleprint);
345 /* Dump public key into stdout */
347 SilcBool silc_show_public_key_file(const char *pub_filename)
349 SilcPublicKey public_key;
352 if (!silc_pkcs_load_public_key((char *)pub_filename,
353 SILC_PKCS_ANY, &public_key)) {
354 fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
358 printf("Public key file : %s\n", pub_filename);
359 ret = silc_show_public_key(public_key);
360 silc_pkcs_public_key_free(public_key);
365 /* Change private key passphrase */
367 SilcBool silc_change_private_key_passphrase(const char *prv_filename,
368 const char *old_passphrase,
369 const char *new_passphrase)
371 SilcPrivateKey private_key;
375 pass = old_passphrase ? strdup(old_passphrase) : NULL;
377 pass = silc_get_input("Old passphrase: ", TRUE);
382 if (!silc_pkcs_load_private_key(prv_filename,
383 (const unsigned char *)pass, strlen(pass),
386 memset(pass, 0, strlen(pass));
388 fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
392 memset(pass, 0, strlen(pass));
395 pass = new_passphrase ? strdup(new_passphrase) : NULL;
398 fprintf(stdout, "\n");
399 pass = silc_get_input("New passphrase: ", TRUE);
405 pass2 = silc_get_input("Retype new passphrase: ", TRUE);
408 if (!strcmp(pass, pass2))
410 fprintf(stderr, "\nPassphrases do not match");
416 rng = silc_rng_alloc();
419 silc_pkcs_save_private_key((char *)prv_filename, private_key,
420 (unsigned char *)pass, strlen(pass),
421 SILC_PKCS_FILE_BIN, rng);
423 fprintf(stdout, "\nPassphrase changed\n");
425 memset(pass, 0, strlen(pass));
428 silc_pkcs_private_key_free(private_key);
434 /* Checks that the 'identifier' string is valid identifier string
435 and does not contain any unassigned or prohibited character. This
436 function is used to check for valid nicknames, channel names,
437 server names, usernames, hostnames, service names, algorithm names,
438 other security property names, and SILC Public Key name. */
440 unsigned char *silc_identifier_check(const unsigned char *identifier,
441 SilcUInt32 identifier_len,
442 SilcStringEncoding identifier_encoding,
443 SilcUInt32 max_allowed_length,
446 unsigned char *utf8s;
447 SilcUInt32 utf8s_len;
448 SilcStringprepStatus status;
450 if (!identifier || !identifier_len)
453 if (max_allowed_length && identifier_len > max_allowed_length)
456 status = silc_stringprep(identifier, identifier_len,
457 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
458 &utf8s, &utf8s_len, SILC_STRING_UTF8);
459 if (status != SILC_STRINGPREP_OK) {
460 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
465 *out_len = utf8s_len;
470 /* Same as above but does not allocate memory, just checks the
471 validity of the string. */
473 SilcBool silc_identifier_verify(const unsigned char *identifier,
474 SilcUInt32 identifier_len,
475 SilcStringEncoding identifier_encoding,
476 SilcUInt32 max_allowed_length)
478 SilcStringprepStatus status;
480 if (!identifier || !identifier_len)
483 if (max_allowed_length && identifier_len > max_allowed_length)
486 status = silc_stringprep(identifier, identifier_len,
487 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
488 NULL, NULL, SILC_STRING_UTF8);
489 if (status != SILC_STRINGPREP_OK) {
490 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
497 unsigned char *silc_channel_name_check(const unsigned char *identifier,
498 SilcUInt32 identifier_len,
499 SilcStringEncoding identifier_encoding,
500 SilcUInt32 max_allowed_length,
503 unsigned char *utf8s;
504 SilcUInt32 utf8s_len;
505 SilcStringprepStatus status;
507 if (!identifier || !identifier_len)
510 if (max_allowed_length && identifier_len > max_allowed_length)
513 status = silc_stringprep(identifier, identifier_len,
514 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
515 &utf8s, &utf8s_len, SILC_STRING_UTF8);
516 if (status != SILC_STRINGPREP_OK) {
517 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
522 *out_len = utf8s_len;
527 /* Same as above but does not allocate memory, just checks the
528 validity of the string. */
530 SilcBool silc_channel_name_verify(const unsigned char *identifier,
531 SilcUInt32 identifier_len,
532 SilcStringEncoding identifier_encoding,
533 SilcUInt32 max_allowed_length)
535 SilcStringprepStatus status;
537 if (!identifier || !identifier_len)
540 if (max_allowed_length && identifier_len > max_allowed_length)
543 status = silc_stringprep(identifier, identifier_len,
544 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
545 NULL, NULL, SILC_STRING_UTF8);
546 if (status != SILC_STRINGPREP_OK) {
547 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
554 /* Return mode list */
556 SilcBool silc_get_mode_list(SilcBuffer mode_list, SilcUInt32 mode_list_count,
561 if (silc_buffer_len(mode_list) / 4 != mode_list_count)
564 *list = silc_calloc(mode_list_count, sizeof(**list));
566 for (i = 0; i < mode_list_count; i++) {
567 SILC_GET32_MSB((*list)[i], mode_list->data);
568 silc_buffer_pull(mode_list, 4);
571 silc_buffer_push(mode_list, mode_list->data - mode_list->head);
576 /* Status message structure. Messages are defined below. */
582 #define STAT(x) SILC_STATUS_ERR_##x
583 static const SilcStatusMessage silc_status_messages[] = {
585 { STAT(NO_SUCH_NICK), "There was no such nickname" },
586 { STAT(NO_SUCH_CHANNEL), "There was no such channel" },
587 { STAT(NO_SUCH_SERVER), "There was no such server" },
588 { STAT(INCOMPLETE_INFORMATION), "Incomplete registration information" },
589 { STAT(NO_RECIPIENT), "No recipient given" },
590 { STAT(UNKNOWN_COMMAND), "Unknown command" },
591 { STAT(WILDCARDS), "Wilcrads not allowed" },
592 { STAT(NO_CLIENT_ID), "No Client ID given" },
593 { STAT(NO_CHANNEL_ID), "No Channel ID given" },
594 { STAT(NO_SERVER_ID), "No Server ID given" },
595 { STAT(BAD_CLIENT_ID), "Bad Client ID" },
596 { STAT(BAD_CHANNEL_ID), "Bad Channel ID" },
597 { STAT(NO_SUCH_CLIENT_ID), "There is no such client" },
598 { STAT(NO_SUCH_CHANNEL_ID),"There is no such channel" },
599 { STAT(NICKNAME_IN_USE), "Nickname already exists" },
600 { STAT(NOT_ON_CHANNEL), "You are not on that channel" },
601 { STAT(USER_NOT_ON_CHANNEL),"They are not on the channel" },
602 { STAT(USER_ON_CHANNEL), "User already on the channel" },
603 { STAT(NOT_REGISTERED), "You have not registered" },
604 { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
605 { STAT(TOO_MANY_PARAMS), "Too many parameters" },
606 { STAT(PERM_DENIED), "Permission denied" },
607 { STAT(BANNED_FROM_SERVER),"You are not allowed to connect" },
608 { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
609 { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
610 { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" },
611 { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" },
612 { STAT(UNKNOWN_MODE), "Unknown mode" },
613 { STAT(NOT_YOU), "Cannot change mode for other users" },
614 { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" },
615 { STAT(NO_CHANNEL_FOPRIV),"Permission denied. You are not channel founder" },
616 { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" },
617 { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" },
618 { STAT(BAD_NICKNAME), "Bad nickname" },
619 { STAT(BAD_CHANNEL), "Bad channel name" },
620 { STAT(AUTH_FAILED), "Authentication failed" },
621 { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" },
622 { STAT(NO_SUCH_SERVER_ID), "No such Server ID" },
623 { STAT(RESOURCE_LIMIT), "No more free resources" },
624 { STAT(NO_SUCH_SERVICE), "Service doesn't exist" },
625 { STAT(NOT_AUTHENTICATED), "You have not been authenticated" },
626 { STAT(BAD_SERVER_ID), "Server ID is not valid" },
627 { STAT(KEY_EXCHANGE_FAILED), "Key exchange failed" },
628 { STAT(BAD_VERSION), "Bad version" },
629 { STAT(TIMEDOUT), "Service timed out" },
630 { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
631 { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
632 { STAT(BAD_SERVER), "Bad server name" },
633 { STAT(BAD_USERNAME), "Bad user name" },
634 { STAT(NO_SUCH_PUBLIC_KEY), "Unknown public key" },
639 /* Returns status message string */
641 const char *silc_get_status_message(unsigned char status)
645 for (i = 0; silc_status_messages[i].message; i++) {
646 if (silc_status_messages[i].status == status)
650 if (silc_status_messages[i].message == NULL)
653 return silc_status_messages[i].message;
656 static const char *packet_name[] = {
667 "PRIVATE MESSAGE KEY",
673 "CONNECTION AUTH REQUEST",
688 /* Returns packet type name */
690 const char *silc_get_packet_name(unsigned char type)
692 if (type >= SILC_PACKET_MAX)
694 if (type >= SILC_PACKET_PRIVATE)
695 return "PRIVATE RANGE";
696 if (type > (sizeof(packet_name) / sizeof(*packet_name)))
698 return packet_name[type];
701 static const char *command_name[] = {
732 /* Returns command name */
734 const char *silc_get_command_name(unsigned char command)
736 if (command >= SILC_COMMAND_RESERVED)
738 if (command >= SILC_COMMAND_PRIVATE)
739 return "PRIVATE RANGE";
740 if (command > (sizeof(command_name) / sizeof(*command_name)))
742 return command_name[command];
745 /* Parses SILC protocol style version string. */
747 SilcBool silc_parse_version_string(const char *version,
748 SilcUInt32 *protocol_version,
749 char **protocol_version_string,
750 SilcUInt32 *software_version,
751 char **software_version_string,
752 char **vendor_version)
755 int maj = 0, min = 0;
757 if (!strstr(version, "SILC-"))
760 cp = (char *)version + 5;
764 /* Take protocol version */
767 if (!strchr(cp, '.'))
769 cp = strchr(cp, '.') + 1;
774 memset(buf, 0, sizeof(buf));
775 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
776 if (protocol_version)
777 *protocol_version = atoi(buf);
778 memset(buf, 0, sizeof(buf));
779 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
780 if (protocol_version_string)
781 *protocol_version_string = strdup(buf);
783 /* Take software version */
787 if (!strchr(cp, '-'))
789 cp = strchr(cp, '-') + 1;
794 if (strchr(cp, '.')) {
795 cp = strchr(cp, '.') + 1;
800 memset(buf, 0, sizeof(buf));
801 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
802 if (software_version)
803 *software_version = atoi(buf);
804 memset(buf, 0, sizeof(buf));
805 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
806 if (software_version_string)
807 *software_version_string = strdup(buf);
809 /* Take vendor string */
811 if (strchr(cp, '.')) {
812 cp = strchr(cp, '.') + 1;
813 if (cp && *cp && vendor_version)
814 *vendor_version = strdup(cp);
815 } else if (strchr(cp, ' ')) {
816 cp = strchr(cp, ' ') + 1;
817 if (cp && *cp && vendor_version)
818 *vendor_version = strdup(cp);
824 /* Converts version string x.x into number representation. */
826 SilcUInt32 silc_version_to_num(const char *version)
828 int maj = 0, min = 0;
834 cp = (char *)version;
836 cp = strchr(cp, '.');
840 memset(buf, 0, sizeof(buf));
841 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
842 return (SilcUInt32)atoi(buf);
845 /* Parses mode mask and returns the mode as string. */
847 char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
854 memset(string, 0, sizeof(string));
856 if (mode & SILC_CHANNEL_MODE_PRIVATE)
857 strncat(string, "p", 1);
859 if (mode & SILC_CHANNEL_MODE_SECRET)
860 strncat(string, "s", 1);
862 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
863 strncat(string, "k", 1);
865 if (mode & SILC_CHANNEL_MODE_INVITE)
866 strncat(string, "i", 1);
868 if (mode & SILC_CHANNEL_MODE_TOPIC)
869 strncat(string, "t", 1);
871 if (mode & SILC_CHANNEL_MODE_ULIMIT)
872 strncat(string, "l", 1);
874 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
875 strncat(string, "a", 1);
877 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
878 strncat(string, "f", 1);
880 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
881 strncat(string, "C", 1);
883 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
884 strncat(string, "m", 1);
886 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
887 strncat(string, "M", 1);
889 if (mode & SILC_CHANNEL_MODE_CIPHER)
890 strncat(string, "c", 1);
892 if (mode & SILC_CHANNEL_MODE_HMAC)
893 strncat(string, "h", 1);
895 if (mode & SILC_CHANNEL_MODE_CIPHER) {
896 if (strlen(cipher) + strlen(string) + 1< sizeof(string)) {
897 strncat(string, " ", 1);
898 strncat(string, cipher, strlen(cipher));
902 if (mode & SILC_CHANNEL_MODE_HMAC) {
903 if (strlen(hmac) + strlen(string) + 1< sizeof(string)) {
904 strncat(string, " ", 1);
905 strncat(string, hmac, strlen(hmac));
909 /* Rest of mode is ignored */
911 return strdup(string);
914 /* Parses channel user mode mask and returns te mode as string */
916 char *silc_client_chumode(SilcUInt32 mode)
923 memset(string, 0, sizeof(string));
925 if (mode & SILC_CHANNEL_UMODE_CHANFO)
926 strncat(string, "f", 1);
928 if (mode & SILC_CHANNEL_UMODE_CHANOP)
929 strncat(string, "o", 1);
931 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
932 strncat(string, "b", 1);
934 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
935 strncat(string, "u", 1);
937 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
938 strncat(string, "r", 1);
940 if (mode & SILC_CHANNEL_UMODE_QUIET)
941 strncat(string, "q", 1);
943 return strdup(string);
946 /* Parses channel user mode and returns it as special mode character. */
948 char *silc_client_chumode_char(SilcUInt32 mode)
955 memset(string, 0, sizeof(string));
957 if (mode & SILC_CHANNEL_UMODE_CHANFO)
958 strncat(string, "*", 1);
960 if (mode & SILC_CHANNEL_UMODE_CHANOP)
961 strncat(string, "@", 1);
963 if (mode & SILC_CHANNEL_UMODE_QUIET)
964 strncat(string, "&", 1);
966 return strdup(string);
969 /* Renders ID to suitable to print for example to log file. */
971 static char rid[256];
972 #define _PUT_STRING(__d__, __s__) \
974 int __sp = sizeof(__d__) - 1 - strlen(__d__); \
975 if (__sp < strlen(__s__)) { \
977 strncat(__d__, __s__, (sizeof(__d__) - 1) - strlen(__d__)); \
979 strncat(__d__, __s__, strlen(__s__)); \
983 char *silc_id_render(void *id, SilcIdType id_type)
986 unsigned char tmps[2];
989 memset(rid, 0, sizeof(rid));
993 SilcServerID *server_id = (SilcServerID *)id;
994 if (server_id->ip.data_len > 4) {
996 struct sockaddr_in6 ipv6;
997 memset(&ipv6, 0, sizeof(ipv6));
998 ipv6.sin6_family = AF_INET6;
999 memmove(&ipv6.sin6_addr, server_id->ip.data, sizeof(ipv6.sin6_addr));
1000 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1001 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1002 _PUT_STRING(rid, tmp);
1005 struct in_addr ipv4;
1006 memmove(&ipv4.s_addr, server_id->ip.data, 4);
1007 cp = inet_ntoa(ipv4);
1009 _PUT_STRING(rid, cp);
1012 memset(tmp, 0, sizeof(tmp));
1013 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(server_id->port));
1014 _PUT_STRING(rid, tmp);
1015 SILC_PUT16_MSB(server_id->rnd, tmps);
1016 memset(tmp, 0, sizeof(tmp));
1017 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1018 _PUT_STRING(rid, tmp);
1021 case SILC_ID_CLIENT:
1023 SilcClientID *client_id = (SilcClientID *)id;
1024 if (client_id->ip.data_len > 4) {
1026 struct sockaddr_in6 ipv6;
1027 memset(&ipv6, 0, sizeof(ipv6));
1028 ipv6.sin6_family = AF_INET6;
1029 memmove(&ipv6.sin6_addr, client_id->ip.data, sizeof(ipv6.sin6_addr));
1030 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1031 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1032 _PUT_STRING(rid, tmp);
1035 struct in_addr ipv4;
1036 memmove(&ipv4.s_addr, client_id->ip.data, 4);
1037 cp = inet_ntoa(ipv4);
1039 _PUT_STRING(rid, cp);
1042 memset(tmp, 0, sizeof(tmp));
1043 silc_snprintf(tmp, sizeof(tmp) - 1, ",%02x,", client_id->rnd);
1044 _PUT_STRING(rid, tmp);
1045 memset(tmp, 0, sizeof(tmp));
1046 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x %02x %02x...]",
1047 client_id->hash[0], client_id->hash[1],
1048 client_id->hash[2], client_id->hash[3]);
1049 _PUT_STRING(rid, tmp);
1052 case SILC_ID_CHANNEL:
1054 SilcChannelID *channel_id = (SilcChannelID *)id;
1055 if (channel_id->ip.data_len > 4) {
1057 struct sockaddr_in6 ipv6;
1058 memset(&ipv6, 0, sizeof(ipv6));
1059 ipv6.sin6_family = AF_INET6;
1060 memmove(&ipv6.sin6_addr, channel_id->ip.data, sizeof(ipv6.sin6_addr));
1061 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1062 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1063 _PUT_STRING(rid, tmp);
1066 struct in_addr ipv4;
1067 memmove(&ipv4.s_addr, channel_id->ip.data, 4);
1068 cp = inet_ntoa(ipv4);
1070 _PUT_STRING(rid, cp);
1073 memset(tmp, 0, sizeof(tmp));
1074 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(channel_id->port));
1075 _PUT_STRING(rid, tmp);
1076 SILC_PUT16_MSB(channel_id->rnd, tmps);
1077 memset(tmp, 0, sizeof(tmp));
1078 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1079 _PUT_STRING(rid, tmp);