|
|
/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
rtchange.c
Abstract:
This module contains a program demonstrating the use of the TCP/IP driver's route-change notification facilities.
Author:
Abolade Gbadegesin (aboladeg) 15-April-2000
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <ntddip.h>
#include <ipinfo.h>
char* ntoa( ULONG IpAddress ) { return inet_ntoa(*(struct in_addr*)&IpAddress); }
NTSTATUS NotifyRouteChange( HANDLE FileHandle, ULONG IoControlCode, ULONG NotifyIpAddress, BOOLEAN OutputRequired ) { HANDLE EventHandle; PVOID InputBuffer; ULONG InputBufferLength; IO_STATUS_BLOCK IoStatus; IPNotifyData NotifyData = {0}; IPRouteNotifyOutput NotifyOutput = {0}; PVOID OutputBuffer; ULONG OutputBufferLength; NTSTATUS Status;
if (NotifyIpAddress == INADDR_NONE) { InputBuffer = NULL; InputBufferLength = 0; } else if (NotifyIpAddress == INADDR_ANY) { NotifyData.Add = 0; InputBuffer = &NotifyData; InputBufferLength = sizeof(NotifyData); } else { NotifyData.Add = NotifyIpAddress; InputBuffer = &NotifyData; InputBufferLength = sizeof(NotifyData); }
if (OutputRequired) { OutputBuffer = &NotifyOutput; OutputBufferLength = sizeof(NotifyOutput); } else { OutputBuffer = NULL; OutputBufferLength = 0; }
Status = NtCreateEvent( &EventHandle, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); if (!NT_SUCCESS(Status)) { printf("NtCreateEvent=%x\n", Status); } else {
Status = NtDeviceIoControlFile( FileHandle, EventHandle, NULL, NULL, &IoStatus, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength ); if (Status == STATUS_PENDING) { printf("NtDeviceIoControlFile=%x, waiting\n", Status); NtWaitForSingleObject(EventHandle, FALSE, NULL); Status = IoStatus.Status; } printf("NtDeviceIoControlFile=%x\n", Status); NtClose(EventHandle);
if (NT_SUCCESS(Status) && OutputRequired) { printf("\tDestination: %s\n", ntoa(NotifyOutput.irno_dest)); printf("\tMask: %s\n", ntoa(NotifyOutput.irno_mask)); printf("\tNext-hop: %s\n", ntoa(NotifyOutput.irno_nexthop)); printf("\tProtocol: %d\n", NotifyOutput.irno_proto); printf("\tIndex: %d\n", NotifyOutput.irno_ifindex); } } return Status; }
typedef struct { IO_STATUS_BLOCK IoStatus; IPRouteNotifyOutput NotifyOutput; } ROUTE_NOTIFY_CONTEXT, *PROUTE_NOTIFY_CONTEXT;
VOID NTAPI NotifyRouteCompletionRoutine( PVOID Context, PIO_STATUS_BLOCK IoStatus, ULONG Reserved ) { PROUTE_NOTIFY_CONTEXT NotifyContext = (PROUTE_NOTIFY_CONTEXT)Context; printf("NotifyRouteCompletionRoutine(%p, %x)\n", Context, IoStatus->Status); if (NT_SUCCESS(IoStatus->Status)) { PIPRouteNotifyOutput NotifyOutput = &NotifyContext->NotifyOutput; printf("\tDestination: %s\n", ntoa(NotifyOutput->irno_dest)); printf("\tMask: %s\n", ntoa(NotifyOutput->irno_mask)); printf("\tNext-hop: %s\n", ntoa(NotifyOutput->irno_nexthop)); printf("\tProtocol: %d\n", NotifyOutput->irno_proto); printf("\tIndex: %d\n", NotifyOutput->irno_ifindex); } }
ULONG QueueNotifyRouteChange( HANDLE FileHandle, IPNotifyVersion Version, ULONG NotificationCount ) { ULONG i; PVOID InputBuffer; ULONG InputBufferLength; PROUTE_NOTIFY_CONTEXT NotifyContext; IPNotifyData NotifyData = {0}; PVOID OutputBuffer; ULONG OutputBufferLength; NTSTATUS Status;
NotifyData.Version = Version; NotifyData.Add = 0; InputBuffer = &NotifyData; InputBufferLength = sizeof(NotifyData);
for (i = 0; i < NotificationCount; i++) { NotifyContext = (PROUTE_NOTIFY_CONTEXT)malloc(sizeof(*NotifyContext)); if (!NotifyContext) { printf("QueueNotifyRouteChange: malloc=<null>\n"); break; } else { printf("QueueNotifyRouteChange: queuing %p\n", NotifyContext); ZeroMemory(NotifyContext, sizeof(*NotifyContext)); Status = NtDeviceIoControlFile( FileHandle, NULL, NotifyRouteCompletionRoutine, NotifyContext, &NotifyContext->IoStatus, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST, InputBuffer, InputBufferLength, &NotifyContext->NotifyOutput, sizeof(NotifyContext->NotifyOutput) ); printf("NtDeviceIoControlFile=%x\n", Status); } }
return i; }
int __cdecl main( int argc, char* argv[] ) { HANDLE FileHandle; IO_STATUS_BLOCK IoStatus; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; UNICODE_STRING UnicodeString;
//
// Open a handle to the IP device-object.
//
RtlInitUnicodeString(&UnicodeString, DD_IP_DEVICE_NAME); InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtCreateFile( &FileHandle, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0 ); if (!NT_SUCCESS(Status)) { printf("NtCreateFile=%x\n", Status); return 0; }
//
// Continually prompt for instructions until interrupted.
//
for (;;) { ULONG Selection; BOOLEAN OutputRequired = TRUE; IPNotifyVersion Version = IPNotifySynchronization;
printf("Simple route-change notification:\n"); printf("\t1. Submit NULL route-change request [no output]\n"); printf("\t2. Submit NULL route-change request\n"); printf("\t3. Submit general route-change request [no output]\n"); printf("\t4. Submit general route-change request\n"); printf("\t5. Submit specific route-change request [no output]\n"); printf("\t6. Submit specific route-change request\n");
printf("Extended route-change notification:\n"); printf("\t7. Submit NULL route-change request [no output]\n"); printf("\t8. Submit NULL route-change request\n"); printf("\t9. Submit general route-change request [no output]\n"); printf("\t10. Submit general route-change request\n"); printf("\t11. Submit specific route-change request [no output]\n"); printf("\t12. Submit specific route-change request\n");
printf("\t13. Submit multiple general route-change requests\n"); printf("\t using 'notification' semantics.\n"); printf("\t14. Submit multiple general route-change requests\n"); printf("\t using 'synchronization' semantics.\n");
printf("\nEnter selection: "); if (!scanf("%d", &Selection)) { break; } switch(Selection) { case 1: OutputRequired = FALSE; case 2: { Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST, INADDR_NONE, OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; } case 3: OutputRequired = FALSE; case 4: { Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST, INADDR_ANY, OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; } case 5: OutputRequired = FALSE; case 6: { UCHAR Destination[16];
printf("Enter destination: "); if (!scanf("%s", Destination)) { break; } Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST, inet_addr(Destination), OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; } case 7: OutputRequired = FALSE; case 8: { Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX, INADDR_NONE, OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; } case 9: OutputRequired = FALSE; case 10: { Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX, INADDR_ANY, OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; } case 11: OutputRequired = FALSE; case 12: { UCHAR Destination[16];
printf("Enter destination: "); if (!scanf("%s", Destination)) { break; } Status = NotifyRouteChange( FileHandle, IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX, inet_addr(Destination), OutputRequired ); printf("NotifyRouteChange=%x\n", Status); break; }
case 13: Version = IPNotifyNotification; case 14: { LARGE_INTEGER Timeout; ULONG NotificationCount = 0;
printf("Enter number of requests to queue: "); if (!scanf("%d", &NotificationCount)) { break; }
NotificationCount = QueueNotifyRouteChange( FileHandle, Version, NotificationCount );
for (; NotificationCount; --NotificationCount) { Timeout.LowPart = 0; Timeout.HighPart = MINLONG; NtDelayExecution(TRUE, &Timeout); }
break; } } } NtClose(FileHandle); return 0; }
|