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

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1998-2001 Microsoft Corporation
  4. //
  5. // Abstract:
  6. //
  7. // Program to perform demonstrate name resolution via getaddrinfo.
  8. //
  9. #include <winsock2.h>
  10. #include <ws2tcpip.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. void DumpAddrInfo(ADDRINFO *AddrInfo);
  14. void ListAddrInfo(ADDRINFO *AddrInfo);
  15. //
  16. // getaddrinfo flags
  17. // This array maps values to names for pretty-printing purposes.
  18. // Used by DecodeAIFlags().
  19. //
  20. // TBD: When we add support for AI_NUMERICSERV, AI_V4MAPPED, AI_ALL, and
  21. // TBD: AI_ADDRCONFIG to getaddrinfo (and thus define them in ws2tcpip.h),
  22. // TBD: we'll need to add them here too.
  23. //
  24. // Note when adding flags: all the string names plus connecting OR symbols
  25. // must fit into the buffer in DecodeAIFlags() below. Enlarge as required.
  26. //
  27. typedef struct GAIFlagsArrayEntry {
  28. int Flag;
  29. char *Name;
  30. } GAIFlagsArrayEntry;
  31. GAIFlagsArrayEntry GAIFlagsArray [] = {
  32. {AI_PASSIVE, "AI_PASSIVE"},
  33. {AI_CANONNAME, "AI_CANONNAME"},
  34. {AI_NUMERICHOST, "AI_NUMERICHOST"}
  35. };
  36. #define NUMBER_FLAGS (sizeof(GAIFlagsArray) / sizeof(GAIFlagsArrayEntry))
  37. //
  38. // Global variables.
  39. //
  40. int Verbose = FALSE;
  41. //
  42. // Inform the user.
  43. //
  44. void Usage(char *ProgName) {
  45. fprintf(stderr, "\nPerforms name to address resolution.\n");
  46. fprintf(stderr, "\n%s [NodeName] [-s ServiceName] [-p] [-c] [-v]\n\n",
  47. ProgName);
  48. WSACleanup();
  49. exit(1);
  50. }
  51. int __cdecl
  52. main(int argc, char **argv)
  53. {
  54. WSADATA wsaData;
  55. char *NodeName = NULL;
  56. char *ServiceName = NULL;
  57. int ReturnValue;
  58. ADDRINFO Hints, *AddrInfo;
  59. int Loop;
  60. int Passive = FALSE;
  61. int Canonical = FALSE;
  62. int GotNodeName = FALSE;
  63. //
  64. // Initialize Winsock.
  65. //
  66. if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
  67. printf("WSAStartup failed\n");
  68. exit(1);
  69. }
  70. //
  71. // Parse command arguments.
  72. //
  73. if (argc > 1) {
  74. for (Loop = 1;Loop < argc; Loop++) {
  75. if (((argv[Loop][0] == '-') || (argv[Loop][0] == '/')) &&
  76. (argv[Loop][1] != 0) && (argv[Loop][2] == 0)) {
  77. switch(tolower(argv[Loop][1])) {
  78. case 's':
  79. if (argv[Loop + 1]) {
  80. if ((argv[Loop + 1][0] != '-') &&
  81. (argv[Loop + 1][0] != '/')) {
  82. ServiceName = argv[++Loop];
  83. break;
  84. }
  85. }
  86. Usage(argv[0]);
  87. break;
  88. case 'p':
  89. Passive = TRUE;
  90. break;
  91. case 'c':
  92. Canonical = TRUE;
  93. break;
  94. case 'v':
  95. Verbose = TRUE;
  96. break;
  97. default:
  98. Usage(argv[0]);
  99. break;
  100. }
  101. } else if (!GotNodeName) {
  102. NodeName = argv[Loop];
  103. GotNodeName = TRUE;
  104. } else {
  105. Usage(argv[0]);
  106. }
  107. }
  108. }
  109. //
  110. // Prepare Hints.
  111. //
  112. memset(&Hints, 0, sizeof(Hints));
  113. Hints.ai_family = PF_UNSPEC;
  114. if (Passive) {
  115. Hints.ai_flags = AI_PASSIVE;
  116. }
  117. if (Canonical) {
  118. Hints.ai_flags |= AI_CANONNAME;
  119. }
  120. if (Verbose) {
  121. printf("\nHints contains:\n");
  122. DumpAddrInfo(&Hints);
  123. }
  124. //
  125. // Make the call.
  126. //
  127. if (Verbose) {
  128. printf("\nCalling getaddrinfo(\"%s\", \"%s\", &Hints, &AddrInfo)\n",
  129. NodeName, ServiceName);
  130. } else {
  131. printf("\nCalling getaddrinfo for node %s", NodeName);
  132. if (ServiceName) {
  133. printf(" and service %s", ServiceName);
  134. }
  135. printf("\n");
  136. }
  137. ReturnValue = getaddrinfo(NodeName, ServiceName, &Hints, &AddrInfo);
  138. printf("Returns %d (%s)\n", ReturnValue,
  139. ReturnValue ? gai_strerror(ReturnValue) : "no error");
  140. if (AddrInfo != NULL) {
  141. if (Verbose) {
  142. printf("AddrInfo contains:\n");
  143. DumpAddrInfo(AddrInfo);
  144. } else {
  145. if (AddrInfo->ai_canonname) {
  146. printf("Canonical name for %s is %s\n", NodeName,
  147. AddrInfo->ai_canonname);
  148. }
  149. printf("AddrInfo contains the following records:\n");
  150. ListAddrInfo(AddrInfo);
  151. }
  152. freeaddrinfo(AddrInfo);
  153. }
  154. printf("\n");
  155. }
  156. //* inet6_ntoa - Converts a binary IPv6 address into a string.
  157. //
  158. // Returns a pointer to the output string.
  159. //
  160. char *
  161. inet6_ntoa(const struct in6_addr *Address)
  162. {
  163. static char buffer[128]; // REVIEW: Use 128 or INET6_ADDRSTRLEN?
  164. DWORD buflen = sizeof buffer;
  165. struct sockaddr_in6 sin6;
  166. memset(&sin6, 0, sizeof sin6);
  167. sin6.sin6_family = AF_INET6;
  168. sin6.sin6_addr = *Address;
  169. if (WSAAddressToString((struct sockaddr *) &sin6,
  170. sizeof sin6,
  171. NULL, // LPWSAPROTOCOL_INFO
  172. buffer,
  173. &buflen) == SOCKET_ERROR)
  174. strcpy(buffer, "<invalid>");
  175. return buffer;
  176. }
  177. //* DecodeAIFlags - converts flag bits to a symbolic string.
  178. // (i.e. 0x03 returns "AI_PASSIVE | AI_CANONNAME")
  179. //
  180. char *
  181. DecodeAIFlags(unsigned int Flags)
  182. {
  183. static char Buffer[1024];
  184. char *Pos;
  185. BOOL First = TRUE;
  186. int Loop;
  187. Pos = Buffer;
  188. for (Loop = 0; Loop < NUMBER_FLAGS; Loop++) {
  189. if (Flags & GAIFlagsArray[Loop].Flag) {
  190. if (!First)
  191. Pos += sprintf(Pos, " | ");
  192. Pos += sprintf(Pos, GAIFlagsArray[Loop].Name);
  193. First = FALSE;
  194. }
  195. }
  196. if (First)
  197. return "NONE";
  198. else
  199. return Buffer;
  200. }
  201. //* DecodeAIFamily - converts address family value to a symbolic string.
  202. //
  203. char *
  204. DecodeAIFamily(unsigned int Family)
  205. {
  206. if (Family == PF_INET)
  207. return "PF_INET";
  208. else if (Family == PF_INET6)
  209. return "PF_INET6";
  210. else if (Family == PF_UNSPEC)
  211. return "PF_UNSPEC";
  212. else
  213. return "UNKNOWN";
  214. }
  215. //* DecodeAISocktype - converts socktype value to a symbolic string.
  216. //
  217. char *
  218. DecodeAISocktype(unsigned int Socktype)
  219. {
  220. if (Socktype == SOCK_STREAM)
  221. return "SOCK_STREAM";
  222. else if (Socktype == SOCK_DGRAM)
  223. return "SOCK_DGRAM";
  224. else if (Socktype == SOCK_RAW)
  225. return "SOCK_RAW";
  226. else if (Socktype == SOCK_RDM)
  227. return "SOCK_RDM";
  228. else if (Socktype == SOCK_SEQPACKET)
  229. return "SOCK_SEQPACKET";
  230. else if (Socktype == 0)
  231. return "UNSPECIFIED";
  232. else
  233. return "UNKNOWN";
  234. }
  235. //* DecodeAIProtocol - converts protocol value to a symbolic string.
  236. //
  237. char *
  238. DecodeAIProtocol(unsigned int Protocol)
  239. {
  240. if (Protocol == IPPROTO_TCP)
  241. return "IPPROTO_TCP";
  242. else if (Protocol == IPPROTO_UDP)
  243. return "IPPROTO_UDP";
  244. else if (Protocol == 0)
  245. return "UNSPECIFIED";
  246. else
  247. return "UNKNOWN";
  248. }
  249. //* DumpAddrInfo - print the contents of an addrinfo structure to standard out.
  250. //
  251. void
  252. DumpAddrInfo(ADDRINFO *AddrInfo)
  253. {
  254. int Count;
  255. if (AddrInfo == NULL) {
  256. printf("AddrInfo = (null)\n");
  257. return;
  258. }
  259. for (Count = 1; AddrInfo != NULL; AddrInfo = AddrInfo->ai_next) {
  260. if ((Count != 1) || (AddrInfo->ai_next != NULL))
  261. printf("Record #%u:\n", Count++);
  262. printf(" ai_flags = %s\n", DecodeAIFlags(AddrInfo->ai_flags));
  263. printf(" ai_family = %s\n", DecodeAIFamily(AddrInfo->ai_family));
  264. printf(" ai_socktype = %s\n", DecodeAISocktype(AddrInfo->ai_socktype));
  265. printf(" ai_protocol = %s\n", DecodeAIProtocol(AddrInfo->ai_protocol));
  266. printf(" ai_addrlen = %u\n", AddrInfo->ai_addrlen);
  267. printf(" ai_canonname = %s\n", AddrInfo->ai_canonname);
  268. if (AddrInfo->ai_addr != NULL) {
  269. if (AddrInfo->ai_addr->sa_family == AF_INET) {
  270. struct sockaddr_in *sin;
  271. sin = (struct sockaddr_in *)AddrInfo->ai_addr;
  272. printf(" ai_addr->sin_family = AF_INET\n");
  273. printf(" ai_addr->sin_port = %u\n", ntohs(sin->sin_port));
  274. printf(" ai_addr->sin_addr = %s\n", inet_ntoa(sin->sin_addr));
  275. } else if (AddrInfo->ai_addr->sa_family == AF_INET6) {
  276. struct sockaddr_in6 *sin6;
  277. sin6 = (struct sockaddr_in6 *)AddrInfo->ai_addr;
  278. printf(" ai_addr->sin6_family = AF_INET6\n");
  279. printf(" ai_addr->sin6_port = %u\n", ntohs(sin6->sin6_port));
  280. printf(" ai_addr->sin6_flowinfo = %u\n", sin6->sin6_flowinfo);
  281. printf(" ai_addr->sin6_scope_id = %u\n", sin6->sin6_scope_id);
  282. printf(" ai_addr->sin6_addr = %s\n",
  283. inet6_ntoa(&sin6->sin6_addr));
  284. } else {
  285. printf(" ai_addr->sa_family = %u\n",
  286. AddrInfo->ai_addr->sa_family);
  287. }
  288. } else {
  289. printf(" ai_addr = (null)\n");
  290. }
  291. }
  292. }
  293. //* ListAddrInfo - succinctly list the contents of an addrinfo structure.
  294. //
  295. void
  296. ListAddrInfo(ADDRINFO *AddrInfo)
  297. {
  298. int ReturnValue;
  299. char Buffer[128];
  300. int Buflen;
  301. if (AddrInfo == NULL) {
  302. printf("AddrInfo = (null)\n");
  303. return;
  304. }
  305. for (; AddrInfo != NULL; AddrInfo = AddrInfo->ai_next) {
  306. Buflen = 128;
  307. ReturnValue = WSAAddressToString(AddrInfo->ai_addr,
  308. AddrInfo->ai_addrlen, NULL,
  309. Buffer, &Buflen);
  310. if (ReturnValue == SOCKET_ERROR) {
  311. printf("<invalid>\n");
  312. } else {
  313. printf("%s\n", Buffer);
  314. }
  315. }
  316. }