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.
894 lines
19 KiB
894 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1997 - 98, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rtmobj2.c
|
|
|
|
Abstract:
|
|
|
|
Contains routines for managing RTM objects
|
|
like Destinations, Routes and Next Hops.
|
|
|
|
Author:
|
|
|
|
Chaitanya Kodeboyina (chaitk) 23-Aug-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pchrtm.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
DWORD
|
|
CreateDest (
|
|
IN PADDRFAM_INFO AddrFamilyInfo,
|
|
IN PRTM_NET_ADDRESS DestAddress,
|
|
OUT PDEST_INFO *NewDest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new destination info structure and initializes it.
|
|
|
|
Arguments:
|
|
|
|
AddrFamilyInfo - Address family that identifies route table,
|
|
|
|
DestAddress - Destination network address for new dest,
|
|
|
|
NewDest - Pointer to the destination info structure
|
|
will be returned through this parameter.
|
|
|
|
Return Value:
|
|
|
|
Status of the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEST_INFO Dest;
|
|
UINT NumOpaquePtrs;
|
|
UINT NumBytes;
|
|
UINT NumViews;
|
|
DWORD Status;
|
|
|
|
*NewDest = NULL;
|
|
|
|
//
|
|
// Allocate and initialize a new route info
|
|
//
|
|
|
|
NumOpaquePtrs = AddrFamilyInfo->MaxOpaquePtrs;
|
|
|
|
NumViews = AddrFamilyInfo->NumberOfViews;
|
|
|
|
NumBytes = sizeof(DEST_INFO) +
|
|
NumOpaquePtrs * sizeof(PVOID) +
|
|
(NumViews - 1) * sizeof(Dest->ViewInfo);
|
|
|
|
Dest = (PDEST_INFO) AllocNZeroObject(NumBytes);
|
|
|
|
if (Dest == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
do
|
|
{
|
|
|
|
#if DBG_HDL
|
|
Dest->ObjectHeader.TypeSign = DEST_ALLOC;
|
|
#endif
|
|
|
|
// Will be removed when first route on dest is added
|
|
INITIALIZE_DEST_REFERENCE(Dest, CREATION_REF);
|
|
|
|
//
|
|
// Initialize change notification bits and list entry
|
|
//
|
|
|
|
Dest->ChangeListLE.Next = NULL;
|
|
|
|
//
|
|
// Initialize the list of routes ont the destination
|
|
//
|
|
|
|
InitializeListHead(&Dest->RouteList);
|
|
|
|
Dest->NumRoutes = 0;
|
|
|
|
// Set the opaque ptr dir to memory at the end of dest
|
|
|
|
Dest->OpaqueInfoPtrs = (PVOID *) ((PUCHAR) Dest +
|
|
NumBytes -
|
|
NumOpaquePtrs * sizeof(PVOID));
|
|
|
|
// Set the destination address from the input parameter
|
|
|
|
CopyMemory(&Dest->DestAddress,
|
|
DestAddress,
|
|
sizeof(RTM_NET_ADDRESS));
|
|
|
|
*NewDest = Dest;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
while (FALSE);
|
|
|
|
//
|
|
// Some error occured in the initialization , clean up
|
|
//
|
|
|
|
#if DBG_HDL
|
|
Dest->ObjectHeader.TypeSign = DEST_FREED;
|
|
#endif
|
|
|
|
FreeObject(Dest);
|
|
|
|
*NewDest = NULL;
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
DestroyDest (
|
|
IN PDEST_INFO Dest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys the destination by freeing resources and
|
|
deallocating it. This function is called when the
|
|
reference count on the dest drops to 0.
|
|
|
|
Arguments:
|
|
|
|
Dest - Pointer to the dest being destroyed.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(Dest->ObjectHeader.RefCount == 0);
|
|
|
|
ASSERT(Dest->HoldRefCount == 0);
|
|
|
|
//
|
|
// Dynamic lock should have been freed
|
|
//
|
|
|
|
ASSERT(Dest->DestLock == NULL);
|
|
|
|
//
|
|
// Free the memory allocated for dest
|
|
//
|
|
|
|
#if DBG_HDL
|
|
Dest->ObjectHeader.TypeSign = DEST_FREED;
|
|
#endif
|
|
|
|
FreeObject(Dest);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateRoute (
|
|
IN PENTITY_INFO Entity,
|
|
IN PRTM_ROUTE_INFO RouteInfo,
|
|
OUT PROUTE_INFO *NewRoute
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new route info structure and initializes it.
|
|
|
|
Arguments:
|
|
|
|
Entity - Entity creating the new route on a dest,
|
|
|
|
RouteInfo - Route info for the new route being created,
|
|
|
|
NewRoute - Pointer to the new route info structure
|
|
will be returned through this parameter.
|
|
|
|
Return Value:
|
|
|
|
Status of the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
RTM_NEXTHOP_HANDLE NextHopHandle;
|
|
PRTM_ROUTE_INFO Info;
|
|
PROUTE_INFO Route;
|
|
PNEXTHOP_INFO NextHop;
|
|
UINT NumNextHops;
|
|
UINT i;
|
|
DWORD Status;
|
|
|
|
*NewRoute = NULL;
|
|
|
|
//
|
|
// Allocate and initialize a new route info
|
|
//
|
|
|
|
NumNextHops = Entity->OwningAddrFamily->MaxNextHopsInRoute;
|
|
|
|
Route = (PROUTE_INFO) AllocNZeroObject(sizeof(ROUTE_INFO) +
|
|
(NumNextHops - 1) *
|
|
sizeof(RTM_NEXTHOP_HANDLE));
|
|
|
|
if (Route == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
do
|
|
{
|
|
#if DBG_HDL
|
|
Route->ObjectHeader.TypeSign = ROUTE_ALLOC;
|
|
#endif
|
|
INITIALIZE_ROUTE_REFERENCE(Route, CREATION_REF);
|
|
|
|
InitializeListHead(&Route->DestLE);
|
|
|
|
InitializeListHead(&Route->RouteListLE);
|
|
|
|
//
|
|
// Initialize the public half of route info
|
|
//
|
|
|
|
Info = &Route->RouteInfo;
|
|
|
|
Info->RouteOwner = MAKE_HANDLE_FROM_POINTER(Entity);
|
|
|
|
REFERENCE_ENTITY(Entity, ROUTE_REF);
|
|
|
|
if (RouteInfo->Neighbour)
|
|
{
|
|
NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
|
|
|
|
REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
|
|
// "Neighbour learnt from" entry is owned by caller
|
|
|
|
ASSERT((NextHop) &&
|
|
(NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
|
|
|
|
Info->Neighbour = RouteInfo->Neighbour;
|
|
}
|
|
|
|
Info->State = RTM_ROUTE_STATE_CREATED;
|
|
|
|
Info->Flags1 = RouteInfo->Flags1;
|
|
|
|
Info->Flags = RouteInfo->Flags;
|
|
|
|
Info->PrefInfo = RouteInfo->PrefInfo;
|
|
|
|
Info->BelongsToViews = RouteInfo->BelongsToViews;
|
|
|
|
Info->EntitySpecificInfo = RouteInfo->EntitySpecificInfo;
|
|
|
|
//
|
|
// Make a copy of the next hops list (as much as u can)
|
|
//
|
|
|
|
if (NumNextHops > RouteInfo->NextHopsList.NumNextHops)
|
|
{
|
|
NumNextHops = RouteInfo->NextHopsList.NumNextHops;
|
|
}
|
|
|
|
Info->NextHopsList.NumNextHops = (USHORT) NumNextHops;
|
|
|
|
for (i = 0; i < NumNextHops; i++)
|
|
{
|
|
NextHopHandle = RouteInfo->NextHopsList.NextHops[i];
|
|
|
|
// Make sure that the next-hop is owned by caller
|
|
|
|
NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
|
|
|
|
ASSERT((NextHop) &&
|
|
(NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
|
|
|
|
Info->NextHopsList.NextHops[i] = NextHopHandle;
|
|
|
|
REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Return a pointer to the new initialized route
|
|
//
|
|
|
|
*NewRoute = Route;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
while (FALSE);
|
|
|
|
//
|
|
// Some error occured in the initialization , clean up
|
|
//
|
|
|
|
#if DBG_HDL
|
|
Route->ObjectHeader.TypeSign = ROUTE_FREED;
|
|
#endif
|
|
|
|
FreeObject(Route);
|
|
|
|
*NewRoute = NULL;
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
ComputeRouteInfoChange(
|
|
IN PRTM_ROUTE_INFO OldRouteInfo,
|
|
IN PRTM_ROUTE_INFO NewRouteInfo,
|
|
IN ULONG PrefChanged,
|
|
OUT PULONG RouteInfoChanged,
|
|
OUT PULONG ForwardingInfoChanged
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates an exising route with new route info. Note that
|
|
only the route's owner is allowed to do this.
|
|
|
|
Arguments:
|
|
|
|
OldRoute - Old route information (except the PrefInfo and
|
|
BelongsToViews info fields already updated),
|
|
|
|
NewRoute - New route information to update old route with,
|
|
|
|
PrefChanged - Whether PrefInfo values changed from old to new,
|
|
|
|
RouteInfoChanged - Whether the route information has changed,
|
|
|
|
ForwardingInfoChanged - Whether forwarding info has been changed.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG DiffFlags;
|
|
UINT i;
|
|
|
|
*RouteInfoChanged = *ForwardingInfoChanged = 0;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Has the preference changed from old to new ?
|
|
//
|
|
|
|
if (PrefChanged)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Are the number and handles to next hops same ?
|
|
//
|
|
|
|
if (OldRouteInfo->NextHopsList.NumNextHops !=
|
|
NewRouteInfo->NextHopsList.NumNextHops)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < OldRouteInfo->NextHopsList.NumNextHops; i++)
|
|
{
|
|
if (OldRouteInfo->NextHopsList.NextHops[i] !=
|
|
NewRouteInfo->NextHopsList.NextHops[i])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i != OldRouteInfo->NextHopsList.NumNextHops)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Have the forwarding flags changed from old ?
|
|
//
|
|
|
|
DiffFlags = OldRouteInfo->Flags ^ NewRouteInfo->Flags;
|
|
|
|
if (DiffFlags & RTM_ROUTE_FLAGS_FORWARDING)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Have non forwarding flags changed from old ?
|
|
//
|
|
|
|
if (DiffFlags)
|
|
{
|
|
*RouteInfoChanged = 1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
while (FALSE);
|
|
|
|
//
|
|
// Forwarding info is a subset of route info
|
|
//
|
|
|
|
*ForwardingInfoChanged = *RouteInfoChanged = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CopyToRoute (
|
|
IN PENTITY_INFO Entity,
|
|
IN PRTM_ROUTE_INFO RouteInfo,
|
|
IN PROUTE_INFO Route
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates an exising route with new route info. Note that
|
|
only the route's owner is allowed to do this.
|
|
|
|
Arguments:
|
|
|
|
Entity - Entity that is updating the existing route,
|
|
|
|
RouteInfo - Route info using which route is being updated,
|
|
|
|
Route - Route that is being updated with above info.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
RTM_NEXTHOP_HANDLE NextHopHandle;
|
|
PRTM_ROUTE_INFO Info;
|
|
PNEXTHOP_INFO NextHop;
|
|
UINT NumNextHops;
|
|
UINT i;
|
|
|
|
Info = &Route->RouteInfo;
|
|
|
|
//
|
|
// Update the route with the new information
|
|
//
|
|
|
|
Info->State = RTM_ROUTE_STATE_CREATED;
|
|
|
|
Info->Flags1 = RouteInfo->Flags1;
|
|
|
|
Info->Flags = RouteInfo->Flags;
|
|
|
|
Info->PrefInfo = RouteInfo->PrefInfo;
|
|
|
|
Info->BelongsToViews = RouteInfo->BelongsToViews;
|
|
|
|
Info->EntitySpecificInfo = RouteInfo->EntitySpecificInfo;
|
|
|
|
//
|
|
// Update the neighbour "learnt from" field
|
|
//
|
|
|
|
if (Info->Neighbour != RouteInfo->Neighbour)
|
|
{
|
|
// Free the previous "neighbour learnt from"
|
|
|
|
if (Info->Neighbour)
|
|
{
|
|
NextHop = NEXTHOP_FROM_HANDLE(Info->Neighbour);
|
|
|
|
DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
// Copy the new neighbour "learnt from" now
|
|
|
|
if (RouteInfo->Neighbour)
|
|
{
|
|
NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
|
|
|
|
REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
|
|
// "Neighbour learnt from" entry is owned by caller
|
|
|
|
ASSERT((NextHop) &&
|
|
(NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
|
|
}
|
|
|
|
Info->Neighbour = RouteInfo->Neighbour;
|
|
}
|
|
|
|
//
|
|
// Count the number of next-hops you can copy
|
|
//
|
|
|
|
NumNextHops = Entity->OwningAddrFamily->MaxNextHopsInRoute;
|
|
|
|
if (NumNextHops > RouteInfo->NextHopsList.NumNextHops)
|
|
{
|
|
NumNextHops = RouteInfo->NextHopsList.NumNextHops;
|
|
}
|
|
|
|
//
|
|
// Reference all next-hops that you will copy
|
|
//
|
|
|
|
for (i = 0; i < NumNextHops; i++)
|
|
{
|
|
NextHopHandle = RouteInfo->NextHopsList.NextHops[i];
|
|
|
|
NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
|
|
|
|
REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Dereference existing next-hops before update
|
|
//
|
|
|
|
for (i = 0; i < Info->NextHopsList.NumNextHops; i++)
|
|
{
|
|
NextHopHandle = Info->NextHopsList.NextHops[i];
|
|
|
|
NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
|
|
|
|
DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Make a copy of the next hops in input list
|
|
//
|
|
|
|
Info->NextHopsList.NumNextHops = (USHORT) NumNextHops;
|
|
|
|
for (i = 0; i < NumNextHops; i++)
|
|
{
|
|
Info->NextHopsList.NextHops[i] = RouteInfo->NextHopsList.NextHops[i];
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
DestroyRoute (
|
|
IN PROUTE_INFO Route
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys the route by freeing resources and
|
|
deallocating it. This function is called when
|
|
reference count on the route drops to 0.
|
|
|
|
Arguments:
|
|
|
|
Route - Pointer to the route being destroyed.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
RTM_NEXTHOP_HANDLE NextHopHandle;
|
|
PRTM_ROUTE_INFO Info;
|
|
PNEXTHOP_INFO NextHop;
|
|
PENTITY_INFO Entity;
|
|
PDEST_INFO Dest;
|
|
UINT i;
|
|
|
|
ASSERT(Route->ObjectHeader.RefCount == 0);
|
|
|
|
Info = &Route->RouteInfo;
|
|
|
|
//
|
|
// Dereference all next-hops before delete
|
|
//
|
|
|
|
for (i = 0; i < Info->NextHopsList.NumNextHops; i++)
|
|
{
|
|
NextHopHandle = Info->NextHopsList.NextHops[i];
|
|
|
|
NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
|
|
|
|
DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Dereference advertising neighbour handle
|
|
//
|
|
|
|
if (Info->Neighbour)
|
|
{
|
|
NextHop = NEXTHOP_FROM_HANDLE(Info->Neighbour);
|
|
|
|
DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Dereference the owning entity handle
|
|
//
|
|
|
|
Entity = ENTITY_FROM_HANDLE(Info->RouteOwner);
|
|
|
|
DEREFERENCE_ENTITY(Entity, ROUTE_REF);
|
|
|
|
|
|
//
|
|
// Dereference the destination for the route
|
|
//
|
|
|
|
if (Info->DestHandle)
|
|
{
|
|
Dest = DEST_FROM_HANDLE(Info->DestHandle);
|
|
|
|
DEREFERENCE_DEST(Dest, ROUTE_REF);
|
|
}
|
|
|
|
//
|
|
// Free the resources allocated for the route
|
|
//
|
|
|
|
#if DBG_HDL
|
|
Route->ObjectHeader.TypeSign = ROUTE_FREED;
|
|
#endif
|
|
|
|
FreeObject(Route);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateNextHop (
|
|
IN PENTITY_INFO Entity,
|
|
IN PRTM_NEXTHOP_INFO NextHopInfo,
|
|
OUT PNEXTHOP_INFO *NewNextHop
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new nexthop info structure and initializes it.
|
|
|
|
Arguments:
|
|
|
|
Entity - Entity creating the new nexthop in table,
|
|
|
|
NextHopInfo - Nexthop info for the nexthop being created,
|
|
|
|
NewNextHop - Pointer to the new nexthop info structure
|
|
will be returned through this parameter.
|
|
|
|
Return Value:
|
|
|
|
Status of the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
PRTM_NEXTHOP_INFO HopInfo;
|
|
PNEXTHOP_INFO NextHop;
|
|
PDEST_INFO Dest;
|
|
|
|
*NewNextHop = NULL;
|
|
|
|
//
|
|
// Allocate and initialize a new next hop info
|
|
//
|
|
|
|
NextHop = (PNEXTHOP_INFO) AllocNZeroObject(sizeof(NEXTHOP_INFO));
|
|
if (NextHop == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
#if DBG_HDL
|
|
NextHop->ObjectHeader.TypeSign = NEXTHOP_ALLOC;
|
|
#endif
|
|
|
|
INITIALIZE_NEXTHOP_REFERENCE(NextHop, CREATION_REF);
|
|
|
|
HopInfo = &NextHop->NextHopInfo;
|
|
|
|
HopInfo->NextHopAddress = NextHopInfo->NextHopAddress;
|
|
|
|
HopInfo->NextHopOwner = MAKE_HANDLE_FROM_POINTER(Entity);
|
|
|
|
HopInfo->InterfaceIndex = NextHopInfo->InterfaceIndex;
|
|
|
|
REFERENCE_ENTITY(Entity, NEXTHOP_REF);
|
|
|
|
HopInfo->State = RTM_NEXTHOP_STATE_CREATED;
|
|
|
|
HopInfo->Flags = NextHopInfo->Flags;
|
|
|
|
HopInfo->EntitySpecificInfo = NextHopInfo->EntitySpecificInfo;
|
|
|
|
HopInfo->RemoteNextHop = NextHopInfo->RemoteNextHop;
|
|
|
|
//
|
|
// Reference the remote nexthop's destination
|
|
//
|
|
|
|
if (HopInfo->RemoteNextHop)
|
|
{
|
|
Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
|
|
|
|
REFERENCE_DEST(Dest, NEXTHOP_REF);
|
|
}
|
|
|
|
//
|
|
// Return a pointer to the new initialized nexthop
|
|
//
|
|
|
|
*NewNextHop = NextHop;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
VOID
|
|
CopyToNextHop (
|
|
IN PENTITY_INFO Entity,
|
|
IN PRTM_NEXTHOP_INFO NextHopInfo,
|
|
IN PNEXTHOP_INFO NextHop
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates an exising nexthop with new nexthop info. Note that
|
|
only the nexthop's owner is allowed to do this.
|
|
|
|
Arguments:
|
|
|
|
Entity - Entity that is updating the existing nexthop,
|
|
|
|
NextHopInfo - Info using which nexthop is being updated,
|
|
|
|
NextHop - Nexthop that is being updated with above info.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PRTM_NEXTHOP_INFO HopInfo;
|
|
PDEST_INFO Dest;
|
|
|
|
UNREFERENCED_PARAMETER(Entity);
|
|
|
|
HopInfo = &NextHop->NextHopInfo;
|
|
|
|
//
|
|
// Update the nexthop with the new information
|
|
//
|
|
|
|
HopInfo->Flags = NextHopInfo->Flags;
|
|
|
|
HopInfo->EntitySpecificInfo = NextHopInfo->EntitySpecificInfo;
|
|
|
|
if (HopInfo->RemoteNextHop != NextHopInfo->RemoteNextHop)
|
|
{
|
|
// Dereference the old next hop and reference new one
|
|
|
|
if (HopInfo->RemoteNextHop)
|
|
{
|
|
Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
|
|
DEREFERENCE_DEST(Dest, NEXTHOP_REF);
|
|
}
|
|
|
|
HopInfo->RemoteNextHop = NextHopInfo->RemoteNextHop;
|
|
|
|
if (HopInfo->RemoteNextHop)
|
|
{
|
|
Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
|
|
REFERENCE_DEST(Dest, NEXTHOP_REF);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DestroyNextHop (
|
|
IN PNEXTHOP_INFO NextHop
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys the nexthop by freeing resources and
|
|
deallocating it. This function is called when
|
|
reference count on the nexthop drops to 0.
|
|
|
|
Arguments:
|
|
|
|
Nexthop - Pointer to the nexthop being destroyed.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PRTM_NEXTHOP_INFO HopInfo;
|
|
PDEST_INFO Dest;
|
|
PENTITY_INFO Entity;
|
|
|
|
|
|
ASSERT(NextHop->ObjectHeader.RefCount == 0);
|
|
|
|
HopInfo = &NextHop->NextHopInfo;
|
|
|
|
//
|
|
// Dereference remote nexthop's destination
|
|
//
|
|
|
|
if (HopInfo->RemoteNextHop)
|
|
{
|
|
Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
|
|
|
|
DEREFERENCE_DEST(Dest, NEXTHOP_REF);
|
|
}
|
|
|
|
Entity = ENTITY_FROM_HANDLE(HopInfo->NextHopOwner);
|
|
|
|
DEREFERENCE_ENTITY(Entity, NEXTHOP_REF);
|
|
|
|
//
|
|
// Free the memory allocated for the next-hop
|
|
//
|
|
|
|
#if DBG_HDL
|
|
NextHop->ObjectHeader.TypeSign = NEXTHOP_FREED;
|
|
#endif
|
|
|
|
FreeObject(NextHop);
|
|
|
|
return NO_ERROR;
|
|
}
|