Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

360 lines
10 KiB

// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// Copyright (c) 1998-2001 Microsoft Corporation
//
// Abstract:
//
// Program to perform demonstrate name resolution via getaddrinfo.
//
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
void DumpAddrInfo(ADDRINFO *AddrInfo);
void ListAddrInfo(ADDRINFO *AddrInfo);
//
// getaddrinfo flags
// This array maps values to names for pretty-printing purposes.
// Used by DecodeAIFlags().
//
// TBD: When we add support for AI_NUMERICSERV, AI_V4MAPPED, AI_ALL, and
// TBD: AI_ADDRCONFIG to getaddrinfo (and thus define them in ws2tcpip.h),
// TBD: we'll need to add them here too.
//
// Note when adding flags: all the string names plus connecting OR symbols
// must fit into the buffer in DecodeAIFlags() below. Enlarge as required.
//
typedef struct GAIFlagsArrayEntry {
int Flag;
char *Name;
} GAIFlagsArrayEntry;
GAIFlagsArrayEntry GAIFlagsArray [] = {
{AI_PASSIVE, "AI_PASSIVE"},
{AI_CANONNAME, "AI_CANONNAME"},
{AI_NUMERICHOST, "AI_NUMERICHOST"}
};
#define NUMBER_FLAGS (sizeof(GAIFlagsArray) / sizeof(GAIFlagsArrayEntry))
//
// Global variables.
//
int Verbose = FALSE;
//
// Inform the user.
//
void Usage(char *ProgName) {
fprintf(stderr, "\nPerforms name to address resolution.\n");
fprintf(stderr, "\n%s [NodeName] [-s ServiceName] [-p] [-c] [-v]\n\n",
ProgName);
WSACleanup();
exit(1);
}
int __cdecl
main(int argc, char **argv)
{
WSADATA wsaData;
char *NodeName = NULL;
char *ServiceName = NULL;
int ReturnValue;
ADDRINFO Hints, *AddrInfo;
int Loop;
int Passive = FALSE;
int Canonical = FALSE;
int GotNodeName = FALSE;
//
// Initialize Winsock.
//
if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
printf("WSAStartup failed\n");
exit(1);
}
//
// Parse command arguments.
//
if (argc > 1) {
for (Loop = 1;Loop < argc; Loop++) {
if (((argv[Loop][0] == '-') || (argv[Loop][0] == '/')) &&
(argv[Loop][1] != 0) && (argv[Loop][2] == 0)) {
switch(tolower(argv[Loop][1])) {
case 's':
if (argv[Loop + 1]) {
if ((argv[Loop + 1][0] != '-') &&
(argv[Loop + 1][0] != '/')) {
ServiceName = argv[++Loop];
break;
}
}
Usage(argv[0]);
break;
case 'p':
Passive = TRUE;
break;
case 'c':
Canonical = TRUE;
break;
case 'v':
Verbose = TRUE;
break;
default:
Usage(argv[0]);
break;
}
} else if (!GotNodeName) {
NodeName = argv[Loop];
GotNodeName = TRUE;
} else {
Usage(argv[0]);
}
}
}
//
// Prepare Hints.
//
memset(&Hints, 0, sizeof(Hints));
Hints.ai_family = PF_UNSPEC;
if (Passive) {
Hints.ai_flags = AI_PASSIVE;
}
if (Canonical) {
Hints.ai_flags |= AI_CANONNAME;
}
if (Verbose) {
printf("\nHints contains:\n");
DumpAddrInfo(&Hints);
}
//
// Make the call.
//
if (Verbose) {
printf("\nCalling getaddrinfo(\"%s\", \"%s\", &Hints, &AddrInfo)\n",
NodeName, ServiceName);
} else {
printf("\nCalling getaddrinfo for node %s", NodeName);
if (ServiceName) {
printf(" and service %s", ServiceName);
}
printf("\n");
}
ReturnValue = getaddrinfo(NodeName, ServiceName, &Hints, &AddrInfo);
printf("Returns %d (%s)\n", ReturnValue,
ReturnValue ? gai_strerror(ReturnValue) : "no error");
if (AddrInfo != NULL) {
if (Verbose) {
printf("AddrInfo contains:\n");
DumpAddrInfo(AddrInfo);
} else {
if (AddrInfo->ai_canonname) {
printf("Canonical name for %s is %s\n", NodeName,
AddrInfo->ai_canonname);
}
printf("AddrInfo contains the following records:\n");
ListAddrInfo(AddrInfo);
}
freeaddrinfo(AddrInfo);
}
printf("\n");
}
//* inet6_ntoa - Converts a binary IPv6 address into a string.
//
// Returns a pointer to the output string.
//
char *
inet6_ntoa(const struct in6_addr *Address)
{
static char buffer[128]; // REVIEW: Use 128 or INET6_ADDRSTRLEN?
DWORD buflen = sizeof buffer;
struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof sin6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *Address;
if (WSAAddressToString((struct sockaddr *) &sin6,
sizeof sin6,
NULL, // LPWSAPROTOCOL_INFO
buffer,
&buflen) == SOCKET_ERROR)
strcpy(buffer, "<invalid>");
return buffer;
}
//* DecodeAIFlags - converts flag bits to a symbolic string.
// (i.e. 0x03 returns "AI_PASSIVE | AI_CANONNAME")
//
char *
DecodeAIFlags(unsigned int Flags)
{
static char Buffer[1024];
char *Pos;
BOOL First = TRUE;
int Loop;
Pos = Buffer;
for (Loop = 0; Loop < NUMBER_FLAGS; Loop++) {
if (Flags & GAIFlagsArray[Loop].Flag) {
if (!First)
Pos += sprintf(Pos, " | ");
Pos += sprintf(Pos, GAIFlagsArray[Loop].Name);
First = FALSE;
}
}
if (First)
return "NONE";
else
return Buffer;
}
//* DecodeAIFamily - converts address family value to a symbolic string.
//
char *
DecodeAIFamily(unsigned int Family)
{
if (Family == PF_INET)
return "PF_INET";
else if (Family == PF_INET6)
return "PF_INET6";
else if (Family == PF_UNSPEC)
return "PF_UNSPEC";
else
return "UNKNOWN";
}
//* DecodeAISocktype - converts socktype value to a symbolic string.
//
char *
DecodeAISocktype(unsigned int Socktype)
{
if (Socktype == SOCK_STREAM)
return "SOCK_STREAM";
else if (Socktype == SOCK_DGRAM)
return "SOCK_DGRAM";
else if (Socktype == SOCK_RAW)
return "SOCK_RAW";
else if (Socktype == SOCK_RDM)
return "SOCK_RDM";
else if (Socktype == SOCK_SEQPACKET)
return "SOCK_SEQPACKET";
else if (Socktype == 0)
return "UNSPECIFIED";
else
return "UNKNOWN";
}
//* DecodeAIProtocol - converts protocol value to a symbolic string.
//
char *
DecodeAIProtocol(unsigned int Protocol)
{
if (Protocol == IPPROTO_TCP)
return "IPPROTO_TCP";
else if (Protocol == IPPROTO_UDP)
return "IPPROTO_UDP";
else if (Protocol == 0)
return "UNSPECIFIED";
else
return "UNKNOWN";
}
//* DumpAddrInfo - print the contents of an addrinfo structure to standard out.
//
void
DumpAddrInfo(ADDRINFO *AddrInfo)
{
int Count;
if (AddrInfo == NULL) {
printf("AddrInfo = (null)\n");
return;
}
for (Count = 1; AddrInfo != NULL; AddrInfo = AddrInfo->ai_next) {
if ((Count != 1) || (AddrInfo->ai_next != NULL))
printf("Record #%u:\n", Count++);
printf(" ai_flags = %s\n", DecodeAIFlags(AddrInfo->ai_flags));
printf(" ai_family = %s\n", DecodeAIFamily(AddrInfo->ai_family));
printf(" ai_socktype = %s\n", DecodeAISocktype(AddrInfo->ai_socktype));
printf(" ai_protocol = %s\n", DecodeAIProtocol(AddrInfo->ai_protocol));
printf(" ai_addrlen = %u\n", AddrInfo->ai_addrlen);
printf(" ai_canonname = %s\n", AddrInfo->ai_canonname);
if (AddrInfo->ai_addr != NULL) {
if (AddrInfo->ai_addr->sa_family == AF_INET) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)AddrInfo->ai_addr;
printf(" ai_addr->sin_family = AF_INET\n");
printf(" ai_addr->sin_port = %u\n", ntohs(sin->sin_port));
printf(" ai_addr->sin_addr = %s\n", inet_ntoa(sin->sin_addr));
} else if (AddrInfo->ai_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)AddrInfo->ai_addr;
printf(" ai_addr->sin6_family = AF_INET6\n");
printf(" ai_addr->sin6_port = %u\n", ntohs(sin6->sin6_port));
printf(" ai_addr->sin6_flowinfo = %u\n", sin6->sin6_flowinfo);
printf(" ai_addr->sin6_scope_id = %u\n", sin6->sin6_scope_id);
printf(" ai_addr->sin6_addr = %s\n",
inet6_ntoa(&sin6->sin6_addr));
} else {
printf(" ai_addr->sa_family = %u\n",
AddrInfo->ai_addr->sa_family);
}
} else {
printf(" ai_addr = (null)\n");
}
}
}
//* ListAddrInfo - succinctly list the contents of an addrinfo structure.
//
void
ListAddrInfo(ADDRINFO *AddrInfo)
{
int ReturnValue;
char Buffer[128];
int Buflen;
if (AddrInfo == NULL) {
printf("AddrInfo = (null)\n");
return;
}
for (; AddrInfo != NULL; AddrInfo = AddrInfo->ai_next) {
Buflen = 128;
ReturnValue = WSAAddressToString(AddrInfo->ai_addr,
AddrInfo->ai_addrlen, NULL,
Buffer, &Buflen);
if (ReturnValue == SOCKET_ERROR) {
printf("<invalid>\n");
} else {
printf("%s\n", Buffer);
}
}
}