2 * Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation
3 * Copyright (C) 2000,2001,2002,2003 Nikos Mavrogiannopoulos
5 * This file is part of GNUTLS.
7 * GNUTLS is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * GNUTLS is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
33 #include <gnutls/gnutls.h>
34 #include <gnutls/extra.h>
35 #include <gnutls/x509.h>
36 #include <gnutls/openpgp.h>
40 #include "read-file.h"
45 #if defined _WIN32 || defined __WIN32__
46 #define select _win_select
57 #define SA struct sockaddr
58 #define ERR(err,s) do { if (err==-1) {perror(s);return(1);} } while (0)
61 /* global stuff here */
62 int resume
, starttls
, insecure
;
63 char *hostname
= NULL
;
69 extern int print_cert
;
71 char *srp_passwd
= NULL
;
79 char *x509_crlfile
= NULL
;
81 static int disable_extensions
;
83 char *psk_username
= NULL
;
84 gnutls_datum_t psk_key
= { NULL
, 0 };
86 static gnutls_srp_client_credentials_t srp_cred
;
87 static gnutls_psk_client_credentials_t psk_cred
;
88 static gnutls_anon_client_credentials_t anon_cred
;
89 static gnutls_certificate_credentials_t xcred
;
93 static int protocol_priority
[PRI_MAX
];
94 static int kx_priority
[PRI_MAX
];
95 static int cipher_priority
[PRI_MAX
];
96 static int comp_priority
[PRI_MAX
];
97 static int mac_priority
[PRI_MAX
];
98 static int cert_type_priority
[PRI_MAX
];
100 /* end of global stuff */
106 gnutls_session_t session
;
111 struct addrinfo
*ptr
;
112 struct addrinfo
*addr_info
;
115 ssize_t
socket_recv (const socket_st
* socket
, void *buffer
, int buffer_size
);
116 ssize_t
socket_send (const socket_st
* socket
, const void *buffer
,
118 void socket_open (socket_st
* hd
, const char *hostname
, const char *service
);
119 void socket_connect (const socket_st
* hd
);
120 void socket_bye (socket_st
* socket
);
122 static void check_rehandshake (socket_st
* socket
, int ret
);
123 static int do_handshake (socket_st
* socket
);
124 static void init_global_tls_stuff (void);
128 #define MAX(X,Y) (X >= Y ? X : Y);
131 /* Helper functions to load a certificate and key
134 static gnutls_datum_t
135 load_file (const char *file
)
138 gnutls_datum_t loaded_file
= { NULL
, 0 };
142 if (!(f
= fopen (file
, "r"))
143 || fseek (f
, 0, SEEK_END
) != 0
144 || (filelen
= ftell (f
)) < 0
145 || fseek (f
, 0, SEEK_SET
) != 0
146 || !(ptr
= malloc ((size_t) filelen
))
147 || fread (ptr
, 1, (size_t) filelen
, f
) < (size_t) filelen
)
152 loaded_file
.data
= ptr
;
153 loaded_file
.size
= (unsigned int) filelen
;
158 unload_file (gnutls_datum_t data
)
164 static unsigned int x509_crt_size
;
165 static gnutls_x509_crt_t x509_crt
[MAX_CRT
];
166 static gnutls_x509_privkey_t x509_key
= NULL
;
168 static gnutls_openpgp_crt_t pgp_crt
= NULL
;
169 static gnutls_openpgp_privkey_t pgp_key
= NULL
;
171 /* Load the certificate and the private key.
176 unsigned int crt_num
;
180 if (x509_certfile
!= NULL
&& x509_keyfile
!= NULL
)
182 data
= load_file (x509_certfile
);
183 if (data
.data
== NULL
)
185 fprintf (stderr
, "*** Error loading cert file.\n");
191 gnutls_x509_crt_list_import (x509_crt
, &crt_num
, &data
,
193 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED
);
196 if (ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
199 "*** Error loading cert file: Too many certs %d\n",
206 "*** Error loading cert file: %s\n",
207 gnutls_strerror (ret
));
212 fprintf (stderr
, "Processed %d client certificates...\n", ret
);
216 data
= load_file (x509_keyfile
);
217 if (data
.data
== NULL
)
219 fprintf (stderr
, "*** Error loading key file.\n");
223 gnutls_x509_privkey_init (&x509_key
);
225 ret
= gnutls_x509_privkey_import (x509_key
, &data
, GNUTLS_X509_FMT_PEM
);
228 fprintf (stderr
, "*** Error loading key file: %s\n",
229 gnutls_strerror (ret
));
235 fprintf (stderr
, "Processed %d client X.509 certificates...\n",
238 #ifdef ENABLE_OPENPGP
239 if (pgp_certfile
!= NULL
&& pgp_keyfile
!= NULL
)
241 data
= load_file (pgp_certfile
);
242 if (data
.data
== NULL
)
244 fprintf (stderr
, "*** Error loading PGP cert file.\n");
247 gnutls_openpgp_crt_init (&pgp_crt
);
250 gnutls_openpgp_crt_import (pgp_crt
, &data
, GNUTLS_OPENPGP_FMT_BASE64
);
254 "*** Error loading PGP cert file: %s\n",
255 gnutls_strerror (ret
));
261 data
= load_file (pgp_keyfile
);
262 if (data
.data
== NULL
)
264 fprintf (stderr
, "*** Error loading PGP key file.\n");
268 gnutls_openpgp_privkey_init (&pgp_key
);
271 gnutls_openpgp_privkey_import (pgp_key
, &data
,
272 GNUTLS_OPENPGP_FMT_BASE64
, NULL
, 0);
276 "*** Error loading PGP key file: %s\n",
277 gnutls_strerror (ret
));
282 fprintf (stderr
, "Processed 1 client PGP certificate...\n");
290 /* This callback should be associated with a session by calling
291 * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
292 * before a handshake.
296 cert_callback (gnutls_session_t session
,
297 const gnutls_datum_t
* req_ca_rdn
, int nreqs
,
298 const gnutls_pk_algorithm_t
* sign_algos
,
299 int sign_algos_length
, gnutls_retr_st
* st
)
308 /* Print the server's trusted CAs
311 printf ("- Server's trusted authorities:\n");
313 printf ("- Server did not send us any trusted authorities names.\n");
315 /* print the names (if any) */
316 for (i
= 0; i
< nreqs
; i
++)
318 len
= sizeof (issuer_dn
);
319 ret
= gnutls_x509_rdn_get (&req_ca_rdn
[i
], issuer_dn
, &len
);
322 printf (" [%d]: ", i
);
323 printf ("%s\n", issuer_dn
);
328 /* Select a certificate and return it.
329 * The certificate must be of any of the "sign algorithms"
330 * supported by the server.
333 st
->type
= gnutls_certificate_type_get (session
);
337 if (st
->type
== GNUTLS_CRT_X509
)
339 if (x509_crt
!= NULL
&& x509_key
!= NULL
)
341 st
->ncerts
= x509_crt_size
;
343 st
->cert
.x509
= x509_crt
;
344 st
->key
.x509
= x509_key
;
351 else if (st
->type
== GNUTLS_CRT_OPENPGP
)
353 if (pgp_key
!= NULL
&& pgp_crt
!= NULL
)
357 st
->cert
.pgp
= pgp_crt
;
358 st
->key
.pgp
= pgp_key
;
366 printf ("- Successfully sent %d certificate(s) to server.\n", st
->ncerts
);
371 /* initializes a gnutls_session_t with some defaults.
373 static gnutls_session_t
374 init_tls_session (const char *hostname
)
378 gnutls_session_t session
;
380 gnutls_init (&session
, GNUTLS_CLIENT
);
382 if (gnutls_priority_set_direct (session
, info
.priorities
, &err
) < 0)
384 fprintf(stderr
, "Syntax error at: %s\n", err
);
388 /* allow the use of private ciphersuites.
390 if (disable_extensions
== 0)
392 gnutls_handshake_set_private_extensions (session
, 1);
393 gnutls_server_name_set (session
, GNUTLS_NAME_DNS
, hostname
,
395 if (cert_type_priority
[0])
396 gnutls_certificate_type_set_priority (session
, cert_type_priority
);
399 if (cipher_priority
[0])
400 gnutls_cipher_set_priority (session
, cipher_priority
);
401 if (comp_priority
[0])
402 gnutls_compression_set_priority (session
, comp_priority
);
404 gnutls_kx_set_priority (session
, kx_priority
);
405 if (protocol_priority
[0])
406 gnutls_protocol_set_priority (session
, protocol_priority
);
408 gnutls_mac_set_priority (session
, mac_priority
);
410 gnutls_dh_set_prime_bits (session
, 512);
412 gnutls_credentials_set (session
, GNUTLS_CRD_ANON
, anon_cred
);
414 gnutls_credentials_set (session
, GNUTLS_CRD_SRP
, srp_cred
);
416 gnutls_credentials_set (session
, GNUTLS_CRD_PSK
, psk_cred
);
417 gnutls_credentials_set (session
, GNUTLS_CRD_CERTIFICATE
, xcred
);
419 gnutls_certificate_client_set_retrieve_function (xcred
, cert_callback
);
421 /* send the fingerprint */
422 if (fingerprint
!= 0)
423 gnutls_openpgp_send_cert (session
, GNUTLS_OPENPGP_CERT_FINGERPRINT
);
425 /* use the max record size extension */
426 if (record_max_size
> 0 && disable_extensions
== 0)
428 if (gnutls_record_set_max_size (session
, record_max_size
) < 0)
431 "Cannot set the maximum record size to %d.\n",
433 fprintf (stderr
, "Possible values: 512, 1024, 2048, 4096.\n");
439 if (info
.opaque_prf_input
)
440 gnutls_oprfi_enable_client (session
, strlen (info
.opaque_prf_input
),
441 info
.opaque_prf_input
);
447 static void gaa_parser (int argc
, char **argv
);
449 /* Returns zero if the error code was successfully handled.
452 handle_error (socket_st
* hd
, int err
)
455 const char *err_type
, *str
;
460 if (gnutls_error_is_fatal (err
) == 0)
463 err_type
= "Non fatal";
471 str
= gnutls_strerror (err
);
474 fprintf (stderr
, "*** %s error: %s\n", err_type
, str
);
476 if (err
== GNUTLS_E_WARNING_ALERT_RECEIVED
477 || err
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
479 alert
= gnutls_alert_get (hd
->session
);
480 str
= gnutls_alert_get_name (alert
);
483 printf ("*** Received alert [%d]: %s\n", alert
, str
);
485 /* In SRP if the alert is MISSING_SRP_USERNAME,
486 * we should read the username/password and
487 * call gnutls_handshake(). This is not implemented
492 check_rehandshake (hd
, ret
);
497 int starttls_alarmed
= 0;
500 starttls_alarm (int signum
)
502 starttls_alarmed
= 1;
506 tls_log_func (int level
, const char *str
)
508 fprintf (stderr
, "|<%d>| %s", level
, str
);
512 main (int argc
, char **argv
)
516 char buffer
[MAX_BUF
+ 1];
517 char *session_data
= NULL
;
518 char *session_id
= NULL
;
519 size_t session_data_size
;
520 size_t session_id_size
;
527 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM
, 0);
529 if ((ret
= gnutls_global_init ()) < 0)
531 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
535 if ((ret
= gnutls_global_init_extra ()) < 0)
537 fprintf (stderr
, "global_init_extra: %s\n", gnutls_strerror (ret
));
541 gaa_parser (argc
, argv
);
542 if (hostname
== NULL
)
544 fprintf (stderr
, "No hostname given\n");
548 gnutls_global_set_log_function (tls_log_func
);
549 gnutls_global_set_log_level (info
.debug
);
554 signal (SIGPIPE
, SIG_IGN
);
557 init_global_tls_stuff ();
559 socket_open (&hd
, hostname
, service
);
560 socket_connect (&hd
);
562 hd
.session
= init_tls_session (hostname
);
564 goto after_handshake
;
566 for (i
= 0; i
< 2; i
++)
572 hd
.session
= init_tls_session (hostname
);
573 gnutls_session_set_data (hd
.session
, session_data
,
578 ret
= do_handshake (&hd
);
582 fprintf (stderr
, "*** Handshake has failed\n");
584 gnutls_deinit (hd
.session
);
589 printf ("- Handshake was completed\n");
590 if (gnutls_session_is_resumed (hd
.session
) != 0)
591 printf ("*** This is a resumed session\n");
596 if (resume
!= 0 && i
== 0)
599 gnutls_session_get_data (hd
.session
, NULL
, &session_data_size
);
600 session_data
= malloc (session_data_size
);
602 gnutls_session_get_data (hd
.session
, session_data
,
605 gnutls_session_get_id (hd
.session
, NULL
, &session_id_size
);
606 session_id
= malloc (session_id_size
);
607 gnutls_session_get_id (hd
.session
, session_id
, &session_id_size
);
609 /* print some information */
610 print_info (hd
.session
, hostname
);
612 printf ("- Disconnecting\n");
616 ("\n\n- Connecting again- trying to resume previous session\n");
617 socket_open (&hd
, hostname
, service
);
618 socket_connect (&hd
);
628 /* Warning! Do not touch this text string, it is used by external
629 programs to search for when gnutls-cli has reached this point. */
630 printf ("\n- Simple Client Mode:\n\n");
633 signal (SIGALRM
, &starttls_alarm
);
637 #if !(defined _WIN32 || defined __WIN32__)
638 setbuf (stdin
, NULL
);
640 setbuf (stdout
, NULL
);
641 setbuf (stderr
, NULL
);
645 if (starttls_alarmed
&& !hd
.secure
)
647 /* Warning! Do not touch this text string, it is used by
648 external programs to search for when gnutls-cli has
649 reached this point. */
650 fprintf (stderr
, "*** Starting TLS handshake\n");
651 ret
= do_handshake (&hd
);
654 fprintf (stderr
, "*** Handshake has failed\n");
662 FD_SET (fileno (stdin
), &rset
);
663 FD_SET (hd
.fd
, &rset
);
665 maxfd
= MAX (fileno (stdin
), hd
.fd
);
669 err
= select (maxfd
+ 1, &rset
, NULL
, NULL
, &tv
);
673 if (FD_ISSET (hd
.fd
, &rset
))
675 memset (buffer
, 0, MAX_BUF
+ 1);
676 ret
= socket_recv (&hd
, buffer
, MAX_BUF
);
680 printf ("- Peer has closed the GNUTLS connection\n");
683 else if (handle_error (&hd
, ret
) < 0 && user_term
== 0)
686 "*** Server has terminated the connection abnormally.\n");
692 printf ("- Received[%d]: ", ret
);
693 for (ii
= 0; ii
< ret
; ii
++)
695 fputc (buffer
[ii
], stdout
);
704 if (FD_ISSET (fileno (stdin
), &rset
))
706 if (fgets (buffer
, MAX_BUF
, stdin
) == NULL
)
710 /* Warning! Do not touch this text string, it is
711 used by external programs to search for when
712 gnutls-cli has reached this point. */
713 fprintf (stderr
, "*** Starting TLS handshake\n");
714 ret
= do_handshake (&hd
);
718 fprintf (stderr
, "*** Handshake has failed\n");
734 char *b
= strchr (buffer
, '\n');
739 ret
= socket_send (&hd
, buffer
, strlen (buffer
));
744 printf ("- Sent: %d bytes\n", ret
);
747 handle_error (&hd
, ret
);
755 gnutls_deinit (hd
.session
);
759 gnutls_srp_free_client_credentials (srp_cred
);
763 gnutls_psk_free_client_credentials (psk_cred
);
766 gnutls_certificate_free_credentials (xcred
);
769 gnutls_anon_free_client_credentials (anon_cred
);
772 gnutls_global_deinit ();
778 gaa_parser (int argc
, char **argv
)
780 if (gaa (argc
, argv
, &info
) != -1)
783 "Error in the arguments. Use the --help or -h parameters to get more information.\n");
787 verbose
= info
.verbose
;
788 disable_extensions
= info
.disable_extensions
;
789 print_cert
= info
.print_cert
;
790 starttls
= info
.starttls
;
791 resume
= info
.resume
;
792 insecure
= info
.insecure
;
794 record_max_size
= info
.record_size
;
795 fingerprint
= info
.fingerprint
;
797 if (info
.fmtder
== 0)
798 x509ctype
= GNUTLS_X509_FMT_PEM
;
800 x509ctype
= GNUTLS_X509_FMT_DER
;
802 srp_username
= info
.srp_username
;
803 srp_passwd
= info
.srp_passwd
;
804 x509_cafile
= info
.x509_cafile
;
805 x509_crlfile
= info
.x509_crlfile
;
806 x509_keyfile
= info
.x509_keyfile
;
807 x509_certfile
= info
.x509_certfile
;
808 pgp_keyfile
= info
.pgp_keyfile
;
809 pgp_certfile
= info
.pgp_certfile
;
811 psk_username
= info
.psk_username
;
812 psk_key
.data
= (unsigned char *) info
.psk_key
;
813 if (info
.psk_key
!= NULL
)
814 psk_key
.size
= strlen (info
.psk_key
);
818 pgp_keyring
= info
.pgp_keyring
;
822 if (info
.rest_args
== NULL
)
823 hostname
= "localhost";
825 hostname
= info
.rest_args
;
827 parse_protocols (info
.proto
, info
.nproto
, protocol_priority
);
828 parse_ciphers (info
.ciphers
, info
.nciphers
, cipher_priority
);
829 parse_macs (info
.macs
, info
.nmacs
, mac_priority
);
830 parse_ctypes (info
.ctype
, info
.nctype
, cert_type_priority
);
831 parse_kx (info
.kx
, info
.nkx
, kx_priority
);
832 parse_comp (info
.comp
, info
.ncomp
, comp_priority
);
838 const char *v
= gnutls_check_version (NULL
);
840 printf ("gnutls-cli (GnuTLS) %s\n", LIBGNUTLS_VERSION
);
841 if (strcmp (v
, LIBGNUTLS_VERSION
) != 0)
842 printf ("libgnutls %s\n", v
);
847 check_rehandshake (socket_st
* socket
, int ret
)
849 if (socket
->secure
&& ret
== GNUTLS_E_REHANDSHAKE
)
851 /* There is a race condition here. If application
852 * data is sent after the rehandshake request,
853 * the server thinks we ignored his request.
854 * This is a bad design of this client.
856 printf ("*** Received rehandshake request\n");
857 /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
859 ret
= do_handshake (socket
);
863 printf ("*** Rehandshake was performed.\n");
867 printf ("*** Rehandshake Failed.\n");
874 do_handshake (socket_st
* socket
)
877 gnutls_transport_set_ptr (socket
->session
,
878 (gnutls_transport_ptr_t
) socket
->fd
);
881 ret
= gnutls_handshake (socket
->session
);
885 handle_error (socket
, ret
);
888 while (ret
< 0 && gnutls_error_is_fatal (ret
) == 0);
892 /* print some information */
893 print_info (socket
->session
, socket
->hostname
);
895 if ((x509_cafile
|| pgp_keyring
) && !insecure
)
900 /* abort if verification fail */
901 rc
= gnutls_certificate_verify_peers2 (socket
->session
, &status
);
902 if (rc
!= 0 || status
!= 0)
904 printf ("*** Verifying server certificate failed...\n");
916 srp_username_callback (gnutls_session_t session
,
917 char **username
, char **password
)
919 if (srp_username
== NULL
|| srp_passwd
== NULL
)
924 *username
= gnutls_strdup (srp_username
);
925 *password
= gnutls_strdup (srp_passwd
);
931 init_global_tls_stuff (void)
936 if (gnutls_certificate_allocate_credentials (&xcred
) < 0)
938 fprintf (stderr
, "Certificate allocation memory error\n");
942 /* there are some CAs that have a v1 certificate *%&@#*%&
944 gnutls_certificate_set_verify_flags (xcred
,
945 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
);
947 if (x509_cafile
!= NULL
)
950 gnutls_certificate_set_x509_trust_file (xcred
,
951 x509_cafile
, x509ctype
);
954 fprintf (stderr
, "Error setting the x509 trust file\n");
958 printf ("Processed %d CA certificate(s).\n", ret
);
962 if (x509_crlfile
!= NULL
)
965 gnutls_certificate_set_x509_crl_file (xcred
, x509_crlfile
, x509ctype
);
968 fprintf (stderr
, "Error setting the x509 CRL file\n");
972 printf ("Processed %d CRL(s).\n", ret
);
979 #ifdef ENABLE_OPENPGP
980 if (pgp_keyring
!= NULL
)
982 ret
= gnutls_certificate_set_openpgp_keyring_file (xcred
, pgp_keyring
, GNUTLS_OPENPGP_FMT_BASE64
);
985 fprintf (stderr
, "Error setting the OpenPGP keyring file\n");
991 if (srp_username
&& srp_passwd
)
994 if (gnutls_srp_allocate_client_credentials (&srp_cred
) < 0)
996 fprintf (stderr
, "SRP authentication error\n");
999 gnutls_srp_set_client_credentials_function (srp_cred
,
1000 srp_username_callback
);
1005 if (psk_username
&& !psk_key
.data
)
1008 if (gnutls_psk_allocate_client_credentials (&psk_cred
) < 0)
1010 fprintf (stderr
, "PSK authentication error\n");
1013 gnutls_psk_set_client_credentials (psk_cred
,
1014 psk_username
, &psk_key
,
1015 GNUTLS_PSK_KEY_HEX
);
1021 if (gnutls_anon_allocate_client_credentials (&anon_cred
) < 0)
1023 fprintf (stderr
, "Anonymous authentication error\n");
1029 /* Functions to manipulate sockets
1033 socket_recv (const socket_st
* socket
, void *buffer
, int buffer_size
)
1040 ret
= gnutls_record_recv (socket
->session
, buffer
, buffer_size
);
1042 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
1046 ret
= recv (socket
->fd
, buffer
, buffer_size
, 0);
1048 while (ret
== -1 && errno
== EINTR
);
1054 socket_send (const socket_st
* socket
, const void *buffer
, int buffer_size
)
1061 ret
= gnutls_record_send (socket
->session
, buffer
, buffer_size
);
1063 while (ret
== GNUTLS_E_AGAIN
|| ret
== GNUTLS_E_INTERRUPTED
);
1067 ret
= send (socket
->fd
, buffer
, buffer_size
, 0);
1069 while (ret
== -1 && errno
== EINTR
);
1071 if (ret
> 0 && ret
!= buffer_size
&& verbose
)
1073 "*** Only sent %d bytes instead of %d.\n", ret
, buffer_size
);
1079 socket_bye (socket_st
* socket
)
1085 ret
= gnutls_bye (socket
->session
, GNUTLS_SHUT_RDWR
);
1086 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
1088 fprintf (stderr
, "*** gnutls_bye() error: %s\n",
1089 gnutls_strerror (ret
));
1090 gnutls_deinit (socket
->session
);
1091 socket
->session
= NULL
;
1094 freeaddrinfo (socket
->addr_info
);
1095 socket
->addr_info
= socket
->ptr
= NULL
;
1098 free (socket
->hostname
);
1099 free (socket
->service
);
1101 shutdown (socket
->fd
, SHUT_RDWR
); /* no more receptions */
1109 socket_connect (const socket_st
* hd
)
1113 printf ("Connecting to '%s:%s'...\n", hd
->ip
, hd
->service
);
1115 err
= connect (hd
->fd
, hd
->ptr
->ai_addr
, hd
->ptr
->ai_addrlen
);
1118 fprintf (stderr
, "Cannot connect to %s:%s: %s\n", hd
->hostname
,
1119 hd
->service
, strerror (errno
));
1125 socket_open (socket_st
* hd
, const char *hostname
, const char *service
)
1127 struct addrinfo hints
, *res
, *ptr
;
1129 char buffer
[MAX_BUF
+ 1];
1130 char portname
[16] = { 0 };
1132 printf ("Resolving '%s'...\n", hostname
);
1133 /* get server name */
1134 memset (&hints
, 0, sizeof (hints
));
1135 hints
.ai_socktype
= SOCK_STREAM
;
1136 if ((err
= getaddrinfo (hostname
, service
, &hints
, &res
)))
1138 fprintf (stderr
, "Cannot resolve %s:%s: %s\n", hostname
, service
,
1139 gai_strerror (err
));
1144 for (ptr
= res
; ptr
!= NULL
; ptr
= ptr
->ai_next
)
1146 sd
= socket (ptr
->ai_family
, ptr
->ai_socktype
, ptr
->ai_protocol
);
1150 if ((err
= getnameinfo (ptr
->ai_addr
, ptr
->ai_addrlen
, buffer
, MAX_BUF
,
1151 portname
, sizeof (portname
),
1152 NI_NUMERICHOST
| NI_NUMERICSERV
)) != 0)
1154 fprintf (stderr
, "getnameinfo(): %s\n", gai_strerror (err
));
1164 fprintf (stderr
, "socket(): %s\n", strerror (errno
));
1170 hd
->hostname
= strdup (hostname
);
1171 hd
->ip
= strdup (buffer
);
1172 hd
->service
= strdup (portname
);
1174 hd
->addr_info
= res
;