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();
37 /* Get username (mandatory) */
38 username = silc_get_username();
42 /* Create default email address, whether it is right or not */
43 silc_snprintf(email, sizeof(email), "%s@%s", username, hostname);
45 ident = silc_pkcs_silc_encode_identifier(username, hostname, realname,
46 email, NULL, NULL, NULL);
55 /* Generate key pair */
57 SilcBool silc_create_key_pair(const char *pkcs_name,
58 SilcUInt32 key_len_bits,
59 const char *pub_filename,
60 const char *prv_filename,
61 const char *pub_identifier,
62 const char *passphrase,
63 SilcPublicKey *return_public_key,
64 SilcPrivateKey *return_private_key,
69 char *pkfile = pub_filename ? strdup(pub_filename) : NULL;
70 char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
71 char *alg = pkcs_name ? strdup(pkcs_name) : NULL;
72 char *identifier = pub_identifier ? strdup(pub_identifier) : NULL;
73 char *pass = passphrase ? strdup(passphrase) : NULL;
74 SilcPublicKey public_key;
75 SilcPrivateKey private_key;
77 if (interactive && (!alg || !pub_filename || !prv_filename))
79 New pair of keys will be created. Please, answer to following questions.\n\
85 alg = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
89 if (*alg == 'l' || *alg == 'L') {
90 char *list = silc_pkcs_get_supported();
102 if (!silc_pkcs_find_algorithm(alg, NULL)) {
103 fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library"
104 "is not initialized", alg);
111 length = silc_get_input("Key length in key_len_bits [2048]: ", FALSE);
113 key_len_bits = atoi(length);
121 char *def = silc_create_pk_identifier();
124 memset(line, 0, sizeof(line));
126 silc_snprintf(line, sizeof(line), "Identifier [%s]: ", def);
128 silc_snprintf(line, sizeof(line),
129 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
130 "RN=Jon Johnson, E=jon@dummy.com): ");
132 while (!identifier) {
133 identifier = silc_get_input(line, FALSE);
134 if (!identifier && def)
135 identifier = strdup(def);
139 fprintf(stderr, "Could not create public key identifier: %s\n",
143 identifier = strdup(def);
149 rng = silc_rng_alloc();
151 silc_rng_global_init(rng);
155 memset(line, 0, sizeof(line));
156 silc_snprintf(line, sizeof(line), "Public key filename [public_key.pub]: ");
157 pkfile = silc_get_input(line, FALSE);
160 pkfile = strdup("public_key.pub");
165 memset(line, 0, sizeof(line));
166 silc_snprintf(line, sizeof(line), "Private key filename [private_key.prv]: ");
167 prvfile = silc_get_input(line, FALSE);
170 prvfile = strdup("private_key.prv");
176 pass = silc_get_input("Private key passphrase: ", TRUE);
183 pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
186 match = !strcmp(pass, pass2);
190 fprintf(stderr, "\nPassphrases do not match\n\n");
196 printf("\nGenerating the key pair...\n");
199 if (!silc_pkcs_silc_generate_key(alg, key_len_bits,
200 identifier, rng, &public_key,
204 /* Save public key into file */
205 silc_pkcs_save_public_key(pkfile, public_key, SILC_PKCS_FILE_BASE64);
207 /* Save private key into file */
208 silc_pkcs_save_private_key(prvfile, private_key,
209 (const unsigned char *)pass, strlen(pass),
210 SILC_PKCS_FILE_BIN, rng);
212 if (return_public_key)
213 *return_public_key = public_key;
215 silc_pkcs_public_key_free(public_key);
217 if (return_private_key)
218 *return_private_key = private_key;
220 silc_pkcs_private_key_free(private_key);
222 printf("Public key has been saved into `%s'.\n", pkfile);
223 printf("Private key has been saved into `%s'.\n", prvfile);
225 printf("Press <Enter> to continue...\n");
233 silc_free(identifier);
234 memset(pass, 0, strlen(pass));
242 SilcBool silc_load_key_pair(const char *pub_filename,
243 const char *prv_filename,
244 const char *passphrase,
245 SilcPublicKey *return_public_key,
246 SilcPrivateKey *return_private_key)
248 char *pass = passphrase ? strdup(passphrase) : NULL;
250 SILC_LOG_DEBUG(("Loading public and private keys"));
252 if (!silc_pkcs_load_public_key(pub_filename, return_public_key)) {
254 memset(pass, 0, strlen(pass));
260 pass = silc_get_input("Private key passphrase: ", TRUE);
265 if (!silc_pkcs_load_private_key(prv_filename,
266 (const unsigned char *)pass, strlen(pass),
267 return_private_key)) {
268 silc_pkcs_public_key_free(*return_public_key);
269 *return_public_key = NULL;
270 memset(pass, 0, strlen(pass));
275 memset(pass, 0, strlen(pass));
280 /* Dump public key into stdout */
282 SilcBool silc_show_public_key(SilcPublicKey public_key)
284 SilcSILCPublicKey silc_pubkey;
285 SilcPublicKeyIdentifier ident;
286 char *fingerprint, *babbleprint;
289 SilcUInt32 key_len = 0;
291 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
295 ident = &silc_pubkey->identifier;
296 key_len = silc_pkcs_public_key_get_len(public_key);
297 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
300 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
301 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
303 printf("Algorithm : %s\n", silc_pkcs_get_name(public_key));
305 printf("Key length (bits) : %d\n", (unsigned int)key_len);
307 printf("Version : %s\n", ident->version);
309 printf("Real name : %s\n", ident->realname);
311 printf("Username : %s\n", ident->username);
313 printf("Hostname : %s\n", ident->host);
315 printf("Email : %s\n", ident->email);
317 printf("Organization : %s\n", ident->org);
319 printf("Country : %s\n", ident->country);
320 printf("Fingerprint (SHA1) : %s\n", fingerprint);
321 printf("Babbleprint (SHA1) : %s\n", babbleprint);
325 silc_free(fingerprint);
326 silc_free(babbleprint);
332 /* Dump public key into stdout */
334 SilcBool silc_show_public_key_file(const char *pub_filename)
336 SilcPublicKey public_key;
339 if (!silc_pkcs_load_public_key((char *)pub_filename, &public_key)) {
340 fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
344 printf("Public key file : %s\n", pub_filename);
345 ret = silc_show_public_key(public_key);
346 silc_pkcs_public_key_free(public_key);
351 /* Change private key passphrase */
353 SilcBool silc_change_private_key_passphrase(const char *prv_filename,
354 const char *old_passphrase,
355 const char *new_passphrase)
357 SilcPrivateKey private_key;
361 pass = old_passphrase ? strdup(old_passphrase) : NULL;
363 pass = silc_get_input("Old passphrase: ", TRUE);
368 if (!silc_pkcs_load_private_key(prv_filename,
369 (const unsigned char *)pass, strlen(pass),
371 memset(pass, 0, strlen(pass));
373 fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
377 memset(pass, 0, strlen(pass));
380 pass = new_passphrase ? strdup(new_passphrase) : NULL;
383 fprintf(stdout, "\n");
384 pass = silc_get_input("New passphrase: ", TRUE);
390 pass2 = silc_get_input("Retype new passphrase: ", TRUE);
393 if (!strcmp(pass, pass2))
395 fprintf(stderr, "\nPassphrases do not match");
401 rng = silc_rng_alloc();
404 silc_pkcs_save_private_key((char *)prv_filename, private_key,
405 (unsigned char *)pass, strlen(pass),
406 SILC_PKCS_FILE_BIN, rng);
408 fprintf(stdout, "\nPassphrase changed\n");
410 memset(pass, 0, strlen(pass));
413 silc_pkcs_private_key_free(private_key);
419 /* Checks that the 'identifier' string is valid identifier string
420 and does not contain any unassigned or prohibited character. This
421 function is used to check for valid nicknames, channel names,
422 server names, usernames, hostnames, service names, algorithm names,
423 other security property names, and SILC Public Key name. */
425 unsigned char *silc_identifier_check(const unsigned char *identifier,
426 SilcUInt32 identifier_len,
427 SilcStringEncoding identifier_encoding,
428 SilcUInt32 max_allowed_length,
431 unsigned char *utf8s;
432 SilcUInt32 utf8s_len;
433 SilcStringprepStatus status;
435 if (!identifier || !identifier_len)
438 if (max_allowed_length && identifier_len > max_allowed_length)
441 status = silc_stringprep(identifier, identifier_len,
442 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
443 &utf8s, &utf8s_len, SILC_STRING_UTF8);
444 if (status != SILC_STRINGPREP_OK) {
445 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
450 *out_len = utf8s_len;
455 /* Same as above but does not allocate memory, just checks the
456 validity of the string. */
458 SilcBool silc_identifier_verify(const unsigned char *identifier,
459 SilcUInt32 identifier_len,
460 SilcStringEncoding identifier_encoding,
461 SilcUInt32 max_allowed_length)
463 SilcStringprepStatus status;
465 if (!identifier || !identifier_len)
468 if (max_allowed_length && identifier_len > max_allowed_length)
471 status = silc_stringprep(identifier, identifier_len,
472 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
473 NULL, NULL, SILC_STRING_UTF8);
474 if (status != SILC_STRINGPREP_OK) {
475 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
482 unsigned char *silc_channel_name_check(const unsigned char *identifier,
483 SilcUInt32 identifier_len,
484 SilcStringEncoding identifier_encoding,
485 SilcUInt32 max_allowed_length,
488 unsigned char *utf8s;
489 SilcUInt32 utf8s_len;
490 SilcStringprepStatus status;
492 if (!identifier || !identifier_len)
495 if (max_allowed_length && identifier_len > max_allowed_length)
498 status = silc_stringprep(identifier, identifier_len,
499 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
500 &utf8s, &utf8s_len, SILC_STRING_UTF8);
501 if (status != SILC_STRINGPREP_OK) {
502 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
507 *out_len = utf8s_len;
512 /* Same as above but does not allocate memory, just checks the
513 validity of the string. */
515 SilcBool silc_channel_name_verify(const unsigned char *identifier,
516 SilcUInt32 identifier_len,
517 SilcStringEncoding identifier_encoding,
518 SilcUInt32 max_allowed_length)
520 SilcStringprepStatus status;
522 if (!identifier || !identifier_len)
525 if (max_allowed_length && identifier_len > max_allowed_length)
528 status = silc_stringprep(identifier, identifier_len,
529 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
530 NULL, NULL, SILC_STRING_UTF8);
531 if (status != SILC_STRINGPREP_OK) {
532 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
539 /* Return mode list */
541 SilcBool silc_get_mode_list(SilcBuffer mode_list, SilcUInt32 mode_list_count,
546 if (silc_buffer_len(mode_list) / 4 != mode_list_count)
549 *list = silc_calloc(mode_list_count, sizeof(**list));
551 for (i = 0; i < mode_list_count; i++) {
552 SILC_GET32_MSB((*list)[i], mode_list->data);
553 silc_buffer_pull(mode_list, 4);
556 silc_buffer_push(mode_list, mode_list->data - mode_list->head);
561 /* Status message structure. Messages are defined below. */
567 #define STAT(x) SILC_STATUS_ERR_##x
568 static const SilcStatusMessage silc_status_messages[] = {
570 { STAT(NO_SUCH_NICK), "There was no such nickname" },
571 { STAT(NO_SUCH_CHANNEL), "There was no such channel" },
572 { STAT(NO_SUCH_SERVER), "There was no such server" },
573 { STAT(INCOMPLETE_INFORMATION), "Incomplete registration information" },
574 { STAT(NO_RECIPIENT), "No recipient given" },
575 { STAT(UNKNOWN_COMMAND), "Unknown command" },
576 { STAT(WILDCARDS), "Wilcrads not allowed" },
577 { STAT(NO_CLIENT_ID), "No Client ID given" },
578 { STAT(NO_CHANNEL_ID), "No Channel ID given" },
579 { STAT(NO_SERVER_ID), "No Server ID given" },
580 { STAT(BAD_CLIENT_ID), "Bad Client ID" },
581 { STAT(BAD_CHANNEL_ID), "Bad Channel ID" },
582 { STAT(NO_SUCH_CLIENT_ID), "There is no such client" },
583 { STAT(NO_SUCH_CHANNEL_ID),"There is no such channel" },
584 { STAT(NICKNAME_IN_USE), "Nickname already exists" },
585 { STAT(NOT_ON_CHANNEL), "You are not on that channel" },
586 { STAT(USER_NOT_ON_CHANNEL),"They are not on the channel" },
587 { STAT(USER_ON_CHANNEL), "User already on the channel" },
588 { STAT(NOT_REGISTERED), "You have not registered" },
589 { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
590 { STAT(TOO_MANY_PARAMS), "Too many parameters" },
591 { STAT(PERM_DENIED), "Permission denied" },
592 { STAT(BANNED_FROM_SERVER),"You are not allowed to connect" },
593 { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
594 { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
595 { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" },
596 { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" },
597 { STAT(UNKNOWN_MODE), "Unknown mode" },
598 { STAT(NOT_YOU), "Cannot change mode for other users" },
599 { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" },
600 { STAT(NO_CHANNEL_FOPRIV),"Permission denied. You are not channel founder" },
601 { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" },
602 { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" },
603 { STAT(BAD_NICKNAME), "Bad nickname" },
604 { STAT(BAD_CHANNEL), "Bad channel name" },
605 { STAT(AUTH_FAILED), "Authentication failed" },
606 { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" },
607 { STAT(NO_SUCH_SERVER_ID), "No such Server ID" },
608 { STAT(RESOURCE_LIMIT), "No more free resources" },
609 { STAT(NO_SUCH_SERVICE), "Service doesn't exist" },
610 { STAT(NOT_AUTHENTICATED), "You have not been authenticated" },
611 { STAT(BAD_SERVER_ID), "Server ID is not valid" },
612 { STAT(KEY_EXCHANGE_FAILED), "Key exchange failed" },
613 { STAT(BAD_VERSION), "Bad version" },
614 { STAT(TIMEDOUT), "Service timed out" },
615 { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
616 { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
617 { STAT(BAD_SERVER), "Bad server name" },
618 { STAT(BAD_USERNAME), "Bad user name" },
619 { STAT(NO_SUCH_PUBLIC_KEY), "Unknown public key" },
624 /* Returns status message string */
626 const char *silc_get_status_message(unsigned char status)
630 for (i = 0; silc_status_messages[i].message; i++) {
631 if (silc_status_messages[i].status == status)
635 if (silc_status_messages[i].message == NULL)
638 return silc_status_messages[i].message;
641 static const char *packet_name[] = {
652 "PRIVATE MESSAGE KEY",
658 "CONNECTION AUTH REQUEST",
673 /* Returns packet type name */
675 const char *silc_get_packet_name(unsigned char type)
677 if (type >= SILC_PACKET_MAX)
679 if (type >= SILC_PACKET_PRIVATE)
680 return "PRIVATE RANGE";
681 if (type > (sizeof(packet_name) / sizeof(*packet_name)))
683 return packet_name[type];
686 static const char *command_name[] = {
717 /* Returns command name */
719 const char *silc_get_command_name(unsigned char command)
721 if (command >= SILC_COMMAND_RESERVED)
723 if (command >= SILC_COMMAND_PRIVATE)
724 return "PRIVATE RANGE";
725 if (command > (sizeof(command_name) / sizeof(*command_name)))
727 return command_name[command];
730 /* Parses SILC protocol style version string. */
732 SilcBool silc_parse_version_string(const char *version,
733 SilcUInt32 *protocol_version,
734 char **protocol_version_string,
735 SilcUInt32 *software_version,
736 char **software_version_string,
737 char **vendor_version)
740 int maj = 0, min = 0;
742 if (!strstr(version, "SILC-"))
745 cp = (char *)version + 5;
749 /* Take protocol version */
752 if (!strchr(cp, '.'))
754 cp = strchr(cp, '.') + 1;
759 memset(buf, 0, sizeof(buf));
760 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
761 if (protocol_version)
762 *protocol_version = atoi(buf);
763 memset(buf, 0, sizeof(buf));
764 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
765 if (protocol_version_string)
766 *protocol_version_string = strdup(buf);
768 /* Take software version */
772 if (!strchr(cp, '-'))
774 cp = strchr(cp, '-') + 1;
779 if (strchr(cp, '.')) {
780 cp = strchr(cp, '.') + 1;
785 memset(buf, 0, sizeof(buf));
786 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
787 if (software_version)
788 *software_version = atoi(buf);
789 memset(buf, 0, sizeof(buf));
790 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
791 if (software_version_string)
792 *software_version_string = strdup(buf);
794 /* Take vendor string */
796 if (strchr(cp, '.')) {
797 cp = strchr(cp, '.') + 1;
798 if (cp && *cp && vendor_version)
799 *vendor_version = strdup(cp);
800 } else if (strchr(cp, ' ')) {
801 cp = strchr(cp, ' ') + 1;
802 if (cp && *cp && vendor_version)
803 *vendor_version = strdup(cp);
809 /* Converts version string x.x into number representation. */
811 SilcUInt32 silc_version_to_num(const char *version)
813 int maj = 0, min = 0;
819 cp = (char *)version;
821 cp = strchr(cp, '.');
825 memset(buf, 0, sizeof(buf));
826 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
827 return (SilcUInt32)atoi(buf);
830 /* Parses mode mask and returns the mode as string. */
832 char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
839 memset(string, 0, sizeof(string));
841 if (mode & SILC_CHANNEL_MODE_PRIVATE)
842 strncat(string, "p", 1);
844 if (mode & SILC_CHANNEL_MODE_SECRET)
845 strncat(string, "s", 1);
847 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
848 strncat(string, "k", 1);
850 if (mode & SILC_CHANNEL_MODE_INVITE)
851 strncat(string, "i", 1);
853 if (mode & SILC_CHANNEL_MODE_TOPIC)
854 strncat(string, "t", 1);
856 if (mode & SILC_CHANNEL_MODE_ULIMIT)
857 strncat(string, "l", 1);
859 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
860 strncat(string, "a", 1);
862 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
863 strncat(string, "f", 1);
865 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
866 strncat(string, "C", 1);
868 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
869 strncat(string, "m", 1);
871 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
872 strncat(string, "M", 1);
874 if (mode & SILC_CHANNEL_MODE_CIPHER)
875 strncat(string, "c", 1);
877 if (mode & SILC_CHANNEL_MODE_HMAC)
878 strncat(string, "h", 1);
880 if (mode & SILC_CHANNEL_MODE_CIPHER) {
881 if (strlen(cipher) + strlen(string) + 1< sizeof(string)) {
882 strncat(string, " ", 1);
883 strncat(string, cipher, strlen(cipher));
887 if (mode & SILC_CHANNEL_MODE_HMAC) {
888 if (strlen(hmac) + strlen(string) + 1< sizeof(string)) {
889 strncat(string, " ", 1);
890 strncat(string, hmac, strlen(hmac));
894 /* Rest of mode is ignored */
896 return strdup(string);
899 /* Parses channel user mode mask and returns te mode as string */
901 char *silc_client_chumode(SilcUInt32 mode)
908 memset(string, 0, sizeof(string));
910 if (mode & SILC_CHANNEL_UMODE_CHANFO)
911 strncat(string, "f", 1);
913 if (mode & SILC_CHANNEL_UMODE_CHANOP)
914 strncat(string, "o", 1);
916 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
917 strncat(string, "b", 1);
919 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
920 strncat(string, "u", 1);
922 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
923 strncat(string, "r", 1);
925 if (mode & SILC_CHANNEL_UMODE_QUIET)
926 strncat(string, "q", 1);
928 return strdup(string);
931 /* Parses channel user mode and returns it as special mode character. */
933 char *silc_client_chumode_char(SilcUInt32 mode)
940 memset(string, 0, sizeof(string));
942 if (mode & SILC_CHANNEL_UMODE_CHANFO)
943 strncat(string, "*", 1);
945 if (mode & SILC_CHANNEL_UMODE_CHANOP)
946 strncat(string, "@", 1);
948 if (mode & SILC_CHANNEL_UMODE_QUIET)
949 strncat(string, "&", 1);
951 return strdup(string);
954 /* Renders ID to suitable to print for example to log file. */
956 static char rid[256];
957 #define _PUT_STRING(__d__, __s__) \
959 int __sp = sizeof(__d__) - 1 - strlen(__d__); \
960 if (__sp < strlen(__s__)) { \
962 strncat(__d__, __s__, (sizeof(__d__) - 1) - strlen(__d__)); \
964 strncat(__d__, __s__, strlen(__s__)); \
968 char *silc_id_render(void *id, SilcIdType id_type)
971 unsigned char tmps[2];
974 memset(rid, 0, sizeof(rid));
978 SilcServerID *server_id = (SilcServerID *)id;
979 if (server_id->ip.data_len > 4) {
981 struct sockaddr_in6 ipv6;
982 memset(&ipv6, 0, sizeof(ipv6));
983 ipv6.sin6_family = AF_INET6;
984 memmove(&ipv6.sin6_addr, server_id->ip.data, sizeof(ipv6.sin6_addr));
985 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
986 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
987 _PUT_STRING(rid, tmp);
991 memmove(&ipv4.s_addr, server_id->ip.data, 4);
992 cp = inet_ntoa(ipv4);
994 _PUT_STRING(rid, cp);
997 memset(tmp, 0, sizeof(tmp));
998 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(server_id->port));
999 _PUT_STRING(rid, tmp);
1000 SILC_PUT16_MSB(server_id->rnd, tmps);
1001 memset(tmp, 0, sizeof(tmp));
1002 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1003 _PUT_STRING(rid, tmp);
1006 case SILC_ID_CLIENT:
1008 SilcClientID *client_id = (SilcClientID *)id;
1009 if (client_id->ip.data_len > 4) {
1011 struct sockaddr_in6 ipv6;
1012 memset(&ipv6, 0, sizeof(ipv6));
1013 ipv6.sin6_family = AF_INET6;
1014 memmove(&ipv6.sin6_addr, client_id->ip.data, sizeof(ipv6.sin6_addr));
1015 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1016 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1017 _PUT_STRING(rid, tmp);
1020 struct in_addr ipv4;
1021 memmove(&ipv4.s_addr, client_id->ip.data, 4);
1022 cp = inet_ntoa(ipv4);
1024 _PUT_STRING(rid, cp);
1027 memset(tmp, 0, sizeof(tmp));
1028 silc_snprintf(tmp, sizeof(tmp) - 1, ",%02x,", client_id->rnd);
1029 _PUT_STRING(rid, tmp);
1030 memset(tmp, 0, sizeof(tmp));
1031 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x %02x %02x...]",
1032 client_id->hash[0], client_id->hash[1],
1033 client_id->hash[2], client_id->hash[3]);
1034 _PUT_STRING(rid, tmp);
1037 case SILC_ID_CHANNEL:
1039 SilcChannelID *channel_id = (SilcChannelID *)id;
1040 if (channel_id->ip.data_len > 4) {
1042 struct sockaddr_in6 ipv6;
1043 memset(&ipv6, 0, sizeof(ipv6));
1044 ipv6.sin6_family = AF_INET6;
1045 memmove(&ipv6.sin6_addr, channel_id->ip.data, sizeof(ipv6.sin6_addr));
1046 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1047 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1048 _PUT_STRING(rid, tmp);
1051 struct in_addr ipv4;
1052 memmove(&ipv4.s_addr, channel_id->ip.data, 4);
1053 cp = inet_ntoa(ipv4);
1055 _PUT_STRING(rid, cp);
1058 memset(tmp, 0, sizeof(tmp));
1059 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(channel_id->port));
1060 _PUT_STRING(rid, tmp);
1061 SILC_PUT16_MSB(channel_id->rnd, tmps);
1062 memset(tmp, 0, sizeof(tmp));
1063 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1064 _PUT_STRING(rid, tmp);