HP OpenVMS Systems Documentation

Content starts here

Compaq TCP/IP Services for OpenVMS
Guide to IPv6


Previous Contents

7.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 7.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.

7.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 7.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.

7.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 7.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 .

7.5.5 Changing Socket Options

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

7.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:



$ DEFINE DECC$SYSTEM_INCLUDE TCPIP$EXAMPLES:
$ DEFINE ARPA TCPIP$EXAMPLES:
$ DEFINE NET TCPIP$EXAMPLES:
$ DEFINE NETINET TCPIP$EXAMPLES:
$ DEFINE SYS TCPIP$EXAMPLES:

$ CC/NOOPT/STANDARD=VAXC/PREFIX=ALL/EXTERN_MODEL=STRICT_REFDEF/DEFINE=(INET6,_SOCKADDR_LEN) client.c
$ LINK/MAP client,TCPIP$LIBRARY:TCPIP$LIB/lib

$ CC/NOOPT/STANDARD=VAXC/PREFIX=ALL/EXTERN_MODEL=STRICT_REFDEF/DEFINE=(INET6,_SOCKADDR_LEN) server.c
$ LINK/MAP server,TCPIP$LIBRARY:TCPIP$LIB/lib

7.6.1 Programs Using AF_INET Sockets

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

7.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.




/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright 2000 Compaq Computer Corporation                 *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer  Corporation.  Possession, use,  duplication  or   *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define SERVER_PORT     7639
#define CLIENT_PORT     7739

#define MAXBUFSIZE 4096

int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in     serveraddr; (1)
    struct sockaddr_in     clientaddr;
    int             serveraddrlen;
    const char      *ap;
    const char      *request = "this is the client's request";
    struct hostent  *hp;
    char            *server;

    if (argc < 2) {
        printf("Usage: client <server>\n");
        exit(1);
    }
    server = argv[1];

    bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); (2)
    serveraddr.sin_family = AF_INET;
    if ((HP = gethostbyname(server)) == NULL) {  (3)
        printf("unknown host: %s\n", server);
        exit(2);
    }
    serveraddr.sin_port = htons(SERVER_PORT);

    while (hp->h_addr_list[0] != NULL) {
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { (4)
            perror("socket");
            exit(3);
        }
        memcpy(&serveraddr.sin_addr.s_addr, HP->h_addr_list[0],
                         HP->h_length);

        if (connect(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
            perror("connect");
            close(s);
            HP->h_addr_list++;
            continue;
        }
        break;
    }
    if (send(s, request, strlen(request), 0) < 0) { (5)
        perror("send");
        exit(5);
    }
    dcount = recv(s, databuf, sizeof(databuf), 0);
    if (dcount < 0) {
        perror("recv");
        exit(6);
    }
    databuf[dcount] = '\0';

    HP = gethostbyaddr((char *)&serveraddr.sin_addr.s_addr, (6)
        sizeof(serveraddr.sin_addr.s_addr), AF_INET);
    ap = inet_ntoa(serveraddr.sin_addr);  (7)
    printf("Response received from");
    if (HP != NULL)
        printf(" %s", HP->h_name);
    if (ap != NULL)
        printf(" (%s)", ap);
    printf(": %s\n", databuf);

    close(s);
}


  1. Declares sockaddr_in structures.
  2. Clears the server address and sets up server variables.
  3. Calls gethostbyname to obtain the server address.
  4. Creates AF_INET socket.
  5. Sends a request to the server.
  6. Calls gethostbyaddr to retrieve the server name.
  7. Calls inet_ntoa to convert the server address to a text string.

7.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.


/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright 2000 Compaq Computer Corporation                 *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer  Corporation.  Possession, use,  duplication  or   *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define SERVER_PORT     7639
#define CLIENT_PORT     7739

#define MAXBUFSIZE 4096

