// -*- 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 #include #include #include 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, ""); 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("\n"); } else { printf("%s\n", Buffer); } } }