HP OpenVMS Systems Documentation

Content starts here HP TCP/IP Services for OpenVMS

HP TCP/IP Services for OpenVMS
Guide to IPv6


Previous Contents Index

8.4.4 inet_addr() Function

Applications that use the inet_addr() function must be changed to use the getaddrinfo() function, as follows:

AF_INET Call AF_INET6 Call
result=inet_addr( &string) err=getaddrinfo( nodename, servname, &hints, &res);
.
.
.
freeaddrinfo( &ai);

Make the following change to your application, as needed:

  1. Change the function name from inet_addr() to getaddrinfo() and provide a character string that contains the node name, a character string that contains the service name to use, a pointer to a hints structure that contains the AI_NUMERICHOST option, and a pointer to an addrinfo structure or structures for the returned address information.
  2. Add a call to the freeaddrinfo() routine to free the addrinfo structure or structures when your application is finished using them.

8.5 Other Application Changes

In addition to the name changes, you should review your code for specific uses of IP address information and variables.

8.5.1 Comparing IP Addresses

If your application compares IP addresses or tests IP addresses for equality, the in6_addr structure changes (see in Section 8.3.1) will change the comparison of int quantities to a comparison of structures. This will break the code and cause compiler errors.

Make either of the following changes to your application, as needed:

AF_INET Code AF_INET6 Code
(addr1->s_addr == addr2->s_addr) (memcmp(addr1, addr2, sizeof(struct in6_addr)) == 0)
  1. Change the equality expression to one that uses the memcmp (memory comparison) function.
AF_INET Code AF_INET6 Code
(addr1->s_addr == addr2->s_addr) IN6_ARE_ADDR_EQUAL(addr1, addr2)
  1. Change the equality expression to one that uses the IN6_ARE_ADDR_EQUAL macro.

8.5.2 Comparing an IP Address to the Wildcard Address

If your application compares an IP address to the wildcard address, the in6_addr structure changes (see Section 8.3.1) will change the comparison of int quantities to a comparison of structures. This will break the code and cause compiler errors.

Make either of the following changes to your application, as needed:

AF_INET Code AF_INET6 Code
(addr->s_addr == INADDR_ANY) IN6_IS_ADDR_UNSPECIFIED(addr)
  1. Change the equality expression to one that uses the IN6_IS_ADDR_UNSPECIFIED macro.
AF_INET Code AF_INET6 Code
(addr->s_addr == INADDR_ANY) (memcmp(addr, in6addr_any, sizeof(struct in6_addr)) == 0)
  1. Change the equality expression to one that uses the memcmp (memory comparison) function.

8.5.3 Using int Data Types to Hold IP Addresses

If your application uses int data types to hold IP addresses, the in6_addr structure changes (see Section 8.3.1 ) will change the assignment. This will break the code and cause compiler errors.

Make the following changes to your application, as needed:

AF_INET Code AF_INET6 Code
struct in_addr foo;
int bar;
.
.
.
bar = foo.s_addr;
struct in6_addr foo;
struct in6_addr bar;
.
.
.
bar = foo;
  1. Change the data type for bar from int to a struct in6_addr .
  2. Change the assignment statement for bar to remove the s_addr field reference.

8.5.4 Using Functions that Return IP Addresses

