diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2006-05-07 12:45:06 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2006-05-07 12:45:06 +0000 |
commit | 16b9dc43197e5e7b476d51d409e7c52654de0303 (patch) | |
tree | 1788ab300775b457a167aedd9f5812562e617d80 /src | |
parent | 88b52b8f26b28cddab566fcdc5c6db1e82844e5d (diff) | |
download | gnutls-16b9dc43197e5e7b476d51d409e7c52654de0303.tar.gz |
some changes for IPv6. Based on patch by Remi Denis-Courmont, sent to Debian bug tracking system.
Diffstat (limited to 'src')
-rw-r--r-- | src/cli.c | 318 | ||||
-rw-r--r-- | src/serv.c | 107 | ||||
-rw-r--r-- | src/tls_test.c | 50 |
3 files changed, 282 insertions, 193 deletions
@@ -110,13 +110,20 @@ typedef struct int fd; gnutls_session session; int secure; - const char *hostname; + char *hostname; + char *ip; + char* service; + struct addrinfo *ptr; + struct addrinfo *addr_info; } socket_st; -ssize_t socket_recv (socket_st socket, void *buffer, int buffer_size); -ssize_t socket_send (socket_st socket, const void *buffer, int buffer_size); +ssize_t socket_recv (const socket_st *socket, void *buffer, int buffer_size); +ssize_t socket_send (const socket_st *socket, const void *buffer, int buffer_size); +void socket_open( socket_st* hd, const char* hostname, const char* service); +void socket_connect( const socket_st* hd); void socket_bye (socket_st * socket); -static void check_rehandshake (socket_st socket, int ret); + +static void check_rehandshake (socket_st *socket, int ret); static int do_handshake (socket_st * socket); static void init_global_tls_stuff (void); @@ -427,7 +434,7 @@ static void gaa_parser (int argc, char **argv); /* Returns zero if the error code was successfully handled. */ static int -handle_error (socket_st hd, int err) +handle_error (socket_st *hd, int err) { int alert, ret; const char *err_type, *str; @@ -454,7 +461,7 @@ handle_error (socket_st hd, int err) if (err == GNUTLS_E_WARNING_ALERT_RECEIVED || err == GNUTLS_E_FATAL_ALERT_RECEIVED) { - alert = gnutls_alert_get (hd.session); + alert = gnutls_alert_get (hd->session); str = gnutls_alert_get_name (alert); if (str == NULL) str = str_unknown; @@ -480,12 +487,12 @@ starttls_alarm (int signum) starttls_alarmed = 1; } + int main (int argc, char **argv) { int err, ret; - int sd, ii, i; - struct sockaddr_in sa; + int ii, i; char buffer[MAX_BUF + 1]; char *session_data = NULL; char *session_id = NULL; @@ -494,8 +501,7 @@ main (int argc, char **argv) fd_set rset; int maxfd; struct timeval tv; - int user_term = 0, port; - struct hostent *server_host; + int user_term = 0; socket_st hd; gaa_parser (argc, argv); @@ -513,45 +519,8 @@ main (int argc, char **argv) init_global_tls_stuff (); - - printf ("Resolving '%s'...\n", hostname); - /* get server name */ - server_host = gethostbyname (hostname); - if (server_host == NULL) - { - fprintf (stderr, "Cannot resolve %s\n", hostname); - exit (1); - } - - sd = socket (AF_INET, SOCK_STREAM, 0); - ERR (sd, "socket"); - - port = service_to_port (service); - if (port == -1) - { - fprintf (stderr, "Unknown service\n"); - return -1; - } - - memset (&sa, '\0', sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - sa.sin_addr.s_addr = *((unsigned int *) server_host->h_addr); - - if (inet_ntop (AF_INET, &sa.sin_addr, buffer, MAX_BUF) == NULL) - { - perror ("inet_ntop()"); - return (1); - } - printf ("Connecting to '%s:%d'...\n", buffer, port); - - err = connect (sd, (SA *) & sa, sizeof (sa)); - ERR (err, "connect"); - - hd.secure = 0; - hd.fd = sd; - hd.hostname = hostname; + socket_open( &hd, hostname, service); + socket_connect( &hd); hd.session = init_tls_session (hostname); if (starttls) @@ -608,14 +577,8 @@ main (int argc, char **argv) printf ("\n\n- Connecting again- trying to resume previous session\n"); - sd = socket (AF_INET, SOCK_STREAM, 0); - ERR (sd, "socket"); - - err = connect (sd, (SA *) & sa, sizeof (sa)); - ERR (err, "connect"); - - hd.fd = sd; - hd.secure = 0; + socket_open( &hd, hostname, service); + socket_connect(&hd); } else { @@ -623,7 +586,6 @@ main (int argc, char **argv) } } - after_handshake: printf ("\n- Simple Client Mode:\n\n"); @@ -654,9 +616,9 @@ after_handshake: FD_ZERO (&rset); FD_SET (fileno (stdin), &rset); - FD_SET (sd, &rset); + FD_SET (hd.fd, &rset); - maxfd = MAX (fileno (stdin), sd); + maxfd = MAX (fileno (stdin), hd.fd); tv.tv_sec = 3; tv.tv_usec = 0; @@ -664,17 +626,17 @@ after_handshake: if (err < 0) continue; - if (FD_ISSET (sd, &rset)) + if (FD_ISSET (hd.fd, &rset)) { memset (buffer, 0, MAX_BUF + 1); - ret = socket_recv (hd, buffer, MAX_BUF); + ret = socket_recv (&hd, buffer, MAX_BUF); if (ret == 0) { printf ("- Peer has closed the GNUTLS connection\n"); break; } - else if (handle_error (hd, ret) < 0 && user_term == 0) + else if (handle_error (&hd, ret) < 0 && user_term == 0) { fprintf (stderr, "*** Server has terminated the connection abnormally.\n"); @@ -725,7 +687,7 @@ after_handshake: strcpy (b, "\r\n"); } - ret = socket_send (hd, buffer, strlen (buffer)); + ret = socket_send (&hd, buffer, strlen (buffer)); if (ret > 0) { @@ -733,7 +695,7 @@ after_handshake: printf ("- Sent: %d bytes\n", ret); } else - handle_error (hd, ret); + handle_error (&hd, ret); } } @@ -834,83 +796,10 @@ cli_version (void) } - -/* Functions to manipulate sockets - */ - -ssize_t -socket_recv (socket_st socket, void *buffer, int buffer_size) -{ - int ret; - - if (socket.secure) - do - { - ret = gnutls_record_recv (socket.session, buffer, buffer_size); - } - while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); - else - do - { - ret = recv (socket.fd, buffer, buffer_size, 0); - } - while (ret == -1 && errno == EINTR); - - return ret; -} - -ssize_t -socket_send (socket_st socket, const void *buffer, int buffer_size) -{ - int ret; - - if (socket.secure) - do - { - ret = gnutls_record_send (socket.session, buffer, buffer_size); - } - while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); - else - do - { - ret = send (socket.fd, buffer, buffer_size, 0); - } - while (ret == -1 && errno == EINTR); - - if (ret > 0 && ret != buffer_size && verbose) - fprintf (stderr, - "*** Only sent %d bytes instead of %d.\n", ret, buffer_size); - - return ret; -} - -void -socket_bye (socket_st * socket) -{ - int ret; - if (socket->secure) - { - do - ret = gnutls_bye (socket->session, GNUTLS_SHUT_RDWR); - while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); - if (ret < 0) - fprintf (stderr, "*** gnutls_bye() error: %s\n", - gnutls_strerror (ret)); - gnutls_deinit (socket->session); - socket->session = NULL; - } - - shutdown (socket->fd, SHUT_RDWR); /* no more receptions */ - close (socket->fd); - - socket->fd = -1; - socket->secure = 0; -} - static void -check_rehandshake (socket_st socket, int ret) +check_rehandshake (socket_st *socket, int ret) { - if (socket.secure && ret == GNUTLS_E_REHANDSHAKE) + if (socket->secure && ret == GNUTLS_E_REHANDSHAKE) { /* There is a race condition here. If application * data is sent after the rehandshake request, @@ -920,7 +809,7 @@ check_rehandshake (socket_st socket, int ret) printf ("*** Received rehandshake request\n"); /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */ - ret = do_handshake (&socket); + ret = do_handshake (socket); if (ret == 0) { @@ -946,7 +835,7 @@ do_handshake (socket_st * socket) if (ret < 0) { - handle_error (*socket, ret); + handle_error (socket, ret); } } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); @@ -1138,3 +1027,148 @@ init_global_tls_stuff (void) #endif } + +/* Functions to manipulate sockets + */ + +ssize_t + socket_recv (const socket_st* socket, void *buffer, int buffer_size) +{ + int ret; + + if (socket->secure) + do + { + ret = gnutls_record_recv (socket->session, buffer, buffer_size); + } + while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); + else + do + { + ret = recv (socket->fd, buffer, buffer_size, 0); + } + while (ret == -1 && errno == EINTR); + + return ret; +} + +ssize_t + socket_send (const socket_st *socket, const void *buffer, int buffer_size) +{ + int ret; + + if (socket->secure) + do + { + ret = gnutls_record_send (socket->session, buffer, buffer_size); + } + while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + else + do + { + ret = send (socket->fd, buffer, buffer_size, 0); + } + while (ret == -1 && errno == EINTR); + + if (ret > 0 && ret != buffer_size && verbose) + fprintf (stderr, + "*** Only sent %d bytes instead of %d.\n", ret, buffer_size); + + return ret; +} + +void + socket_bye (socket_st * socket) +{ + int ret; + if (socket->secure) + { + do + ret = gnutls_bye (socket->session, GNUTLS_SHUT_RDWR); + while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); + if (ret < 0) + fprintf (stderr, "*** gnutls_bye() error: %s\n", + gnutls_strerror (ret)); + gnutls_deinit (socket->session); + socket->session = NULL; + } + + freeaddrinfo( socket->addr_info); + socket->addr_info = socket->ptr = NULL; + + free( socket->ip); + free( socket->hostname); + free( socket->service); + + shutdown (socket->fd, SHUT_RDWR); /* no more receptions */ + close (socket->fd); + + socket->fd = -1; + socket->secure = 0; +} + +void socket_connect( const socket_st* hd) +{ + int err; + + printf ("Connecting to '%s:%s'...\n", hd->ip, hd->service); + + err = connect (hd->fd, hd->ptr->ai_addr, hd->ptr->ai_addrlen); + if (err < 0) + { + fprintf (stderr, "Cannot connect to %s:%s: %s\n", hd->hostname, hd->service, + strerror (errno)); + exit (1); + } +} + +void socket_open( socket_st* hd, const char* hostname, const char* service) +{ + struct addrinfo hints, *res, *ptr; + int sd, err; + char buffer[MAX_BUF + 1]; + char portname[16] = { 0 }; + + printf ("Resolving '%s'...\n", hostname); + /* get server name */ + memset (&hints, 0, sizeof (hints)); + hints.ai_socktype = SOCK_STREAM; + if ((err = getaddrinfo (hostname, service, &hints, &res))) + { + fprintf (stderr, "Cannot resolve %s:%s: %s\n", hostname, service, + gai_strerror (err)); + exit (1); + } + + sd = -1; + for (ptr = res; ptr != NULL; ptr = ptr->ai_next) + { + sd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + if (sd == -1) continue; + + if ((err = getnameinfo (ptr->ai_addr, ptr->ai_addrlen, buffer, MAX_BUF, + portname, sizeof (portname), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) + { + fprintf (stderr, "getnameinfo(): %s\n", gai_strerror (err)); + freeaddrinfo (res); + exit (1); + } + + break; + } + + if (sd==-1) { + fprintf (stderr, "socket(): %s\n", strerror (errno)); + exit (1); + } + + hd->secure = 0; + hd->fd = sd; + hd->hostname = strdup(hostname); + hd->ip = strdup(buffer); + hd->service = strdup(portname); + hd->ptr = ptr; + hd->addr_info = res; + + return; +} diff --git a/src/serv.c b/src/serv.c index 492b598707..15a5e622ba 100644 --- a/src/serv.c +++ b/src/serv.c @@ -507,41 +507,62 @@ peer_print_info (gnutls_session session, int *ret_length, const char *header) static int listen_socket (const char *name, int listen_port) { - struct sockaddr_in a; + struct addrinfo hints, *res, *ptr; + char portname[6]; int s; int yes; - if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) - { - perror ("socket() failed"); - return -1; - } - yes = 1; + snprintf (portname, sizeof (portname), "%d", listen_port); + memset (&hints, 0, sizeof (hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; - if (setsockopt - (s, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof (yes)) < 0) + if ((s = getaddrinfo (NULL, portname, &hints, &res)) != 0) { - perror ("setsockopt() failed"); - failed: - close (s); + fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (s)); return -1; } - memset (&a, 0, sizeof (a)); - a.sin_port = htons (listen_port); - a.sin_family = AF_INET; - if (bind (s, (struct sockaddr *) &a, sizeof (a)) < 0) + s = -1; + + for (ptr = res; (ptr != NULL) && (s == -1); ptr = ptr->ai_next) { - perror ("bind() failed"); - goto failed; + if ((s = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol)) < 0) + { + perror ("socket() failed"); + continue; + } + + yes = 1; + if (setsockopt + (s, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof (yes)) < 0) + { + perror ("setsockopt() failed"); + failed: + close (s); + s = -1; + continue; + } + + if (bind (s, res->ai_addr, res->ai_addrlen) < 0) + { + perror ("bind() failed"); + goto failed; + } + + if (listen (s, 10) < 0) + { + perror ("listen() failed"); + goto failed; + } } - if (listen (s, 10) < 0) + freeaddrinfo (res); + if (s == -1) { - perror ("listen() failed"); - goto failed; + return -1; } - printf ("%s ready. Listening to port '%d'.\n\n", name, listen_port); + printf ("%s ready. Listening to port '%s'.\n\n", name, portname); return s; } @@ -618,6 +639,28 @@ tls_log_func (int level, const char *str) static void gaa_parser (int argc, char **argv); +static int get_port (const struct sockaddr_storage *addr) +{ + switch (addr->ss_family) + { + case AF_INET6: + return ntohs (((const struct sockaddr_in6 *)addr)->sin6_port); + case AF_INET: + return ntohs (((const struct sockaddr_in *)addr)->sin_port); + } + return -1; +} + +static const char *addr_ntop (const struct sockaddr *sa, socklen_t salen, + char *buf, size_t buflen) +{ + if (getnameinfo (sa, salen, buf, buflen, NULL, 0, NI_NUMERICHOST) == 0) + { + return buf; + } + return NULL; +} + int main (int argc, char **argv) { @@ -625,7 +668,8 @@ main (int argc, char **argv) char topbuf[512]; char name[256]; int accept_fd; - struct sockaddr_in client_address; + struct sockaddr_storage client_address; + socklen_t calen; #ifndef _WIN32 signal (SIGPIPE, SIG_IGN); @@ -879,14 +923,13 @@ main (int argc, char **argv) /* a new connection has arrived */ if (FD_ISSET (h, &rd)) { - unsigned int l; gnutls_session tls_session; tls_session = initialize_session (); - l = sizeof (client_address); - memset (&client_address, 0, l); - accept_fd = accept (h, (struct sockaddr *) &client_address, &l); + calen = sizeof (client_address); + memset (&client_address, 0, calen); + accept_fd = accept (h, (struct sockaddr *) &client_address, &calen); if (accept_fd < 0) { @@ -965,10 +1008,9 @@ main (int argc, char **argv) if (verbose == 0) { printf ("\n* connection from %s, port %d\n", - inet_ntop (AF_INET, - &client_address.sin_addr, + addr_ntop ((struct sockaddr *)&client_address, calen, topbuf, sizeof (topbuf)), - ntohs (client_address.sin_port)); + get_port (&client_address)); print_info (j->tls_session, NULL); } j->handshake_ok = 1; @@ -1062,10 +1104,9 @@ main (int argc, char **argv) if (verbose == 0) { printf ("- connection from %s, port %d\n", - inet_ntop (AF_INET, - &client_address.sin_addr, + addr_ntop ((struct sockaddr*) &client_address, calen, topbuf, sizeof (topbuf)), - ntohs (client_address.sin_port)); + get_port (&client_address)); print_info (j->tls_session, NULL); } diff --git a/src/tls_test.c b/src/tls_test.c index 43365ff876..8f06385610 100644 --- a/src/tls_test.c +++ b/src/tls_test.c @@ -155,18 +155,6 @@ static const TLS_TEST tls_tests[] = { static int tt = 0; const char *ip; -#define CONNECT() \ - sd = socket(AF_INET, SOCK_STREAM, 0); \ - ERR(sd, "socket"); \ - memset(&sa, '\0', sizeof(sa)); \ - sa.sin_family = AF_INET; \ - sa.sin_port = htons(port); \ - sa.sin_addr.s_addr = *((unsigned int *) server_host->h_addr); \ - ip = inet_ntop(AF_INET, &sa.sin_addr, buffer, MAX_BUF); \ - if (tt++ == 0) printf("Connecting to '%s:%d'...\n", ip, port); \ - err = connect(sd, (SA *) & sa, sizeof(sa)); \ - ERR(err, "connect") - static void gaa_parser (int argc, char **argv); int @@ -174,10 +162,10 @@ main (int argc, char **argv) { int err, ret; int sd, i; - struct sockaddr_in sa; gnutls_session state; char buffer[MAX_BUF + 1]; - struct hostent *server_host; + char portname[6]; + struct addrinfo hints, *res, *ptr; gaa_parser (argc, argv); @@ -204,10 +192,14 @@ main (int argc, char **argv) printf ("Resolving '%s'...\n", hostname); /* get server name */ - server_host = gethostbyname (hostname); - if (server_host == NULL) + memset (&hints, 0, sizeof (hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICSERV; + snprintf (portname, sizeof (portname), "%d", port); + if ((err = getaddrinfo (hostname, portname, &hints, &res)) != 0) { - fprintf (stderr, "Cannot resolve %s\n", hostname); + fprintf (stderr, "Cannot resolve %s: %s\n", hostname, + gai_strerror (err)); exit (1); } @@ -253,7 +245,27 @@ main (int argc, char **argv) break; } - CONNECT (); + sd = -1; + for (ptr = res; ptr != NULL; ptr = ptr->ai_next) + { + sd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + if (sd == -1) + { + continue; + } + + getnameinfo (ptr->ai_addr, ptr->ai_addrlen, buffer, MAX_BUF, + NULL, 0, NI_NUMERICHOST); + if (tt++ == 0) printf("Connecting to '%s:%d'...\n", buffer, port); + if ((err = connect(sd, ptr->ai_addr, ptr->ai_addrlen)) != 0) + { + close (sd); + sd = -1; + continue; + } + } + ERR(err, "connect") + gnutls_init (&state, GNUTLS_CLIENT); gnutls_transport_set_ptr (state, (gnutls_transport_ptr) sd); @@ -286,6 +298,8 @@ main (int argc, char **argv) } while (1); + freeaddrinfo (res); + #ifdef ENABLE_SRP gnutls_srp_free_client_credentials (srp_cred); #endif |