207 lines
4.6 KiB
C
207 lines
4.6 KiB
C
/*++
|
|
|
|
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;
|
|
}
|