IPv6 Programming on Windows Tutorial

IPv6 Programming on Windows Tutorial

tags:
IPv6 Programming on Windows Tutorial
Part 1: Development Environment Installation and Win32 API Basics
(2005.10.24)

Junya Kato
NTT Information Sharing Platform Laboratories



Introduction

The most recent Windows OS released by Microsoft already contains IPv6 features.  IPv6 support is implemented in a wide range of OSs, from OSs that are made for PCs, such as Windows XP and Windows Server 2003, to OSs that are made for embedded devices, such as Windows CE .NET.  It is said that Windows Vista (codenamed Longhorn), which is the successor to Windows XP, will be released with IPv6 features enabled by default.  It is likely that application developers will be developing more IPv6-ready applications in the future.

In this six-part series, I will discuss how to create IPv6 applications that target Windows OSs.  I will especially focus on the knowledge that is needed to start developing IPv6 applications on Windows for those who have experience in developing IPv4 applications on Windows and UNIX.  In the first half of the series, I will explain how to use APIs that are available for both UNIX and Windows.  Please read the reference documents as well.  Additionally, I will discuss network programming specific to Windows, which is the purpose of this series.  Many Windows applications use the WinSock API, which is a sockets implementation that was enhanced specifically for Windows.  For example, features such as asynchronous I/O, multiple I/O, IP Helper API, etc. were added.  In order to create applications that behave like Windows applications, I will discuss these as well.

In Part 1, I will explain how to set up the development environment and we will compile and run a simple sample program.  Also, for those who don’t have much programming experience on Windows, but have development experience on UNIX, I will explain the difference between the WinSock/Win32 API and Berkley sockets (UNIX system).


Setting up the target environment and development tools

In this series, I will assume the use of the Win32 API (WinSock 2) from the C/C++ language on Windows XP SP2.  On Windows, IPv6 programming is possible from programming languages such as C#, .NET Framework and Java, but I will not cover those languages in this series.  If possible, I will cover them separately.

List of necessary software and software installation
  1. Microsoft Windows XP SP2
  2. Microsoft Visual Studio .NET 2003
  3. Microsoft Platform SDK for Windows Server 2003 SP1
Preparing the OS

Regarding #1 above, please install Windows XP SP2 and enable the IPv6 features.

Preparing the compiler

Regarding #2 above, we will use Microsoft Visual Studio .NET 2003 to compile.  Please install it in the environment that you are going to use.  It is likely that Microsoft Visual Studio 6.0 and above will work as well, however, the sample code in this article will be compiled and tested using Microsoft Visual Studio .NET 2003.

Free development environment set up with Microsoft Visual C++ Toolkit 2003

Microsoft Visual Studio .NET 2003 is a commercial product, however, the C/C++ compiler part of this product is released free from Microsoft.  You can obtain the Microsoft Visual C++ Toolkit 2003 from the URL below:

http://msdn.microsoft.com/visualc/vctoolkit2003/

Please note that the tools provided at this site are command line tools only. The GUI Integrated Development Environment (IDE) isn’t included.  Please also note that they come only with the bare minimum headers and libraries related to the language specifications.  So, it means that you won’t be able to create exactly the same environment as Microsoft Visual Studio .NET 2003.  In this series, I will provide sample code that can be compiled and tested by using Microsoft Visual C++ Toolkit 2003 as much as possible, but there may be some code that cannot be complied with the free tools.


Obtaining and installing the Platform SDK

Next, please obtain the Microsoft Platform SDK for Windows Server 2003 SP1 mentioned in #3 above.  The name states that it is for Windows Server 2003, but this also contains the SDK that is needed for development on Windows XP.  The Platform SDK is also provided for free, so please download it from the URL below:

http://www.microsoft.com/downloads/
details.aspx?FamilyId=
A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5
&displaylang=en

Once you start the installer after downloading, a screen to select the components that you want to be installed will appear.

