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 [4096]: ", 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 if (!strstr(identifier, "UN=") || !strstr(identifier, "HN=")) {
150 fprintf(stderr, "Invalid public key identifier. You must specify both "
155 rng = silc_rng_alloc();
157 silc_rng_global_init(rng);
161 memset(line, 0, sizeof(line));
162 silc_snprintf(line, sizeof(line), "Public key filename [public_key.pub]: ");
163 pkfile = silc_get_input(line, FALSE);
166 pkfile = strdup("public_key.pub");
171 memset(line, 0, sizeof(line));
172 silc_snprintf(line, sizeof(line), "Private key filename [private_key.prv]: ");
173 prvfile = silc_get_input(line, FALSE);
176 prvfile = strdup("private_key.prv");
182 pass = silc_get_input("Private key passphrase: ", TRUE);
189 pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
192 match = !strcmp(pass, pass2);
196 fprintf(stderr, "\nPassphrases do not match\n\n");
202 printf("\nGenerating the key pair...\n");
205 if (!silc_pkcs_silc_generate_key(alg, key_len_bits,
206 identifier, rng, &public_key,
210 /* Save public key into file */
211 if (!silc_pkcs_save_public_key(pkfile, public_key, SILC_PKCS_FILE_BASE64))
214 /* Save private key into file */
215 if (!silc_pkcs_save_private_key(prvfile, private_key,
216 (const unsigned char *)pass, strlen(pass),
217 SILC_PKCS_FILE_BIN, rng))
220 if (return_public_key)
221 *return_public_key = public_key;
223 silc_pkcs_public_key_free(public_key);
225 if (return_private_key)
226 *return_private_key = private_key;
228 silc_pkcs_private_key_free(private_key);
230 printf("Public key has been saved into `%s'.\n", pkfile);
231 printf("Private key has been saved into `%s'.\n", prvfile);
233 printf("Press <Enter> to continue...\n");
241 silc_free(identifier);
242 memset(pass, 0, strlen(pass));
250 SilcBool silc_load_key_pair(const char *pub_filename,
251 const char *prv_filename,
252 const char *passphrase,
253 SilcPublicKey *return_public_key,
254 SilcPrivateKey *return_private_key)
256 char *pass = passphrase ? strdup(passphrase) : NULL;
258 SILC_LOG_DEBUG(("Loading public and private keys"));
260 if (!silc_pkcs_load_public_key(pub_filename, return_public_key)) {
262 memset(pass, 0, strlen(pass));
268 pass = silc_get_input("Private key passphrase: ", TRUE);
273 if (!silc_pkcs_load_private_key(prv_filename,
274 (const unsigned char *)pass, strlen(pass),
275 return_private_key)) {
276 silc_pkcs_public_key_free(*return_public_key);
277 *return_public_key = NULL;
278 memset(pass, 0, strlen(pass));
283 memset(pass, 0, strlen(pass));
288 /* Dump public key into stdout */
290 SilcBool silc_show_public_key(SilcPublicKey public_key)
292 SilcSILCPublicKey silc_pubkey;
293 SilcPublicKeyIdentifier ident;
294 char *fingerprint, *babbleprint;
297 SilcUInt32 key_len = 0;
299 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
303 ident = &silc_pubkey->identifier;
304 key_len = silc_pkcs_public_key_get_len(public_key);
305 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
308 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
309 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
311 printf("Algorithm : %s\n", silc_pkcs_get_name(public_key));
313 printf("Key length (bits) : %d\n", (unsigned int)key_len);
315 printf("Version : %s\n", ident->version);
317 printf("Real name : %s\n", ident->realname);
319 printf("Username : %s\n", ident->username);
321 printf("Hostname : %s\n", ident->host);
323 printf("Email : %s\n", ident->email);
325 printf("Organization : %s\n", ident->org);
327 printf("Country : %s\n", ident->country);
328 printf("Fingerprint (SHA1) : %s\n", fingerprint);
329 printf("Babbleprint (SHA1) : %s\n", babbleprint);
333 silc_free(fingerprint);
334 silc_free(babbleprint);
340 /* Dump public key into stdout */
342 SilcBool silc_show_public_key_file(const char *pub_filename)
344 SilcPublicKey public_key;
347 if (!silc_pkcs_load_public_key((char *)pub_filename, &public_key)) {
348 fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
352 printf("Public key file : %s\n", pub_filename);
353 ret = silc_show_public_key(public_key);
354 silc_pkcs_public_key_free(public_key);
359 /* Change private key passphrase */
361 SilcBool silc_change_private_key_passphrase(const char *prv_filename,
362 const char *old_passphrase,
363 const char *new_passphrase)
365 SilcPrivateKey private_key;
369 pass = old_passphrase ? strdup(old_passphrase) : NULL;
371 pass = silc_get_input("Old passphrase: ", TRUE);
376 if (!silc_pkcs_load_private_key(prv_filename,
377 (const unsigned char *)pass, strlen(pass),
379 memset(pass, 0, strlen(pass));
381 fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
385 memset(pass, 0, strlen(pass));
388 pass = new_passphrase ? strdup(new_passphrase) : NULL;
391 fprintf(stdout, "\n");
392 pass = silc_get_input("New passphrase: ", TRUE);
398 pass2 = silc_get_input("Retype new passphrase: ", TRUE);
401 if (!strcmp(pass, pass2))
403 fprintf(stderr, "\nPassphrases do not match");
409 rng = silc_rng_alloc();
412 silc_pkcs_save_private_key((char *)prv_filename, private_key,
413 (unsigned char *)pass, strlen(pass),
414 SILC_PKCS_FILE_BIN, rng);
416 fprintf(stdout, "\nPassphrase changed\n");
418 memset(pass, 0, strlen(pass));
421 silc_pkcs_private_key_free(private_key);
427 /* Checks that the 'identifier' string is valid identifier string
428 and does not contain any unassigned or prohibited character. This
429 function is used to check for valid nicknames, channel names,
430 server names, usernames, hostnames, service names, algorithm names,
431 other security property names, and SILC Public Key name. */
433 unsigned char *silc_identifier_check(const unsigned char *identifier,
434 SilcUInt32 identifier_len,
435 SilcStringEncoding identifier_encoding,
436 SilcUInt32 max_allowed_length,
439 unsigned char *utf8s;
440 SilcUInt32 utf8s_len;
441 SilcStringprepStatus status;
443 if (!identifier || !identifier_len)
446 if (max_allowed_length && identifier_len > max_allowed_length)
449 status = silc_stringprep(identifier, identifier_len,
450 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
451 &utf8s, &utf8s_len, SILC_STRING_UTF8);
452 if (status != SILC_STRINGPREP_OK) {
453 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
458 *out_len = utf8s_len;
463 /* Same as above but does not allocate memory, just checks the
464 validity of the string. */
466 SilcBool silc_identifier_verify(const unsigned char *identifier,
467 SilcUInt32 identifier_len,
468 SilcStringEncoding identifier_encoding,
469 SilcUInt32 max_allowed_length)
471 SilcStringprepStatus status;
473 if (!identifier || !identifier_len)
476 if (max_allowed_length && identifier_len > max_allowed_length)
479 status = silc_stringprep(identifier, identifier_len,
480 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
481 NULL, NULL, SILC_STRING_UTF8);
482 if (status != SILC_STRINGPREP_OK) {
483 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
490 unsigned char *silc_channel_name_check(const unsigned char *identifier,
491 SilcUInt32 identifier_len,
492 SilcStringEncoding identifier_encoding,
493 SilcUInt32 max_allowed_length,
496 unsigned char *utf8s;
497 SilcUInt32 utf8s_len;
498 SilcStringprepStatus status;
500 if (!identifier || !identifier_len)
503 if (max_allowed_length && identifier_len > max_allowed_length)
506 status = silc_stringprep(identifier, identifier_len,
507 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
508 &utf8s, &utf8s_len, SILC_STRING_UTF8);
509 if (status != SILC_STRINGPREP_OK) {
510 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
515 *out_len = utf8s_len;
520 /* Same as above but does not allocate memory, just checks the
521 validity of the string. */
523 SilcBool silc_channel_name_verify(const unsigned char *identifier,
524 SilcUInt32 identifier_len,
525 SilcStringEncoding identifier_encoding,
526 SilcUInt32 max_allowed_length)
528 SilcStringprepStatus status;
530 if (!identifier || !identifier_len)
533 if (max_allowed_length && identifier_len > max_allowed_length)
536 status = silc_stringprep(identifier, identifier_len,
537 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
538 NULL, NULL, SILC_STRING_UTF8);
539 if (status != SILC_STRINGPREP_OK) {
540 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
547 /* Return mode list */
549 SilcBool silc_get_mode_list(SilcBuffer mode_list, SilcUInt32 mode_list_count,
554 if (silc_buffer_len(mode_list) / 4 != mode_list_count)
557 *list = silc_calloc(mode_list_count, sizeof(**list));
559 for (i = 0; i < mode_list_count; i++) {
560 SILC_GET32_MSB((*list)[i], mode_list->data);
561 silc_buffer_pull(mode_list, 4);
564 silc_buffer_push(mode_list, mode_list->data - mode_list->head);
569 /* Status message structure. Messages are defined below. */
575 #define STAT(x) SILC_STATUS_ERR_##x
576 static const SilcStatusMessage silc_status_messages[] = {
578 { STAT(NO_SUCH_NICK), "There was no such nickname" },
579 { STAT(NO_SUCH_CHANNEL), "There was no such channel" },
580 { STAT(NO_SUCH_SERVER), "There was no such server" },
581 { STAT(INCOMPLETE_INFORMATION), "Incomplete registration information" },
582 { STAT(NO_RECIPIENT), "No recipient given" },
583 { STAT(UNKNOWN_COMMAND), "Unknown command" },
584 { STAT(WILDCARDS), "Wilcrads not allowed" },
585 { STAT(NO_CLIENT_ID), "No Client ID given" },
586 { STAT(NO_CHANNEL_ID), "No Channel ID given" },
587 { STAT(NO_SERVER_ID), "No Server ID given" },
588 { STAT(BAD_CLIENT_ID), "Bad Client ID" },
589 { STAT(BAD_CHANNEL_ID), "Bad Channel ID" },
590 { STAT(NO_SUCH_CLIENT_ID), "There is no such client" },
591 { STAT(NO_SUCH_CHANNEL_ID),"There is no such channel" },
592 { STAT(NICKNAME_IN_USE), "Nickname already exists" },
593 { STAT(NOT_ON_CHANNEL), "You are not on that channel" },
594 { STAT(USER_NOT_ON_CHANNEL),"They are not on the channel" },
595 { STAT(USER_ON_CHANNEL), "User already on the channel" },
596 { STAT(NOT_REGISTERED), "You have not registered" },
597 { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
598 { STAT(TOO_MANY_PARAMS), "Too many parameters" },
599 { STAT(PERM_DENIED), "Permission denied" },
600 { STAT(BANNED_FROM_SERVER),"You are not allowed to connect" },
601 { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
602 { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
603 { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" },
604 { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" },
605 { STAT(UNKNOWN_MODE), "Unknown mode" },
606 { STAT(NOT_YOU), "Cannot change mode for other users" },
607 { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" },
608 { STAT(NO_CHANNEL_FOPRIV),"Permission denied. You are not channel founder" },
609 { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" },
610 { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" },
611 { STAT(BAD_NICKNAME), "Bad nickname" },
612 { STAT(BAD_CHANNEL), "Bad channel name" },
613 { STAT(AUTH_FAILED), "Authentication failed" },
614 { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" },
615 { STAT(NO_SUCH_SERVER_ID), "No such Server ID" },
616 { STAT(RESOURCE_LIMIT), "No more free resources" },
617 { STAT(NO_SUCH_SERVICE), "Service doesn't exist" },
618 { STAT(NOT_AUTHENTICATED), "You have not been authenticated" },
619 { STAT(BAD_SERVER_ID), "Server ID is not valid" },
620 { STAT(KEY_EXCHANGE_FAILED), "Key exchange failed" },
621 { STAT(BAD_VERSION), "Bad version" },
622 { STAT(TIMEDOUT), "Service timed out" },
623 { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
624 { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
625 { STAT(BAD_SERVER), "Bad server name" },
626 { STAT(BAD_USERNAME), "Bad user name" },
627 { STAT(NO_SUCH_PUBLIC_KEY), "Unknown public key" },
632 /* Returns status message string */
634 const char *silc_get_status_message(unsigned char status)
638 for (i = 0; silc_status_messages[i].message; i++) {
639 if (silc_status_messages[i].status == status)
643 if (silc_status_messages[i].message == NULL)
646 return silc_status_messages[i].message;
649 static const char *packet_name[] = {
660 "PRIVATE MESSAGE KEY",
666 "CONNECTION AUTH REQUEST",
681 /* Returns packet type name */
683 const char *silc_get_packet_name(unsigned char type)
685 if (type >= SILC_PACKET_MAX)
687 if (type >= SILC_PACKET_PRIVATE)
688 return "PRIVATE RANGE";
689 if (type > (sizeof(packet_name) / sizeof(*packet_name)))
691 return packet_name[type];
694 static const char *command_name[] = {
725 /* Returns command name */
727 const char *silc_get_command_name(unsigned char command)
729 if (command >= SILC_COMMAND_RESERVED)
731 if (command >= SILC_COMMAND_PRIVATE)
732 return "PRIVATE RANGE";
733 if (command > (sizeof(command_name) / sizeof(*command_name)))
735 return command_name[command];
738 /* Parses SILC protocol style version string. */
740 SilcBool silc_parse_version_string(const char *version,
741 SilcUInt32 *protocol_version,
742 char **protocol_version_string,
743 SilcUInt32 *software_version,
744 char **software_version_string,
745 char **vendor_version)
748 int maj = 0, min = 0;
750 if (!strstr(version, "SILC-"))
753 cp = (char *)version + 5;
757 /* Take protocol version */
760 if (!strchr(cp, '.'))
762 cp = strchr(cp, '.') + 1;
767 memset(buf, 0, sizeof(buf));
768 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
769 if (protocol_version)
770 *protocol_version = atoi(buf);
771 memset(buf, 0, sizeof(buf));
772 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
773 if (protocol_version_string)
774 *protocol_version_string = strdup(buf);
776 /* Take software version */
780 if (!strchr(cp, '-'))
782 cp = strchr(cp, '-') + 1;
787 if (strchr(cp, '.')) {
788 cp = strchr(cp, '.') + 1;
793 memset(buf, 0, sizeof(buf));
794 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
795 if (software_version)
796 *software_version = atoi(buf);
797 memset(buf, 0, sizeof(buf));
798 silc_snprintf(buf, sizeof(buf) - 1, "%d.%d", maj, min);
799 if (software_version_string)
800 *software_version_string = strdup(buf);
802 /* Take vendor string */
804 if (strchr(cp, '.')) {
805 cp = strchr(cp, '.') + 1;
806 if (cp && *cp && vendor_version)
807 *vendor_version = strdup(cp);
808 } else if (strchr(cp, ' ')) {
809 cp = strchr(cp, ' ') + 1;
810 if (cp && *cp && vendor_version)
811 *vendor_version = strdup(cp);
817 /* Converts version string x.x into number representation. */
819 SilcUInt32 silc_version_to_num(const char *version)
821 int maj = 0, min = 0;
827 cp = (char *)version;
829 cp = strchr(cp, '.');
833 memset(buf, 0, sizeof(buf));
834 silc_snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
835 return (SilcUInt32)atoi(buf);
838 /* Parses mode mask and returns the mode as string. */
840 char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
847 memset(string, 0, sizeof(string));
849 if (mode & SILC_CHANNEL_MODE_PRIVATE)
850 strncat(string, "p", 1);
852 if (mode & SILC_CHANNEL_MODE_SECRET)
853 strncat(string, "s", 1);
855 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
856 strncat(string, "k", 1);
858 if (mode & SILC_CHANNEL_MODE_INVITE)
859 strncat(string, "i", 1);
861 if (mode & SILC_CHANNEL_MODE_TOPIC)
862 strncat(string, "t", 1);
864 if (mode & SILC_CHANNEL_MODE_ULIMIT)
865 strncat(string, "l", 1);
867 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
868 strncat(string, "a", 1);
870 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
871 strncat(string, "f", 1);
873 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
874 strncat(string, "C", 1);
876 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
877 strncat(string, "m", 1);
879 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
880 strncat(string, "M", 1);
882 if (mode & SILC_CHANNEL_MODE_CIPHER)
883 strncat(string, "c", 1);
885 if (mode & SILC_CHANNEL_MODE_HMAC)
886 strncat(string, "h", 1);
888 if (mode & SILC_CHANNEL_MODE_CIPHER) {
889 if (strlen(cipher) + strlen(string) + 1< sizeof(string)) {
890 strncat(string, " ", 1);
891 strncat(string, cipher, strlen(cipher));
895 if (mode & SILC_CHANNEL_MODE_HMAC) {
896 if (strlen(hmac) + strlen(string) + 1< sizeof(string)) {
897 strncat(string, " ", 1);
898 strncat(string, hmac, strlen(hmac));
902 /* Rest of mode is ignored */
904 return strdup(string);
907 /* Parses channel user mode mask and returns te mode as string */
909 char *silc_client_chumode(SilcUInt32 mode)
916 memset(string, 0, sizeof(string));
918 if (mode & SILC_CHANNEL_UMODE_CHANFO)
919 strncat(string, "f", 1);
921 if (mode & SILC_CHANNEL_UMODE_CHANOP)
922 strncat(string, "o", 1);
924 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
925 strncat(string, "b", 1);
927 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
928 strncat(string, "u", 1);
930 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
931 strncat(string, "r", 1);
933 if (mode & SILC_CHANNEL_UMODE_QUIET)
934 strncat(string, "q", 1);
936 return strdup(string);
939 /* Parses channel user mode and returns it as special mode character. */
941 char *silc_client_chumode_char(SilcUInt32 mode)
948 memset(string, 0, sizeof(string));
950 if (mode & SILC_CHANNEL_UMODE_CHANFO)
951 strncat(string, "*", 1);
953 if (mode & SILC_CHANNEL_UMODE_CHANOP)
954 strncat(string, "@", 1);
956 if (mode & SILC_CHANNEL_UMODE_QUIET)
957 strncat(string, "&", 1);
959 return strdup(string);
962 /* Renders ID to suitable to print for example to log file. */
964 static char rid[256];
965 #define _PUT_STRING(__d__, __s__) \
967 int __sp = sizeof(__d__) - 1 - strlen(__d__); \
968 if (__sp < strlen(__s__)) { \
970 strncat(__d__, __s__, (sizeof(__d__) - 1) - strlen(__d__)); \
972 strncat(__d__, __s__, strlen(__s__)); \
976 char *silc_id_render(void *id, SilcIdType id_type)
979 unsigned char tmps[2];
982 memset(rid, 0, sizeof(rid));
986 SilcServerID *server_id = (SilcServerID *)id;
987 if (server_id->ip.data_len > 4) {
989 struct sockaddr_in6 ipv6;
990 memset(&ipv6, 0, sizeof(ipv6));
991 ipv6.sin6_family = AF_INET6;
992 memmove(&ipv6.sin6_addr, server_id->ip.data, sizeof(ipv6.sin6_addr));
993 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
994 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
995 _PUT_STRING(rid, tmp);
999 memmove(&ipv4.s_addr, server_id->ip.data, 4);
1000 cp = inet_ntoa(ipv4);
1002 _PUT_STRING(rid, cp);
1005 memset(tmp, 0, sizeof(tmp));
1006 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(server_id->port));
1007 _PUT_STRING(rid, tmp);
1008 SILC_PUT16_MSB(server_id->rnd, tmps);
1009 memset(tmp, 0, sizeof(tmp));
1010 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1011 _PUT_STRING(rid, tmp);
1014 case SILC_ID_CLIENT:
1016 SilcClientID *client_id = (SilcClientID *)id;
1017 if (client_id->ip.data_len > 4) {
1019 struct sockaddr_in6 ipv6;
1020 memset(&ipv6, 0, sizeof(ipv6));
1021 ipv6.sin6_family = AF_INET6;
1022 memmove(&ipv6.sin6_addr, client_id->ip.data, sizeof(ipv6.sin6_addr));
1023 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1024 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1025 _PUT_STRING(rid, tmp);
1028 struct in_addr ipv4;
1029 memmove(&ipv4.s_addr, client_id->ip.data, 4);
1030 cp = inet_ntoa(ipv4);
1032 _PUT_STRING(rid, cp);
1035 memset(tmp, 0, sizeof(tmp));
1036 silc_snprintf(tmp, sizeof(tmp) - 1, ",%02x,", client_id->rnd);
1037 _PUT_STRING(rid, tmp);
1038 memset(tmp, 0, sizeof(tmp));
1039 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x %02x %02x...]",
1040 client_id->hash[0], client_id->hash[1],
1041 client_id->hash[2], client_id->hash[3]);
1042 _PUT_STRING(rid, tmp);
1045 case SILC_ID_CHANNEL:
1047 SilcChannelID *channel_id = (SilcChannelID *)id;
1048 if (channel_id->ip.data_len > 4) {
1050 struct sockaddr_in6 ipv6;
1051 memset(&ipv6, 0, sizeof(ipv6));
1052 ipv6.sin6_family = AF_INET6;
1053 memmove(&ipv6.sin6_addr, channel_id->ip.data, sizeof(ipv6.sin6_addr));
1054 if (!getnameinfo((struct sockaddr *)&ipv6, sizeof(ipv6),
1055 tmp, sizeof(tmp) - 1, NULL, 0, NI_NUMERICHOST))
1056 _PUT_STRING(rid, tmp);
1059 struct in_addr ipv4;
1060 memmove(&ipv4.s_addr, channel_id->ip.data, 4);
1061 cp = inet_ntoa(ipv4);
1063 _PUT_STRING(rid, cp);
1066 memset(tmp, 0, sizeof(tmp));
1067 silc_snprintf(tmp, sizeof(tmp) - 1, ",%d,", ntohs(channel_id->port));
1068 _PUT_STRING(rid, tmp);
1069 SILC_PUT16_MSB(channel_id->rnd, tmps);
1070 memset(tmp, 0, sizeof(tmp));
1071 silc_snprintf(tmp, sizeof(tmp) - 1, "[%02x %02x]", tmps[0], tmps[1]);
1072 _PUT_STRING(rid, tmp);