/*++ Copyright (c) 1997 - 98, Microsoft Corporation Module Name: rtminfo.c Abstract: Contains routines for getting information on various objects pointed to by handles. Author: Chaitanya Kodeboyina (chaitk) 22-Aug-1998 Revision History: --*/ #include "pchrtm.h" #pragma hdrstop DWORD WINAPI RtmGetEntityInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ENTITY_HANDLE EntityHandle, OUT PRTM_ENTITY_INFO EntityInfo ) /*++ Routine Description: Retrieves information pertaining to a registered entity. Arguments: RtmRegHandle - RTM registration handle for calling entity, EntityHandle - RTM handle for entity whose info we want, EntityInfo - Block in which the entity info is returned. Return Value: Status of the operation --*/ { PADDRFAM_INFO AddrFamilyInfo; PENTITY_INFO Entity; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_ENTITY_HANDLE(EntityHandle, &Entity); // // Copy the entity information to output buffer // AddrFamilyInfo = Entity->OwningAddrFamily; EntityInfo->RtmInstanceId = AddrFamilyInfo->Instance->RtmInstanceId; EntityInfo->AddressFamily = AddrFamilyInfo->AddressFamily; EntityInfo->EntityId = Entity->EntityId; return NO_ERROR; } DWORD WINAPI RtmGetDestInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_DEST_HANDLE DestHandle, IN ULONG ProtocolId, IN RTM_VIEW_SET TargetViews, OUT PRTM_DEST_INFO DestInfo ) /*++ Routine Description: Retrieves information for a destination in the route table Arguments: RtmRegHandle - RTM registration handle for calling entity, DestHandle - RTM handle for dest whose info we want, ProtocolId - Protocol whose best route info is retd, TargetViews - Views in which best route info is retd, DestInfo - Block in which the dest info is returned. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PDEST_INFO Dest; VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); // VALIDATE_DEST_HANDLE(DestHandle, &Dest); Dest = DEST_FROM_HANDLE(DestHandle); if (!Dest) { return ERROR_INVALID_HANDLE; } ACQUIRE_DEST_READ_LOCK(Dest); GetDestInfo(Entity, Dest, ProtocolId, TargetViews, DestInfo); RELEASE_DEST_READ_LOCK(Dest); return NO_ERROR; } VOID GetDestInfo ( IN PENTITY_INFO Entity, IN PDEST_INFO Dest, IN ULONG ProtocolId, IN RTM_VIEW_SET TargetViews, OUT PRTM_DEST_INFO DestInfo ) /*++ Routine Description: Retrieves information for a destination in the route table Arguments: Entity - RTM registration info for calling entity, Dest - Pointer to the dest whose info we want, ProtocolId - Protocol whose best route info is retd, TargetViews - Views in which best route info is retd, DestInfo - Block in which the dest info is returned. Return Value: None --*/ { PENTITY_INFO Owner; PROUTE_INFO Route; RTM_VIEW_SET ViewsSeen; RTM_VIEW_SET ViewSet; RTM_VIEW_SET BelongsToViews; PLIST_ENTRY p; UINT i, j, k; // Limit caller's interest to set of views supported TargetViews &= Entity->OwningAddrFamily->ViewsSupported; // // Copy dest info to output and ref handles given out // DestInfo->DestHandle = MAKE_HANDLE_FROM_POINTER(Dest); REFERENCE_DEST(Dest, HANDLE_REF); CopyMemory(&DestInfo->DestAddress, &Dest->DestAddress, sizeof(RTM_NET_ADDRESS)); DestInfo->LastChanged = Dest->LastChanged; DestInfo->BelongsToViews = Dest->BelongsToViews; // // Copy the holddown route out in all requested views // ViewSet = TargetViews; for (i = j = 0; ViewSet && (i < RTM_VIEW_MASK_SIZE); i++) { if (ViewSet & 0x01) { k = Entity->OwningAddrFamily->ViewIndexFromId[i]; Route = Dest->ViewInfo[k].HoldRoute; // // Init view info and fill the holddown route // ZeroMemory(&DestInfo->ViewInfo[j], sizeof(DestInfo->ViewInfo[0])); DestInfo->ViewInfo[j].ViewId = i; if (Route) { DestInfo->ViewInfo[j].HoldRoute = MAKE_HANDLE_FROM_POINTER(Route); REFERENCE_ROUTE(Route, HANDLE_REF); } j++; } ViewSet >>= 1; } // Keep track of total number of view info slots filled in DestInfo->NumberOfViews = j; // // Fill up information in all the views he is interested in // if (TargetViews & Dest->BelongsToViews) { // Resolve the protocol id if it is RTM_THIS_PROTOCOL if (ProtocolId == RTM_THIS_PROTOCOL) { ProtocolId = Entity->EntityId.EntityProtocolId; } ViewsSeen = 0; // // Copy best route in each view & ref handles given out // for (p = Dest->RouteList.Flink; p != &Dest->RouteList; p = p->Flink) { Route = CONTAINING_RECORD(p, ROUTE_INFO, DestLE); // // Make sure that this agrees with our protocol id // Owner = ENTITY_FROM_HANDLE(Route->RouteInfo.RouteOwner); if (ProtocolId != RTM_BEST_PROTOCOL) { if (Owner->EntityId.EntityProtocolId != ProtocolId) { continue; } } // // Does this route belong to any interested views // if ((TargetViews & Route->RouteInfo.BelongsToViews) == 0) { continue; } // // Update dest info in each view that route belongs to // BelongsToViews = Route->RouteInfo.BelongsToViews; ViewSet = TargetViews; for (i = j = 0; ViewSet && (i < RTM_VIEW_MASK_SIZE); i++) { if (ViewSet & 0x01) { if (BelongsToViews & 0x01) { // // Increment number of routes in this view // DestInfo->ViewInfo[j].NumRoutes++; // // If you not already seen this view (in // other words got the best route in it) // update the DestInfo for this view now // if (!(ViewsSeen & VIEW_MASK(i))) { DestInfo->ViewInfo[j].Route = MAKE_HANDLE_FROM_POINTER(Route); REFERENCE_ROUTE(Route, HANDLE_REF); DestInfo->ViewInfo[j].Owner = MAKE_HANDLE_FROM_POINTER(Owner); REFERENCE_ENTITY(Owner, HANDLE_REF); DestInfo->ViewInfo[j].DestFlags = Route->RouteInfo.Flags; } } j++; } ViewSet >>= 1; BelongsToViews >>= 1; } ViewsSeen |= Route->RouteInfo.BelongsToViews; } } return; } DWORD WINAPI RtmGetRouteInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_ROUTE_HANDLE RouteHandle, OUT PRTM_ROUTE_INFO RouteInfo OPTIONAL, OUT PRTM_NET_ADDRESS DestAddress OPTIONAL ) /*++ Routine Description: Retrieves information for a route in the route table Arguments: RtmRegHandle - RTM registration handle for calling entity, RouteHandle - RTM handle for route whose info we want, RouteInfo - Block in which the route info is returned. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PROUTE_INFO Route; PDEST_INFO Dest; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); #if 1 Route = ROUTE_FROM_HANDLE(RouteHandle); if (!Route) { return ERROR_INVALID_HANDLE; } #else VALIDATE_ROUTE_HANDLE(RouteHandle, &Route); #endif Dest = DEST_FROM_HANDLE(Route->RouteInfo.DestHandle); // Get a consitent picture of the route ACQUIRE_DEST_READ_LOCK(Dest); if (ARGUMENT_PRESENT(RouteInfo)) { GetRouteInfo(Dest, Route, RouteInfo); } RELEASE_DEST_READ_LOCK(Dest); // No lock reqd - dest addr is constant if (ARGUMENT_PRESENT(DestAddress)) { CopyMemory(DestAddress, &Dest->DestAddress, sizeof(RTM_NET_ADDRESS)); } return NO_ERROR; } VOID WINAPI GetRouteInfo ( IN PDEST_INFO Dest, IN PROUTE_INFO Route, OUT PRTM_ROUTE_INFO RouteInfo ) /*++ Routine Description: Retrieves information for a route in the route table Arguments: Dest - Pointer to the destination of the route, Route - Pointer to the route whose info we want, RouteInfo - Block in which the route info is returned. Return Value: None --*/ { PENTITY_INFO Entity; PNEXTHOP_INFO Neighbour; PNEXTHOP_INFO NextHop; UINT NumBytes; UINT i; // // Copy the route information to output buffer // NumBytes = sizeof(RTM_ROUTE_INFO) + sizeof(RTM_NEXTHOP_HANDLE) * (Route->RouteInfo.NextHopsList.NumNextHops - 1); CopyMemory(RouteInfo, &Route->RouteInfo, NumBytes); // // Reference handles that are given out in info // Entity = ENTITY_FROM_HANDLE(RouteInfo->RouteOwner); REFERENCE_ENTITY(Entity, HANDLE_REF); if (RouteInfo->Neighbour) { Neighbour = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour); REFERENCE_NEXTHOP(Neighbour, HANDLE_REF); } for (i = 0; i < RouteInfo->NextHopsList.NumNextHops; i++) { NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->NextHopsList.NextHops[i]); REFERENCE_NEXTHOP(NextHop, HANDLE_REF); } REFERENCE_DEST(Dest, HANDLE_REF); return; } DWORD WINAPI RtmGetNextHopInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN RTM_NEXTHOP_HANDLE NextHopHandle, OUT PRTM_NEXTHOP_INFO NextHopInfo ) /*++ Routine Description: Retrieves information for a next-hop in the route table Arguments: RtmRegHandle - RTM registration handle for calling entity, NextHopHandle - RTM handle for next-hop whose info we want, NextHopInfo - Block in which the next-hop info is returned. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PNEXTHOP_INFO NextHop; PDEST_INFO Dest; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); VALIDATE_NEXTHOP_HANDLE(NextHopHandle, &NextHop); Entity = ENTITY_FROM_HANDLE(NextHop->NextHopInfo.NextHopOwner); ACQUIRE_NHOP_TABLE_READ_LOCK(Entity); // // Copy the next-hop information to output buffer // CopyMemory(NextHopInfo, &NextHop->NextHopInfo, sizeof(RTM_NEXTHOP_INFO)); // // Reference handles that are given out in info // if (NextHop->NextHopInfo.RemoteNextHop) { Dest = DEST_FROM_HANDLE(NextHop->NextHopInfo.RemoteNextHop); REFERENCE_DEST(Dest, HANDLE_REF); } REFERENCE_ENTITY(Entity, HANDLE_REF); RELEASE_NHOP_TABLE_READ_LOCK(Entity); return NO_ERROR; } DWORD WINAPI RtmReleaseEntityInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN PRTM_ENTITY_INFO EntityInfo ) /*++ Routine Description: Releases all handles present in the input info structure Arguments: RtmRegHandle - RTM registration handle for calling entity, EntityInfo - All handles in this info are de-referenced. Return Value: Status of the operation --*/ { UNREFERENCED_PARAMETER(RtmRegHandle); UNREFERENCED_PARAMETER(EntityInfo); return NO_ERROR; } DWORD WINAPI RtmReleaseDestInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN PRTM_DEST_INFO DestInfo ) /*++ Routine Description: Releases all handles present in the input info structure Arguments: RtmRegHandle - RTM registration handle for calling entity, DestInfo - All handles in this info are de-referenced. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PENTITY_INFO Owner; PDEST_INFO Dest; PROUTE_INFO Route; UINT i; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); for (i = 0; i < DestInfo->NumberOfViews; i++) { // // If a best route, dereference it and its owner // if (DestInfo->ViewInfo[i].Route) { Route = ROUTE_FROM_HANDLE(DestInfo->ViewInfo[i].Route); DEREFERENCE_ROUTE(Route, HANDLE_REF); Owner = ENTITY_FROM_HANDLE(DestInfo->ViewInfo[i].Owner); DEREFERENCE_ENTITY(Owner, HANDLE_REF); } // // If we have a holddown route, dereference it // if (DestInfo->ViewInfo[i].HoldRoute) { Route = ROUTE_FROM_HANDLE(DestInfo->ViewInfo[i].HoldRoute); DEREFERENCE_ROUTE(Route, HANDLE_REF); } } Dest = DEST_FROM_HANDLE(DestInfo->DestHandle); DEREFERENCE_DEST(Dest, HANDLE_REF); return NO_ERROR; } DWORD WINAPI RtmReleaseRouteInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN PRTM_ROUTE_INFO RouteInfo ) /*++ Routine Description: Releases all handles present in the input info structure Arguments: RtmRegHandle - RTM registration handle for calling entity, RouteInfo - All handles in this info are de-referenced. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PDEST_INFO Dest; PNEXTHOP_INFO Neighbour; PNEXTHOP_INFO NextHop; UINT i; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); for (i = 0; i < RouteInfo->NextHopsList.NumNextHops; i++) { NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->NextHopsList.NextHops[i]); DEREFERENCE_NEXTHOP(NextHop, HANDLE_REF); } if (RouteInfo->Neighbour) { Neighbour = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour); DEREFERENCE_NEXTHOP(Neighbour, HANDLE_REF); } Entity = ENTITY_FROM_HANDLE(RouteInfo->RouteOwner); DEREFERENCE_ENTITY(Entity, HANDLE_REF); Dest = DEST_FROM_HANDLE(RouteInfo->DestHandle); DEREFERENCE_DEST(Dest, HANDLE_REF); return NO_ERROR; } DWORD WINAPI RtmReleaseNextHopInfo ( IN RTM_ENTITY_HANDLE RtmRegHandle, IN PRTM_NEXTHOP_INFO NextHopInfo ) /*++ Routine Description: Releases all handles present in the input info structure Arguments: RtmRegHandle - RTM registration handle for calling entity, NextHopInfo - All handles in this info are de-referenced. Return Value: Status of the operation --*/ { PENTITY_INFO Entity; PDEST_INFO Dest; DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity); if (NextHopInfo->RemoteNextHop) { Dest = DEST_FROM_HANDLE(NextHopInfo->RemoteNextHop); if (Dest) { DEREFERENCE_DEST(Dest, HANDLE_REF); } } Entity = ENTITY_FROM_HANDLE(NextHopInfo->NextHopOwner); DEREFERENCE_ENTITY(Entity, HANDLE_REF); return NO_ERROR; }