windows-nt/Source/XPSP1/NT/net/rras/ras/autodial/rasauto/access.c
2020-09-26 16:20:57 +08:00

1068 lines
30 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright(c) 1995 Microsoft Corporation
MODULE NAME
access.c
ABSTRACT
Address accessibility routines for automatic connections
AUTHOR
Anthony Discolo (adiscolo) 26-Jul-1995
REVISION HISTORY
--*/
#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdlib.h>
#include <windows.h>
#include <tdi.h>
#include <nb30.h>
#include <nbtioctl.h>
#include <stdio.h>
#include <npapi.h>
#include <ctype.h>
#include <winsock.h>
#include <acd.h>
#include <ras.h>
#include <raserror.h>
#include <rasman.h>
#include <debug.h>
#include <ipexport.h>
#include <icmpapi.h>
#include "reg.h"
#include "rasprocs.h"
#include "misc.h"
#include "table.h"
#include "addrmap.h"
#include "imperson.h"
//
// The format of Adapter Status responses.
//
typedef struct _ADAPTERSTATUS
{
ADAPTER_STATUS AdapterInfo;
NAME_BUFFER Names[32];
} ADAPTERSTATUS, *PADAPTERSTATUS;
//
// Icmp.dll library entrypoints.
//
#define ICMP_MODULE L"icmp"
HANDLE hIcmpG;
#define ICMPCREATEFILE "IcmpCreateFile"
FARPROC lpfnIcmpCreateFileG;
#define ICMPSENDECHO "IcmpSendEcho"
FARPROC lpfnIcmpSendEchoG;
#define ICMPCLOSEHANDLE "IcmpCloseHandle"
FARPROC lpfnIcmpCloseHandleG;
//
// PingIpAddress constants
//
#define PING_SEND_SIZE 32
#define PING_RECV_SIZE (0x2000 - 8)
#define PING_TTL 32
#define PING_TIMEOUT 2000L // needs to be long enough to succeed over slow links
//
// External variables
//
extern HANDLE hTerminatingG;
BOOLEAN
CopyNetbiosName(
IN NAME_BUFFER *pNames,
IN DWORD dwcNames,
OUT LPSTR pszNetbiosName
)
{
BOOLEAN fFound = FALSE;
DWORD i, iWks = 0;
CHAR szWks[NCBNAMSZ];
PCHAR p = pszNetbiosName;
//
// Find the unique workstation name.
//
again:
szWks[0] = '\0';
for (i = iWks; i < dwcNames; i++) {
RASAUTO_TRACE2(
"CopyNetbiosName: wks %15.15s (0x%x)",
pNames[i].name,
pNames[i].name[NCBNAMSZ - 1]);
if (pNames[i].name[NCBNAMSZ - 1] == 0x0 &&
!(pNames[i].name_flags & GROUP_NAME))
{
RASAUTO_TRACE1("CopyNetbiosName: iWks=%d\n", iWks);
iWks = i;
memcpy(szWks, pNames[i].name, NCBNAMSZ - 1);
break;
}
}
//
// Check to make sure we found one.
//
if (szWks[0] == '\0')
return FALSE;
//
// Find the unique server name and make
// sure it matches the workstation name.
//
for (i = 0; i < dwcNames; i++) {
RASAUTO_TRACE3(
"CopyNetbiosName: srv %15.15s (0x%x), cmp=%d",
pNames[i].name,
pNames[i].name[NCBNAMSZ - 1],
memcmp(szWks, pNames[i].name, NCBNAMSZ - 1));
if (pNames[i].name[NCBNAMSZ - 1] == 0x20 &&
!(pNames[i].name_flags & GROUP_NAME) &&
!memcmp(szWks, pNames[i].name, NCBNAMSZ - 1))
{
DWORD j;
//
// Copy up to a null or a space.
//
for (j = 0; j < NCBNAMSZ - 1; j++) {
if (pNames[i].name[j] == '\0' || pNames[i].name[j] == ' ')
break;
*p++ = pNames[i].name[j];
}
*p++ = '\0';
return TRUE;
}
}
//
// No match found. Look for another unique workstation
// name and try again if we haven't exhausted the list.
//
if (++iWks >= dwcNames)
return FALSE;
goto again;
} // CopyNetbiosName
LPTSTR
IpAddressToNetbiosName(
IN LPTSTR pszIpAddress,
IN HPORT hPort
)
{
BOOLEAN fFound;
RAS_PROTOCOLS Protocols;
DWORD i, dwcProtocols;
RASMAN_ROUTEINFO *pRoute;
WCHAR szAdapterName[MAX_PATH];
NTSTATUS status;
HANDLE fd;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
UNICODE_STRING unicodeString;
ULONG ipaddr;
CHAR szIpAddress[17];
tIPANDNAMEINFO ipAndNameInfo;
PVOID pBuffer;
DWORD dwSize;
PADAPTERSTATUS pAdapterStatus;
NAME_BUFFER *pNames;
DWORD dwcNames;
LPTSTR pszNetbiosName = NULL;
//
// Enumerate the bindings for the port to
// try to find the Netbt device.
//
GetPortProtocols(hPort, &Protocols, &dwcProtocols);
fFound = FALSE;
for (i = 0; i < dwcProtocols; i++) {
pRoute = &Protocols.RP_ProtocolInfo[i];
RASAUTO_TRACE3(
"IpAddressToNetbiosName: adapter type=%d, name=%S, xport=%S",
pRoute->RI_Type,
pRoute->RI_AdapterName,
pRoute->RI_XportName);
if (pRoute->RI_Type == IP) {
wcscpy(szAdapterName, L"\\Device\\Netbt_Tcpip_");
wcscat(szAdapterName, &pRoute->RI_AdapterName[8]);
fFound = TRUE;
break;
}
}
if (!fFound)
return NULL;
//
// Open the device and issue a remote
// adapter status command.
//
RtlInitUnicodeString(&unicodeString, szAdapterName);
InitializeObjectAttributes(
&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtCreateFile(
&fd,
SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
if (!NT_SUCCESS(status)) {
RASAUTO_TRACE1(
"IpAddressToNetbiosName: NtCreateFile failed (status=0x%x)\n",
status);
return NULL;
}
UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress));
ipaddr = inet_addr(szIpAddress);
if (ipaddr == INADDR_ANY)
return NULL;
RtlZeroMemory(&ipAndNameInfo, sizeof (ipAndNameInfo));
ipAndNameInfo.IpAddress = ntohl(ipaddr);
ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*';
ipAndNameInfo.NetbiosAddress.TAAddressCount = 1;
ipAndNameInfo.NetbiosAddress.Address[0].AddressLength =
sizeof (TDI_ADDRESS_NETBIOS);
ipAndNameInfo.NetbiosAddress.Address[0].AddressType =
TDI_ADDRESS_TYPE_NETBIOS;
ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosNameType =
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
dwSize = 2048;
for (;;) {
pBuffer = LocalAlloc(LPTR, dwSize);
if (pBuffer == NULL) {
RASAUTO_TRACE("IpAddressToNetbiosName: LocalAlloc failed");
return NULL;
}
status = NtDeviceIoControlFile(
fd,
NULL,
NULL,
NULL,
&ioStatusBlock,
IOCTL_NETBT_ADAPTER_STATUS,
&ipAndNameInfo,
sizeof (tIPANDNAMEINFO),
pBuffer,
dwSize);
if (status != STATUS_BUFFER_OVERFLOW)
break;
LocalFree(pBuffer);
dwSize *= 2;
if (dwSize >= 0xffff) {
RASAUTO_TRACE("IpAddressToNetbiosName: Unable to allocate packet");
return NULL;
}
}
if (status == STATUS_PENDING) {
status = NtWaitForSingleObject(fd, TRUE, NULL);
if (status == STATUS_SUCCESS)
status = ioStatusBlock.Status;
}
NtClose(fd);
pAdapterStatus = (PADAPTERSTATUS)pBuffer;
dwcNames = pAdapterStatus->AdapterInfo.name_count;
RASAUTO_TRACE2(
"IpAddressToNetbiosName: results (status=0x%x, dwcNames=%d)\n",
status,
dwcNames);
if (status == STATUS_SUCCESS && dwcNames) {
CHAR szNetbiosName[NCBNAMSZ + 1];
pNames = pAdapterStatus->Names;
if (CopyNetbiosName(pNames, dwcNames, szNetbiosName))
pszNetbiosName = AnsiStringToUnicodeString(szNetbiosName, NULL, 0);
}
LocalFree(pBuffer);
return pszNetbiosName;
} // IpAddressToNetbiosName
UCHAR
HexByte(
IN PCHAR p
)
{
UCHAR c;
c = *(UCHAR *)p;
if (c >= '0' && c <= '9')
return c - '0';
if ((c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f'))
{
return c - ('A' - 10);
}
return 0xff;
} // HexByte
VOID
StringToNodeNumber(
IN PCHAR pszString,
OUT PCHAR pszNode
)
{
UCHAR c1, c2;
INT i;
if (strlen(pszString) != 12) {
RASAUTO_TRACE("StringToNodeNumber: bad node number length\n");
return;
}
for (i = 0; i < 6; i++) {
c1 = HexByte(pszString++);
c2 = HexByte(pszString++);
if (c1 == 0xff || c2 == 0xff) {
RASAUTO_TRACE("StringToNodeNumber: bad digit");
return;
}
*pszNode++ = (c1 << 4) + c2;
}
} // StringToNodeNumber
VOID
NodeNumberToString(
IN PCHAR pszNode,
OUT PCHAR pszString
)
{
UCHAR c1, c2;
INT i;
sprintf(
pszString,
"%02x:%02x:%02x:%02x:%02x:%02x",
pszNode[0],
pszNode[1],
pszNode[2],
pszNode[3],
pszNode[4],
pszNode[5]);
} // NodeNumberToString
LPTSTR
IpxAddressToNetbiosName(
IN LPTSTR pszIpxAddress
)
{
NTSTATUS status;
HANDLE fd;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
UNICODE_STRING unicodeString;
PTDI_REQUEST_QUERY_INFORMATION pQuery;
PTDI_CONNECTION_INFORMATION pConnectionInformation;
PTA_NETBIOS_ADDRESS pRemoteAddress;
CHAR szIpxAddress[13];
PVOID pBuffer;
DWORD dwQuerySize, dwBufferSize;
PADAPTERSTATUS pAdapterStatus;
NAME_BUFFER *pNames;
DWORD dwcNames;
LPTSTR pszNetbiosName = NULL;
RtlInitUnicodeString(&unicodeString, L"\\Device\\Nwlnknb");
InitializeObjectAttributes(
&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtCreateFile(
&fd,
SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
if (!NT_SUCCESS(status)) {
RASAUTO_TRACE1("IpxAddressToNetbiosName: NtCreateFile failed (status=0x%x)", status);
return NULL;
}
dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) +
sizeof (TDI_CONNECTION_INFORMATION) +
sizeof (TA_NETBIOS_ADDRESS);
pQuery = LocalAlloc(LPTR, dwQuerySize);
if (pQuery == NULL) {
RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed");
return NULL;
}
pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS;
(PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation;
pQuery->RequestConnectionInformation =
(PTDI_CONNECTION_INFORMATION)(pQuery + 1);
pConnectionInformation = pQuery->RequestConnectionInformation;
pConnectionInformation->UserDataLength = 0;
pConnectionInformation->UserData = NULL;
pConnectionInformation->OptionsLength = 0;
pConnectionInformation->Options = NULL;
pConnectionInformation->RemoteAddressLength = sizeof (TDI_ADDRESS_NETBIOS);
pConnectionInformation->RemoteAddress =
(PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1);
pRemoteAddress = pConnectionInformation->RemoteAddress;
pRemoteAddress->TAAddressCount = 1;
pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
pRemoteAddress->Address[0].Address[0].NetbiosNameType =
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
UnicodeStringToAnsiString(
pszIpxAddress,
szIpxAddress,
sizeof (szIpxAddress));
RtlZeroMemory((PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName, 10);
StringToNodeNumber(
(PCHAR)szIpxAddress,
(PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName[10]);
RASAUTO_TRACE6("IpxAddressToNetbiosName: Node=%02x:%02x:%02x:%02x:%02x:%02x\n",
pRemoteAddress->Address[0].Address[0].NetbiosName[10],
pRemoteAddress->Address[0].Address[0].NetbiosName[11],
pRemoteAddress->Address[0].Address[0].NetbiosName[12],
pRemoteAddress->Address[0].Address[0].NetbiosName[13],
pRemoteAddress->Address[0].Address[0].NetbiosName[14],
pRemoteAddress->Address[0].Address[0].NetbiosName[15]);
dwBufferSize = 2048;
for (;;) {
pBuffer = LocalAlloc(LPTR, dwBufferSize);
if (pBuffer == NULL) {
RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed");
LocalFree(pQuery);
return NULL;
}
status = NtDeviceIoControlFile(
fd,
NULL,
NULL,
NULL,
&ioStatusBlock,
IOCTL_TDI_QUERY_INFORMATION,
pQuery,
dwQuerySize,
pBuffer,
dwBufferSize);
if (status != STATUS_BUFFER_OVERFLOW)
break;
LocalFree(pBuffer);
dwBufferSize *= 2;
if (dwBufferSize >= 0xffff) {
RASAUTO_TRACE("IpxAddressToNetbiosName: Unable to allocate packet");
LocalFree(pQuery);
return NULL;
}
}
if (status == STATUS_PENDING) {
status = NtWaitForSingleObject(fd, TRUE, NULL);
if (status == STATUS_SUCCESS)
status = ioStatusBlock.Status;
}
NtClose(fd);
pAdapterStatus = (PADAPTERSTATUS)pBuffer;
dwcNames = pAdapterStatus->AdapterInfo.name_count;
RASAUTO_TRACE2(
"IpxAddressToNetbiosName: results (status=0x%x, dwcNames=%d)",
status,
dwcNames);
if (status == STATUS_SUCCESS && dwcNames) {
CHAR szNetbiosName[NCBNAMSZ + 1];
pNames = pAdapterStatus->Names;
if (CopyNetbiosName(pNames, dwcNames, szNetbiosName))
pszNetbiosName = AnsiStringToUnicodeString(pNames->name, NULL, 0);
}
LocalFree(pBuffer);
LocalFree(pQuery);
return pszNetbiosName;
} // IpxAddressToNetbiosName
BOOLEAN
NetbiosFindName(
IN LPTSTR *pszDevices,
IN DWORD dwcDevices,
IN LPTSTR pszAddress
)
{
NTSTATUS *pStatus;
PHANDLE pfd;
PHANDLE pEvent;
POBJECT_ATTRIBUTES pObjectAttributes;
PIO_STATUS_BLOCK pIoStatusBlock;
PUNICODE_STRING pUnicodeString;
PTDI_REQUEST_QUERY_INFORMATION pQuery;
PTDI_CONNECTION_INFORMATION pConnectionInformation;
PTA_NETBIOS_ADDRESS pRemoteAddress;
CHAR szAddress[NCBNAMSZ];
PVOID *pBuffer;
DWORD i, dwQuerySize, dwBufferSize;
PADAPTERSTATUS pAdapterStatus;
NAME_BUFFER *pNames;
DWORD dwcWait, dwcNames;
BOOLEAN bFound = FALSE;
//
// If there are no Netbios devices, then we're done.
//
if (pszDevices == NULL || !dwcDevices)
return FALSE;
//
// Allocate our arrays up front.
//
pStatus = (NTSTATUS *)LocalAlloc(LPTR, dwcDevices * sizeof (NTSTATUS));
if (pStatus == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
return FALSE;
}
pfd = (PHANDLE)LocalAlloc(LPTR, dwcDevices * sizeof (HANDLE));
if (pfd == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
return FALSE;
}
pUnicodeString = (PUNICODE_STRING)LocalAlloc(LPTR, dwcDevices * sizeof (UNICODE_STRING));
if (pUnicodeString == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
return FALSE;
}
pEvent = (PHANDLE)LocalAlloc(
LPTR,
dwcDevices * sizeof (HANDLE));
if (pEvent == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
return FALSE;
}
pObjectAttributes = (POBJECT_ATTRIBUTES)LocalAlloc(
LPTR,
dwcDevices * sizeof (OBJECT_ATTRIBUTES));
if (pObjectAttributes == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
LocalFree(pEvent);
return FALSE;
}
pIoStatusBlock = (PIO_STATUS_BLOCK)LocalAlloc(
LPTR,
dwcDevices * sizeof (IO_STATUS_BLOCK));
if (pIoStatusBlock == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
LocalFree(pEvent);
LocalFree(pObjectAttributes);
return FALSE;
}
pBuffer = LocalAlloc(LPTR, dwcDevices * sizeof (PVOID));
if (pBuffer == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
LocalFree(pEvent);
LocalFree(pObjectAttributes);
LocalFree(pIoStatusBlock);
return FALSE;
}
//
// Allocate and initialize our query structure.
// We will give the same query to all the devices.
//
dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) +
sizeof (TDI_CONNECTION_INFORMATION) +
sizeof (TA_NETBIOS_ADDRESS);
pQuery = LocalAlloc(LPTR, dwQuerySize);
if (pQuery == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
LocalFree(pEvent);
LocalFree(pObjectAttributes);
LocalFree(pIoStatusBlock);
return FALSE;
}
pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS;
(PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation;
pQuery->RequestConnectionInformation =
(PTDI_CONNECTION_INFORMATION)(pQuery + 1);
pConnectionInformation = pQuery->RequestConnectionInformation;
pConnectionInformation->UserDataLength = 0;
pConnectionInformation->UserData = NULL;
pConnectionInformation->OptionsLength = 0;
pConnectionInformation->Options = NULL;
pConnectionInformation->RemoteAddressLength = sizeof (TA_NETBIOS_ADDRESS);
pConnectionInformation->RemoteAddress =
(PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1);
pRemoteAddress = pConnectionInformation->RemoteAddress;
pRemoteAddress->TAAddressCount = 1;
pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
pRemoteAddress->Address[0].Address[0].NetbiosNameType =
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
UnicodeStringToAnsiString(
pszAddress,
szAddress,
sizeof (szAddress));
RtlFillMemory(
(PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName,
NCBNAMSZ,
' ');
//
// Make sure the Netbios name is in uppercase!
//
_strupr(szAddress);
RtlCopyMemory(
(PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName,
szAddress,
strlen(szAddress));
pRemoteAddress->Address[0].Address[0].NetbiosName[NCBNAMSZ - 1] = '\0';
RASAUTO_TRACE1("NetbiosFindName: address=%s", szAddress);
//
// Initialize the OBJECT_ATTRIBUTES structure,
// open the device, and start the query
// for each device.
//
for (i = 0; i < dwcDevices; i++) {
pBuffer[i] = NULL;
RtlInitUnicodeString(&pUnicodeString[i], pszDevices[i]);
InitializeObjectAttributes(
&pObjectAttributes[i],
&pUnicodeString[i],
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
pEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pEvent[i] == NULL) {
RASAUTO_TRACE("NetbiosFindName: CreateEvent failed");
goto done;
}
pStatus[i] = NtCreateFile(
&pfd[i],
FILE_READ_DATA|FILE_WRITE_DATA,
&pObjectAttributes[i],
&pIoStatusBlock[i],
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
if (!NT_SUCCESS(pStatus[i])) {
RASAUTO_TRACE1("NetbiosFindName: NtCreateFile failed (status=0x%x)", pStatus[i]);
continue;
}
//
// Allocate the results buffer.
//
dwBufferSize = 2048;
for (;;) {
pBuffer[i] = LocalAlloc(LPTR, dwBufferSize);
if (pBuffer[i] == NULL) {
RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
goto done;
}
pStatus[i] = NtDeviceIoControlFile(
pfd[i],
pEvent[i],
NULL,
NULL,
&pIoStatusBlock[i],
IOCTL_TDI_QUERY_INFORMATION,
pQuery,
dwQuerySize,
pBuffer[i],
dwBufferSize);
if (pStatus[i] != STATUS_BUFFER_OVERFLOW)
break;
LocalFree(pBuffer[i]);
pBuffer[i] = NULL;
dwBufferSize *= 2;
if (dwBufferSize >= 0xffff) {
RASAUTO_TRACE("NetbiosFindName: Unable to allocate packet");
break;
}
}
}
//
// Determine whether any of the
// requests returned STATUS_SUCCESS.
//
RASAUTO_TRACE("NetbiosFindName: checking for STATUS_SUCCESS");
dwcWait = 0;
for (i = 0; i < dwcDevices; i++) {
RASAUTO_TRACE2("NetbiosFindName: %S: status=%d", pszDevices[i], pStatus[i]);
if (pStatus[i] == STATUS_SUCCESS) {
pAdapterStatus = (PADAPTERSTATUS)pBuffer[i];
dwcNames = pAdapterStatus->AdapterInfo.name_count;
RASAUTO_TRACE2(
"NetbiosFindName: %S: dwcNames=%d",
pszDevices[i],
dwcNames);
if (dwcNames) {
bFound = TRUE;
goto done;
}
}
else if (pStatus[i] == STATUS_PENDING)
dwcWait++;
}
//
// If we didn't find a successful return,
// then wait for the others to complete.
//
RASAUTO_TRACE1("NetbiosFindName: dwcWait=%d", dwcWait);
for (i = 0; i < dwcWait; i++) {
NTSTATUS status;
DWORD dwiDevice;
status = WaitForMultipleObjects(dwcDevices, pEvent, FALSE, INFINITE);
RASAUTO_TRACE1("NetbiosFindName: WaitForMultipleObjects returned 0x%x", status);
if (status == WAIT_FAILED) {
RASAUTO_TRACE1(
"NetbiosFindName: WaitForMultipleObjects failed (status=0x%x)",
GetLastError());
goto done;
}
dwiDevice = (DWORD)status - WAIT_OBJECT_0;
if (dwiDevice >= dwcDevices) {
RASAUTO_TRACE(
"NetbiosFindName: WaitForMultipleObjects returned STATUS_ABANDONED?");
goto done;
}
pStatus[dwiDevice] = pIoStatusBlock[dwiDevice].Status;
RASAUTO_TRACE2(
"NetbiosFindName: %S returned status 0x%x from wait",
pszDevices[dwiDevice],
pStatus[dwiDevice]);
if (pStatus[dwiDevice] == STATUS_SUCCESS) {
pAdapterStatus = (PADAPTERSTATUS)pBuffer[dwiDevice];
dwcNames = pAdapterStatus->AdapterInfo.name_count;
RASAUTO_TRACE2(
"NetbiosFindName: %S: dwcNames=%d",
pszDevices[dwiDevice],
dwcNames);
if (dwcNames) {
bFound = TRUE;
goto done;
}
}
}
done:
//
// Free the resources associated with
// each device.
//
for (i = 0; i < dwcDevices; i++) {
RASAUTO_TRACE4(
"NetbiosFindName: pIoStatusBlock[%d]=0x%x, pBuffer[%d]=0x%x",
i,
&pIoStatusBlock[i],
i,
pBuffer[i]);
if (pfd[i] != NULL)
{
(void)NtCancelIoFile(pfd[i], &pIoStatusBlock[i]);
NtClose(pfd[i]);
}
if (pEvent[i] != NULL)
CloseHandle(pEvent[i]);
if (pBuffer[i] != NULL)
LocalFree(pBuffer[i]);
}
//
// Free the buffers we allocated above.
//
LocalFree(pStatus);
LocalFree(pfd);
LocalFree(pUnicodeString);
LocalFree(pEvent);
LocalFree(pObjectAttributes);
LocalFree(pIoStatusBlock);
LocalFree(pBuffer);
return bFound;
} // NetbiosFindName
struct hostent *
IpAddressToHostent(
IN LPTSTR pszInetAddress
)
{
CHAR szInetAddress[ACD_ADDR_INET_LEN];
ULONG inaddr;
struct hostent *hp;
UnicodeStringToAnsiString(
pszInetAddress,
szInetAddress,
sizeof (szInetAddress));
inaddr = inet_addr(szInetAddress);
//
// Disable the address so when we call gethostbyname(),
// we won't cause an autodial attempt. Enable it after
// we're done.
//
SetAddressDisabled(pszInetAddress, TRUE);
hp = gethostbyaddr((char *)&inaddr, 4, PF_INET);
SetAddressDisabled(pszInetAddress, FALSE);
return hp;
} // InetAddressToHostent
struct hostent *
InetAddressToHostent(
IN LPTSTR pszInetAddress
)
{
CHAR szInetAddress[ACD_ADDR_INET_LEN];
struct hostent *hp;
UnicodeStringToAnsiString(
pszInetAddress,
szInetAddress,
sizeof (szInetAddress));
//
// Disable the address so when we call gethostbyname(),
// we won't cause an autodial attempt. Enable it after
// we're done.
//
SetAddressDisabled(pszInetAddress, TRUE);
hp = gethostbyname(szInetAddress);
SetAddressDisabled(pszInetAddress, FALSE);
return hp;
} // InetAddressToHostEnt
BOOLEAN
PingIpAddress(
IN LPTSTR pszIpAddress
)
/*++
DESCRIPTION
Determine whether an IP address is accessible by pinging it.
ARGUMENTS
lpszAddress: the IP address
RETURN VALUE
TRUE if lpszAddress is accessible, FALSE otherwise.
--*/
{
BOOLEAN fSuccess = FALSE;
LONG inaddr;
char szIpAddress[17];
int i, nReplies, nTry;
char *lpSendBuf = NULL, *lpRecvBuf = NULL;
HANDLE hIcmp = NULL;
IP_OPTION_INFORMATION SendOpts;
PICMP_ECHO_REPLY lpReply;
UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress));
inaddr = inet_addr(szIpAddress);
RASAUTO_TRACE2("PingIpAddress: IP address=(%s, 0x%x)", szIpAddress, inaddr);
//
// Check to make sure we loaded icmp.dll.
//
if (hIcmpG == NULL) {
RASAUTO_TRACE("PingIpAddress: icmp.dll not loaded!");
return FALSE;
}
//
// Open the icmp device.
//
hIcmp = (HANDLE)(*lpfnIcmpCreateFileG)();
if (hIcmp == INVALID_HANDLE_VALUE) {
RASAUTO_TRACE("PingIpAddress: IcmpCreateFile failed");
return FALSE;
}
//
// Allocate the send and receive buffers.
//
lpSendBuf = LocalAlloc(LMEM_FIXED, PING_SEND_SIZE);
if (lpSendBuf == NULL) {
RASAUTO_TRACE("PingIpAddress: LocalAlloc failed");
goto done;
}
lpRecvBuf = LocalAlloc(LMEM_FIXED, PING_RECV_SIZE);
if (lpRecvBuf == NULL) {
RASAUTO_TRACE("PingIpAddress: LocalAlloc failed");
goto done;
}
//
// Initialize the send buffer pattern.
//
for (i = 0; i < PING_SEND_SIZE; i++)
lpSendBuf[i] = 'a' + (i % 23);
//
// Initialize the send options.
//
SendOpts.OptionsData = (unsigned char FAR *)0;
SendOpts.OptionsSize = 0;
SendOpts.Ttl = PING_TTL;
SendOpts.Tos = 0;
SendOpts.Flags = 0;
//
// Ping the host.
//
for (nTry = 0; nTry < 3; nTry++) {
DWORD dwTimeout = 750;
#ifdef notdef
if (nTry < 2)
dwTimeout = 750;
else
dwTimeout = 2000;
#endif
//
// Check to make sure the service isn't shutting
// down before we start on our next iteration.
//
if (WaitForSingleObject(hTerminatingG, 0) != WAIT_TIMEOUT) {
RASAUTO_TRACE("PingIpAddress: shutting down");
LocalFree(lpRecvBuf);
LocalFree(lpSendBuf);
return FALSE;
}
nReplies = (int) (*lpfnIcmpSendEchoG)(
hIcmp,
inaddr,
lpSendBuf,
(unsigned short)PING_SEND_SIZE,
&SendOpts,
lpRecvBuf,
PING_RECV_SIZE,
dwTimeout);
//
// Look at the responses to see
// if any are successful.
//
for (lpReply = (PICMP_ECHO_REPLY)lpRecvBuf, i = 0;
i < nReplies;
lpReply++, i++)
{
RASAUTO_TRACE2(
"PingIpAddress: ping reply status[%d]=%d",
i,
lpReply->Status);
//
// Unless the status is IP_REQ_TIMED_OUT,
// we're done.
//
fSuccess = (lpReply->Status == IP_SUCCESS);
if (lpReply->Status != IP_REQ_TIMED_OUT)
goto done;
}
}
//
// Clean up.
//
done:
if (lpRecvBuf != NULL)
LocalFree(lpRecvBuf);
if (lpSendBuf != NULL)
LocalFree(lpSendBuf);
if (hIcmp != NULL)
(*lpfnIcmpCloseHandleG)(hIcmp);
return fSuccess;
} // PingIpAddress
VOID
LoadIcmpDll(VOID)
{
hIcmpG = LoadLibrary(ICMP_MODULE);
if (hIcmpG == NULL)
return;
lpfnIcmpCreateFileG = GetProcAddress(hIcmpG, ICMPCREATEFILE);
lpfnIcmpSendEchoG = GetProcAddress(hIcmpG, ICMPSENDECHO);
lpfnIcmpCloseHandleG = GetProcAddress(hIcmpG, ICMPCLOSEHANDLE);
if (lpfnIcmpCreateFileG == NULL ||
lpfnIcmpSendEchoG == NULL ||
lpfnIcmpCloseHandleG == NULL)
{
FreeLibrary(hIcmpG);
hIcmpG = NULL;
return;
}
} // LoadIcmpDll
VOID
UnloadIcmpDll(VOID)
{
if (hIcmpG != NULL) {
FreeLibrary(hIcmpG);
hIcmpG = NULL;
}
}