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.

311 lines
10 KiB

  1. //
  2. // rawsend.c - Example showing use of raw sockets.
  3. //
  4. // This is a part of the Microsoft Source Code Samples.
  5. // Copyright 1996 - 2000 Microsoft Corporation.
  6. // All rights reserved.
  7. // This source code is only intended as a supplement to
  8. // Microsoft Development Tools and/or WinHelp documentation.
  9. // See these sources for detailed information regarding the
  10. // Microsoft samples programs.
  11. //
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <winsock2.h>
  14. #include <ws2tcpip.h>
  15. #include <tpipv6.h> // Needed for IPv6 Tech Preview.
  16. #include <ip6.h> // For IPv6Header strucuture.
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. //
  21. // It's too much trouble to include icmp6.h
  22. //
  23. typedef struct ICMPv6Header {
  24. unsigned char Type;
  25. unsigned char Code;
  26. unsigned short Checksum;
  27. } ICMPv6Header;
  28. #define DEFAULT_SERVER NULL // Will use the loopback interface
  29. #define DEFAULT_PROTOCOL 254 // Arbitrary unassigned protocol
  30. #define BUFFER_SIZE 65536
  31. #define DATA_SIZE 64
  32. void Usage(char *ProgName) {
  33. fprintf(stderr, "\nRaw socket send program.\n");
  34. fprintf(stderr, "\n%s [-s server] [-p protocol] [-n number]\n\n",
  35. ProgName);
  36. fprintf(stderr, " server\tServer name or IP address. (default: %s)\n",
  37. (DEFAULT_SERVER == NULL) ? "loopback address" : DEFAULT_SERVER);
  38. fprintf(stderr, " protocol\tNextHeader field value. (default: %u)\n",
  39. DEFAULT_PROTOCOL);
  40. fprintf(stderr, " number\tNumber of sends to perform. (default: 1)\n");
  41. fprintf(stderr, " (-n by itself makes client run in an infinite loop,");
  42. fprintf(stderr, " Hit Ctrl-C to terminate)\n");
  43. WSACleanup();
  44. exit(1);
  45. }
  46. LPSTR DecodeError(int ErrorCode)
  47. {
  48. static char Message[1024];
  49. // If this program was multi-threaded, we'd want to use
  50. // FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here.
  51. // (And of course, free the buffer when we were done with it)
  52. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
  53. FORMAT_MESSAGE_MAX_WIDTH_MASK,
  54. NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  55. (LPSTR)Message, 1024, NULL);
  56. return Message;
  57. }
  58. int main(int argc, char **argv) {
  59. char Buffer[BUFFER_SIZE], AddrName[NI_MAXHOST];
  60. char *Server = DEFAULT_SERVER;
  61. int i, RetVal;
  62. unsigned int Iteration, MaxIterations = 1;
  63. unsigned int AmountToSend;
  64. unsigned short PayloadLength;
  65. BOOL RunForever = FALSE;
  66. BOOL True = TRUE;
  67. WSADATA wsaData;
  68. ADDRINFO Hints, *AddrInfo, *AI;
  69. SOCKET Sock;
  70. SOCKADDR_IN6 OurAddr, PeerAddr;
  71. unsigned char Protocol = DEFAULT_PROTOCOL;
  72. IPv6Header *IP = (IPv6Header *)Buffer;
  73. ICMPv6Header *ICMP;
  74. if (argc > 1) {
  75. for (i = 1;i < argc; i++) {
  76. if (((argv[i][0] == '-') || (argv[i][0] == '/')) &&
  77. (argv[i][1] != 0) && (argv[i][2] == 0)) {
  78. switch(tolower(argv[i][1])) {
  79. case 's':
  80. if (argv[i+1]) {
  81. if (argv[i+1][0] != '-') {
  82. Server = argv[++i];
  83. break;
  84. }
  85. }
  86. Usage(argv[0]);
  87. break;
  88. case 'n':
  89. if (argv[i+1]) {
  90. if (argv[i+1][0] != '-') {
  91. MaxIterations = atoi(argv[++i]);
  92. break;
  93. }
  94. }
  95. RunForever = TRUE;
  96. break;
  97. case 'p':
  98. if (argv[i+1]) {
  99. if (argv[i+1][0] != '-') {
  100. Protocol = atoi(argv[++i]);
  101. break;
  102. }
  103. }
  104. Usage(argv[0]);
  105. break;
  106. default:
  107. Usage(argv[0]);
  108. break;
  109. }
  110. }
  111. else
  112. Usage(argv[0]);
  113. }
  114. }
  115. // Ask for Winsock version 2.2.
  116. if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {
  117. fprintf(stderr, "WSAStartup failed with error %d: %s\n",
  118. RetVal, DecodeError(RetVal));
  119. WSACleanup();
  120. return -1;
  121. }
  122. //
  123. // By not setting the AI_PASSIVE flag in the hints to getaddrinfo, we're
  124. // indicating that we intend to use the resulting address(es) to connect
  125. // to a service. This means that when the Server parameter is NULL,
  126. // getaddrinfo will return one entry per allowed protocol family
  127. // containing the loopback address for that family.
  128. //
  129. memset(&Hints, 0, sizeof(Hints));
  130. Hints.ai_family = PF_INET6;
  131. Hints.ai_socktype = SOCK_DGRAM; // Lie until getaddrinfo is fixed.
  132. Hints.ai_protocol = Protocol;
  133. RetVal = getaddrinfo(Server, "1" /* Dummy */, &Hints, &AddrInfo);
  134. if (RetVal != 0) {
  135. fprintf(stderr, "Cannot resolve address [%s], error %d: %s\n",
  136. Server, RetVal, gai_strerror(RetVal));
  137. WSACleanup();
  138. return -1;
  139. }
  140. //
  141. // Try each address getaddrinfo returned, until we find one to which
  142. // we can sucessfully connect.
  143. //
  144. for (AI = AddrInfo; AI != NULL; AI = AI->ai_next) {
  145. Sock = socket(AI->ai_family, SOCK_RAW, AI->ai_protocol);
  146. if (Sock == INVALID_SOCKET) {
  147. fprintf(stderr,"Error Opening socket, error %d: %s\n",
  148. WSAGetLastError(), DecodeError(WSAGetLastError()));
  149. continue;
  150. }
  151. if (getnameinfo((LPSOCKADDR)AI->ai_addr, AI->ai_addrlen, AddrName,
  152. sizeof(AddrName), NULL, 0, NI_NUMERICHOST) != 0)
  153. strcpy(AddrName, "<unknown>");
  154. printf("Attempting to connect to: %s (%s)\n",
  155. Server ? Server : "localhost", AddrName);
  156. if (connect(Sock, AI->ai_addr, AI->ai_addrlen) != SOCKET_ERROR)
  157. break;
  158. i = WSAGetLastError();
  159. fprintf(stderr, "connect() failed with error %d: %s\n",
  160. i, DecodeError(i));
  161. }
  162. if (AI == NULL) {
  163. fprintf(stderr, "Fatal error: unable to connect to the server.\n");
  164. closesocket(Sock);
  165. WSACleanup();
  166. return -1;
  167. }
  168. PeerAddr = *(SOCKADDR_IN6 *)(AI->ai_addr);
  169. // We are done with the address info chain, so we can free it.
  170. freeaddrinfo(AddrInfo);
  171. //
  172. // Make up a source address to use.
  173. // Use the unspecified address for now.
  174. //
  175. memset(&OurAddr, 0, sizeof(OurAddr));
  176. //
  177. // Let the stack know that we'll be contributing the IPv6 header.
  178. //
  179. if (setsockopt(Sock, IPPROTO_IPV6, IPV6_HDRINCL, (char *)&True,
  180. sizeof(True)) == SOCKET_ERROR) {
  181. fprintf(stderr, "setsockopt() failed with error %d: %s\n",
  182. WSAGetLastError(), DecodeError(WSAGetLastError()));
  183. }
  184. //
  185. // Compose a message to send.
  186. // Start with IPv6 packet header.
  187. //
  188. IP->VersClassFlow = htonl(6 << 28);
  189. PayloadLength = 0;
  190. IP->NextHeader = Protocol;
  191. IP->HopLimit = 32;
  192. IP->Source = OurAddr.sin6_addr;
  193. IP->Dest = PeerAddr.sin6_addr;
  194. AmountToSend = sizeof(*IP);
  195. if (Protocol == IP_PROTOCOL_ICMPv6) {
  196. //
  197. // Put an ICMPv6 header on next.
  198. //
  199. ICMP = (ICMPv6Header *)(IP + 1);
  200. if (MaxIterations == 1)
  201. ICMP->Type = 255; // Unassigned informational message.
  202. else
  203. ICMP->Type = 127; // Unassigned error message.
  204. ICMP->Code = 42;
  205. ICMP->Checksum = 0; // Calculated below.
  206. PayloadLength += sizeof(*ICMP);
  207. AmountToSend += sizeof(*ICMP);
  208. }
  209. //
  210. // Add some meaningless data.
  211. //
  212. for (i = 0; i < DATA_SIZE; i++) {
  213. Buffer[AmountToSend++] = (char)(i + 0x40);
  214. }
  215. PayloadLength += DATA_SIZE;
  216. if (Protocol == IP_PROTOCOL_ICMPv6) {
  217. unsigned short *Data;
  218. unsigned int Checksum = 0;
  219. //
  220. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  221. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  222. //
  223. // Pseudo-header.
  224. Data = (unsigned short *)&IP->Source;
  225. for (i = 0; i < 16; i++)
  226. Checksum += *Data++;
  227. Checksum += htons(PayloadLength);
  228. Checksum += (IP_PROTOCOL_ICMPv6 << 8);
  229. // Packet data.
  230. Data = (unsigned short *)ICMP;
  231. for (i = 0; i < (PayloadLength / 2); i++)
  232. Checksum += *Data++;
  233. // Wrap in carries.
  234. Checksum = (Checksum >> 16) + (Checksum & 0xffff);
  235. Checksum += (Checksum >> 16);
  236. // Take ones-complement and replace 0 with 0xffff.
  237. Checksum = (unsigned short) ~Checksum;
  238. if (Checksum == 0)
  239. Checksum = 0xffff;
  240. ICMP->Checksum = (unsigned short)Checksum;
  241. }
  242. IP->PayloadLength = htons(PayloadLength);
  243. //
  244. // Send and receive in a loop for the requested number of iterations.
  245. //
  246. for (Iteration = 0; RunForever || Iteration < MaxIterations; Iteration++) {
  247. //
  248. // Send the message. Since we are using a blocking socket, this
  249. // call shouldn't return until it's able to send the entire amount.
  250. //
  251. RetVal = send(Sock, Buffer, AmountToSend, 0);
  252. if (RetVal == SOCKET_ERROR) {
  253. fprintf(stderr, "send() failed with error %d: %s\n",
  254. WSAGetLastError(), DecodeError(WSAGetLastError()));
  255. WSACleanup();
  256. return -1;
  257. }
  258. printf("Sent %d bytes (out of %d bytes) of data: [%.*s]\n",
  259. RetVal, AmountToSend, AmountToSend, Buffer);
  260. }
  261. // Tell system we're done sending.
  262. printf("Done sending\n");
  263. shutdown(Sock, SD_SEND);
  264. closesocket(Sock);
  265. WSACleanup();
  266. return 0;
  267. }