1668 lines
40 KiB
C
1668 lines
40 KiB
C
#include "ipxdefs.h"
|
|
|
|
HANDLE FwdDriverHandle=NULL;
|
|
HANDLE FltDriverHandle=NULL;
|
|
DWORD FltTraceId;
|
|
extern DWORD g_dwTraceId;
|
|
|
|
#define FLT_LOG_BUFFER_SIZE 16384
|
|
#define NUM_FILTER_LOG_ENTRIES 2
|
|
|
|
typedef struct _FLT_LOG_ENTRY {
|
|
OVERLAPPED ovlp;
|
|
UCHAR buffer[FLT_LOG_BUFFER_SIZE];
|
|
} FLT_LOG_ENTRY, *PFLT_LOG_ENTRY;
|
|
|
|
FLT_LOG_ENTRY FltLogEntry [NUM_FILTER_LOG_ENTRIES];
|
|
|
|
|
|
VOID WINAPI
|
|
DumpFilterLog (
|
|
DWORD error,
|
|
DWORD cbCount,
|
|
LPOVERLAPPED ovlp
|
|
) {
|
|
BOOL res;
|
|
PFLT_LOG_ENTRY pEntry = CONTAINING_RECORD (ovlp, FLT_LOG_ENTRY, ovlp);
|
|
|
|
if (error==NO_ERROR) {
|
|
PFLT_PACKET_LOG pLog = (PFLT_PACKET_LOG)pEntry->buffer;
|
|
TracePuts (FltTraceId, TEXT (""));
|
|
TracePrintfEx (FltTraceId,
|
|
DBG_FLT_LOG_ERRORS|TRACE_USE_MASK|TRACE_NO_STDINFO,
|
|
TEXT ("%d bytes returned in IRP buffer.\n"), cbCount);
|
|
while (((PUCHAR)pLog->Header<=&pEntry->buffer[cbCount])
|
|
&& (&pLog->Header[pLog->DataSize]<=&pEntry->buffer[cbCount])) {
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO,
|
|
TEXT ("Packet # %d,"), pLog->SeqNum);
|
|
if (pLog->SrcIfIdx!=-1)
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO,
|
|
TEXT (" received on interface: %d,"), pLog->SrcIfIdx);
|
|
else
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO,
|
|
TEXT (" no source interface context,"));
|
|
if (pLog->DstIfIdx!=-1)
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO,
|
|
TEXT (" sent on interface: %d."), pLog->DstIfIdx);
|
|
else
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO,
|
|
TEXT (" no destination interface context."));
|
|
TraceDumpEx (FltTraceId, TRACE_NO_STDINFO ,
|
|
pLog->Header, pLog->DataSize, 1,
|
|
FALSE, NULL);
|
|
TracePrintfEx (FltTraceId, TRACE_NO_STDINFO, TEXT("\n"));
|
|
pLog = (PFLT_PACKET_LOG)((ULONG_PTR)(&pLog->Header[pLog->DataSize]+3)&(~(ULONG_PTR)3));
|
|
}
|
|
}
|
|
else {
|
|
TracePrintfEx (FltTraceId, DBG_FLT_LOG_ERRORS|TRACE_USE_MASK,
|
|
TEXT ("IOCTL_FLT_GET_LOGGED_PACKETS completed with error %d\n"),
|
|
error);
|
|
}
|
|
|
|
if (FltDriverHandle!=NULL) {
|
|
res = DeviceIoControl(
|
|
FltDriverHandle,
|
|
IOCTL_FLT_GET_LOGGED_PACKETS,
|
|
NULL,
|
|
0,
|
|
pEntry->buffer,
|
|
sizeof (pEntry->buffer),
|
|
NULL,
|
|
&pEntry->ovlp);
|
|
if (!res&&(GetLastError ()!=ERROR_IO_PENDING))
|
|
TracePrintfEx (FltTraceId, DBG_FLT_LOG_ERRORS|TRACE_USE_MASK,
|
|
TEXT ("DeviceIoControl failed with error %d"),
|
|
GetLastError ());
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
FwStart (
|
|
ULONG RouteHashTableSize,
|
|
BOOL ThisMachineOnly // allow access to this machine only
|
|
// for dialin clients
|
|
) {
|
|
SC_HANDLE ScMgrHandle;
|
|
SC_HANDLE FwdServiceHandle, FltServiceHandle;
|
|
DWORD error = NO_ERROR;
|
|
BOOL bOk;
|
|
|
|
ASSERT (FwdDriverHandle==NULL);
|
|
|
|
ScMgrHandle = OpenSCManager (NULL, NULL, 0);
|
|
if (ScMgrHandle!=NULL) {
|
|
|
|
FwdServiceHandle = OpenService (ScMgrHandle,
|
|
TEXT ("NwLnkFwd"),
|
|
SERVICE_START|SERVICE_STOP);
|
|
if (FwdServiceHandle!=NULL) {
|
|
if (StartService (FwdServiceHandle, 0, NULL)
|
|
|| (GetLastError ()==ERROR_SERVICE_ALREADY_RUNNING)) {
|
|
UNICODE_STRING FileString;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
|
|
RtlInitUnicodeString (&FileString, IPXFWD_NAME);
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&FileString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
|
|
status = NtOpenFile(
|
|
&FwdDriverHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0);
|
|
if (NT_SUCCESS (status)) {
|
|
FWD_START_PARAMS params;
|
|
params.RouteHashTableSize = RouteHashTableSize;
|
|
params.ThisMachineOnly = (UCHAR)ThisMachineOnly;
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_START,
|
|
¶ms,
|
|
sizeof(params),
|
|
NULL,
|
|
0);
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
FltServiceHandle = OpenService (ScMgrHandle,
|
|
TEXT ("NwLnkFlt"),
|
|
SERVICE_START|SERVICE_STOP);
|
|
if (FltServiceHandle!=NULL) {
|
|
if (StartService (FltServiceHandle, 0, NULL)
|
|
|| (GetLastError ()==ERROR_SERVICE_ALREADY_RUNNING)) {
|
|
UNICODE_STRING FileString;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
|
|
RtlInitUnicodeString (&FileString, IPXFLT_NAME);
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&FileString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
|
|
status = NtOpenFile(
|
|
&FltDriverHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0);
|
|
if (NT_SUCCESS (status)) {
|
|
status = NtDeviceIoControlFile(
|
|
FltDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FLT_START,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0);
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FltDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
if (NT_SUCCESS (status)) {
|
|
INT i;
|
|
FltTraceId = TraceRegister (
|
|
TEXT ("IPX Traffic Filter Logging"));
|
|
|
|
error = NO_ERROR;
|
|
bOk = BindIoCompletionCallback (
|
|
FltDriverHandle,
|
|
DumpFilterLog,
|
|
0);
|
|
if (!bOk)
|
|
{
|
|
error = GetLastError();
|
|
}
|
|
ASSERTMSG ("Can't set io completion proc", error==NO_ERROR);
|
|
for (i=0; i<NUM_FILTER_LOG_ENTRIES; i++) {
|
|
BOOL res;
|
|
FltLogEntry[i].ovlp.hEvent = NULL;
|
|
res = DeviceIoControl(
|
|
FltDriverHandle,
|
|
IOCTL_FLT_GET_LOGGED_PACKETS,
|
|
NULL,
|
|
0,
|
|
FltLogEntry[i].buffer,
|
|
sizeof (FltLogEntry[i].buffer),
|
|
NULL,
|
|
&FltLogEntry[i].ovlp);
|
|
if (!res&&(GetLastError ()!=ERROR_IO_PENDING))
|
|
TracePrintfEx (FltTraceId,
|
|
DBG_FLT_LOG_ERRORS|TRACE_USE_MASK,
|
|
TEXT ("DeviceIoControl failed with error %d"),
|
|
GetLastError ());
|
|
}
|
|
SetLastError (NO_ERROR);
|
|
}
|
|
else {
|
|
NtClose (FltDriverHandle);
|
|
FltDriverHandle = NULL;
|
|
error = RtlNtStatusToDosError (status);
|
|
}
|
|
}
|
|
else
|
|
error = RtlNtStatusToDosError (status);
|
|
if (!NT_SUCCESS (status)) {
|
|
SERVICE_STATUS serviceStatus;
|
|
ControlService (FltServiceHandle,
|
|
SERVICE_CONTROL_STOP,
|
|
&serviceStatus);
|
|
}
|
|
}
|
|
else
|
|
error = GetLastError ();
|
|
CloseServiceHandle (FltServiceHandle);
|
|
}
|
|
else
|
|
error = GetLastError ();
|
|
}
|
|
else
|
|
error = RtlNtStatusToDosError (status);
|
|
if (!NT_SUCCESS (status)) {
|
|
NtClose (FwdDriverHandle);
|
|
FwdDriverHandle = NULL;
|
|
}
|
|
}
|
|
else
|
|
error = RtlNtStatusToDosError (status);
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
SERVICE_STATUS serviceStatus;
|
|
ControlService (FwdServiceHandle,
|
|
SERVICE_CONTROL_STOP,
|
|
&serviceStatus);
|
|
}
|
|
}
|
|
else
|
|
error = GetLastError ();
|
|
CloseServiceHandle (FwdServiceHandle);
|
|
}
|
|
else
|
|
error = GetLastError ();
|
|
CloseServiceHandle (ScMgrHandle);
|
|
}
|
|
else
|
|
error = GetLastError ();
|
|
SetLastError (error);
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Function: FwIsStarted
|
|
//
|
|
// Reports whether the forwarder has been started/is running.
|
|
//
|
|
//
|
|
DWORD FwIsStarted (OUT PBOOL pbIsStarted) {
|
|
SC_HANDLE hScMgr = NULL, hFwdService = NULL;
|
|
SERVICE_STATUS ServiceStatus;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
// Sanity check
|
|
if (!pbIsStarted)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
// Get a reference to the service controller
|
|
hScMgr = OpenSCManager (NULL, NULL, 0);
|
|
if (hScMgr == NULL)
|
|
return GetLastError();
|
|
|
|
__try {
|
|
// Get a handle to the service
|
|
hFwdService = OpenService (hScMgr, TEXT ("NwLnkFwd"), SERVICE_QUERY_STATUS);
|
|
if (hFwdService == NULL)
|
|
return GetLastError();
|
|
|
|
// Query the service ServiceStatus
|
|
if (! QueryServiceStatus(hFwdService, &ServiceStatus))
|
|
return GetLastError();
|
|
|
|
// Return accordingly
|
|
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING ||
|
|
ServiceStatus.dwCurrentState == SERVICE_START_PENDING ||
|
|
ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING ||
|
|
ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING ||
|
|
ServiceStatus.dwCurrentState == SERVICE_PAUSED)
|
|
*pbIsStarted = TRUE;
|
|
else
|
|
*pbIsStarted = FALSE;
|
|
}
|
|
__finally {
|
|
if (hScMgr)
|
|
CloseServiceHandle(hScMgr);
|
|
if (hFwdService)
|
|
CloseServiceHandle(hFwdService);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Returns whether the given state is a pending state
|
|
//
|
|
BOOL
|
|
FwIsPendingState (
|
|
IN DWORD dwState)
|
|
{
|
|
return (BOOL) ((dwState == SERVICE_START_PENDING) ||
|
|
(dwState == SERVICE_STOP_PENDING) ||
|
|
(dwState == SERVICE_CONTINUE_PENDING) ||
|
|
(dwState == SERVICE_PAUSE_PENDING)
|
|
);
|
|
}
|
|
|
|
// Stops the service referred by the opened hService
|
|
// handle. It's assumed that the handle is opened for
|
|
// stopping the service and querying its status.
|
|
//
|
|
DWORD
|
|
FwStopService(
|
|
IN HANDLE hService,
|
|
IN DWORD dwSecsTimeout)
|
|
{
|
|
SERVICE_STATUS SStatus;
|
|
DWORD dwState, dwErr, dwOrigTimeout = dwSecsTimeout;
|
|
BOOL bOk;
|
|
|
|
// Get the current status of the service
|
|
if (! QueryServiceStatus(hService, &SStatus))
|
|
{
|
|
dwErr = GetLastError();
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("QueryServiceStatus returned %d"),
|
|
dwErr);
|
|
return dwErr;
|
|
}
|
|
|
|
// If it's already stopped, we're done
|
|
if (SStatus.dwCurrentState == SERVICE_STOPPED)
|
|
return NO_ERROR;
|
|
dwState = SStatus.dwCurrentState;
|
|
|
|
// Tell the service to stop
|
|
bOk = ControlService (
|
|
hService,
|
|
SERVICE_CONTROL_STOP,
|
|
&SStatus);
|
|
if (! bOk)
|
|
{
|
|
dwErr = GetLastError();
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("ControlService(Stop) returned %d"),
|
|
dwErr);
|
|
return dwErr;
|
|
}
|
|
|
|
// Wait for the service to change states or for the timeout to
|
|
// expire.
|
|
dwSecsTimeout *= 4;
|
|
while (dwSecsTimeout != 0) {
|
|
// Get the status of the service
|
|
bOk = QueryServiceStatus (
|
|
hService,
|
|
&SStatus);
|
|
if (! bOk)
|
|
{
|
|
dwErr = GetLastError();
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("QueryServiceStatus (2) returned %d"),
|
|
dwErr);
|
|
return dwErr;
|
|
}
|
|
|
|
// See if the state changed
|
|
if (dwState != SStatus.dwCurrentState)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Service status changed from %d to %d"),
|
|
dwState,
|
|
SStatus.dwCurrentState);
|
|
|
|
// If the service changed to a pending state, continue
|
|
if (FwIsPendingState (SStatus.dwCurrentState))
|
|
{
|
|
dwState = SStatus.dwCurrentState;
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Pending state detected -- continuing to wait."));
|
|
|
|
}
|
|
|
|
// Otherwise, we're either stopped or running
|
|
else
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Non-Pending state detected -- waiting complete."));
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Service state hasn't changed from %d. Waiting..."),
|
|
dwState);
|
|
}
|
|
|
|
// Wait for something to happen
|
|
Sleep(250);
|
|
dwSecsTimeout--;
|
|
}
|
|
|
|
// Return a timeout error if appropriate
|
|
if (dwSecsTimeout == 0)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Timeout of %d seconds expired waiting for service to stop."),
|
|
dwOrigTimeout);
|
|
|
|
return ERROR_TIMEOUT;
|
|
}
|
|
|
|
// If the service is now stopped, then everything
|
|
// worked great.
|
|
if (SStatus.dwCurrentState == SERVICE_STOPPED)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Service stoppped successfully."));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Otherwise, return the fact that we were'nt able to
|
|
// get to a running state
|
|
if (SStatus.dwWin32ExitCode != NO_ERROR)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Service stop failed with code %d."),
|
|
SStatus.dwWin32ExitCode);
|
|
|
|
return SStatus.dwWin32ExitCode;
|
|
}
|
|
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Service stop failed, no error reported."));
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
DWORD
|
|
FwStop (
|
|
void
|
|
) {
|
|
SC_HANDLE ScMgrHandle;
|
|
SC_HANDLE FwdServiceHandle, FltServiceHandle;
|
|
NTSTATUS status;
|
|
DWORD dwErr;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
ASSERT (FltDriverHandle!=NULL);
|
|
|
|
// Close references to the filter and forwarder
|
|
// drivers
|
|
status = NtClose (FltDriverHandle);
|
|
FltDriverHandle = NULL;
|
|
status = NtClose (FwdDriverHandle);
|
|
FwdDriverHandle = NULL;
|
|
|
|
// Open the service controller
|
|
ScMgrHandle = OpenSCManager (NULL, NULL, 0);
|
|
if (ScMgrHandle!=NULL)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Stopping the filter driver..."));
|
|
|
|
// Open the service handle to the
|
|
// filter service
|
|
//
|
|
FltServiceHandle = OpenService (
|
|
ScMgrHandle,
|
|
"NwLnkFlt",
|
|
SERVICE_STOP | SERVICE_QUERY_STATUS);
|
|
|
|
// Stop the filter service
|
|
if (FltServiceHandle != NULL)
|
|
{
|
|
dwErr = FwStopService(FltServiceHandle, 10);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("FwStopService returned %d"),
|
|
dwErr);
|
|
}
|
|
CloseServiceHandle (FltServiceHandle);
|
|
}
|
|
else
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Unable to open the filter driver service handle %d"),
|
|
GetLastError());
|
|
}
|
|
|
|
// Open the service handle to the
|
|
// fowarder driver
|
|
//
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Stopping the forwarder driver..."));
|
|
|
|
FwdServiceHandle = OpenService (
|
|
ScMgrHandle,
|
|
"NwLnkFwd",
|
|
SERVICE_STOP | SERVICE_QUERY_STATUS);
|
|
|
|
// Stop the forwarder driver
|
|
//
|
|
if (FwdServiceHandle != NULL)
|
|
{
|
|
dwErr = FwStopService(FwdServiceHandle, 10);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("FwStopService returned %d"),
|
|
dwErr);
|
|
}
|
|
CloseServiceHandle (FwdServiceHandle);
|
|
}
|
|
else
|
|
{
|
|
TracePrintfEx (
|
|
g_dwTraceId,
|
|
DBG_FLT_LOG_ERRORS | TRACE_USE_MASK,
|
|
TEXT ("Unable to open the forwarder driver service handle %d"),
|
|
GetLastError());
|
|
}
|
|
|
|
CloseServiceHandle (ScMgrHandle);
|
|
}
|
|
|
|
TraceDeregister (FltTraceId);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Added for pnp resetting of forwarder's ThisMachineOnly
|
|
// setting.
|
|
DWORD
|
|
FwUpdateConfig(BOOL ThisMachineOnly) {
|
|
FWD_UPDATE_CONFIG_PARAMS Params;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
|
|
Params.bThisMachineOnly = (BOOLEAN)(!!ThisMachineOnly);
|
|
|
|
// Send the ioctl
|
|
status = NtDeviceIoControlFile(FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_UPDATE_CONFIG,
|
|
&Params,
|
|
sizeof (Params),
|
|
NULL,
|
|
0);
|
|
|
|
// Wait for completion
|
|
if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
VOID
|
|
FwCleanup (
|
|
void
|
|
) {
|
|
if (FwdDriverHandle!=NULL)
|
|
FwStop ();
|
|
}
|
|
DWORD
|
|
FwCreateInterface (
|
|
IN ULONG InterfaceIndex,
|
|
IN NET_INTERFACE_TYPE InterfaceType,
|
|
IN PFW_IF_INFO FwIfInfo
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
FWD_IF_CREATE_PARAMS params;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
params.Index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
params.Index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
switch (InterfaceType) {
|
|
case PERMANENT:
|
|
params.InterfaceType = FWD_IF_PERMANENT;
|
|
break;
|
|
case DEMAND_DIAL:
|
|
params.InterfaceType = FWD_IF_DEMAND_DIAL;
|
|
break;
|
|
case LOCAL_WORKSTATION_DIAL:
|
|
params.InterfaceType = FWD_IF_LOCAL_WORKSTATION;
|
|
break;
|
|
case REMOTE_WORKSTATION_DIAL:
|
|
params.InterfaceType = FWD_IF_REMOTE_WORKSTATION;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid interface type ", FALSE);
|
|
}
|
|
|
|
switch (FwIfInfo->NetbiosAccept) {
|
|
case ADMIN_STATE_ENABLED:
|
|
params.NetbiosAccept = TRUE;
|
|
break;
|
|
case ADMIN_STATE_DISABLED:
|
|
params.NetbiosAccept = FALSE;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid netbios state ", FALSE);
|
|
}
|
|
|
|
switch (FwIfInfo->NetbiosDeliver) {
|
|
case ADMIN_STATE_ENABLED:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_ALL;
|
|
break;
|
|
case ADMIN_STATE_DISABLED:
|
|
params.NetbiosDeliver = FWD_NB_DONT_DELIVER;
|
|
break;
|
|
case ADMIN_STATE_ENABLED_ONLY_FOR_NETBIOS_STATIC_ROUTING:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_STATIC;
|
|
break;
|
|
case ADMIN_STATE_ENABLED_ONLY_FOR_OPER_STATE_UP:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_IF_UP;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid netbios state ", FALSE);
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_CREATE_INTERFACE,
|
|
¶ms,
|
|
sizeof (params),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwDeleteInterface (
|
|
IN ULONG InterfaceIndex
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_DELETE_INTERFACE,
|
|
&index,
|
|
sizeof (index),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwSetInterface (
|
|
IN ULONG InterfaceIndex,
|
|
IN PFW_IF_INFO FwIfInfo
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
FWD_IF_SET_PARAMS params;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
params.Index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
params.Index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
switch (FwIfInfo->NetbiosAccept) {
|
|
case ADMIN_STATE_ENABLED:
|
|
params.NetbiosAccept = TRUE;
|
|
break;
|
|
case ADMIN_STATE_DISABLED:
|
|
params.NetbiosAccept = FALSE;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid netbios state ", FALSE);
|
|
}
|
|
|
|
switch (FwIfInfo->NetbiosDeliver) {
|
|
case ADMIN_STATE_ENABLED:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_ALL;
|
|
break;
|
|
case ADMIN_STATE_DISABLED:
|
|
params.NetbiosDeliver = FWD_NB_DONT_DELIVER;
|
|
break;
|
|
case ADMIN_STATE_ENABLED_ONLY_FOR_NETBIOS_STATIC_ROUTING:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_STATIC;
|
|
break;
|
|
case ADMIN_STATE_ENABLED_ONLY_FOR_OPER_STATE_UP:
|
|
params.NetbiosDeliver = FWD_NB_DELIVER_IF_UP;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid netbios state ", FALSE);
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_SET_INTERFACE,
|
|
¶ms,
|
|
sizeof (params),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwGetInterface (
|
|
IN ULONG InterfaceIndex,
|
|
OUT PFW_IF_INFO FwIfInfo,
|
|
OUT PFW_IF_STATS FwIfStats
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
union {
|
|
FWD_IF_GET_PARAMS params;
|
|
ULONG index;
|
|
} iob;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
iob.index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
iob.index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_GET_INTERFACE,
|
|
&iob,
|
|
sizeof (iob.index),
|
|
&iob,
|
|
sizeof (iob.params));
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
if (iob.params.NetbiosAccept)
|
|
FwIfInfo->NetbiosAccept = ADMIN_STATE_ENABLED;
|
|
else
|
|
FwIfInfo->NetbiosAccept = ADMIN_STATE_DISABLED;
|
|
|
|
switch (iob.params.NetbiosDeliver) {
|
|
case FWD_NB_DONT_DELIVER:
|
|
FwIfInfo->NetbiosDeliver = ADMIN_STATE_DISABLED;
|
|
break;
|
|
case FWD_NB_DELIVER_STATIC:
|
|
FwIfInfo->NetbiosDeliver = ADMIN_STATE_ENABLED_ONLY_FOR_NETBIOS_STATIC_ROUTING;
|
|
break;
|
|
case FWD_NB_DELIVER_IF_UP:
|
|
FwIfInfo->NetbiosDeliver = ADMIN_STATE_ENABLED_ONLY_FOR_OPER_STATE_UP;
|
|
break;
|
|
case FWD_NB_DELIVER_ALL:
|
|
FwIfInfo->NetbiosDeliver = ADMIN_STATE_ENABLED;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid NetbiosDeliver state ", FALSE);
|
|
}
|
|
|
|
|
|
switch (iob.params.Stats.OperationalState) {
|
|
case FWD_OPER_STATE_UP:
|
|
FwIfStats->IfOperState = OPER_STATE_UP;
|
|
break;
|
|
case FWD_OPER_STATE_DOWN:
|
|
FwIfStats->IfOperState = OPER_STATE_DOWN;
|
|
break;
|
|
case FWD_OPER_STATE_SLEEPING:
|
|
FwIfStats->IfOperState = OPER_STATE_SLEEPING;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid interface state ", FALSE);
|
|
}
|
|
|
|
|
|
FwIfStats->MaxPacketSize = iob.params.Stats.MaxPacketSize;
|
|
FwIfStats->InHdrErrors = iob.params.Stats.InHdrErrors;
|
|
FwIfStats->InFiltered = iob.params.Stats.InFiltered;
|
|
FwIfStats->InNoRoutes = iob.params.Stats.InNoRoutes;
|
|
FwIfStats->InDiscards = iob.params.Stats.InDiscards;
|
|
FwIfStats->InDelivers = iob.params.Stats.InDelivers;
|
|
FwIfStats->OutFiltered = iob.params.Stats.OutFiltered;
|
|
FwIfStats->OutDiscards = iob.params.Stats.OutDiscards;
|
|
FwIfStats->OutDelivers = iob.params.Stats.OutDelivers;
|
|
FwIfStats->NetbiosReceived = iob.params.Stats.NetbiosReceived;
|
|
FwIfStats->NetbiosSent = iob.params.Stats.NetbiosSent;
|
|
return NO_ERROR;
|
|
}
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwBindFwInterfaceToAdapter (
|
|
IN ULONG InterfaceIndex,
|
|
IN PIPX_ADAPTER_BINDING_INFO AdptBindingInfo
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
FWD_IF_BIND_PARAMS params;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
params.Index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
params.Index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
params.Info.AdapterIndex = (ULONG)NicMapGetPhysicalNicId((USHORT)AdptBindingInfo->AdapterIndex);
|
|
GETLONG2ULONG (¶ms.Info.Network, AdptBindingInfo->Network);
|
|
IPX_NODENUM_CPY (¶ms.Info.LocalNode, AdptBindingInfo->LocalNode);
|
|
IPX_NODENUM_CPY (params.Info.RemoteNode, AdptBindingInfo->RemoteNode);
|
|
params.Info.MaxPacketSize = AdptBindingInfo->MaxPacketSize;
|
|
params.Info.LinkSpeed = AdptBindingInfo->LinkSpeed;
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_BIND_INTERFACE,
|
|
¶ms,
|
|
sizeof (params),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
//
|
|
// Function FwRenumberNics
|
|
//
|
|
// Instructs the forwarder to increment or decrement all nicids above
|
|
// the given threshold. This allows the forwarder to keep in sync with
|
|
// nic-id compaction that occurs in the stack.
|
|
//
|
|
DWORD
|
|
FwRenumberNics (DWORD dwOpCode,
|
|
USHORT usThreshold)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
FWD_RENUMBER_NICS_DATA FwRenumData;
|
|
|
|
if (NULL == FwdDriverHandle)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Assign the opcode
|
|
if (dwOpCode == NIC_OPCODE_INCREMENT_NICIDS)
|
|
FwRenumData.ulOpCode = FWD_NIC_OPCODE_INCREMENT;
|
|
else if (dwOpCode == NIC_OPCODE_DECREMENT_NICIDS)
|
|
FwRenumData.ulOpCode = FWD_NIC_OPCODE_DECREMENT;
|
|
else
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
// Assign the threshold
|
|
FwRenumData.usThreshold = usThreshold;
|
|
|
|
// Send the ioctl
|
|
status = NtDeviceIoControlFile(FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_RENUMBER_NICS,
|
|
&FwRenumData,
|
|
sizeof (FwRenumData),
|
|
NULL,
|
|
0);
|
|
|
|
// Wait for completion (we might take this out)
|
|
//if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
//}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
FwUnbindFwInterfaceFromAdapter (
|
|
IN ULONG InterfaceIndex
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_UNBIND_INTERFACE,
|
|
&index,
|
|
sizeof (index),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwDisableFwInterface (
|
|
IN ULONG InterfaceIndex
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_DISABLE_INTERFACE,
|
|
&index,
|
|
sizeof (index),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwEnableFwInterface (
|
|
IN ULONG InterfaceIndex
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_ENABLE_INTERFACE,
|
|
&index,
|
|
sizeof (index),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwConnectionRequestFailed (
|
|
IN ULONG InterfaceIndex
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_DIAL_REQUEST_FAILED,
|
|
&index,
|
|
sizeof (index),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
FwNotifyConnectionRequest (
|
|
OUT PFW_DIAL_REQUEST Request, // Buffer to be filled with interface index
|
|
//that requires connection plus packet
|
|
// that forced it
|
|
IN ULONG RequestSize, // Size of the buffer (must at least
|
|
// be sizeof (FW_DIAL_REQUEST)
|
|
IN LPOVERLAPPED lpOverlapped // structure for asyncrhronous
|
|
// operation, hEvent must be set
|
|
) {
|
|
NTSTATUS status;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
ASSERT (lpOverlapped->hEvent!=NULL);
|
|
ASSERT (FIELD_OFFSET (FW_DIAL_REQUEST, IfIndex)==FIELD_OFFSET (FWD_DIAL_REQUEST, IfIndex));
|
|
ASSERT (FIELD_OFFSET (FW_DIAL_REQUEST, Packet)==FIELD_OFFSET (FWD_DIAL_REQUEST, Packet));
|
|
|
|
if (RequestSize<sizeof (FWD_DIAL_REQUEST))
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
|
|
status = NtDeviceIoControlFile (
|
|
FwdDriverHandle,
|
|
lpOverlapped->hEvent,
|
|
NULL,
|
|
NULL,
|
|
(PIO_STATUS_BLOCK)lpOverlapped,
|
|
IOCTL_FWD_GET_DIAL_REQUEST,
|
|
NULL,
|
|
0,
|
|
Request,
|
|
RequestSize);
|
|
if (status==STATUS_PENDING)
|
|
return NO_ERROR;
|
|
else
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
// Returns result of notification request. Should be called when
|
|
// the event set in the lpOverlapped structure is signalled.
|
|
//
|
|
DWORD
|
|
FwGetNotificationResult (
|
|
IN LPOVERLAPPED lpOverlapped,
|
|
OUT PULONG nBytes // Number of bytes placed into
|
|
// the request buffer
|
|
) {
|
|
if (NT_SUCCESS(((PIO_STATUS_BLOCK)lpOverlapped)->Status)) {
|
|
*nBytes = (ULONG)((PIO_STATUS_BLOCK)lpOverlapped)->Information;
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
return RtlNtStatusToDosError (
|
|
((PIO_STATUS_BLOCK)lpOverlapped)->Status);
|
|
}
|
|
|
|
VOID
|
|
FwUpdateRouteTable (
|
|
DWORD ChangeFlags,
|
|
PVOID CurRoute,
|
|
PVOID PrevRoute
|
|
) {
|
|
#define IPXCurRoute ((PRTM_IPX_ROUTE)CurRoute)
|
|
#define IPXPrevRoute ((PRTM_IPX_ROUTE)PrevRoute)
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
FWD_ROUTE_SET_PARAMS params;
|
|
|
|
switch (ChangeFlags) {
|
|
case RTM_ROUTE_ADDED:
|
|
params.Action = FWD_ADD_ROUTE;
|
|
params.Network = IPXCurRoute->RR_Network.N_NetNumber;
|
|
IPX_NODENUM_CPY (params.NextHopAddress, IPXCurRoute->RR_NextHopAddress.NHA_Mac);
|
|
params.TickCount = IPXCurRoute->RR_FamilySpecificData.FSD_TickCount;
|
|
params.HopCount = IPXCurRoute->RR_FamilySpecificData.FSD_HopCount;
|
|
params.InterfaceIndex = IPXCurRoute->RR_InterfaceID;
|
|
break;
|
|
case RTM_ROUTE_DELETED:
|
|
params.Action = FWD_DELETE_ROUTE;
|
|
params.Network = IPXPrevRoute->RR_Network.N_NetNumber;
|
|
IPX_NODENUM_CPY (params.NextHopAddress, IPXPrevRoute->RR_NextHopAddress.NHA_Mac);
|
|
params.TickCount = IPXPrevRoute->RR_FamilySpecificData.FSD_TickCount;
|
|
params.HopCount = IPXPrevRoute->RR_FamilySpecificData.FSD_HopCount;
|
|
params.InterfaceIndex = IPXPrevRoute->RR_InterfaceID;
|
|
break;
|
|
case RTM_ROUTE_CHANGED:
|
|
if ((IPX_NODENUM_CMP (IPXPrevRoute->RR_NextHopAddress.NHA_Mac,
|
|
IPXCurRoute->RR_NextHopAddress.NHA_Mac)!=0)
|
|
|| (IPXPrevRoute->RR_FamilySpecificData.FSD_TickCount
|
|
!=IPXCurRoute->RR_FamilySpecificData.FSD_TickCount)
|
|
|| (IPXPrevRoute->RR_FamilySpecificData.FSD_HopCount
|
|
!=IPXCurRoute->RR_FamilySpecificData.FSD_HopCount)
|
|
|| (IPXPrevRoute->RR_InterfaceID
|
|
!=IPXCurRoute->RR_InterfaceID)) {
|
|
params.Action = FWD_UPDATE_ROUTE;
|
|
params.Network = IPXCurRoute->RR_Network.N_NetNumber;
|
|
IPX_NODENUM_CPY (params.NextHopAddress, IPXCurRoute->RR_NextHopAddress.NHA_Mac);
|
|
params.TickCount = IPXCurRoute->RR_FamilySpecificData.FSD_TickCount;
|
|
params.HopCount = IPXCurRoute->RR_FamilySpecificData.FSD_HopCount;
|
|
params.InterfaceIndex = IPXCurRoute->RR_InterfaceID;
|
|
break;
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_SET_ROUTES,
|
|
¶ms,
|
|
sizeof (params),
|
|
NULL,
|
|
0);
|
|
|
|
if (status==STATUS_PENDING){
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
|
|
return;
|
|
#undef IPXPrevRoute
|
|
#undef IPXCurRoute
|
|
}
|
|
|
|
//
|
|
// Sets the netbios static routing information on this interface
|
|
//
|
|
|
|
DWORD
|
|
FwSetStaticNetbiosNames (
|
|
ULONG InterfaceIndex,
|
|
ULONG NetbiosNamesCount,
|
|
PIPX_STATIC_NETBIOS_NAME_INFO NetbiosNames
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
ULONG index;
|
|
NTSTATUS status;
|
|
|
|
ASSERT (FwdDriverHandle!=NULL);
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
if (NetbiosNamesCount>0) {
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_SET_NB_NAMES,
|
|
&index,
|
|
sizeof(index),
|
|
NetbiosNames,
|
|
NetbiosNamesCount
|
|
*sizeof(IPX_STATIC_NETBIOS_NAME_INFO)
|
|
);
|
|
}
|
|
else {
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_RESET_NB_NAMES,
|
|
&index,
|
|
sizeof(index),
|
|
NULL,
|
|
0);
|
|
}
|
|
|
|
if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
//
|
|
// Gets the netbios static routing information on this interface
|
|
//
|
|
// If NetbiosNamesCount < nr of names or NetbiosName == NULL then set the
|
|
// correct value in NetbiosNamesCount and return ERROR_INSUFFICIENT_BUFFER
|
|
|
|
DWORD
|
|
FwGetStaticNetbiosNames (
|
|
ULONG InterfaceIndex,
|
|
PULONG NetbiosNamesCount,
|
|
PIPX_STATIC_NETBIOS_NAME_INFO NetbiosName
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
ULONG bSize;
|
|
PFWD_NB_NAMES_PARAMS params=NULL;
|
|
// Local buffer for small amounts of data
|
|
UCHAR localBuf[FIELD_OFFSET (FWD_NB_NAMES_PARAMS,Names)];
|
|
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
bSize = FIELD_OFFSET (FWD_NB_NAMES_PARAMS,
|
|
Names[*NetbiosNamesCount]);
|
|
if (bSize<=sizeof (localBuf)) {
|
|
params = (PFWD_NB_NAMES_PARAMS)&localBuf;
|
|
}
|
|
else {
|
|
params = (PFWD_NB_NAMES_PARAMS)RtlAllocateHeap (
|
|
RtlProcessHeap (), 0,
|
|
bSize);
|
|
}
|
|
|
|
if (params!=NULL) {
|
|
status = NtDeviceIoControlFile(
|
|
FwdDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_FWD_GET_NB_NAMES,
|
|
&index,
|
|
sizeof (index),
|
|
params,
|
|
bSize);
|
|
|
|
if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FwdDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
switch (status) {
|
|
case STATUS_SUCCESS:
|
|
case STATUS_BUFFER_OVERFLOW:
|
|
if (IoStatus.Information>FIELD_OFFSET (FWD_NB_NAMES_PARAMS,Names))
|
|
if (NetbiosName)
|
|
{
|
|
ULONG_PTR dwInfoSize, dwBufferSize;
|
|
|
|
dwInfoSize =
|
|
IoStatus.Information -
|
|
FIELD_OFFSET (FWD_NB_NAMES_PARAMS,Names);
|
|
|
|
dwBufferSize =
|
|
*NetbiosNamesCount * sizeof(IPX_STATIC_NETBIOS_NAME_INFO);
|
|
|
|
RtlCopyMemory (
|
|
NetbiosName,
|
|
¶ms->Names,
|
|
(dwInfoSize > dwBufferSize) ? dwBufferSize : dwInfoSize);
|
|
}
|
|
else if (status==STATUS_BUFFER_OVERFLOW)
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
*NetbiosNamesCount = params->TotalCount;
|
|
break;
|
|
}
|
|
|
|
if (params!=(PFWD_NB_NAMES_PARAMS)localBuf)
|
|
RtlFreeHeap (RtlProcessHeap (), 0, params);
|
|
}
|
|
else
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
SetFilters (
|
|
IN ULONG InterfaceIndex,
|
|
IN ULONG FilterMode, // inbound, outbound
|
|
IN ULONG FilterAction,
|
|
IN ULONG FilterSize,
|
|
IN LPVOID FilterInfo,
|
|
IN ULONG FilterInfoSize
|
|
) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
FLT_IF_SET_PARAMS params;
|
|
NTSTATUS status;
|
|
ULONG code;
|
|
|
|
ASSERT (FltDriverHandle!=NULL);
|
|
|
|
switch (FilterMode) {
|
|
case IPX_TRAFFIC_FILTER_INBOUND:
|
|
if (FilterInfoSize>0)
|
|
code = IOCTL_FLT_IF_SET_IN_FILTERS;
|
|
else
|
|
code = IOCTL_FLT_IF_RESET_IN_FILTERS;
|
|
break;
|
|
case IPX_TRAFFIC_FILTER_OUTBOUND:
|
|
if (FilterInfoSize>0)
|
|
code = IOCTL_FLT_IF_SET_OUT_FILTERS;
|
|
else
|
|
code = IOCTL_FLT_IF_RESET_OUT_FILTERS;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid filter mode ", FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
params.InterfaceIndex = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
params.InterfaceIndex = InterfaceIndex;
|
|
break;
|
|
}
|
|
if (FilterInfoSize>0) {
|
|
params.FilterAction = FilterAction;
|
|
params.FilterSize = FilterSize;
|
|
status = NtDeviceIoControlFile(
|
|
FltDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
code,
|
|
¶ms,
|
|
sizeof(params),
|
|
FilterInfo,
|
|
FilterInfoSize
|
|
);
|
|
}
|
|
else {
|
|
status = NtDeviceIoControlFile(
|
|
FltDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
code,
|
|
¶ms.InterfaceIndex,
|
|
sizeof(params.InterfaceIndex),
|
|
NULL,
|
|
0
|
|
);
|
|
}
|
|
|
|
if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FltDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
DWORD
|
|
GetFilters(IN ULONG InterfaceIndex,
|
|
IN ULONG FilterMode, // inbound, outbound
|
|
OUT PULONG FilterAction,
|
|
OUT PULONG FilterSize,
|
|
OUT LPVOID FilterInfo,
|
|
IN OUT PULONG FilterInfoSize) {
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS status;
|
|
ULONG index;
|
|
ULONG code;
|
|
PFLT_IF_GET_PARAMS params=NULL;
|
|
ULONG bSize;
|
|
// Local buffer for small amounts of data
|
|
UCHAR localBuf[sizeof (FLT_IF_GET_PARAMS)];
|
|
|
|
|
|
switch (FilterMode) {
|
|
case IPX_TRAFFIC_FILTER_INBOUND:
|
|
code = IOCTL_FLT_IF_GET_IN_FILTERS;
|
|
break;
|
|
case IPX_TRAFFIC_FILTER_OUTBOUND:
|
|
code = IOCTL_FLT_IF_GET_OUT_FILTERS;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Invalid filter mode ", FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (InterfaceIndex) {
|
|
case 0:
|
|
index = FWD_INTERNAL_INTERFACE_INDEX;
|
|
break;
|
|
default:
|
|
index = InterfaceIndex;
|
|
break;
|
|
}
|
|
|
|
bSize = sizeof (FLT_IF_GET_PARAMS)+*FilterInfoSize;
|
|
if (bSize<=sizeof (localBuf)) {
|
|
params = (PFLT_IF_GET_PARAMS)&localBuf;
|
|
}
|
|
else {
|
|
params = (PFLT_IF_GET_PARAMS)RtlAllocateHeap (
|
|
RtlProcessHeap (), 0,
|
|
bSize);
|
|
}
|
|
|
|
if (params!=NULL) {
|
|
status = NtDeviceIoControlFile(
|
|
FltDriverHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
code,
|
|
&index,
|
|
sizeof (index),
|
|
params,
|
|
bSize);
|
|
|
|
if (status==STATUS_PENDING) {
|
|
status = NtWaitForSingleObject (FltDriverHandle, FALSE, NULL);
|
|
if (NT_SUCCESS (status))
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
switch (status) {
|
|
case STATUS_SUCCESS:
|
|
case STATUS_BUFFER_OVERFLOW:
|
|
if (FilterInfo && IoStatus.Information>=sizeof (FLT_IF_GET_PARAMS))
|
|
RtlCopyMemory (FilterInfo, ¶ms[1],
|
|
IoStatus.Information
|
|
-sizeof (FLT_IF_GET_PARAMS));
|
|
else if (status==STATUS_BUFFER_OVERFLOW)
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
*FilterInfoSize = params->TotalSize;
|
|
*FilterAction = params->FilterAction;
|
|
*FilterSize = params->FilterSize;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (params!=(PFLT_IF_GET_PARAMS)localBuf)
|
|
RtlFreeHeap (RtlProcessHeap (), 0, params);
|
|
}
|
|
else
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
return RtlNtStatusToDosError (status);
|
|
}
|
|
|
|
|
|
|