Platform SDK?I`?gu?N?e`?AE?C??g?X?g?[??q

On this screen, please make sure you remember to check “Microsoft Windows Core SDK”.  It includes the Win32 API/WinSock related header files, import libraries, and basic tools including the make command, resource compilers, etc.

Verifying environment variables

Please verify the command line search path (PATH environment variable), and the search path for header files (INCLUDE environment variable) and import libraries (LIB environment variable).  The installers for Visual Studio .NET 2003 and Platform SDK will configure this for you, but please check the order of the search path just in case.  The key is to configure it so that the Platform SDK related folders are searched before the Visual Studio .NET 2003 environment.

In the example below, the underlined (^^^^) parts are the configuration lines for Platform SDK.  The other configuration lines related to Microsoft Visual Studio .NET 2003 are the environment variables that were configured by the compiler’s installer.


  •PATH=
    C:\Program Files\Microsoft Platform SDK\Bin;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    C:\Program Files\Microsoft Platform SDK\Bin\WinNT;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;
    C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;
    C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;
    C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;
    C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;
    C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\v1.1.4322

  •INCLUDE=
    C:\Program Files\Microsoft Platform SDK\include;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\ATLMFC\INCLUDE;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\INCLUDE;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\PlatformSDK\include\prerelease;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\PlatformSDK\include;
    C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\include

  •LIB=
    C:\Program Files\Microsoft Platform SDK\lib;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\ATLMFC\LIB;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\LIB;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\PlatformSDK\lib\prerelease;
    C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\PlatformSDK\lib;
    C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\lib

These are the configurations of the environment variables when you use Microsoft Visual C++ Toolkit 2003.

  •PATH=
    C:\Program Files\Microsoft Platform SDK\Bin;
    C:\Program Files\Microsoft Platform SDK\Bin\WinNT;
    C:\Program Files\Microsoft Visual C++ Toolkit 2003\bin


  •INCLUDE=
    C:\Program Files\Microsoft Platform SDK\include;
    C:\Program Files\Microsoft Visual C++ Toolkit 2003\include

  •LIB=
    C:\Program Files\Microsoft Platform SDK\lib;
    C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib


Testing the compiler

Please download the code that will be inserted within the {getv6addr.c} listing.  In order to compile it, open a command prompt and insert the c1command as shown in the figure {Compiling getv6addr.c and example}.

getv6addr.exe is a program that finds the IPv6 address for the host name passed in as an argument.  Please give a host name to the binary that was created by compiling, and execute it.  The sample execution in the bottom of the figure {Compiling getv6addr.c and example} shows the IPv6 address for the host www.ipv6style.jp after obtaining it.

C:\>cl getv6addr.c ws2_32.lib    ---Compiling from the command line
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

getv6addr.c
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:getv6addr.exe
getv6addr.obj
ws2_32.lib

C:\>getv6addr www.ipv6styel.jp     --- Executing the binary
www.ipv6style.jp IPv6 address : 2001:218:2001:3000::56

getv6addr.c listing

#include ‹winsock2.h›
#include ‹ws2tcpip.h›
#include ‹stdio.h›

int main(int argc, char *argv[])
{
    char *nodename;
    WSADATA wsaData;
    ADDRINFO hints;
    LPADDRINFO ai, ai0;
    int e;

    /* parsing command line argument */
    if (argc != 2) {
	fprintf(stderr, "syntax: getv6addr HOSTNAME\n");
	exit(1);
    }
    nodename = argv[1];

    /* initilizing Windows Socket */
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    /* resolving "www.ipv6style.jp" */
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET6;
    if (e = getaddrinfo(nodename, NULL, &hints, &ai0)) {
	fprintf(stderr, "%s: %s\n", nodename, gai_strerror(e));
	WSACleanup();
	exit(1);
    }

    /* print IPv6 address if resolv process is succeeded */
    for (ai = ai0; ai; ai = ai->ai_next) {
	char v6addrstr[NI_MAXHOST];
	getnameinfo(ai->ai_addr, ai->ai_addrlen,
		    v6addrstr, sizeof(v6addrstr),  NULL, 0, NI_NUMERICHOST);

	printf("%s IPv6 address: %s\n", nodename, v6addrstr);
    }

    /* cleanup */
    freeaddrinfo(ai0);
    WSACleanup();
}



Explanation of getv6addr.c

Difference among header files

In order to use the WinSock API for IPv6 programming, include the two headers shown below:

 #include ‹winsock2.h›
 #include ‹ws2tcpip.h›

The {getv6addr.c} listing also includes winsock2.h and ws2tcpip.h.  When using Berkeley sockets in a UNIX environment, it is common practice to include the headers shown below at the beginning of the source code.

 #include ‹sys/types.h›
 #include ‹sys/socket.h›
 #include ‹netdb.h›

Please be careful since sys/types.h, sys/socket.h, and netdb.h are header files that do not exist in the WinSock API.

Linking the library

An import library, “ws2_32.lib”, is linked in when compiling the {getv6addr.c} listing as shown in the figure {Compiling getv6addr.c and example}. 

   cl getv6addr.c ws2_32.lib
                  ^^^^^^^^^^ 

This library contains the API entry point, and you always need to link it when you use the WinSock2 API.  (see endnote 1)

General flow of getv6addr.c

The general flow of the getv6addr.c program is shown below.

[start the program]
|
[check the command line arguments and obtain the character string of the host name]
|
[start up WinSock]
|
[obtain the IPv6 address from the host name using the getaddrinfo( ) function (name resolution)] .... (1)
|
[if the name resolution is successful, convert the IPv6 address to a character string using getnameinfo( ) function and display on the screen] .... (2)
|
[release the result of the name resolution using freeaddrinfo( ) ] .... (3)
|
[shut down WinSock]
|
[the program closes]


In the {getc6addr.c} listing, in block (1), the getaddrinfo( ) function takes a host name and stores the IPv6 address that was obtained from name resolution in the ADDRINFO structure.  If multiple IPv6 addresses are obtained from the name resolution, it will return the first item (ai0) of the ADDRINFO list.  The buffer for the ADDRINFO structure list where this IPv6 address is stored will be created by the getaddrinfo( ) function.  You don’t need to allocate it in the program beforehand, however, you will need to release it using the freeaddrinfo( ) function (block (3) ) when you don’t need it any more.

In block (2), iterate through the ADDRINFO structure list that was returned by getaddrinfo( ) using a for statement.  For each one, the binary IPv6 address (binary network format) is converted to a character string (presentation format).  The API which is used here is the getnameinfo( ) function.  The result of the character string conversion will be stored in v6addr.  The primary role of the getnameinfo( ) function is finding the host name from an IP address (reverse lookup), however, it can convert a binary representation to a character string as well.  (see endnote 2)

The four APIs that I used, which are getaddrinfo( ), getnameinfo( ), freeaddrinfo( ), and gai_strerror( ), are important APIs that can be used in many programs regardless of the server/client OS.  RFC 3493 defines how to use them, and they can be used on most of the IPv6 ready OSs although there are some restrictions and differences from system to system.  I have only outlined those functions this time.  I will explain the details of the related data structure (ADDRINFO structure) and the meaning of the arguments in the next article.


Differences between WinSock (Windows) and Berkeley sockets (UNIX)

WinSock is a programming API derived from Berkeley sockets.  So, because they are similar, developers who have experience in network programming on UNIX can use it without difficulty.  However, while Windows was being developed, many unique APIs were created, and also with regards to coding style, a unique vernacular has been developed.  Below, I will discuss the differences between the terminology used frequently in the Win32 API and the terminology of the WinSock API and Berkeley sockets for those who have development experience on UNIX.

Basic integer types

The integer types that are frequently used in Windows programming are WORD and DWORD types.

    WORD and DWORD Types in 32-bit Environment
   type | typedef defined as |        meaning
  ------+--------------------+-------------------------
  WORD  |    unsigned short  | unsigned 16-bit integer
  DWORD |    unsigned int    | unsigned 32-bit integer

Macro
  MAKEWORD(a, b) = b * 16 + a

In the {getv6addr.c} listing, there is a line MAKEWORD(2, 2).  This is a macro that creates a 16-bit WORD integer and is very often used when designating the WinSock version.  So, MAKEWORD(2, 2) = 0x0202.  In the WORD value that is created by this macro, the first argument is the least significant byte and the second argument is the most significant byte.  e.g. MAKEWORD(0x03, 0x04)=4*16+3=67.  Please be careful about the order of the arguments.

### Representation of structure and pointer types

In Windows programming, not just WinSock, there is a custom that structure and pointer types are written in all caps.  An example is shown below.


     Definition of Structure Type
   Type      | typedef defined as
  -----------+-----------------------
  ADDRINFO   | struct addrinfo
  PADDRINFO  | struct addrinfo *
  LPADDRINFO | struct addrinfo FAR *

The SOCKADDR type is defined as struct sockaddr type, and, furthermore, its pointer type is PSOCKADDR.  The third one has a FAR modifier for the pointer.  It is an old expression from the days of 16-bit programming that indicates that it exceeds the segment.  Nowadays 32-bit programming is common and PSOCKADDR and LPSOCKADDR have the same meaning.

WinSock version and initialization

WinSock version

Features in the WinSock API differ largely from version to version.  Version 1.1 supports only TCP/IP (IPv4) and is included with Windows 95 and OSs before that.  Windows NT/98 and above come with WinSock 2 by default.  It has been made multi-protocol so that it can support not only TCP/IP but multiple protocols as well.  It also supports access models such as overlapped I/O.  For IPv6 programming, designate version 2.2.

Initializing WinSock


In the {getc6addr.c} listing, there is a variable wsaData of WSADATA type, and there are also functions WSAStartup( ), which refers to the variable, and WSACleanup( ).  These are extensions unique to Windows that do not exist in Berkeley sockets.  For WinSock, initialization (WSAStartup( ) ) and shut down (WSACleanup( ) ) are always needed before you use any of the socket APIs.


Function prototypes
  int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
  int WSACleanup(void);

For the first argument of WSAStartup( ), designate the WinSock version that is required by the program.  If version 2.2 is required, designate MAKEWORD(2, 2) (0x0202 in hexadecimal integer value).  For the WSAStartup( ) function, if the return value is 0, startup was successful (the  required WinSock version can be used), and if it failed, values other than 0 are returned.  When the function returns, the WinSock version that can be used is filled in to the lpWSAData structure that was passed in as the second argument.  By checking the contents of the lpWSAData structure, you will be able to learn about the WinSock version that comes with the OS.

In the {getc6addr.c} listing, the WSACleanup( ) function is called when the program ends.  This is a function that shuts down WinSock.


Conclusion


I have shown how to configure the development environment and compile a simple sample program this time.  I also explained the differences between the Win32 API/WinSock and Berkeley sockets, mainly geared towards UNIX programmers.  I will explain the creation of IPv6 programs using TCP in the next article.

References

[1]  Hagino, Junichiro. Translated by Ogawa, Ayako. IPv6 Network Programming, ASCII, April 2003.

[2]  Ookawa, Makoto. “How to upgrade WinSock application to support IPv6.” IPv6style July 2003. Impress. <http://www.ipv6style.jp/en/apps/20030711/index.shtml>.

[3]  Napper, Lewis. Translated by Emura, Yutaka. WinSock 2 Programming, Revised, 2nd edition, Soft Bank Publishing, January 2005.

Endnote

1.  For WinSock version 1.1, use wsock32.lib as the import library.  For IPv6 programming, since the use of WinSock2 is assumed, please link in ws2_32.lib.  As for the WinSock version, please refer to the section, “WinSock version”.

2.  For converting the representation, on UNIX (Free BSD/Linux/etc.), you can also use the inet_ntop( )/inet_pton( ) functions, and in the WinSock API, you can use the WSAAddressToString( )/WSAStringToAddress( ) functions.

この記事のトラックバックURL

http://www.ipv6style.jp/trackback/628
Ads by Google

Link

go6 is a community based portal dedicated to advancing the deployment of IPv6.
http://go6.net/