|
|
/*++
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; }
|