If your application uses functions that return IP addresses as int data types, the in6_addr structure changes (see Section 8.3.1 will change the destination of the return value from an int to an array of char. This will break the code and cause compiler errors.

Make the following changes to your application, as needed:

AF_INET Code AF_INET6 Code
struct in_addr *addr;
addr->s_addr = foo( xxx);
struct in6_addr * addr;
foo( xxx, addr);
  1. Restructure the function to enable you to pass the address of the structure in the call. In addition, modify the function to write the return value into the structure pointed to by addr .

8.5.5 Changing Socket Options

If your application uses IPv4 IP-level socket options, change them to the corresponding IPv6 options.

8.6 Sample Client/Server Programs

This section contains sample client and server programs that demonstrate the differences between IPv4 and IPv6 coding conventions:

To build the examples, use the following commands:




$ CC/DEFINE=(_SOCKADDR_LEN)/INCLUDE=TCPIP$EXAMPLES: client.c
$ LINK client, TCPIP$LIBRARY:TCPIP$LIB/LIBRARY

$ CC/DEFINE=(_SOCKADDR_LEN)/INCLUDE=TCPIP$EXAMPLES: server.c
$ LINK server, TCPIP$LIBRARY:TCPIP$LIB/LIBRARY


8.6.1 Programs Using AF_INET Sockets

This section contains a client and a server program that use AF_INET sockets.

8.6.1.1 Client Program

The following is a sample client program that you can build, compile and run on your system. The program sends a request to and receives a response from the system specified on the command line.



#include <in.h>          /* define internet related constants,   */
                                    /* functions, and structures     */
#include <inet.h>        /* define network address info     */

#include <netdb.h>       /* define network database library info */

#include <socket.h>      /* define BSD 4.x socket api     */
#include <stdio.h>       /* define standard i/o functions     */
#include <stdlib.h>      /* define standard library functions    */
#include <string.h>      /* define string handling functions     */

#include <unixio.h>      /* define unix i/o       */


#define BUFSZ           1024           /* user input buffer size     */
#define SERV_PORTNUM    12345          /* server port number      */


int  main( void );                     /* client main       */
void get_serv_addr( void * );(1)        /* get server host address    */


int
main( void )
{
    int sockfd;                        /* connection socket descriptor     */

    char buf[512];                     /* client data buffer      */

    struct sockaddr_in serv_addr;(2)    /* server socket address structure  */

    memset( &serv_addr, 0, sizeof(serv_addr) );(3)
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port   = htons( SERV_PORTNUM );
    get_serv_addr( &serv_addr.sin_addr );(4)

    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )(5)
 {
 perror( "Failed to create socket" );
 exit( EXIT_FAILURE );
 }

    printf( "Initiated connection to host: %s, port: %d\n",
     inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)(6)
   );

    if ( connect(sockfd,
   (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )(7)
 {
 perror( "Failed to connect to server" );
 exit( EXIT_FAILURE );
 }

    if ( recv(sockfd, buf, sizeof(buf), 0) < 0 )
 {
 perror( "Failed to read data from server connection" );
 exit( EXIT_FAILURE );
 }

    printf( "Data received: %s\n", buf );  /* output client's data buffer  */

    if ( shutdown(sockfd, 2) < 0 )
 {
 perror( "Failed to shutdown server connection" );
 exit( EXIT_FAILURE );
 }

    if ( close(sockfd) < 0 )
 {
 perror( "Failed to close socket" );
 exit( EXIT_FAILURE );
 }

    exit( EXIT_SUCCESS );
}

void
get_serv_addr( void *addrptr )(8)
{
    char buf[BUFSZ];        /* input data buffer       */
    struct in_addr val;     /* remote host address structure  */
    struct hostent *host;   /* remote host hostent structure  */

    while ( TRUE )
 {
 printf( "Enter remote host: " );

 if ( fgets(buf, sizeof(buf), stdin) == NULL )
     {
     printf( "Failed to read User input\n" );
     exit( EXIT_FAILURE );
     }

 buf[strlen(buf)-1] = 0;

 val.s_addr = inet_addr( buf );

 if ( val.s_addr != INADDR_NONE )
     {
     memcpy( addrptr, &val, sizeof(struct in_addr) );
     break;
     }

 if ( (host = gethostbyname(buf)) )(9)
     {
     memcpy( addrptr, host->h_addr, sizeof(struct in_addr) );
     break;
     }
 }
}

  1. Function code prototype for server host address/name translation function.
  2. Declares sockaddr_in structure.
  3. Clears the server sockaddr_in structure and sets values for fields of the structure
  4. Calls get_serv_addr passing a pointer to the socket address structure's sin_addr field.
  5. Creates an AF_INET socket
  6. Calls inet_ntoa to convert the server address to a text string.
  7. Calls connect passing a pointer to the sockaddr_in structure.
  8. Retrieves the server host's address from the user and then stores it in the server's socket address structure. The user can specify a server host by using either an IPv4 address in dotted decimal notation or a host domain name
  9. Calls gethostbyname() to retrieve the server host's address.

8.6.1.2 Server Program

The following is a sample server program that you can build, compile, and run on your system. The program receives requests from and sends responses to client programs on other systems.


#include <in.h>          /* define internet related constants,   */
                                    /* functions, and structures     */
#include <inet.h>        /* define network address info     */

#include <netdb.h>       /* define network database library info */

#include <socket.h>      /* define BSD 4.x socket api     */
#include <stdio.h>       /* define standard i/o functions     */
#include <stdlib.h>      /* define standard library functions    */
#include <string.h>      /* define string handling functions     */

#include <unixio.h>      /* define unix i/o       */


#define SERV_BACKLOG 1               /* server backlog      */
#define SERV_PORTNUM 12345           /* server port number      */


int  main( void );                      /* server main       */


int
main( void )
{
    int optval = 1;                     /* SO_REUSEADDR'S option value (on) */

    int conn_sockfd;                    /* connection socket descriptor     */
    int listen_sockfd;                  /* listen socket descriptor     */

    unsigned int client_addrlen;        /* returned length of client socket */
                                        /* address structure      */
    struct sockaddr_in client_addr;(1)   /* client socket address structure  */
    struct sockaddr_in serv_addr;       /* server socket address structure  */

    struct hostent *host;(2)             /* host name structure      */

    char buf[] = "Hello, world!";       /* server data buffer      */

    memset( &client_addr, 0, sizeof(client_addr) );

    memset( &serv_addr, 0, sizeof(serv_addr) );(3)
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_port       = htons( SERV_PORTNUM );
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )(4)
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    if ( setsockopt(listen_sockfd,
      SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 )
        {
        perror( "Failed to set socket option" );
        exit( EXIT_FAILURE );
        }

    if ( bind(listen_sockfd,
       (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
        {
        perror( "Failed to bind socket" );
        exit( EXIT_FAILURE );
        }

    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
        {
        perror( "Failed to set socket passive" );
        exit( EXIT_FAILURE );
        }

    printf( "Waiting for a client connection on port: %d\n",
     ntohs(serv_addr.sin_port)
          );

    client_addrlen = sizeof(client_addr);

    conn_sockfd = accept( listen_sockfd,
                          (struct sockaddr *) &client_addr,
                          &client_addrlen
                        );
    if ( conn_sockfd < 0 )
        {
        perror( "Failed to accept client connection" );
        exit( EXIT_FAILURE );
        }

    host = gethostbyaddr( (char *)&client_addr.sin_addr.s_addr,
                         sizeof(client_addr.sin_addr.s_addr), AF_INET(5)
                         );

    if ( host == NULL )
        {
        perror( "Failed to translate client address\n" );
        exit( EXIT_FAILURE );
        }

    printf( "Accepted connection from host: %s (%s), port: %d\n",
            host->h_name, inet_ntoa(client_addr.sin_addr),
            ntohs(client_addr.sin_port)
          );

    if ( send(conn_sockfd, buf, sizeof(buf), 0) < 0 )
        {
        perror( "Failed to write data to client connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Data sent: %s\n", buf );    /* output server's data buffer  */

    if ( shutdown(conn_sockfd, 2) < 0 )
        {
        perror( "Failed to shutdown client connection" );
        exit( EXIT_FAILURE );
        }

    if ( close(conn_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    if ( close(listen_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}





  1. Declares sockaddr_in structures.
  2. Declares hostent structure.
  3. Clears the server sockaddr_in structure and sets values for fields of the structure.
  4. Creates an AF_INET socket.
  5. Calls gethostbyaddr() to retrieve client name.

8.6.2 Programs Using AF_INET6 Sockets

This section contains a client and a server program that use AF_INET6 sockets.

8.6.2.1 Client Program

The following is a sample client program that you can build, compile and run on your system. The program sends a request to and receives a response from the system specified on the command line.


#include <in.h>            /* define internet related constants,   */
                                      /* functions, and structures     */
#include <inet.h>          /* define network address info     */

#include <netdb.h>         /* define network database library info */

#include <socket.h>        /* define BSD 4.x socket api     */
#include <stdio.h>         /* define standard i/o functions     */
#include <stdlib.h>        /* define standard library functions    */
#include <string.h>        /* define string handling functions     */

#include <unixio.h>        /* define unix i/o       */


#define BUFSZ           1024          /* user input buffer size     */
#define SERV_PORTNUM    "12345"       /* server port number string     */


int main( void );                     /* client main       */
void get_serv_addr( struct addrinfo *hints, struct addrinfo **res );(1)
                                      /* get server host address          */

int
main( void )
{
    int sockfd;                             /* connection socket descriptor     */

    char buf[512];                          /* client data buffer      */

    struct addrinfo hints;                  /* input values to direct operation */
    struct addrinfo *res;(2)                 /* linked list of addrinfo structs  */

    memset( &hints, 0, sizeof(hints) );(3)
    hints.ai_family = AF_INET6;
    hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_CANONNAME;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;
    get_serv_addr( &hints, &res );(4)

    if ( (sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0 )(5)
 {
 perror( "Failed to create socket" );
 exit( EXIT_FAILURE );
 }

    printf( "Initiated connection to host: %s, port: %d\n",
     res->ai_canonname,
     htons(((struct sockaddr_in6 *)res->ai_addr)->sin6_port)(6)
   );

    if ( connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 )(7)
 {
 perror( "Failed to connect to server" );
 exit( EXIT_FAILURE );
 }

    if ( recv(sockfd, buf, sizeof(buf), 0) < 0 )
 {
 perror( "Failed to read data from server connection" );
 exit( EXIT_FAILURE );
 }

    printf( "Data received: %s\n", buf );  /* output client's data buffer  */

    if ( shutdown(sockfd, 2) < 0 )
 {
 perror( "Failed to shutdown server connection" );
 exit( EXIT_FAILURE );
 }

    if ( close(sockfd) < 0 )
 {
 perror( "Failed to close socket" );
 exit( EXIT_FAILURE );
 }

    exit( EXIT_SUCCESS );
}

void
get_serv_addr( struct addrinfo *hints, struct addrinfo **res )(8)
{
    int gai_error;   /* return value of getaddrinfo()  */
    char buf[BUFSZ];          /* input data buffer              */
    const char *port = SERV_PORTNUM;    /* server port number             */

    while ( TRUE )
        {
 printf( "Enter remote host: " );

 if ( fgets(buf, sizeof(buf), stdin) == NULL )
     {
     printf( "Failed to read User input\n" );
     exit( EXIT_FAILURE );
     }

 buf[strlen(buf)-1] = 0;

 gai_error = getaddrinfo( buf, port, hints, res );(9)
 if ( gai_error )
            printf( "Failed to resolve name or address: %s\n",
                    gai_strerror(gai_error)(10)
                  );
 else
     break;
 }
}




  1. Function prototype for server host address/name translation function.
  2. Declares addrinfo structures.
  3. Clears the addrinfo structure and sets values for fields of the structure.
  4. Calls get_serv_addr() passing pointers to the input and output addrinfo structures.
  5. Creates an AF_INET6 socket.
  6. Uses values from the output addrinfo structure for host name and port.
  7. Calls connect() using values from the output addrinfo structure.
  8. Retrieves the server host's address from the user and stores it in the addrinfo structure. The user can specify a server host by using any of the following:
    • An IPv4 address in dotted-decimal notation
    • An IPv6 address in hexadecimal
    • An Ipv4-mapped IPv6 address in hexadecimal
    • A host domain name
  9. Calls getaddrinfo() to retrieve the server host's name or address.
  10. Calls gai_strerror() to convert one of the EAI_xx return values to a string describing the error.

8.6.2.2 Server Program

The following is a sample server program that you can build, compile, and run on your system. The program receives requests from and sends responses to client programs on other systems.



#include <in.h>                  /* define internet related constants,
                                            /* functions, and structures     */
#include <inet.h>                /* define network address info     */

#include <netdb.h>               /* define network database library info */

#include <socket.h>              /* define BSD 4.x socket api     */
#include <stdio.h>               /* define standard i/o functions     */
#include <stdlib.h>              /* define standard library functions    */
#include <string.h>              /* define string handling functions     */

#include <unixio.h>              /* define unix i/o       */


#define SERV_BACKLOG    1                   /* server backlog      */
#define SERV_PORTNUM    12345               /* server port number      */


int  main( void );                          /* server main       */

int
main( void )
{
    int optval = 1;                         /* SO_REUSEADDR'S option value (on) */

    int conn_sockfd;                        /* connection socket descriptor     */
    int listen_sockfd;                      /* listen socket descriptor     */
    int gni_error;(1)                        /* return status for getnameinfo()  */

    unsigned int client_addrlen;            /* returned length of client socket */
                                            /* address structure      */
    struct sockaddr_in6 client_addr;        /* client socket address structure  */
    struct sockaddr_in6 serv_addr;(2)        /* server socket address structure  */

    char buf[] = "Hello, world!";           /* server data buffer      */
    char node[NI_MAXHOST];(3)                /* buffer to receive node name      */
    char port[NI_MAXHOST];                  /* buffer to receive port number    */
    char addrbuf[INET6_ADDRSTRLEN];         /* buffer to receive host's address */

    memset( &client_addr, 0, sizeof(client_addr) );

    memset( &serv_addr, 0, sizeof(serv_addr) );(4)
    serv_addr.sin6_family      = AF_INET6;
    serv_addr.sin6_port        = htons( SERV_PORTNUM );
    serv_addr.sin6_addr        = in6addr_any;

    if ( (listen_sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0 )(5)
 {
 perror( "Failed to create socket" );
 exit( EXIT_FAILURE );
 }

    if ( setsockopt(listen_sockfd,
      SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 )
 {
 perror( "Failed to set socket option" );
 exit( EXIT_FAILURE );
 }

    if ( bind(listen_sockfd,
       (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
 {
 perror( "Failed to bind socket" );
 exit( EXIT_FAILURE );
 }

    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
 {
 perror( "Failed to set socket passive" );
 exit( EXIT_FAILURE );
 }

    printf( "Waiting for a client connection on port: %d\n",
     ntohs(serv_addr.sin6_port)
   );

    client_addrlen = sizeof(client_addr);

    conn_sockfd = accept( listen_sockfd,
     (struct sockaddr *) &client_addr,
     &client_addrlen
   );
    if ( conn_sockfd < 0 )
 {
 perror( "Failed to accept client connection" );
 exit( EXIT_FAILURE );
 }

    gni_error = getnameinfo( (struct sockaddr *)&client_addr, client_addrlen,
(6)
        node, sizeof(node), NULL, 0, NI_NAMEREQD
      );
    if ( gni_error )
 {
 printf( "Failed to translate client address: %s\n",
  gai_strerror(gni_error) (7)
       );
 exit( EXIT_FAILURE );
 }

    gni_error = getnameinfo( (struct sockaddr *)&client_addr, client_addrlen,
        addrbuf, sizeof(addrbuf), port, sizeof(port),
        NI_NUMERICHOST | NI_NUMERICSERV (8)
      );
    if ( gni_error )
 {
 printf( "Failed to translate client address and/or port: %s\n",
  gai_strerror(gni_error)
       );
 exit( EXIT_FAILURE );
 }

    printf( "Accepted connection from host: %s (%s), port: %s\n",
     node, addrbuf, port
   );

    if ( send(conn_sockfd, buf, sizeof(buf), 0) < 0 )
 {
 perror( "Failed to write data to client connection" );
 exit( EXIT_FAILURE );
 }

    printf( "Data sent: %s\n", buf );    /* output server's data buffer  */

    if ( shutdown(conn_sockfd, 2) < 0 )
 {
 perror( "Failed to shutdown client connection" );
 exit( EXIT_FAILURE );
 }

    if ( close(conn_sockfd) < 0 )
 {
 perror( "Failed to close socket" );
 exit( EXIT_FAILURE );
 }

    if ( close(listen_sockfd) < 0 )
 {
 perror( "Failed to close socket" );
 exit( EXIT_FAILURE );
 }

    exit( EXIT_SUCCESS );
}



Previous Next Contents Index