/*++ Copyright (c) 1999, Microsoft Corporation Module Name: sample\rtmapi.c Abstract: The file contains RTMv2 API implementations. --*/ #include "pchsample.h" #pragma hdrstop #ifdef DEBUG DWORD RTM_DisplayDestInfo( IN PRTM_DEST_INFO prdi) /*++ Routine Description Displays an RTM_DEST_INFO object. Locks None Arguments prdi buffer containing the rtm dest info Return Value NO_ERROR always --*/ { IPADDRESS ip; if (!prdi) return NO_ERROR; RTM_GetAddress(&ip, &(prdi->DestAddress)); TRACE2(NETWORK, "RtmDestInfo Destination %s/%u", INET_NTOA(ip), (prdi->DestAddress).NumBits); return NO_ERROR; } #else #define DisplayRtmDestInfo(prdi) #endif // DEBUG DWORD RTM_NextHop ( IN PRTM_DEST_INFO prdiDestination, OUT PDWORD pdwIfIndex, OUT PIPADDRESS pipNeighbor) /*++ Routine Description Obtain the next hop for a destination (typically a data source or an RP). Locks None Arguments prdiDestination destination information obtained from rtm dwIfIndex next hop interface index pipNeighbor ip address of next hop neighbor Return Value NO_ERROR success Error Code o/w --*/ { DWORD dwErr = NO_ERROR; PRTM_ROUTE_INFO prriRoute; RTM_NEXTHOP_INFO rniNextHop; BOOL bRoute, bNextHop; // flags indicating handles held bRoute = bNextHop = FALSE; do // breakout loop { // allocate route info structure MALLOC(&prriRoute, RTM_SIZE_OF_ROUTE_INFO(g_ce.rrpRtmProfile.MaxNextHopsInRoute), &dwErr); if (dwErr != NO_ERROR) break; // get route info (best route in mcast view) dwErr = RtmGetRouteInfo ( g_ce.hRtmHandle, prdiDestination->ViewInfo[0].Route, prriRoute, NULL); if (dwErr != NO_ERROR) { TRACE1(ANY, "Error %u getting route", dwErr); break; } bRoute = TRUE; // get nexthop info (first next hop for now...) dwErr = RtmGetNextHopInfo( g_ce.hRtmHandle, prriRoute->NextHopsList.NextHops[0], &rniNextHop); if (dwErr != NO_ERROR) { TRACE1(ANY, "Error %u getting next hop", dwErr); break; } bNextHop = TRUE; // finally!!! THIS SHOULD NOT BE A REMOTE NEXT HOP!!! *(pdwIfIndex) = rniNextHop.InterfaceIndex; RTM_GetAddress(pipNeighbor, &(rniNextHop.NextHopAddress)); } while (FALSE); if (dwErr != NO_ERROR) TRACE1(ANY, "Error %u obtaining next hop", dwErr); // release the handle to the next hop if (bNextHop) { if (RtmReleaseNextHopInfo(g_ce.hRtmHandle, &rniNextHop) != NO_ERROR) TRACE0(ANY, "Error releasing next hop, continuing..."); } // release the handle to the route if (bRoute) { if (RtmReleaseRouteInfo(g_ce.hRtmHandle, prriRoute) != NO_ERROR) TRACE0(ANY, "Error releasing route, continuing..."); } // deallocate route info structure if (prriRoute) FREE(prriRoute); return dwErr; } //////////////////////////////////////// // CALLBACKFUNCTIONS //////////////////////////////////////// DWORD APIENTRY RTM_CallbackEvent ( IN RTM_ENTITY_HANDLE hRtmHandle, // registration handle IN RTM_EVENT_TYPE retEvent, IN PVOID pvContext1, IN PVOID pvContext2) /*++ Routine Description Processes an RTMv2 event. Used to inform entities of new entities registering, entities deregistering, route expiration, route changes. Locks None (for now) Arguments retEvent rtmv2 event type Return Value NO_ERROR success Error Code o/w --*/ { DWORD dwErr = NO_ERROR; TRACE1(ENTER, "Entering RTM_CallbackEvent: %u", retEvent); do // breakout loop { UNREFERENCED_PARAMETER(hRtmHandle); UNREFERENCED_PARAMETER(pvContext1); UNREFERENCED_PARAMETER(pvContext2); // only route change notifications are processed if (retEvent != RTM_CHANGE_NOTIFICATION) { dwErr = ERROR_NOT_SUPPORTED; break; } dwErr = NM_ProcessRouteChange(); } while (FALSE); TRACE0(LEAVE, "Leaving RTM_CallbackEvent"); return dwErr; }