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

- Section 7.6.1 contains sample programs using IPv4 AF_INET sockets.
- Section 7.6.2 contains sample programs using IPv6 AF_INET6 sockets.

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