1108 lines
28 KiB
C
1108 lines
28 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999, Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
sample\rmapi.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
The file contains IP router manager API implementations.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pchsample.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
StartProtocol (
|
||
|
IN HANDLE NotificationEvent,
|
||
|
IN PSUPPORT_FUNCTIONS SupportFunctions,
|
||
|
IN LPVOID GlobalInfo,
|
||
|
IN ULONG StructureVersion,
|
||
|
IN ULONG StructureSize,
|
||
|
IN ULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
After the protocol has been registered, the IP Router Manager calls
|
||
|
this function to tell the protocol to start. Most of the startup code
|
||
|
is executed here.
|
||
|
|
||
|
Arguments
|
||
|
NotificationEvent Event to Set if the IP Router Manager needs to
|
||
|
be notified to take any action on our behalf
|
||
|
SupportFunctions Some functions exported by IP Router Manager
|
||
|
GlobalInfo Our global configuration which was setup by our
|
||
|
setup/admin DLL
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE3(ENTER, "Entering StartProtocol 0x%08x 0x%08x 0x%08x",
|
||
|
NotificationEvent, SupportFunctions, GlobalInfo);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if (!NotificationEvent or
|
||
|
!SupportFunctions or
|
||
|
!GlobalInfo)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = CM_StartProtocol(NotificationEvent,
|
||
|
SupportFunctions,
|
||
|
GlobalInfo);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving StartProtocol: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
StartComplete (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
TRACE0(ENTER, "Entering StartComplete");
|
||
|
TRACE0(LEAVE, "Leaving StartComplete");
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
StopProtocol (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called by the IP Router Manager to tell the protocol
|
||
|
to stop. We set the protocol state to IPSAMPLE_STATUS_STOPPING to
|
||
|
prevent us from servicing any more requests and wait for all pending
|
||
|
threads to finish. Meanwhile we return PENDING to the IP Router
|
||
|
Manager.
|
||
|
|
||
|
Arguments
|
||
|
None
|
||
|
|
||
|
Return Value
|
||
|
ERROR_PROTOCOL_STOP_PENDING Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE0(ENTER, "Entering StopProtocol");
|
||
|
|
||
|
dwErr = CM_StopProtocol();
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving StopProtocol: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
GetGlobalInfo (
|
||
|
IN PVOID GlobalInfo,
|
||
|
IN OUT PULONG BufferSize,
|
||
|
OUT PULONG StructureVersion,
|
||
|
OUT PULONG StructureSize,
|
||
|
OUT PULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
The function is called by the IP Router Manager, usually because of a
|
||
|
query by the admin utility. We see if we have space enough to return
|
||
|
our global config. If we do, we return it, otherwise we return the size
|
||
|
needed.
|
||
|
|
||
|
Arguments
|
||
|
GlobalInfo Pointer to allocated buffer to store our config
|
||
|
BufferSize Size of config.
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
ERROR_INSUFFICIENT_BUFFER If the size of the buffer is too small
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE2(ENTER, "Entering GetGlobalInfo: 0x%08x 0x%08x",
|
||
|
GlobalInfo, BufferSize);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if (!BufferSize)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = CM_GetGlobalInfo(GlobalInfo,
|
||
|
BufferSize,
|
||
|
StructureVersion,
|
||
|
StructureSize,
|
||
|
StructureCount);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving GetGlobalInfo: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
SetGlobalInfo (
|
||
|
IN PVOID GlobalInfo,
|
||
|
IN ULONG StructureVersion,
|
||
|
IN ULONG StructureSize,
|
||
|
IN ULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Called by the IP Router Manager usually in response to an admin utility
|
||
|
changing the global config. We verify the info and set it.
|
||
|
|
||
|
Arguments
|
||
|
GlobalInfo Our globals configuration
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE1(ENTER, "Entering SetGlobalInfo: 0x%08x", GlobalInfo);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if (!GlobalInfo)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = CM_SetGlobalInfo(GlobalInfo);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving SetGlobalInfo: %u", dwErr);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
AddInterface (
|
||
|
IN LPWSTR InterfaceName,
|
||
|
IN ULONG InterfaceIndex,
|
||
|
IN NET_INTERFACE_TYPE InterfaceType,
|
||
|
IN DWORD MediaType,
|
||
|
IN WORD AccessType,
|
||
|
IN WORD ConnectionType,
|
||
|
IN PVOID InterfaceInfo,
|
||
|
IN ULONG StructureVersion,
|
||
|
IN ULONG StructureSize,
|
||
|
IN ULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Called by the ip router manager to add an interface when it finds our
|
||
|
information block within the interface's configuration. We verify the
|
||
|
information and create an entry for the interface in our interface
|
||
|
table. Then we see all the configured addresses for the interface and
|
||
|
create a binding structure for each address The interface comes up as
|
||
|
UNBOUND-DISABLED (INACTIVE).
|
||
|
|
||
|
Arguments
|
||
|
InterfaceName The name of the interface, used for logging.
|
||
|
InterfaceIndex The positive integer used to refer to this interface.
|
||
|
AccessType Access type of the interface
|
||
|
InterfaceInfo Our config for this interface
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE4(ENTER, "Entering AddInterface: %S %u %u 0x%08x",
|
||
|
InterfaceName, InterfaceIndex, AccessType, InterfaceInfo);
|
||
|
|
||
|
// interface properties unused for now
|
||
|
UNREFERENCED_PARAMETER(InterfaceType);
|
||
|
UNREFERENCED_PARAMETER(MediaType);
|
||
|
UNREFERENCED_PARAMETER(ConnectionType);
|
||
|
|
||
|
if (AccessType != IF_ACCESS_POINTTOPOINT)
|
||
|
AccessType = IF_ACCESS_BROADCAST;
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if ((wcslen(InterfaceName) is 0) or
|
||
|
!((AccessType is IF_ACCESS_BROADCAST) or
|
||
|
(AccessType is IF_ACCESS_POINTTOPOINT)) or
|
||
|
!InterfaceInfo)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = NM_AddInterface(InterfaceName,
|
||
|
InterfaceIndex,
|
||
|
AccessType,
|
||
|
InterfaceInfo);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving AddInterface: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
DeleteInterface (
|
||
|
IN ULONG InterfaceIndex
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Called by the ip router manager to delete an interface and free its
|
||
|
resources. If the interface is ACTIVE we shut it down.
|
||
|
|
||
|
Arguments
|
||
|
InterfaceIndex The index of the interface to be deleted
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE1(ENTER, "Entering DeleteInterface: %u", InterfaceIndex);
|
||
|
|
||
|
dwErr = NM_DeleteInterface(InterfaceIndex);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving DeleteInterface: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
InterfaceStatus (
|
||
|
IN ULONG InterfaceIndex,
|
||
|
IN BOOL InterfaceActive,
|
||
|
IN DWORD StatusType,
|
||
|
IN PVOID StatusInfo
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
|
||
|
Called by ip router manager to bind/unbind/activate/deactivate interfaces.
|
||
|
|
||
|
BIND (
|
||
|
(StatusType is RIS_INTERFACE_ADDRESS_CHANGE) and
|
||
|
(((PIP_ADAPTER_BINDING_INFO) StatusInfo)->AddressCount > 0)
|
||
|
)
|
||
|
|
||
|
Called by the ip router manager once it learns the address(es) on an
|
||
|
interface. This may happen as soon as the router starts (after the
|
||
|
interface is added, of course) when the interface has a static address
|
||
|
or may happen when an interface acquires a DHCP address or may happen
|
||
|
when IPCP acquires the address for a dial up link. The binding may
|
||
|
consist of one or more addresses.
|
||
|
|
||
|
UNBIND (
|
||
|
(StatusType is RIS_INTERFACE_ADDRESS_CHANGE) and
|
||
|
(((PIP_ADAPTER_BINDING_INFO) StatusInfo)->AddressCount is 0)
|
||
|
)
|
||
|
|
||
|
Called when the interface loses its ip Address(es). This may happen
|
||
|
when the interface is shutting down. It may be because an admin
|
||
|
disabled IP on the interface (as opposed to just disabling the protocol
|
||
|
on the interface). It can happen when the admin releases a DHCP
|
||
|
acquired interface or when a dial up link disconnects.
|
||
|
|
||
|
ENABLED (RIS_INTERFACE_ENABLED)
|
||
|
|
||
|
Called to enable the interface after it has been added or when the
|
||
|
interface is being reenabled after being disabled by the admin. The
|
||
|
bindings on an interface are kept across Enable-Disable.
|
||
|
|
||
|
DISABLED (RIS_INTERFACE_DISABLED)
|
||
|
|
||
|
Called to disable an interface. This is usually in response to an
|
||
|
admin setting the AdminStatus in IP to DOWN. This is different from an
|
||
|
admin trying to disable an interface by setting a flag in our interface
|
||
|
config because that is opaque to IP. That is a routing protocol
|
||
|
specific disable and is conveyed to us via SetInterfaceConfig() calls.
|
||
|
THIS IS AN IMPORTANT DISTINCTION. A ROUTING PROTOCOL NEEDS TO MANTAIN
|
||
|
TWO STATES - AN NT STATE AND A PROTOCOL SPECIFIC STATE.
|
||
|
|
||
|
INTERFACE ACTIVE
|
||
|
|
||
|
This flag is used to activate the protocol over the interface
|
||
|
independent of whether the interface has been bound or enabled.
|
||
|
An unnumbered interface will not have a binding even when activated.
|
||
|
|
||
|
Arguments
|
||
|
InterfaceIndex The index of the interface in question
|
||
|
InterfaceActive Whether the interface can send and receive data
|
||
|
StatusType RIS_INTERFACE_[ADDRESS_CHANGED|ENABLED|DISABLED]
|
||
|
SattusInfo Pointer to IP_ADAPTER_BINDING_INFO containing info
|
||
|
about the addresses on the interface
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE4(ENTER, "Entering InterfaceStatus: %u %u %u 0x%08x",
|
||
|
InterfaceIndex, InterfaceActive, StatusType, StatusInfo);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
dwErr = NM_InterfaceStatus(InterfaceIndex,
|
||
|
InterfaceActive,
|
||
|
StatusType,
|
||
|
StatusInfo);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving InterfaceStatus: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
GetInterfaceConfigInfo (
|
||
|
IN ULONG InterfaceIndex,
|
||
|
IN PVOID InterfaceInfo,
|
||
|
IN OUT PULONG BufferSize,
|
||
|
OUT PULONG StructureVersion,
|
||
|
OUT PULONG StructureSize,
|
||
|
OUT PULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Called by the IP Router Manager to retrieve an interface's
|
||
|
configuration. Usually this is because an admin utility is displaying
|
||
|
this information. The Router Manager calls us with a NULL config and
|
||
|
ZERO size. We return the required size to it. It then allocates the
|
||
|
needed memory and calls us a second time with a valid buffer. We
|
||
|
validate parameters each time and copy out our config if we can.
|
||
|
|
||
|
Arguments
|
||
|
InterfaceIndex Index of the interface being queried
|
||
|
InterfaceInfo Pointer to buffer to store the config
|
||
|
BufferSize Size of the buffer
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE3(ENTER, "Entering GetInterfaceConfigInfo: %u 0x%08x 0x%08x",
|
||
|
InterfaceIndex, InterfaceInfo, BufferSize);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if(BufferSize is NULL)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = NM_GetInterfaceInfo(InterfaceIndex,
|
||
|
InterfaceInfo,
|
||
|
BufferSize,
|
||
|
StructureVersion,
|
||
|
StructureSize,
|
||
|
StructureCount);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving GetInterfaceConfigInfo: %u",
|
||
|
dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
SetInterfaceConfigInfo (
|
||
|
IN ULONG InterfaceIndex,
|
||
|
IN PVOID InterfaceInfo,
|
||
|
IN ULONG StructureVersion,
|
||
|
IN ULONG StructureSize,
|
||
|
IN ULONG StructureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Called by the IP Router Manager to set an interface's configuration.
|
||
|
Usually this is because an admin utility modified this information.
|
||
|
After validating parameters we update our config if we can.
|
||
|
|
||
|
Arguments
|
||
|
InterfaceIndex Index of the interface being updated
|
||
|
InterfaceInfo Buffer with our updated configuration
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE2(ENTER, "Entering SetInterfaceConfigInfo: %u 0x%08x",
|
||
|
InterfaceIndex, InterfaceInfo);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if(InterfaceInfo is NULL)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = NM_SetInterfaceInfo(InterfaceIndex, InterfaceInfo);
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving SetInterfaceConfigInfo: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
GetEventMessage (
|
||
|
OUT ROUTING_PROTOCOL_EVENTS *Event,
|
||
|
OUT MESSAGE *Result
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This is called by the IP Router Manager if we indicate that we have a
|
||
|
message in our queue to be delivered to it (by setting the
|
||
|
g_ce.hMgrNotificationEvent)
|
||
|
|
||
|
Arguments
|
||
|
Event Routing Protocol Event Type
|
||
|
Result Message associated with the event
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE2(ENTER, "Entering GetEventMessage: 0x%08x 0x%08x",
|
||
|
Event, Result);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if (!Event or !Result)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = CM_GetEventMessage(Event, Result);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving GetEventMessage: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
DoUpdateRoutes (
|
||
|
IN ULONG InterfaceIndex
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called by the IP Router Manger to ask us to update
|
||
|
routes over a Demand Dial link. The link has already been brought up
|
||
|
so should be in ENABLED-BOUND state. After we are done we need to set
|
||
|
the g_ce.hMgrNotificationEvent to inform the Router Manager that we
|
||
|
have a message in our queue to be delivered to it. The Router Manager
|
||
|
will call our GetEventMessage() function in which we will inform it
|
||
|
that we are done with update routes (and the routes have been stored in
|
||
|
RTMv2). The Router Manager will "freeze" these routes by converting
|
||
|
them to AUTOSTATIC.
|
||
|
|
||
|
Arguments
|
||
|
InterfaceIndex Interface index on which to do the update
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR Success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE1(ENTER, "Entering DoUpdateRoutes: %u", InterfaceIndex);
|
||
|
|
||
|
dwErr = NM_DoUpdateRoutes(InterfaceIndex);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving DoUpdateRoutes: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibCreate (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function does nothing, since IPSAMPLE does not support creation of
|
||
|
interface objects via SNMP. However, this could be implemented as a
|
||
|
sequence of calls to NM_AddInterface(), IE_BindInterface() and
|
||
|
IE_EnableInterface. The input data would then have to contain the
|
||
|
interface's index, configuration, and binding.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, some struct defined in ipsamplerm.h
|
||
|
InputDataSize Size of the input
|
||
|
|
||
|
Return Value
|
||
|
ERROR_CAN_NOT_COMPLETE for now
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
|
|
||
|
TRACE2(ENTER, "Entering MibCreate: %u 0x%08x",
|
||
|
InputDataSize, InputData);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibCreate: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibDelete (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function does nothing, since IPSAMPLE does not support deletion of
|
||
|
interface objects via SNMP. However, this could be implemented as a
|
||
|
call to NM_DeleteInterface(). The input data would then have to
|
||
|
contain the interface's index.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, some struct defined in ipsamplerm.h
|
||
|
InputDataSize Size of the input
|
||
|
|
||
|
Return Value
|
||
|
ERROR_CAN_NOT_COMPLETE for now
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
|
|
||
|
TRACE2(ENTER, "Entering MibDelete: %u 0x%08x",
|
||
|
InputDataSize, InputData);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibDelete: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibSet (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function sets IPSAMPLE's global or interface configuration.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, struct IPSAMPLE_MIB_SET_INPUT_DATA
|
||
|
InputDataSize Size of the input
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE2(ENTER, "Entering MibSet: %u 0x%08x",
|
||
|
InputDataSize, InputData);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if ((!InputData) or
|
||
|
(InputDataSize < sizeof(IPSAMPLE_MIB_SET_INPUT_DATA)))
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = MM_MibSet((PIPSAMPLE_MIB_SET_INPUT_DATA) InputData);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibSet: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibGet (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData,
|
||
|
IN OUT PULONG OutputDataSize,
|
||
|
OUT PVOID OutputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function retrieves one of...
|
||
|
. global configuration
|
||
|
. interface configuration
|
||
|
. global stats
|
||
|
. interface stats
|
||
|
. interface binding
|
||
|
|
||
|
Called by an admin (SNMP) utility. It actually passes through the IP
|
||
|
Router Manager, but all that does is demux the call to the desired
|
||
|
routing protocol.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
|
||
|
InputDataSize Size of the input
|
||
|
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
|
||
|
OutputDataSize IN size of output buffer received
|
||
|
OUT size of output buffer required
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE4(ENTER, "Entering MibGet: %u 0x%08x 0x%08x 0x%08x",
|
||
|
InputDataSize, InputData, OutputDataSize, OutputData);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if ((!InputData) or
|
||
|
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
|
||
|
(!OutputDataSize))
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
|
||
|
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
|
||
|
OutputDataSize,
|
||
|
GET_EXACT);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibGet: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibGetFirst (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData,
|
||
|
IN OUT PULONG OutputDataSize,
|
||
|
OUT PVOID OutputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function retrieves one of...
|
||
|
. global configuration
|
||
|
. interface configuration
|
||
|
. global stats
|
||
|
. interface stats
|
||
|
. interface binding
|
||
|
|
||
|
It differs from MibGet() in that it always returns the FIRST entry in
|
||
|
whichever table is being queried. There is only one entry in the
|
||
|
global configuration and global stats tables, but the interface
|
||
|
configuration, interface stats, and interface binding tables are sorted
|
||
|
by IP address; this function returns the first entry from these.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
|
||
|
InputDataSize Size of the input
|
||
|
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
|
||
|
OutputDataSize IN size of output buffer received
|
||
|
OUT size of output buffer required
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE4(ENTER, "Entering MibGetFirst: %u 0x%08x 0x%08x 0x%08x",
|
||
|
InputDataSize, InputData, OutputDataSize, OutputData);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if ((!InputData) or
|
||
|
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
|
||
|
(!OutputDataSize))
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
|
||
|
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
|
||
|
OutputDataSize,
|
||
|
GET_FIRST);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibGetFirst: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibGetNext (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData,
|
||
|
IN OUT PULONG OutputDataSize,
|
||
|
OUT PVOID OutputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function retrieves one of...
|
||
|
. global configuration
|
||
|
. interface configuration
|
||
|
. global stats
|
||
|
. interface stats
|
||
|
. interface binding
|
||
|
|
||
|
It differs from both MibGet() and MibGetFirst() in that it returns the
|
||
|
entry AFTER the one specified in the indicated table. Thus, in the
|
||
|
interface configuration, interface stats, and interface binding tables,
|
||
|
this function supplies the entry after the one with the input address.
|
||
|
|
||
|
If there are no more entries in the table being queried we return
|
||
|
ERROR_NO_MORE_ITEMS. Unlike SNMP we don't walk to the next table.
|
||
|
This does not take away any functionality since the NT SNMP agent
|
||
|
will try the next variable (having ID one greater than the ID passed
|
||
|
in) automatically on getting this error.
|
||
|
|
||
|
Arguments
|
||
|
InputData Relevant input, struct IPSAMPLE_MIB_GET_INPUT_DATA
|
||
|
InputDataSize Size of the input
|
||
|
OutputData Buffer for struct IPSAMPLE_MIB_GET_OUTPUT_DATA
|
||
|
OutputDataSize IN size of output buffer received
|
||
|
OUT size of output buffer required
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE4(ENTER, "Entering MibGetFirst: %u 0x%08x 0x%08x 0x%08x",
|
||
|
InputDataSize, InputData, OutputDataSize, OutputData);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// validate parameters
|
||
|
if ((!InputData) or
|
||
|
(InputDataSize < sizeof(IPSAMPLE_MIB_GET_INPUT_DATA)) or
|
||
|
(!OutputDataSize))
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = MM_MibGet((PIPSAMPLE_MIB_GET_INPUT_DATA) InputData,
|
||
|
(PIPSAMPLE_MIB_GET_OUTPUT_DATA) OutputData,
|
||
|
OutputDataSize,
|
||
|
GET_NEXT);
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving MibGetNext: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibSetTrapInfo (
|
||
|
IN HANDLE Event,
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData,
|
||
|
OUT PULONG OutputDataSize,
|
||
|
OUT PVOID OutputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function does nothing at the moment...
|
||
|
|
||
|
Return Value
|
||
|
ERROR_CAN_NOT_COMPLETE for now
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
|
|
||
|
TRACE0(ENTER, "Entering MibSetTrapInfo");
|
||
|
TRACE1(LEAVE, "Leaving MibSetTrapInfo: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
WINAPI
|
||
|
MibGetTrapInfo (
|
||
|
IN ULONG InputDataSize,
|
||
|
IN PVOID InputData,
|
||
|
OUT PULONG OutputDataSize,
|
||
|
OUT PVOID OutputData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function does nothing at the moment...
|
||
|
|
||
|
Return Value
|
||
|
ERROR_CAN_NOT_COMPLETE for now
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
|
|
||
|
TRACE0(ENTER, "Entering MibGetTrapInfo");
|
||
|
TRACE1(LEAVE, "Leaving MibGetTrapInfo: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function: RegisterProtocol
|
||
|
//
|
||
|
// Returns protocol ID and functionality for IPRIP
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
APIENTRY
|
||
|
RegisterProtocol(
|
||
|
IN OUT PMPR_ROUTING_CHARACTERISTICS pRoutingChar,
|
||
|
IN OUT PMPR_SERVICE_CHARACTERISTICS pServiceChar
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This is the first function called by the IP Router Manager. The Router
|
||
|
Manager tells the routing protocol its version and capabilities. It
|
||
|
also tells our DLL, the ID of the protocol it expects us to register.
|
||
|
This allows one DLL to support multiple routing protocols. We return
|
||
|
the functionality we support and a pointer to our functions.
|
||
|
|
||
|
Arguments
|
||
|
pRoutingChar The routing characteristics
|
||
|
pServiceChar The service characteristics (IPX 'thingy')
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
ERROR_NOT_SUPPORTED o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
TRACE0(ENTER, "Entering RegisterProtocol");
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
if(pRoutingChar->dwProtocolId != MS_IP_SAMPLE)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_SUPPORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((pRoutingChar->fSupportedFunctionality
|
||
|
& (RF_ROUTING|RF_DEMAND_UPDATE_ROUTES)) !=
|
||
|
(RF_ROUTING|RF_DEMAND_UPDATE_ROUTES))
|
||
|
{
|
||
|
dwErr = ERROR_NOT_SUPPORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pRoutingChar->fSupportedFunctionality =
|
||
|
(RF_ROUTING | RF_DEMAND_UPDATE_ROUTES);
|
||
|
|
||
|
// Since we are not a service advertiser (and IPX thing)
|
||
|
pServiceChar->fSupportedFunctionality = 0;
|
||
|
|
||
|
pRoutingChar->pfnStartProtocol = StartProtocol;
|
||
|
pRoutingChar->pfnStartComplete = StartComplete;
|
||
|
pRoutingChar->pfnStopProtocol = StopProtocol;
|
||
|
pRoutingChar->pfnGetGlobalInfo = GetGlobalInfo;
|
||
|
pRoutingChar->pfnSetGlobalInfo = SetGlobalInfo;
|
||
|
pRoutingChar->pfnQueryPower = NULL;
|
||
|
pRoutingChar->pfnSetPower = NULL;
|
||
|
|
||
|
pRoutingChar->pfnAddInterface = AddInterface;
|
||
|
pRoutingChar->pfnDeleteInterface = DeleteInterface;
|
||
|
pRoutingChar->pfnInterfaceStatus = InterfaceStatus;
|
||
|
pRoutingChar->pfnGetInterfaceInfo = GetInterfaceConfigInfo;
|
||
|
pRoutingChar->pfnSetInterfaceInfo = SetInterfaceConfigInfo;
|
||
|
|
||
|
pRoutingChar->pfnGetEventMessage = GetEventMessage;
|
||
|
|
||
|
pRoutingChar->pfnUpdateRoutes = DoUpdateRoutes;
|
||
|
|
||
|
pRoutingChar->pfnConnectClient = NULL;
|
||
|
pRoutingChar->pfnDisconnectClient = NULL;
|
||
|
|
||
|
pRoutingChar->pfnGetNeighbors = NULL;
|
||
|
pRoutingChar->pfnGetMfeStatus = NULL;
|
||
|
|
||
|
pRoutingChar->pfnMibCreateEntry = MibCreate;
|
||
|
pRoutingChar->pfnMibDeleteEntry = MibDelete;
|
||
|
pRoutingChar->pfnMibGetEntry = MibGet;
|
||
|
pRoutingChar->pfnMibSetEntry = MibSet;
|
||
|
pRoutingChar->pfnMibGetFirstEntry = MibGetFirst;
|
||
|
pRoutingChar->pfnMibGetNextEntry = MibGetNext;
|
||
|
pRoutingChar->pfnMibSetTrapInfo = MibSetTrapInfo;
|
||
|
pRoutingChar->pfnMibGetTrapInfo = MibGetTrapInfo;
|
||
|
} while (FALSE);
|
||
|
|
||
|
TRACE1(LEAVE, "Leaving RegisterProtocol: %u", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|