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.
 
 
 
 
 
 

2178 lines
58 KiB

/*++
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
apitest.c
Abstract:
Contains routines for testing the RTMv2 API.
Author:
Chaitanya Kodeboyina (chaitk) 26-Jun-1998
Revision History:
--*/
#include "apitest.h"
MY_ENTITY_EXPORT_METHODS
Rip2Methods =
{
5,
{
EntityExportMethod,
EntityExportMethod,
NULL,
EntityExportMethod,
EntityExportMethod
}
};
MY_ENTITY_EXPORT_METHODS
OspfMethods =
{
6,
{
EntityExportMethod,
EntityExportMethod,
EntityExportMethod,
EntityExportMethod,
EntityExportMethod,
EntityExportMethod
}
};
MY_ENTITY_EXPORT_METHODS
Bgp4Methods =
{
4,
{
EntityExportMethod,
EntityExportMethod,
EntityExportMethod,
EntityExportMethod
}
};
ENTITY_CHARS
GlobalEntityChars [] =
{
//
// {
// Rtmv2Registration,
// { RtmInstanceId, AddressFamily, { EntityProtocolId, EntityInstanceId } },
// EntityEventCallback, ExportMethods,
// RoutesFileName,
// }
//
/*
{
FALSE,
{ 0, RTM_PROTOCOL_FAMILY_IP, { PROTO_IP_RIP, 1 } },
EntityEventCallback, &Rip2Methods,
"test.out"
},
*/
{
TRUE,
{ 1, AF_INET, { PROTO_IP_RIP, 1 } },
EntityEventCallback, &Rip2Methods,
"test.out"
},
{
TRUE,
{ 1, AF_INET, { PROTO_IP_OSPF, 1 } },
EntityEventCallback, &OspfMethods,
"test.out"
},
{
TRUE,
{ 1, AF_INET, { PROTO_IP_BGP, 1 } },
EntityEventCallback, &Bgp4Methods,
"test.out"
},
{
TRUE,
{ 0, 0, { 0, 0 } },
NULL, NULL,
""
}
};
const RTM_VIEW_SET VIEW_MASK_ARR[]
= {
0,
RTM_VIEW_MASK_UCAST,
RTM_VIEW_MASK_MCAST,
RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST
};
// Disable warnings for unreferenced params and local variables
#pragma warning(disable: 4100)
#pragma warning(disable: 4101)
//
// Main
//
#if !LOOKUP_TESTING
int
__cdecl
main (void)
{
PENTITY_CHARS Entity;
DWORD Status;
LPTHREAD_START_ROUTINE EntityThreadProc;
#if MT
UINT NumThreads;
HANDLE Threads[64];
#endif
Entity = &GlobalEntityChars[0];
#if MT
NumThreads = 0;
#endif
while (Entity->EntityInformation.EntityId.EntityId != 0)
{
if (Entity->Rtmv2Registration)
{
EntityThreadProc = Rtmv2EntityThreadProc;
}
else
{
EntityThreadProc = Rtmv1EntityThreadProc;
}
#if MT
Threads[NumThreads] = CreateThread(NULL,
0,
EntityThreadProc,
Entity++,
0,
NULL);
Print("Thread ID %d: %p\n", NumThreads, Threads[NumThreads]);
NumThreads++;
#else
Status = EntityThreadProc(Entity++);
#endif
}
#if MT
WaitForMultipleObjects(NumThreads, Threads, TRUE, INFINITE);
#endif
return 0;
}
#endif
//
// A general state machine for a protocol thread (RTMv1)
//
DWORD Rtmv1EntityThreadProc (LPVOID ThreadParameters)
{
RTM_PROTOCOL_FAMILY_CONFIG FamilyConfig;
PENTITY_CHARS EntityChars;
PRTM_ENTITY_INFO EntityInfo;
HANDLE Event;
HANDLE V1RegnHandle;
DWORD ProtocolId;
UINT i;
FILE *FilePtr;
IP_NETWORK Network;
UINT NumDests;
UINT NumRoutes;
Route ThisRoute;
Route Routes[MAXROUTES];
RTM_IP_ROUTE V1Route;
RTM_IP_ROUTE V1Route2;
HANDLE V1EnumHandle;
BOOL Exists;
DWORD Flags;
DWORD Status;
//
// Get all characteristics of this entity
//
EntityChars = (PENTITY_CHARS) ThreadParameters;
EntityInfo = &EntityChars->EntityInformation;
Assert(EntityInfo->AddressFamily == RTM_PROTOCOL_FAMILY_IP);
Print("\n--------------------------------------------------------\n");
#if WRAPPER
FamilyConfig.RPFC_Validate = ValidateRouteCallback;
FamilyConfig.RPFC_Change = RouteChangeCallback;
Status = RtmCreateRouteTable(EntityInfo->AddressFamily, &FamilyConfig);
if (Status != ERROR_ALREADY_EXISTS)
{
Check(Status, 50);
}
else
{
Print("Protocol Family's Route Table already created\n");
}
Event = CreateEvent(NULL, TRUE, FALSE, NULL);
Assert(Event != NULL);
ProtocolId = EntityInfo->EntityId.EntityProtocolId,
V1RegnHandle = RtmRegisterClient(EntityInfo->AddressFamily,
ProtocolId,
NULL,
NULL); // RTM_PROTOCOL_SINGLE_ROUTE);
if (V1RegnHandle == NULL)
{
Status = GetLastError();
Check(Status, 52);
}
if ((FilePtr = fopen(EntityChars->RoutesFileName, "r")) == NULL)
{
Fatal("Failed open route database with status = %p\n",
ERROR_OPENING_DATABASE);
}
NumRoutes = ReadRoutesFromFile(FilePtr, MAX_ROUTES, Routes);
fclose(FilePtr);
//
// How many destinations do we have in table ?
//
NumDests = RtmGetNetworkCount(EntityInfo->AddressFamily);
if (NumDests == 0)
{
Check(Status, 63);
}
Print("Number of destinations = %lu\n\n", NumDests);
//
// Add a bunch of routes from the input file
//
for (i = 0; i < NumRoutes; i++)
{
// Print("Add Route: Addr = %08x, Mask = %08x\n",
// Routes[i].addr,
// Routes[i].mask);
ConvertRouteToV1Route(&Routes[i], &V1Route);
V1Route.RR_ProtocolSpecificData.PSD_Data[0] =
V1Route.RR_ProtocolSpecificData.PSD_Data[1] =
V1Route.RR_ProtocolSpecificData.PSD_Data[2] =
V1Route.RR_ProtocolSpecificData.PSD_Data[3] = i;
V1Route.RR_FamilySpecificData.FSD_Priority = ProtocolId;
V1Route.RR_FamilySpecificData.FSD_Flags = (ULONG) ~0;
Status = RtmAddRoute(V1RegnHandle,
&V1Route,
INFINITE,
&Flags,
NULL,
NULL);
Check(Status, 54);
}
//
// Check if routes exist to the destination
//
for (i = 0; i < NumRoutes; i++)
{
Network.N_NetNumber = Routes[i].addr;
Network.N_NetMask = Routes[i].mask;
Exists = RtmIsRoute(EntityInfo->AddressFamily,
&Network,
&V1Route);
if (!Exists)
{
Check(Status, 64);
continue;
}
// ConvertV1RouteToRoute(&V1Route, &ThisRoute);
// PrintRoute(&ThisRoute);
Exists = RtmLookupIPDestination(Routes[i].addr,
&V1Route2);
if (Exists)
{
if (!RtlEqualMemory(&V1Route, &V1Route2, sizeof(RTM_IP_ROUTE)))
{
Print("Routes different: \n");
ConvertV1RouteToRoute(&V1Route, &ThisRoute);
// PrintRoute(&ThisRoute);
ConvertV1RouteToRoute(&V1Route2, &ThisRoute);
// PrintRoute(&ThisRoute);
Print("\n");
}
}
else
{
Status = GetLastError();
PrintIPAddr(&Routes[i].addr); Print("\n");
Check(Status, 65);
}
}
//
// How many destinations do we have in table ?
//
NumDests = RtmGetNetworkCount(EntityInfo->AddressFamily);
if (NumDests == 0)
{
Check(Status, 63);
}
Print("Number of destinations = %lu\n\n", NumDests);
// Try using RtmGetFirstRoute and RtmGetNextRoute
NumRoutes = 0;
Status = RtmGetFirstRoute(EntityInfo->AddressFamily,
NULL,
&V1Route);
// Check(Status, 59);
while (SUCCESS(Status))
{
NumRoutes++;
// Print the V1 Route that is next in the enum
// ConvertV1RouteToRoute(&V1Route, &ThisRoute);
// PrintRoute(&ThisRoute);
Status = RtmGetNextRoute(EntityInfo->AddressFamily,
NULL,
&V1Route);
// Check(Status, 60);
}
// Print("Num of routes in table : %lu\n", NumRoutes);
//
// Disable and reenable all routes that match criteria
//
V1Route.RR_InterfaceID = 3;
Status = RtmBlockSetRouteEnable(V1RegnHandle,
RTM_ONLY_THIS_INTERFACE,
&V1Route,
FALSE);
Check(Status, 66);
/*
V1Route.RR_InterfaceID = 3;
Status = RtmBlockSetRouteEnable(V1RegnHandle,
RTM_ONLY_THIS_INTERFACE,
&V1Route,
TRUE);
Check(Status, 66);
//
// Convert all routes that match criteria to static
//
V1Route.RR_InterfaceID = 3;
Status = RtmBlockConvertRoutesToStatic(V1RegnHandle,
RTM_ONLY_THIS_INTERFACE,
&V1Route);
Check(Status, 62);
*/
//
// Delete all routes that match the criteria
//
ZeroMemory(&V1Route, sizeof(RTM_IP_ROUTE));
V1Route.RR_InterfaceID = 2;
Status= RtmBlockDeleteRoutes(V1RegnHandle,
RTM_ONLY_THIS_INTERFACE|RTM_ONLY_THIS_NETWORK,
&V1Route);
Check(Status, 61);
//
// Enum and del this regn's routes in the table
//
V1Route.RR_RoutingProtocol = ProtocolId;
V1EnumHandle = RtmCreateEnumerationHandle(EntityInfo->AddressFamily,
RTM_ONLY_THIS_PROTOCOL,
&V1Route);
if (V1EnumHandle == NULL)
{
Status = GetLastError();
Check(Status, 56);
}
NumRoutes = 0;
do
{
Status = RtmEnumerateGetNextRoute(V1EnumHandle,
&V1Route);
// Check(Status, 58);
if (!SUCCESS(Status))
{
break;
}
NumRoutes++;
// Print the V1 Route that is next in the enum
// ConvertV1RouteToRoute(&V1Route, &ThisRoute);
// PrintRoute(&ThisRoute);
// Delete this route from the table forever
Status = RtmDeleteRoute(V1RegnHandle,
&V1Route,
&Flags,
NULL);
Check(Status, 55);
}
while (TRUE);
Print("Num of routes in table : %lu\n", NumRoutes);
Status = RtmCloseEnumerationHandle(V1EnumHandle);
Check(Status, 57);
//
// Enumerate all routes in table once again
//
V1EnumHandle = RtmCreateEnumerationHandle(EntityInfo->AddressFamily,
RTM_INCLUDE_DISABLED_ROUTES,
NULL);
if (V1EnumHandle == NULL)
{
Status = GetLastError();
Check(Status, 56);
}
NumRoutes = 0;
do
{
Status = RtmEnumerateGetNextRoute(V1EnumHandle,
&V1Route);
// Check(Status, 58);
if (!SUCCESS(Status))
{
break;
}
NumRoutes++;
// Print the V1 Route that is next in the enum
ConvertV1RouteToRoute(&V1Route, &ThisRoute);
// PrintRoute(&ThisRoute);
UNREFERENCED_PARAMETER(Flags);
Status = RtmDeleteRoute(V1RegnHandle,
&V1Route,
&Flags,
NULL);
Check(Status, 55);
}
while (TRUE);
Print("Num of routes in table : %lu\n", NumRoutes);
Status = RtmCloseEnumerationHandle(V1EnumHandle);
Check(Status, 57);
//
// Deregister the entity and clean up now
//
Status = RtmDeregisterClient(V1RegnHandle);
Check(Status, 53);
if (Event)
{
CloseHandle(Event);
}
Status = RtmDeleteRouteTable(EntityInfo->AddressFamily);
Check(Status, 51);
#endif
Print("\n--------------------------------------------------------\n");
return 0;
}
VOID
ConvertRouteToV1Route(Route *ThisRoute, RTM_IP_ROUTE *V1Route)
{
ZeroMemory(V1Route, sizeof(RTM_IP_ROUTE));
V1Route->RR_Network.N_NetNumber = ThisRoute->addr;
V1Route->RR_Network.N_NetMask = ThisRoute->mask;
V1Route->RR_InterfaceID = PtrToUlong(ThisRoute->interface);
V1Route->RR_NextHopAddress.N_NetNumber = ThisRoute->nexthop;
V1Route->RR_NextHopAddress.N_NetMask = 0xFFFFFFFF;
V1Route->RR_FamilySpecificData.FSD_Metric = ThisRoute->metric;
return;
}
VOID
ConvertV1RouteToRoute(RTM_IP_ROUTE *V1Route, Route *ThisRoute)
{
DWORD Mask;
ZeroMemory(ThisRoute, sizeof(Route));
ThisRoute->addr = V1Route->RR_Network.N_NetNumber;
ThisRoute->mask = V1Route->RR_Network.N_NetMask;
ThisRoute->len = 0;
// No checking for contiguous masks
Mask = ThisRoute->mask;
while (Mask)
{
if (Mask & 1)
{
ThisRoute->len++;
}
Mask >>= 1;
}
ThisRoute->interface = ULongToPtr(V1Route->RR_InterfaceID);
ThisRoute->nexthop = V1Route->RR_NextHopAddress.N_NetNumber;
Assert(V1Route->RR_NextHopAddress.N_NetMask == 0xFFFFFFFF);
ThisRoute->metric = V1Route->RR_FamilySpecificData.FSD_Metric;
Print("Owner = %08x, ", V1Route->RR_RoutingProtocol);
PrintRoute(ThisRoute);
return;
}
DWORD
ValidateRouteCallback(
IN PVOID Route
)
{
UNREFERENCED_PARAMETER(Route);
return NO_ERROR;
}
VOID
RouteChangeCallback(
IN DWORD Flags,
IN PVOID CurrBestRoute,
IN PVOID PrevBestRoute
)
{
Route ThisRoute;
Print("Route Change Notification:\n");
Print("Flags = %08x\n", Flags);
Print("Prev Route = ");
if (Flags & RTM_PREVIOUS_BEST_ROUTE)
{
ConvertV1RouteToRoute((RTM_IP_ROUTE *) PrevBestRoute, &ThisRoute);
// PrintRoute(ThisRoute);
}
else
{
Print("NULL Route\n");
}
// Print("Curr Route = ");
if (Flags & RTM_CURRENT_BEST_ROUTE)
{
ConvertV1RouteToRoute((RTM_IP_ROUTE *) CurrBestRoute, &ThisRoute);
// PrintRoute(ThisRoute);
}
else
{
Print("NULL Route\n");
}
return;
}
//
// A general state machine for a protocol thread (RTMv2)
//
DWORD Rtmv2EntityThreadProc (LPVOID ThreadParameters)
{
PENTITY_CHARS EntityChars;
PRTM_ENTITY_INFO EntityInfo;
RTM_INSTANCE_CONFIG InstanceConfig;
RTM_ADDRESS_FAMILY_CONFIG AddrFamConfig;
RTM_ADDRESS_FAMILY_INFO AddrFamilyInfo;
RTM_ENTITY_HANDLE RtmRegHandle;
RTM_VIEW_SET ViewSet;
UINT NumViews;
UINT NumInstances;
RTM_INSTANCE_INFO Instances[MAX_INSTANCES];
RTM_ADDRESS_FAMILY_INFO AddrFams[MAX_ADDR_FAMS];
UINT NumEntities;
RTM_ENTITY_HANDLE EntityHandles[MAX_ENTITIES];
RTM_ENTITY_INFO EntityInfos[MAX_ENTITIES];
UINT NumMethods;
RTM_ENTITY_EXPORT_METHOD ExportMethods[MAX_METHODS];
RTM_ENTITY_METHOD_INPUT Input;
UINT OutputHdrSize;
UINT OutputSize;
RTM_ENTITY_METHOD_OUTPUT Output[MAX_METHODS];
UINT i, j, k, l, m;
UCHAR *p;
FILE *FilePtr;
UINT NumRoutes;
Route Routes[MAXROUTES];
RTM_NEXTHOP_INFO NextHopInfo;
RTM_NEXTHOP_HANDLE NextHopHandle;
PRTM_NEXTHOP_INFO NextHopPointer;
DWORD ChangeFlags;
RTM_ENUM_HANDLE EnumHandle;
RTM_ENUM_HANDLE EnumHandle1;
RTM_ENUM_HANDLE EnumHandle2;
UINT TotalHandles;
UINT NumHandles;
HANDLE Handles[MAX_HANDLES];
RTM_NET_ADDRESS NetAddress;
UINT DestInfoSize;
PRTM_DEST_INFO DestInfo1;
PRTM_DEST_INFO DestInfo2;
UINT NumInfos;
PRTM_DEST_INFO DestInfos;
RTM_ROUTE_INFO RouteInfo;
RTM_ROUTE_HANDLE RouteHandle;
PRTM_ROUTE_INFO RoutePointer;
RTM_PREF_INFO PrefInfo;
RTM_ROUTE_LIST_HANDLE RouteListHandle1;
RTM_ROUTE_LIST_HANDLE RouteListHandle2;
RTM_NOTIFY_HANDLE NotifyHandle;
BOOL Marked;
DWORD Status;
DWORD Status1;
DWORD Status2;
//
// Test the mask to len conversion macros in rtmv2.h
//
for (i = 0; i < 33; i++)
{
j = RTM_IPV4_MASK_FROM_LEN(i);
p = (PUCHAR) &j;
RTM_IPV4_LEN_FROM_MASK(k, j);
Assert(i == k);
printf("Len %2d: %08x: %02x.%02x.%02x.%02x: %2d\n",
i, j, p[0], p[1], p[2], p[3], k);
}
//
// Get all characteristics of this entity
//
EntityChars = (PENTITY_CHARS) ThreadParameters;
EntityInfo = &EntityChars->EntityInformation;
Print("\n--------------------------------------------------------\n");
//
// -00- Is this addr family config in registry
//
Status = RtmReadAddressFamilyConfig(EntityInfo->RtmInstanceId,
EntityInfo->AddressFamily,
&AddrFamConfig);
DBG_UNREFERENCED_LOCAL_VARIABLE(InstanceConfig);
if (!SUCCESS(Status))
{
// Fill in the instance config
Status = RtmWriteInstanceConfig(EntityInfo->RtmInstanceId,
&InstanceConfig);
Check(Status, 0);
// Fill in the address family config
AddrFamConfig.AddressSize = sizeof(DWORD);
AddrFamConfig.MaxChangeNotifyRegns = 10;
AddrFamConfig.MaxOpaqueInfoPtrs = 10;
AddrFamConfig.MaxNextHopsInRoute = 5;
AddrFamConfig.MaxHandlesInEnum = 100;
AddrFamConfig.ViewsSupported = RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST;
Status = RtmWriteAddressFamilyConfig(EntityInfo->RtmInstanceId,
EntityInfo->AddressFamily,
&AddrFamConfig);
Check(Status, 0);
}
//
// -01- Register with an AF on an RTM instance
//
Status = RtmRegisterEntity(EntityInfo,
(PRTM_ENTITY_EXPORT_METHODS)
EntityChars->ExportMethods,
EntityChars->EventCallback,
TRUE,
&EntityChars->RegnProfile,
&RtmRegHandle);
Check(Status, 1);
//
// Count the number of views for later use
//
NumViews = EntityChars->RegnProfile.NumberOfViews;
//
// Test all the management APIs before others
//
NumInstances = MAX_INSTANCES;
Status = RtmGetInstances(&NumInstances,
&Instances[0]);
Check(Status, 100);
for (i = 0; i < NumInstances; i++)
{
Status = RtmGetInstanceInfo(Instances[i].RtmInstanceId,
&Instances[i],
&Instances[i].NumAddressFamilies,
AddrFams);
Check(Status, 101);
}
//
// Query the appropriate table to check regn
//
NumEntities = MAX_ENTITIES;
Status = RtmGetAddressFamilyInfo(EntityInfo->RtmInstanceId,
EntityInfo->AddressFamily,
&AddrFamilyInfo,
&NumEntities,
EntityInfos);
Check(Status, 102);
//
// -03- Get all currently registered entities
//
NumEntities = MAX_ENTITIES;
Status = RtmGetRegisteredEntities(RtmRegHandle,
&NumEntities,
EntityHandles,
EntityInfos);
Print("\n");
for (i = 0; i < NumEntities; i++)
{
Print("%02d: Handle: %p\n", i, EntityHandles[i]);
}
Print("\n");
Check(Status, 3);
//
// -04- Get all exports methods of each entity
//
for (i = 0; i < NumEntities; i++)
{
NumMethods = 0;
Status = RtmGetEntityMethods(RtmRegHandle,
EntityHandles[i],
&NumMethods,
NULL);
Check(Status, 4);
Print("\n");
Print("Number of methods for %p = %2d\n",
EntityHandles[i],
NumMethods);
Print("\n");
Status = RtmGetEntityMethods(RtmRegHandle,
EntityHandles[i],
&NumMethods,
ExportMethods);
Check(Status, 4);
/*
//
// -06- Try blocking methods & then calling invoke
// Wont block as thread owns Critical Section
//
Status = RtmBlockMethods(RtmRegHandle,
NULL,
0,
RTM_BLOCK_METHODS);
Check(Status, 6);
*/
// for (j = 0; j < NumMethods; j++)
{
//
// -05- Invoke all exports methods of an entity
//
Input.MethodType = METHOD_TYPE_ALL_METHODS; // 1 << j;
Input.InputSize = 0;
OutputHdrSize = FIELD_OFFSET(RTM_ENTITY_METHOD_OUTPUT, OutputData);
OutputSize = OutputHdrSize * MAX_METHODS;
Status = RtmInvokeMethod(RtmRegHandle,
EntityHandles[i],
&Input,
&OutputSize,
Output);
Print("\n");
Print("Num Methods Called = %d\n", OutputSize / OutputHdrSize);
Print("\n");
Check(Status, 5);
}
}
//
// -44- Release handles we have on the entities
//
Status = RtmReleaseEntities(RtmRegHandle,
NumEntities,
EntityHandles);
Check(Status, 44);
//
// -07- Add next hops to the table (from the info file)
//
if ((FilePtr = fopen(EntityChars->RoutesFileName, "r")) == NULL)
{
Fatal("Failed open route database with status = %x\n",
ERROR_OPENING_DATABASE);
}
NumRoutes = ReadRoutesFromFile(FilePtr,
MAX_ROUTES,
Routes);
fclose(FilePtr);
// For each route, add its next-hop to the next-hop table
for (i = 0; i < NumRoutes; i++)
{
RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
Routes[i].nexthop,
ADDRSIZE);
NextHopInfo.RemoteNextHop = NULL;
NextHopInfo.Flags = 0;
NextHopInfo.EntitySpecificInfo = UIntToPtr(i);
NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
NextHopHandle = NULL;
Status = RtmAddNextHop(RtmRegHandle,
&NextHopInfo,
&NextHopHandle,
&ChangeFlags);
Check(Status, 7);
// Print("Add Next Hop %lu: %p\n", i, NextHopHandle);
if (!(ChangeFlags & RTM_NEXTHOP_CHANGE_NEW))
{
Status = RtmReleaseNextHops(RtmRegHandle,
1,
&NextHopHandle);
Check(Status, 15);
}
#if _DBG_
else
{
Status = RtmDeleteNextHop(RtmRegHandle,
NextHopHandle,
NULL);
Check(Status, 14);
}
#endif
}
//
// 08 - Find the next-hops added using RtmFindNextHop
//
for (i = 0; i < NumRoutes; i++)
{
RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
Routes[i].nexthop,
ADDRSIZE);
NextHopInfo.NextHopOwner = RtmRegHandle;
NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
NextHopHandle = NULL;
Status = RtmFindNextHop(RtmRegHandle,
&NextHopInfo,
&NextHopHandle,
&NextHopPointer);
// Print("NextHop: Handle: %p,\n\t Addr: ", NextHopHandle);
// Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[0]);
// Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[1]);
// Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[2]);
// Print("%3d ", (UINT) NextHopPointer->NextHopAddress.AddrBits[3]);
// Print("\n\tInterface = %lu\n", NextHopPointer->InterfaceIndex);
Check(Status, 8);
Status = RtmReleaseNextHops(RtmRegHandle,
1,
&NextHopHandle);
Check(Status, 15);
}
//
// -40- Register with RTM for getting change notifications
//
Status = RtmRegisterForChangeNotification(RtmRegHandle,
RTM_VIEW_MASK_MCAST,
RTM_CHANGE_TYPE_BEST,
// RTM_NOTIFY_ONLY_MARKED_DESTS,
EntityChars,
&NotifyHandle);
Check(Status, 40);
Print("Change Notification Registration Successful\n\n");
//
// -35- Create an entity specific list to add routes to
//
Status = RtmCreateRouteList(RtmRegHandle,
&RouteListHandle1);
Check(Status, 35);
//
// -17- Add routes to RIB with approprate next-hops
//
for (i = 0; i < NumRoutes; i++)
{
// Get the next hop handle using next hop address
RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
Routes[i].nexthop,
ADDRSIZE);
NextHopInfo.NextHopOwner = RtmRegHandle;
NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
NextHopHandle = NULL;
Status = RtmFindNextHop(RtmRegHandle,
&NextHopInfo,
&NextHopHandle,
NULL);
Check(Status, 8);
// Now do the route add with the right information
RouteHandle = NULL;
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
Routes[i].addr,
Routes[i].len);
// Print("Add Route: Len : %08x, Addr = %3d.%3d.%3d.%3d\n",
// NetAddress.NumBits,
// NetAddress.AddrBits[0],
// NetAddress.AddrBits[1],
// NetAddress.AddrBits[2],
// NetAddress.AddrBits[3]);
ZeroMemory(&RouteInfo, sizeof(RTM_ROUTE_INFO));
// Assume 'neighbour learnt from' is the 1st nexthop
RouteInfo.Neighbour = NextHopHandle;
RouteInfo.PrefInfo.Preference = EntityInfo->EntityId.EntityProtocolId;
RouteInfo.PrefInfo.Metric = Routes[i].metric;
RouteInfo.BelongsToViews = VIEW_MASK_ARR[1 + (i % 3)];
RouteInfo.EntitySpecificInfo = UIntToPtr(i);
RouteInfo.NextHopsList.NumNextHops = 1;
RouteInfo.NextHopsList.NextHops[0] = NextHopHandle;
ChangeFlags = RTM_ROUTE_CHANGE_NEW;
Status = RtmAddRouteToDest(RtmRegHandle,
&RouteHandle,
&NetAddress,
&RouteInfo,
INFINITE,
RouteListHandle1,
0,
NULL,
&ChangeFlags);
Check(Status, 17);
// Update the same route using the handle
ChangeFlags = 0;
RouteInfo.Flags = RTM_ROUTE_FLAGS_DISCARD;
Status = RtmAddRouteToDest(RtmRegHandle,
&RouteHandle,
&NetAddress,
&RouteInfo,
INFINITE,
RouteListHandle1,
0,
NULL,
&ChangeFlags);
Check(Status, 17);
// Print("Add Route %lu: %p\n", i, RouteHandle);
Status = RtmLockRoute(RtmRegHandle,
RouteHandle,
TRUE,
TRUE,
&RoutePointer);
Check(Status, 46);
// Update route parameters in place
RoutePointer->PrefInfo.Metric = 1000 - RoutePointer->PrefInfo.Metric;
RoutePointer->BelongsToViews = VIEW_MASK_ARR[i % 3];
RoutePointer->EntitySpecificInfo = UIntToPtr(1000 - i);
Status = RtmUpdateAndUnlockRoute(RtmRegHandle,
RouteHandle,
10, // INFINITE,
NULL,
0,
NULL,
&ChangeFlags);
Check(Status, 47);
// Print("Update Route %lu: %p\n", i, RouteHandle);
if (!SUCCESS(Status))
{
Status = RtmLockRoute(RtmRegHandle,
RouteHandle,
TRUE,
FALSE,
NULL);
Check(Status, 46);
}
// Try doing a add specifying the route handle
RouteInfo.PrefInfo.Metric = Routes[i].metric;
RouteInfo.BelongsToViews = VIEW_MASK_ARR[1 + (i % 3)];
RouteInfo.EntitySpecificInfo = UIntToPtr(i);
ChangeFlags = 0;
Status = RtmAddRouteToDest(RtmRegHandle,
&RouteHandle,
&NetAddress,
&RouteInfo,
INFINITE,
RouteListHandle1,
0,
NULL,
&ChangeFlags);
Check(Status, 17);
Status = RtmReleaseNextHops(RtmRegHandle,
1,
&NextHopHandle);
// Check(Status, 15);
if (!SUCCESS(Status))
{
// Print("%p %p\n", RtmRegHandle,NextHopHandle);
Status = RtmReleaseNextHops(RtmRegHandle,
1,
&NextHopHandle);
Check(Status, 15);
}
}
Status = RtmCreateRouteList(RtmRegHandle,
&RouteListHandle2);
Check(Status, 35);
//
// -38- Create an enumeration on the route list
//
Status = RtmCreateRouteListEnum(RtmRegHandle,
RouteListHandle1,
&EnumHandle);
Check(Status, 38);
TotalHandles = 0;
do
{
//
// -39- Get next set of routes on the enum
//
NumHandles = MAX_HANDLES;
Status = RtmGetListEnumRoutes(RtmRegHandle,
EnumHandle,
&NumHandles,
Handles);
Check(Status, 39);
TotalHandles += NumHandles;
for (i = 0; i < NumHandles; i++)
{
; // Print("Route Handle %5lu: %p\n", i, Handles[i]);
}
//
// -37- Move all routes in one route list to another
//
Status = RtmInsertInRouteList(RtmRegHandle,
RouteListHandle2,
NumHandles,
Handles);
Check(Status, 37);
//
// Release the routes that have been enum'ed
//
Status = RtmReleaseRoutes(RtmRegHandle, NumHandles, Handles);
Check(Status, 27);
}
while (NumHandles == MAX_HANDLES);
Print("\nTotal Num of handles in list: %lu\n", TotalHandles);
//
// -36- Destroy all the entity specific lists
//
Status = RtmDeleteRouteList(RtmRegHandle, RouteListHandle1);
Check(Status, 36);
Status = RtmDeleteRouteList(RtmRegHandle, RouteListHandle2);
Check(Status, 36);
DestInfoSize = RTM_SIZE_OF_DEST_INFO(NumViews);
DestInfo1 = ALLOC_RTM_DEST_INFO(NumViews, 1);
DestInfo2 = ALLOC_RTM_DEST_INFO(NumViews, 1);
//
// -18- Get dests from the table using exact match
//
for (i = 0; i < NumRoutes; i++)
{
// Query for the route with the right information
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress, Routes[i].addr, Routes[i].len);
Status = RtmGetExactMatchDestination(RtmRegHandle,
&NetAddress,
RTM_BEST_PROTOCOL,
0,
DestInfo1);
Check(Status, 18);
//
// For each destination in table, mark the dest
//
Status = RtmMarkDestForChangeNotification(RtmRegHandle,
NotifyHandle,
DestInfo1->DestHandle,
TRUE);
Check(Status, 48);
Status = RtmIsMarkedForChangeNotification(RtmRegHandle,
NotifyHandle,
DestInfo1->DestHandle,
&Marked);
Check(Status, 49);
Assert(Marked == TRUE);
Status = RtmReleaseDestInfo(RtmRegHandle, DestInfo1);
Check(Status, 22);
}
DestInfo1 = ALLOC_RTM_DEST_INFO(NumViews, 1);
DestInfo2 = ALLOC_RTM_DEST_INFO(NumViews, 1);
//
// -29- Get routes from the table using exact match
//
for (i = 0; i < NumRoutes; i++)
{
// Get the next hop handle using next hop address
RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
Routes[i].nexthop,
ADDRSIZE);
NextHopInfo.NextHopOwner = RtmRegHandle;
NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
NextHopHandle = NULL;
Status = RtmFindNextHop(RtmRegHandle,
&NextHopInfo,
&NextHopHandle,
NULL);
Check(Status, 8);
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
Routes[i].addr,
Routes[i].len);
// Query for the route with the right information
RouteInfo.Neighbour = NextHopHandle;
RouteInfo.RouteOwner = RtmRegHandle;
RouteInfo.PrefInfo.Preference = EntityInfo->EntityId.EntityProtocolId;
RouteInfo.PrefInfo.Metric = Routes[i].metric;
RouteInfo.NextHopsList.NumNextHops = 1;
RouteInfo.NextHopsList.NextHops[0] = NextHopHandle;
Status = RtmGetExactMatchRoute(RtmRegHandle,
&NetAddress,
RTM_MATCH_FULL,
&RouteInfo,
PtrToUlong(Routes[i].interface),
0,
&RouteHandle);
Check(Status, 29);
Status = RtmReleaseNextHops(RtmRegHandle,
1,
&NextHopHandle);
Check(Status, 15);
Status = RtmReleaseRoutes(RtmRegHandle, 1, &RouteHandle);
Check(Status, 27);
Status = RtmReleaseRouteInfo(RtmRegHandle, &RouteInfo);
Check(Status, 31);
}
//
// -19- Get dests from the table using prefix match
//
// -20- Do a prefix walk up the tree for each dest
//
for (i = j = 0; i < NumRoutes; i++)
{
// Query for the route with the right information
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
Routes[i].addr,
Routes[i].len);
Status = RtmGetMostSpecificDestination(RtmRegHandle,
&NetAddress,
RTM_BEST_PROTOCOL,
RTM_VIEW_MASK_UCAST,
DestInfo1);
// Check(Status, 19);
if (DestInfo1->DestAddress.NumBits != NetAddress.NumBits)
{
; // Print("No Exact Match : %5lu\n", j++);
}
while (SUCCESS(Status))
{
Status = RtmGetLessSpecificDestination(RtmRegHandle,
DestInfo1->DestHandle,
RTM_BEST_PROTOCOL,
RTM_VIEW_MASK_UCAST,
DestInfo2);
// Check(Status, 20);
Check(RtmReleaseDestInfo(RtmRegHandle, DestInfo1), 22);
if (!SUCCESS(Status)) break;
// Print("NumBits: %d\n", DestInfo2->DestAddress.NumBits);
Status = RtmGetLessSpecificDestination(RtmRegHandle,
DestInfo2->DestHandle,
RTM_BEST_PROTOCOL,
RTM_VIEW_MASK_UCAST,
DestInfo1);
// Check(Status, 20);
Check(RtmReleaseDestInfo(RtmRegHandle, DestInfo2), 20);
if (!SUCCESS(Status)) break;
// Print("NumBits: %d\n", DestInfo1->DestAddress.NumBits);
}
}
#if DBG
for (i = 0; i < 100000000; i++) { ; }
#endif
//
// Just do a "route enum" over the whole table
//
Status2 = RtmCreateRouteEnum(RtmRegHandle,
NULL,
0, // RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST,
RTM_ENUM_OWN_ROUTES,
NULL,
0,
NULL,
0,
&EnumHandle2);
Check(Status2, 25);
l = 0;
do
{
NumHandles = MAX_HANDLES;
Status2 = RtmGetEnumRoutes(RtmRegHandle,
EnumHandle2,
&NumHandles,
Handles);
// Check(Status2, 26);
for (k = 0; k < NumHandles; k++)
{
; // Print("Route %d: %p\n", l++, Handles[k]);
}
Check(RtmReleaseRoutes(RtmRegHandle,
NumHandles,
Handles), 27);
}
while (SUCCESS(Status2));
//
// Just try a enum query after ERROR_NO_MORE_ITEMS is retd
//
NumHandles = MAX_HANDLES;
Status2 = RtmGetEnumRoutes(RtmRegHandle,
EnumHandle2,
&NumHandles,
Handles);
Assert((NumHandles == 0) && (Status2 == ERROR_NO_MORE_ITEMS));
Status2 = RtmDeleteEnumHandle(RtmRegHandle,
EnumHandle2);
Check(Status2, 16);
//
// Get dests from the table using an enumeration
// -23- Open a new dest enumeration
// -24- Get dests in enum
// -16- Close destination enum.
//
DestInfos = ALLOC_RTM_DEST_INFO(NumViews, MAX_HANDLES);
#if MCAST_ENUM
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
0x000000E0,
4);
#else
RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
0x00000000,
0);
#endif
Status = RtmCreateDestEnum(RtmRegHandle,
RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST,
RTM_ENUM_RANGE | RTM_ENUM_OWN_DESTS,
&NetAddress,
RTM_THIS_PROTOCOL,
&EnumHandle1);
Check(Status, 23);
m = j = 0;
do
{
NumInfos = MAX_HANDLES;
Status1 = RtmGetEnumDests(RtmRegHandle,
EnumHandle1,
&NumInfos,
DestInfos);
// Check(Status1, 24);
for (i = 0; i < NumInfos; i++)
{
DestInfo1 = (PRTM_DEST_INFO) ((PUCHAR)DestInfos+(i*DestInfoSize));
// Print("Dest %d: %p\n", j++, DestInfo1->DestHandle);
// PrintDestInfo(DestInfo1);
Status2 = RtmCreateRouteEnum(RtmRegHandle,
DestInfo1->DestHandle,
RTM_VIEW_MASK_UCAST |
RTM_VIEW_MASK_MCAST,
RTM_ENUM_OWN_ROUTES,
NULL,
0, // RTM_MATCH_INTERFACE,
NULL,
0,
&EnumHandle2);
Check(Status2, 25);
/*
Check(RtmHoldDestination(RtmRegHandle,
DestInfo1->DestHandle,
RTM_VIEW_MASK_UCAST,
100), 33);
*/
l = 0;
PrefInfo.Preference = (ULONG) ~0;
PrefInfo.Metric = (ULONG) 0;
do
{
NumHandles = MAX_HANDLES;
Status2 = RtmGetEnumRoutes(RtmRegHandle,
EnumHandle2,
&NumHandles,
Handles);
// Check(Status2, 26);
for (k = 0; k < NumHandles; k++)
{
// Print("\tRoute %d: %p\t", l++, Handles[k]);
// PrintRouteInfo(Handles[k]);
Status = RtmIsBestRoute(RtmRegHandle,
Handles[k],
&ViewSet);
Check(Status, 28);
// Print("Best In Views: %08x\n", ViewSet);
Status = RtmGetRouteInfo(RtmRegHandle,
Handles[k],
&RouteInfo,
&NetAddress);
Check(Status, 30);
Print("RouteDest: Len : %08x," \
" Addr = %3d.%3d.%3d.%3d," \
" Pref = %08x, %08x\n",
NetAddress.NumBits,
NetAddress.AddrBits[0],
NetAddress.AddrBits[1],
NetAddress.AddrBits[2],
NetAddress.AddrBits[3],
RouteInfo.PrefInfo.Preference,
RouteInfo.PrefInfo.Metric);
//
// Make sure that list is ordered by PrefInfo
//
if ((PrefInfo.Preference < RouteInfo.PrefInfo.Preference)||
((PrefInfo.Preference == RouteInfo.PrefInfo.Preference)
&& (PrefInfo.Metric > RouteInfo.PrefInfo.Metric)))
{
Check(ERROR_INVALID_DATA, 150);
}
Status = RtmReleaseRouteInfo(RtmRegHandle,
&RouteInfo);
Check(Status, 31);
// Print("Del Route %lu: %p\n", m++, Handles[k]);
Status = RtmDeleteRouteToDest(RtmRegHandle,
Handles[k],
&ChangeFlags);
Check(Status, 32);
}
Check(RtmReleaseRoutes(RtmRegHandle,
NumHandles,
Handles), 27);
}
while (SUCCESS(Status2));
//
// Just try a enum query after ERROR_NO_MORE_ITEMS is retd
//
NumHandles = MAX_HANDLES;
Status2 = RtmGetEnumRoutes(RtmRegHandle,
EnumHandle2,
&NumHandles,
Handles);
Assert((NumHandles == 0) && (Status2 == ERROR_NO_MORE_ITEMS));
/*
Check(RtmHoldDestination(RtmRegHandle,
DestInfo1->DestHandle,
RTM_VIEW_MASK_MCAST,
100), 33);
*/
Status2 = RtmDeleteEnumHandle(RtmRegHandle,
EnumHandle2);
Check(Status2, 16);
// Check(RtmReleaseDestInfo(RtmRegHandle,
// DestInfo1), 22);
}
Check(RtmReleaseDests(RtmRegHandle,
NumInfos,
DestInfos), 34);
}
while (SUCCESS(Status1));
//
// Just try a enum query after ERROR_NO_MORE_ITEMS is retd
//
NumInfos = MAX_HANDLES;
Status1 = RtmGetEnumDests(RtmRegHandle,
EnumHandle1,
&NumInfos,
DestInfos);
Assert((NumInfos == 0) && (Status1 == ERROR_NO_MORE_ITEMS));
Status1 = RtmDeleteEnumHandle(RtmRegHandle,
EnumHandle1);
Check(Status1, 16);
//
// -10- Enumerate all the next-hops in table,
//
// -11- For each next-hop in table
// -12- Get the next hop info,
// -14- Delete the next-hop,
// -13- Release next hop info.
//
// -15- Release all the next-hops in table,
//
// -16- Close the next hop enumeration handle.
//
Status = RtmCreateNextHopEnum(RtmRegHandle,
0,
NULL,
&EnumHandle);
Check(Status, 10);
j = 0;
do
{
NumHandles = 5; // MAX_HANDLES;
Status = RtmGetEnumNextHops(RtmRegHandle,
EnumHandle,
&NumHandles,
Handles);
// Check(Status, 11);
for (i = 0; i < NumHandles; i++)
{
Check(RtmGetNextHopInfo(RtmRegHandle,
Handles[i],
&NextHopInfo), 12);
// Print("Deleting NextHop %lu: %p\n", j++, Handles[i]);
// Print("State: %04x, Interface: %d\n",
// NextHopInfo.State,
// NextHopInfo.InterfaceIndex);
Check(RtmDeleteNextHop(RtmRegHandle,
Handles[i],
NULL), 14);
Check(RtmReleaseNextHopInfo(RtmRegHandle,
&NextHopInfo), 13);
}
Check(RtmReleaseNextHops(RtmRegHandle,
NumHandles,
Handles), 15);
}
while (SUCCESS(Status));
//
// Just try a enum query after ERROR_NO_MORE_ITEMS is retd
//
NumHandles = MAX_HANDLES;
Status = RtmGetEnumNextHops(RtmRegHandle,
EnumHandle,
&NumHandles,
Handles);
Assert((NumHandles == 0) && (Status == ERROR_NO_MORE_ITEMS));
Status = RtmDeleteEnumHandle(RtmRegHandle,
EnumHandle);
Check(Status, 16);
//
// Make sure that the next hop table is empty now
//
Status = RtmCreateNextHopEnum(RtmRegHandle,
0,
NULL,
&EnumHandle);
NumHandles = MAX_HANDLES;
Status = RtmGetEnumNextHops(RtmRegHandle,
EnumHandle,
&NumHandles,
Handles);
if ((Status != ERROR_NO_MORE_ITEMS) || (NumHandles != 0))
{
Check(Status, 11);
}
Status = RtmDeleteEnumHandle(RtmRegHandle,
EnumHandle);
Check(Status, 16);
Sleep(1000);
//
// -41- Deregister all existing change notif registrations
//
Status = RtmDeregisterFromChangeNotification(RtmRegHandle,
NotifyHandle);
Check(Status, 41);
Print("Change Notification Deregistration Successful\n\n");
//
// -02- De-register with the RTM before exiting
//
Status = RtmDeregisterEntity(RtmRegHandle);
Check(Status, 2);
#if _DBG_
Status = RtmDeregisterEntity(RtmRegHandle);
Check(Status, 2);
#endif
Print("\n--------------------------------------------------------\n");
return NO_ERROR;
}
DWORD
EntityEventCallback (
IN RTM_ENTITY_HANDLE RtmRegHandle,
IN RTM_EVENT_TYPE EventType,
IN PVOID Context1,
IN PVOID Context2
)
{
RTM_ENTITY_HANDLE EntityHandle;
PENTITY_CHARS EntityChars;
PRTM_ENTITY_INFO EntityInfo;
RTM_NOTIFY_HANDLE NotifyHandle;
PRTM_DEST_INFO DestInfos;
UINT NumDests;
UINT NumViews;
RTM_ROUTE_HANDLE RouteHandle;
PRTM_ROUTE_INFO RoutePointer;
DWORD ChangeFlags;
DWORD Status;
Print("\nEvent callback called for %p :", RtmRegHandle);
Status = NO_ERROR;
Print("\n\tEntity Event = ");
switch (EventType)
{
case RTM_ENTITY_REGISTERED:
EntityHandle = (RTM_ENTITY_HANDLE) Context1;
EntityInfo = (PRTM_ENTITY_INFO) Context2;
Print("Registration\n\tEntity Handle = %p\n\tEntity IdInst = %p\n\n",
EntityHandle,
EntityInfo->EntityId);
/*
//
// -45- Make a copy of the handle of new entity
//
Status = RtmReferenceHandles(RtmRegHandle,
1,
&EntityHandle);
Check(Status, 45);
*/
break;
case RTM_ENTITY_DEREGISTERED:
EntityHandle = (RTM_ENTITY_HANDLE) Context1;
EntityInfo = (PRTM_ENTITY_INFO) Context2;
Print("Deregistration\n\tEntity Handle = %p\n\tEntity IdInst = %p\n\n",
EntityHandle,
EntityInfo->EntityId);
/*
//
// -44- Release the handle we have on the entity
//
Status = RtmReleaseEntities(RtmRegHandle,
1,
&EntityHandle);
Check(Status, 44);
*/
break;
case RTM_CHANGE_NOTIFICATION:
NotifyHandle = (RTM_NOTIFY_HANDLE) Context1;
EntityChars = (PENTITY_CHARS) Context2;
Print("Changes Available\n\tNotify Handle = %p\n\tEntity Ch = %p\n\n",
NotifyHandle,
EntityChars);
//
// Count the number of view for later use
//
NumViews = EntityChars->RegnProfile.NumberOfViews;
//
// -43- Get all changes to destinations
//
DestInfos = ALLOC_RTM_DEST_INFO(NumViews, MAX_HANDLES);
do
{
NumDests = MAX_HANDLES;
Status = RtmGetChangedDests(RtmRegHandle,
NotifyHandle,
&NumDests,
DestInfos);
// Check(Status, 42);
printf("Status = %lu\n", Status);
Print("Num Changed Dests = %d\n", NumDests);
EntityChars->TotalChangedDests += NumDests;
Status = RtmReleaseChangedDests(RtmRegHandle,
NotifyHandle,
NumDests,
DestInfos);
Check(Status, 43);
}
while (NumDests > 0);
Print("Total Changed Dests = %d\n", EntityChars->TotalChangedDests);
break;
case RTM_ROUTE_EXPIRED:
RouteHandle = (RTM_ROUTE_HANDLE) Context1;
RoutePointer = (PRTM_ROUTE_INFO) Context2;
Print("Route Aged Out\n\tRoute Handle = %p\n\tRoute Pointer = %p\n\n",
RouteHandle,
RoutePointer);
// Refresh the route by doing dummy update in place
Status = RtmLockRoute(RtmRegHandle,
RouteHandle,
TRUE,
TRUE,
NULL);
// Check(Status, 46);
if (Status == NO_ERROR)
{
Status = RtmUpdateAndUnlockRoute(RtmRegHandle,
RouteHandle,
INFINITE,
NULL,
0,
NULL,
&ChangeFlags);
Check(Status, 47);
if (!SUCCESS(Status))
{
Status = RtmLockRoute(RtmRegHandle,
RouteHandle,
TRUE,
FALSE,
NULL);
Check(Status, 46);
}
}
Check(RtmReleaseRoutes(RtmRegHandle,
1,
&RouteHandle), 27);
break;
default:
Status = ERROR_NOT_SUPPORTED;
}
return Status;
}
VOID
EntityExportMethod (
IN RTM_ENTITY_HANDLE CallerHandle,
IN RTM_ENTITY_HANDLE CalleeHandle,
IN RTM_ENTITY_METHOD_INPUT *Input,
OUT RTM_ENTITY_METHOD_OUTPUT *Output
)
{
Print("Export Function %2d called on %p: Caller = %p\n\n",
Input->MethodType,
CalleeHandle,
CallerHandle);
Output->MethodStatus = NO_ERROR;
return;
}
// Default warnings for unreferenced params and local variables
#pragma warning(default: 4100)
#pragma warning(default: 4101)
#if _DBG_
00 RtmReadAddrFamilyConfig
00 RtmWriteAddrFamilyConfig
00 RtmWriteInstanceConfig
01 RtmRegisterEntity
02 RtmDeregisterEntity
03 RtmGetRegdEntities
04 RtmGetEntityMethods
05 RtmInvokeMethod
06 RtmBlockMethods
07 RtmAddNextHop
08 RtmFindNextHop
09 RtmLockNextHop
10 RtmCreateNextHopEnum
11 RtmGetEnumNextHops
12 RtmGetNextHopInfo
13 RtmReleaseNextHopInfo
14 RtmDelNextHop
15 RtmReleaseNextHops
16 RtmDeleteEnumHandle
17 RtmAddRouteToDest
18 RtmGetExactMatchDestination
19 RtmGetMostSpecificDestination
20 RtmGetLessSpecificDestination
21 RtmGetDestInfo
22 RtmReleaseDestInfo
23 RtmCreateDestEnum
24 RtmGetEnumDests
25 RtmCreateRouteEnum
26 RtmGetEnumRoutes
27 RtmReleaseRoutes
28 RtmIsBestRoute
29 RtmGetExactMatchRoute
30 RtmGetRouteInfo
31 RtmReleaseRouteInfo
32 RtmDelRoute
33 RtmHoldDestination
34 RtmReleaseDests
35 RtmCreateRouteList
36 RtmDeleteRouteList
37 RtmInsertInRouteList
38 RtmCreateRouteListEnum
39 RtmGetListEnumRoutes
40 RtmRegisterForChangeNotification
41 RtmDeregisterFromChangeNotification
42 RtmGetChangedDests
43 RtmReleaseChangedDests
44 RtmReleaseEntities
45 RtmReferenceHandles
46 RtmLockRoute
47 RtmUpdateAndUnlockRoute
48 RtmMarkDestForChangeNotification
49 RtmIsMarkedForChangeNotification
50 RtmCreateRouteTable
51 RtmDeleteRouteTable
52 RtmRegisterClient
53 RtmDeregisterClient
54 RtmAddRoute
55 RtmDeleteRoute
56 RtmCreateEnumerationHandle
57 RtmCloseEnumerationHandle
58 RtmEnumerateGetNextRoute
59 RtmGetFirstRoute
60 RtmGetNextRoute
61 RtmBlockDeleteRoutes
62 RtmBlockConvertRoutesToStatic
63 RtmGetNetworkCount
64 RtmIsRoute
65 RtmLookupIPDestination
66 RtmBlockSetRouteEnable
#endif