int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in    serveraddr; (1)
    struct sockaddr_in    clientaddr;
    int                   clientaddrlen;
    struct hostent        *hp;
    const char            *ap;
    const char            *response = "this is the server's response";
    u_short               port;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { (2)
        perror("socket");
        exit(1);
    }

    bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); (3)
    serveraddr.sin_family      = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port        = htons(SERVER_PORT);

    if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
        perror("bind");
        exit(2);
    }
    if (listen(s, SOMAXCONN) < 0) {
        perror("Listen");
        close(s);
        exit(3);

    while (1) {
        int new_s;
        clientaddrlen = sizeof(clientaddr);
        new_s = accept(s, (Struct sockaddr*)&clientaddr, &clientaddrlen);

        dcount = recv(new_s, databuf, sizeof(databuf), 0);
        if (dcount <= 0) {
            perror("recv");
            close(new_s);
            continue;
        }
        databuf[dcount] = '\0';
        HP = gethostbyaddr((char *)&clientaddr.sin_addr.s_addr, (4)
            sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        ap = inet_ntoa(clientaddr.sin_addr); (5)
        port = ntohs(clientaddr.sin_port);
        printf("Request received from");
        if (HP != NULL)
            printf(" %s", HP->h_name);
        if (ap != NULL)
            printf(" (%s)", ap);
        printf(" port %d \"%s\"\n", port, databuf);

        if (send(new_s, response, strlen(response), 0) < 0) {
            perror("send");
            continue;
        }
        close(new_s);
    }
    close(s);
}

  1. Declares sockaddr_in structures.
  2. Creates an AF_INET socket.
  3. Clears the server address and sets up server variables.
  4. Calls gethostbyaddr to retrieve client name.
  5. Calls inet_ntoa to convert the client address to a text string.

7.6.2 Programs Using AF_INET6 Sockets

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

7.6.2.1 Client Program

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


/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright 2000 Compaq Computer Corporation                 *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer Corporation.  Possession, use,  duplication  or    *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define SERVER_PORT     7639
#define CLIENT_PORT     7739

#define MAXBUFSIZE 4096

int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct addrinfo *server_info;  (1)
    struct addrinfo *cur_info;
    struct addrinfo hints;
    struct sockaddr_in6    serveraddr;
    char            addrbuf[INET6_ADDRSTRLEN];
    char            node[MAXDNAME];
    char            service[MAXDNAME];
    int             ni;
    int             err;
    int             serveraddrlen;
    const char      *request = "this is the client's request";
    char            *server;

    if (argc < 2) {
        printf("Usage: client client <server>\n");
        exit(1);
    }
    server = argv[1];
    bzero((char *) &hints, sizeof(hints)); (2)
    hints.ai_family = AF_INET6;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_DEFAULT;

    sprintf(service, "%d", SERVER_PORT);

    err = getaddrinfo(server, service, &hints, &server_info);  (3)
    if (err != 0) {
        if (err == EAI_SYSTEM)
            perror("getaddrinfo");
        else
            printf("%s", gai_strerror(err0));
        exit(2);
    }
    cur_info = server_info;

    while (cur_info != NULL) {
        if ((s = socket(cur_info->ai_family, cur_info->ai_socktype, 0)) < 0) { (4)
            perror("socket");
            exit(3);
        }
        if (connect(s, cur_info->ai_addr, cur_info->ai_addrlen) <0 {
            close(s);
            cur_info = cur_info->ai_next;
            continue;
        }
        break;
    }
    freeaddrinfo(server_info); (5)

    if (send(s, request, strlen(request), 0) < 0) { (6)
        perror("send");
        exit(5);
    }
    dcount = recv(s, databuf, sizeof(databuf), 0);
    if (dcount < 0) {
        perror("recv");
        exit(6);
    }
    databuf[dcount] = '\0';
    serveraddrlen = sizeof(serveraddr);
    if (getpeername(s, (struct sockaddr*) &serveraddr, &serveraddrlen) < 0 {
        perror("getpeername");
        exit(7);
    }
    printf("Response received from");
    ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, (7)
                        node, sizeof(node), NULL, 0, NI_NAMEREQD);
    if (ni == 0)
        printf(" %s", node);
    ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, (8)
                        addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
    if (ni == 0)
        printf(" (%s)", addrbuf);

    printf(": %s\n", databuf);

    close(s);
}

  1. Declares addrinfo structures, hints structure, sockaddr_in6 structure, address string buffer, node name string buffer, service name string buffer, error number variable, and server address length variable.
  2. Clears the hints structure and sets up hints variables.
  3. Calls getaddrinfo to obtain the server address.
  4. Creates an AF_INET6 socket.
  5. Frees all addrinfo structures.
  6. Sends a request to the server.
  7. Calls getnameinfo to obtain the server name.
  8. Calls getnameinfo to obtain the server's numeric address and message data.

7.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.



/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright 2000 Compaq Computer Corporation                 *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer Corporation.  Possession, use,  duplication  or    *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define SERVER_PORT     7639
#define CLIENT_PORT     7739

#define MAXBUFSIZE 4096

int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in6   serveraddr; (1)
    struct storage        clientaddr;
    char                  addrbuf[INET6_ADDRSTRLEN];
    char                  node[MAXDNAME];
    char                  port[MAXDNAME];
    int                   err;
    int                   ni;
    int                   clientaddrlen;
    const char            *response = "this is the server's response";

    if ((s = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { (2)
        perror("socket");
        exit(1);
    }

    bzero((char *) &serveraddr, sizeof(struct sockaddr_in6)); (3)
    serveraddr.sin6_family      = AF_INET6;
    serveraddr.sin6_addr        = in6addr_any;
    serveraddr.sin6_port        = htons(SERVER_PORT);

    if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
        perror("bind");
        exit(2);
    }
    if (listen(s, SOMAXCONN) < 0) {
        perror("listen");
        close(s);
        exit(3);
    }
    while (1) {
        int new_s;
        clientaddrlen = sizeof(clientaddr);
        bzero((char *)&clientaddr, clientaddrlen); (4)
        new_s = accept(s, (struct sockaddr*)&clientaddr, &clientaddrlen);
        if (new_s < 0) {
            perror("accept");
            continue;
        }
        dcount = recv(s, databuf, sizeof(databuf), 0);
        if (dcount <= 0) {
            perror("recv");
            close(new_s);
            continue;
        }
        databuf[dcount] = '\0';

        printf("Request received from");
        ni = getnameinfo((struct sockaddr *)&clientaddr, (5)
            clientaddrlen, node, sizeof(node), NULL, 0, NI_NAMEREQD);
        if (ni == 0)
            printf(" %s", node);
        ni = getnameinfo((struct sockaddr *)&clientaddr, (6)
            clientaddrlen, addrbuf, sizeof(addrbuf), port, sizeof(port),
            NI_NUMERICHOST|NI_NUMERICSERV);
        if (ni == 0)
            printf(" (%s) port %d, addrbuf, port);
        printf(" \"%s\"\n", port, databuf);

        if (send(new_s, response, strlen(response), 0) < 0) {
            perror("send");
            close(new_s);
            continue;
        }
        close(new_s);
    }
    close(s);
}

  1. Declares sockaddr_in6 structures, address string buffer, and error number variable.
  2. Creates an AF_INET6 socket.
  3. Clears the server address and sets up the server variables.
  4. Clears the client address.
  5. Calls getnameinfo to retrieve the client name.
  6. Calls getnameinfo to obtain the client's address, port, and message data.

7.6.3 Sample Program Output

This section contains sample output from the preceding server and client programs. The server program makes and receives all requests on an AF_INET6 socket using sockaddr_in6 . For requests received over IPv4, sockaddr_in6 contains an IPv4-mapped IPv6 address.

The following example shows a client program running on node hostb6 and sending a request to node hosta6. The program uses an AF_INET6 socket. The node hosta6 has the IPv6 address 3ffe:1200::a00:2bff:fe97:7be0 in the Domain Name System (DNS).



$ client :== $client.exe
$ client hosta6
Response received from hosta6.ipv6.corp.example (3ffe:1200::a00:2bff:fe97:7be0):
 this is the server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostb6:



$ run server
Request received from hostb6.ipv6.corp.example (3ffe:1200::a00:2bff:fe2d:02b2
 port 7739 "this is the client's request"

The following example shows the client program running on node hostb and sending a request to node hosta. The program uses an AF_INET6 socket. The hosta node has the IPv4 address 10.10.10.13 in the DNS.



$ client :== $client.exe
$ client hosta
Response received from hosta.corp.example (::ffff:10.10.10.13): this is the
 server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostb:



$ run server
Request received from hostb.corp.example (::ffff:10.10.10.251) port 7739
 "this is the client's request"

The following example shows the client program running on node hostc and sending a request to node hosta. The program was built and run on an IPv4-only system using an AF_INET socket.



$ client :== $client.exe
$ client hosta
Response received from hosta.corp.example (10.10.10.13): this is the
 server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostc:



$ run server
Request received from hostc.corp.example (::ffff:10.10.10.63) port 7739
 "this is the client's request"


Previous Next Contents