Source code of Windows XP (NT5)
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.

379 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. rtchange.c
  5. Abstract:
  6. This module contains a program demonstrating the use of the TCP/IP driver's
  7. route-change notification facilities.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 15-April-2000
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <winsock2.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ntddip.h>
  19. #include <ipinfo.h>
  20. char*
  21. ntoa(
  22. ULONG IpAddress
  23. )
  24. {
  25. return inet_ntoa(*(struct in_addr*)&IpAddress);
  26. }
  27. NTSTATUS
  28. NotifyRouteChange(
  29. HANDLE FileHandle,
  30. ULONG IoControlCode,
  31. ULONG NotifyIpAddress,
  32. BOOLEAN OutputRequired
  33. )
  34. {
  35. HANDLE EventHandle;
  36. PVOID InputBuffer;
  37. ULONG InputBufferLength;
  38. IO_STATUS_BLOCK IoStatus;
  39. IPNotifyData NotifyData = {0};
  40. IPRouteNotifyOutput NotifyOutput = {0};
  41. PVOID OutputBuffer;
  42. ULONG OutputBufferLength;
  43. NTSTATUS Status;
  44. if (NotifyIpAddress == INADDR_NONE) {
  45. InputBuffer = NULL;
  46. InputBufferLength = 0;
  47. } else if (NotifyIpAddress == INADDR_ANY) {
  48. NotifyData.Add = 0;
  49. InputBuffer = &NotifyData;
  50. InputBufferLength = sizeof(NotifyData);
  51. } else {
  52. NotifyData.Add = NotifyIpAddress;
  53. InputBuffer = &NotifyData;
  54. InputBufferLength = sizeof(NotifyData);
  55. }
  56. if (OutputRequired) {
  57. OutputBuffer = &NotifyOutput;
  58. OutputBufferLength = sizeof(NotifyOutput);
  59. } else {
  60. OutputBuffer = NULL;
  61. OutputBufferLength = 0;
  62. }
  63. Status =
  64. NtCreateEvent(
  65. &EventHandle, EVENT_ALL_ACCESS, NULL,
  66. SynchronizationEvent, FALSE
  67. );
  68. if (!NT_SUCCESS(Status)) {
  69. printf("NtCreateEvent=%x\n", Status);
  70. } else {
  71. Status =
  72. NtDeviceIoControlFile(
  73. FileHandle,
  74. EventHandle,
  75. NULL,
  76. NULL,
  77. &IoStatus,
  78. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  79. InputBuffer,
  80. InputBufferLength,
  81. OutputBuffer,
  82. OutputBufferLength
  83. );
  84. if (Status == STATUS_PENDING) {
  85. printf("NtDeviceIoControlFile=%x, waiting\n", Status);
  86. NtWaitForSingleObject(EventHandle, FALSE, NULL);
  87. Status = IoStatus.Status;
  88. }
  89. printf("NtDeviceIoControlFile=%x\n", Status);
  90. NtClose(EventHandle);
  91. if (NT_SUCCESS(Status) && OutputRequired) {
  92. printf("\tDestination: %s\n", ntoa(NotifyOutput.irno_dest));
  93. printf("\tMask: %s\n", ntoa(NotifyOutput.irno_mask));
  94. printf("\tNext-hop: %s\n", ntoa(NotifyOutput.irno_nexthop));
  95. printf("\tProtocol: %d\n", NotifyOutput.irno_proto);
  96. printf("\tIndex: %d\n", NotifyOutput.irno_ifindex);
  97. }
  98. }
  99. return Status;
  100. }
  101. typedef struct {
  102. IO_STATUS_BLOCK IoStatus;
  103. IPRouteNotifyOutput NotifyOutput;
  104. } ROUTE_NOTIFY_CONTEXT, *PROUTE_NOTIFY_CONTEXT;
  105. VOID NTAPI
  106. NotifyRouteCompletionRoutine(
  107. PVOID Context,
  108. PIO_STATUS_BLOCK IoStatus,
  109. ULONG Reserved
  110. )
  111. {
  112. PROUTE_NOTIFY_CONTEXT NotifyContext = (PROUTE_NOTIFY_CONTEXT)Context;
  113. printf("NotifyRouteCompletionRoutine(%p, %x)\n", Context, IoStatus->Status);
  114. if (NT_SUCCESS(IoStatus->Status)) {
  115. PIPRouteNotifyOutput NotifyOutput = &NotifyContext->NotifyOutput;
  116. printf("\tDestination: %s\n", ntoa(NotifyOutput->irno_dest));
  117. printf("\tMask: %s\n", ntoa(NotifyOutput->irno_mask));
  118. printf("\tNext-hop: %s\n", ntoa(NotifyOutput->irno_nexthop));
  119. printf("\tProtocol: %d\n", NotifyOutput->irno_proto);
  120. printf("\tIndex: %d\n", NotifyOutput->irno_ifindex);
  121. }
  122. }
  123. ULONG
  124. QueueNotifyRouteChange(
  125. HANDLE FileHandle,
  126. IPNotifyVersion Version,
  127. ULONG NotificationCount
  128. )
  129. {
  130. ULONG i;
  131. PVOID InputBuffer;
  132. ULONG InputBufferLength;
  133. PROUTE_NOTIFY_CONTEXT NotifyContext;
  134. IPNotifyData NotifyData = {0};
  135. PVOID OutputBuffer;
  136. ULONG OutputBufferLength;
  137. NTSTATUS Status;
  138. NotifyData.Version = Version;
  139. NotifyData.Add = 0;
  140. InputBuffer = &NotifyData;
  141. InputBufferLength = sizeof(NotifyData);
  142. for (i = 0; i < NotificationCount; i++) {
  143. NotifyContext = (PROUTE_NOTIFY_CONTEXT)malloc(sizeof(*NotifyContext));
  144. if (!NotifyContext) {
  145. printf("QueueNotifyRouteChange: malloc=<null>\n");
  146. break;
  147. } else {
  148. printf("QueueNotifyRouteChange: queuing %p\n", NotifyContext);
  149. ZeroMemory(NotifyContext, sizeof(*NotifyContext));
  150. Status =
  151. NtDeviceIoControlFile(
  152. FileHandle,
  153. NULL,
  154. NotifyRouteCompletionRoutine,
  155. NotifyContext,
  156. &NotifyContext->IoStatus,
  157. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  158. InputBuffer,
  159. InputBufferLength,
  160. &NotifyContext->NotifyOutput,
  161. sizeof(NotifyContext->NotifyOutput)
  162. );
  163. printf("NtDeviceIoControlFile=%x\n", Status);
  164. }
  165. }
  166. return i;
  167. }
  168. int __cdecl
  169. main(
  170. int argc,
  171. char* argv[]
  172. )
  173. {
  174. HANDLE FileHandle;
  175. IO_STATUS_BLOCK IoStatus;
  176. OBJECT_ATTRIBUTES ObjectAttributes;
  177. NTSTATUS Status;
  178. UNICODE_STRING UnicodeString;
  179. //
  180. // Open a handle to the IP device-object.
  181. //
  182. RtlInitUnicodeString(&UnicodeString, DD_IP_DEVICE_NAME);
  183. InitializeObjectAttributes(
  184. &ObjectAttributes,
  185. &UnicodeString,
  186. OBJ_CASE_INSENSITIVE,
  187. NULL,
  188. NULL
  189. );
  190. Status =
  191. NtCreateFile(
  192. &FileHandle,
  193. GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
  194. &ObjectAttributes,
  195. &IoStatus,
  196. NULL,
  197. 0,
  198. FILE_SHARE_READ|FILE_SHARE_WRITE,
  199. FILE_OPEN_IF,
  200. 0,
  201. NULL,
  202. 0
  203. );
  204. if (!NT_SUCCESS(Status)) {
  205. printf("NtCreateFile=%x\n", Status);
  206. return 0;
  207. }
  208. //
  209. // Continually prompt for instructions until interrupted.
  210. //
  211. for (;;) {
  212. ULONG Selection;
  213. BOOLEAN OutputRequired = TRUE;
  214. IPNotifyVersion Version = IPNotifySynchronization;
  215. printf("Simple route-change notification:\n");
  216. printf("\t1. Submit NULL route-change request [no output]\n");
  217. printf("\t2. Submit NULL route-change request\n");
  218. printf("\t3. Submit general route-change request [no output]\n");
  219. printf("\t4. Submit general route-change request\n");
  220. printf("\t5. Submit specific route-change request [no output]\n");
  221. printf("\t6. Submit specific route-change request\n");
  222. printf("Extended route-change notification:\n");
  223. printf("\t7. Submit NULL route-change request [no output]\n");
  224. printf("\t8. Submit NULL route-change request\n");
  225. printf("\t9. Submit general route-change request [no output]\n");
  226. printf("\t10. Submit general route-change request\n");
  227. printf("\t11. Submit specific route-change request [no output]\n");
  228. printf("\t12. Submit specific route-change request\n");
  229. printf("\t13. Submit multiple general route-change requests\n");
  230. printf("\t using 'notification' semantics.\n");
  231. printf("\t14. Submit multiple general route-change requests\n");
  232. printf("\t using 'synchronization' semantics.\n");
  233. printf("\nEnter selection: ");
  234. if (!scanf("%d", &Selection)) {
  235. break;
  236. }
  237. switch(Selection) {
  238. case 1:
  239. OutputRequired = FALSE;
  240. case 2: {
  241. Status =
  242. NotifyRouteChange(
  243. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  244. INADDR_NONE, OutputRequired
  245. );
  246. printf("NotifyRouteChange=%x\n", Status);
  247. break;
  248. }
  249. case 3:
  250. OutputRequired = FALSE;
  251. case 4: {
  252. Status =
  253. NotifyRouteChange(
  254. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  255. INADDR_ANY, OutputRequired
  256. );
  257. printf("NotifyRouteChange=%x\n", Status);
  258. break;
  259. }
  260. case 5:
  261. OutputRequired = FALSE;
  262. case 6: {
  263. UCHAR Destination[16];
  264. printf("Enter destination: ");
  265. if (!scanf("%s", Destination)) {
  266. break;
  267. }
  268. Status =
  269. NotifyRouteChange(
  270. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  271. inet_addr(Destination), OutputRequired
  272. );
  273. printf("NotifyRouteChange=%x\n", Status);
  274. break;
  275. }
  276. case 7:
  277. OutputRequired = FALSE;
  278. case 8: {
  279. Status =
  280. NotifyRouteChange(
  281. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX,
  282. INADDR_NONE, OutputRequired
  283. );
  284. printf("NotifyRouteChange=%x\n", Status);
  285. break;
  286. }
  287. case 9:
  288. OutputRequired = FALSE;
  289. case 10: {
  290. Status =
  291. NotifyRouteChange(
  292. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX,
  293. INADDR_ANY, OutputRequired
  294. );
  295. printf("NotifyRouteChange=%x\n", Status);
  296. break;
  297. }
  298. case 11:
  299. OutputRequired = FALSE;
  300. case 12: {
  301. UCHAR Destination[16];
  302. printf("Enter destination: ");
  303. if (!scanf("%s", Destination)) {
  304. break;
  305. }
  306. Status =
  307. NotifyRouteChange(
  308. FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX,
  309. inet_addr(Destination), OutputRequired
  310. );
  311. printf("NotifyRouteChange=%x\n", Status);
  312. break;
  313. }
  314. case 13:
  315. Version = IPNotifyNotification;
  316. case 14: {
  317. LARGE_INTEGER Timeout;
  318. ULONG NotificationCount = 0;
  319. printf("Enter number of requests to queue: ");
  320. if (!scanf("%d", &NotificationCount)) {
  321. break;
  322. }
  323. NotificationCount =
  324. QueueNotifyRouteChange(
  325. FileHandle, Version, NotificationCount
  326. );
  327. for (; NotificationCount; --NotificationCount) {
  328. Timeout.LowPart = 0;
  329. Timeout.HighPart = MINLONG;
  330. NtDelayExecution(TRUE, &Timeout);
  331. }
  332. break;
  333. }
  334. }
  335. }
  336. NtClose(FileHandle);
  337. return 0;
  338. }