windows-nt/Source/XPSP1/NT/net/tapi/skywalker/mdhcp/local.cpp
2020-09-26 16:20:57 +08:00

500 lines
14 KiB
C++

// MDHCP COM wrapper
// Copyright (c) 1998-1999 Microsoft Corporation
//
// Module: local.cpp
//
// Author: Zoltan Szilagyi
//
// This file contains my implementation of local address allocation, plus a
// function to see if we are doing local address allocation (based on the
// registry). Prototypes are in local.cpp.
//
// These functions are called within CMDhcp, and just delegate calls to the
// corresponding C API calls for MDHCP if the registry indicates that we
// are using MDHCP. Otherwise they try to mimic the MDHCP behavior using
// local allocation.
#include "stdafx.h"
#include "resource.h"
#include "local.h"
#include <string.h>
#include <time.h>
#include <winsock2.h>
DWORD
LocalEnumerateScopes(
IN OUT PMCAST_SCOPE_ENTRY pScopeList,
IN OUT PDWORD pScopeLen,
OUT PDWORD pScopeCount,
IN OUT BOOL * pfLocal
)
/*++
Routine Description:
This routine enumerates the multicast scopes available on the network.
Arguments:
pScopeList - pointer to the buffer where the scopelist is to be retrieved.
This parameter can be NULL if only the length of the buffer is
being retrieved.
When this buffer is NULL, the API will force the re-query of the
scope list from the MDHCP servers.
pScopeLen - Pointer to a variable that specifies the size, in bytes, of the
buffer pointed to by the pScopeList parameter. When the function returns,
this variable contains the size of the data copied to pScopeList;
The pScopeLen parameter can not be NULL.
If the buffer specified by pScopeList parameter is not large enough
to hold the data, the function returns the value ERROR_MORE_DATA, and
stores the required buffer size, in bytes, into the variable pointed
to by pScopeLen.
If pScopeList is NULL, and pScopeLen is non-NULL, the function returns
ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable
pointed to by pScopeLen. This lets an application determine the best
way to allocate a buffer for the scope list.
pScopeCount - Pointer to a variable that will store total number of scopes returned
in the pScopeList buffer.
pfLocal - points to a BOOL value that on exit is set to true if this
is a locally-generated scope. If set to true on entry, then
we go straight to local alloc (this usually means that this
is the second call and the previous call returned local
alloc)
Return Value:
The status of the operation.
--*/
{
_ASSERTE( pfLocal );
if ( *pfLocal == FALSE )
{
DWORD dwResult = McastEnumerateScopes(
AF_INET, // this means IPv4
pScopeList == NULL, // requery if asking for num scopes
pScopeList,
pScopeLen,
pScopeCount);
if ( dwResult == ERROR_SUCCESS )
{
*pfLocal = FALSE;
return dwResult;
}
}
_ASSERTE(pScopeLen);
_ASSERTE(pScopeCount);
*pfLocal = TRUE;
//
// First set up the string for the name of the scope.
//
const int ciAllocSize = 2048;
static BOOL fFirstCall = TRUE;
static WCHAR wszScopeDesc[ciAllocSize] = L"";
static DWORD dwScopeDescLen = 0;
if ( fFirstCall )
{
//
// Get the string from the string table.
//
int iReturn = LoadString( _Module.GetModuleInstance(),
IDS_LocalScopeName,
wszScopeDesc,
ciAllocSize - 1 );
if ( iReturn == 0 )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwScopeDescLen = sizeof(WCHAR) * (lstrlenW(wszScopeDesc) + 1);
fFirstCall = FALSE;
}
//
// When doing local allocation, there is only one scope. Return info about it.
//
*pScopeCount = 1;
*pScopeLen = sizeof(MCAST_SCOPE_ENTRY) + dwScopeDescLen;
if (pScopeList != NULL)
{
// wszDest points to the place in pScopeList right after the contents
// of the MCAST_SCOPE_ENTRY structure.
WCHAR * wszDest = (WCHAR *) (((BYTE *) pScopeList) + sizeof(MCAST_SCOPE_ENTRY));
CopyMemory(wszDest, wszScopeDesc, dwScopeDescLen);
pScopeList[0].ScopeCtx.ScopeID.IpAddrV4 = 0x01000000; // 1 -- net byte order
pScopeList[0].ScopeCtx.ServerID.IpAddrV4 = 0x0100007f; // 127.0.0.1 localhost -- net byte order
pScopeList[0].ScopeCtx.Interface.IpAddrV4 = 0x0100007f; // 127.0.0.1 loopback if -- net byte order
pScopeList[0].ScopeDesc.Length = (USHORT) dwScopeDescLen;
pScopeList[0].ScopeDesc.MaximumLength = (USHORT) dwScopeDescLen;
pScopeList[0].ScopeDesc.Buffer = wszDest;
pScopeList[0].TTL = 15;
}
return ERROR_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// ConvertLeaseInfoToRequest
//
// Given pRequestInfo, which points to a valid, contiguously stored
// MCAST_LEASE_INFO (aka MCAST_LEASE_RESPONSE) structure for a request, fill
// out the MCAST_LEASE_REQUEST structure pointed to by pRealRequest. The
// pRealRequest structure points to the same addresses array as the
// pRequestInfo structure, which makes it convenient to allocate on the stack.
//
void
ConvertLeaseInfoToRequest(
IN PMCAST_LEASE_INFO pRequestInfo,
OUT PMCAST_LEASE_REQUEST pRealRequest
)
{
DWORD dwDuration = (DWORD)(pRequestInfo->LeaseEndTime - pRequestInfo->LeaseStartTime);
pRealRequest->LeaseStartTime = pRequestInfo->LeaseStartTime;
pRealRequest->MaxLeaseStartTime = pRequestInfo->LeaseStartTime;
pRealRequest->LeaseDuration = dwDuration;
pRealRequest->MinLeaseDuration = dwDuration;
pRealRequest->ServerAddress = pRequestInfo->ServerAddress;
pRealRequest->MinAddrCount = pRequestInfo->AddrCount;
pRealRequest->AddrCount = pRequestInfo->AddrCount;
pRealRequest->pAddrBuf = pRequestInfo->pAddrBuf; // see above
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
DWORD
LocalRequestAddress(
IN BOOL fLocal,
IN LPMCAST_CLIENT_UID pRequestID,
IN PMCAST_SCOPE_CTX pScopeCtx,
IN PMCAST_LEASE_INFO pAddrRequest,
IN OUT PMCAST_LEASE_INFO pAddrResponse
)
/*++
Routine Description:
This routine request multicast address(es) from the MDHCP server.
Arguments:
fLocal - if true, do not go to server
pRequestID - Unique identifier for this request. Client is responsible for
generating unique identifier for every request. One recommendation
is to use application specific context hashed by time.
pRequestIDLen - Length of the pRequestID buffer.
pScopeCtx - Pointer to the context of the scope from which the address is to
be allocated. Scope context has to be retrieved via MDhcpEnumerateScopes
call before calling this.
pAddrRequest - Pointer to the block containing all the parameters pertaining
to multicast address request.
pAddrResponse - Pointer to the block which contains the response paramters for
the multicast address request.
Return Value:
The status of the operation.
--*/
{
if ( ! fLocal )
{
MCAST_LEASE_REQUEST RealRequest;
ConvertLeaseInfoToRequest(
pAddrRequest,
& RealRequest
);
//
// Tell the C API where to stick the returned addresses and how many
// we have space for.
//
pAddrResponse->pAddrBuf =
( (PBYTE) pAddrResponse ) + sizeof( MCAST_LEASE_INFO );
pAddrResponse->AddrCount = RealRequest.AddrCount;
return McastRequestAddress(AF_INET, // this means IPv4
pRequestID,
pScopeCtx,
& RealRequest,
pAddrResponse);
}
//
// Local allocation case...
//
DWORD dwAddrCount = pAddrRequest->AddrCount;
if (dwAddrCount == 0)
{
return ERROR_INVALID_DATA;
}
//
// Seed the random number generator the first time we are called.
//
static bool fFirstCall = true;
if ( fFirstCall )
{
srand( (unsigned)time( NULL ) );
fFirstCall = false;
}
//
// We always grant whatever request the user wants. Start by copying the
// relevant fields. This gives us valid start time, end time, and
// address count. Still need to fill out serveraddress and array of
// returned addresses.
//
CopyMemory(pAddrResponse,
pAddrRequest,
sizeof(MCAST_LEASE_INFO));
//
// The array of returned addresses will be contiguous in the strucutre.
//
pAddrResponse->pAddrBuf =
( (PBYTE) pAddrResponse ) + sizeof( MCAST_LEASE_INFO );
//
// The server address is the local host: 127.0.0.1 in net byte order
//
pAddrResponse->ServerAddress.IpAddrV4 = 0x0100007f;
//
// Allocate the random addresses (Based on Rajeev's code)
// note: we do not support ipv6 (ipv4 assumed throughout)
//
// get mask
DWORD dwNetworkMask = 0xffff8000; // 255.255.128.0
// if the desired number of addresses are more than the range allows
if ( dwAddrCount > ~ dwNetworkMask )
{
return ERROR_INVALID_DATA;
}
// get base address
DWORD dwBaseAddress = 0xe0028000; // 224.2.128.0
// transform base address (AND base address with mask)
dwBaseAddress &= dwNetworkMask;
//
// choose unmasked bits of generated number and OR with transformed
// base address
// ZoltanS: added - 1 so that we can give out odd addresses too
//
DWORD * pdwAddresses = (DWORD *) pAddrResponse->pAddrBuf;
pdwAddresses[0] = htonl(
dwBaseAddress | ( rand() & ( ~ dwNetworkMask - (dwAddrCount - 1) )) );
//
// Set the rest of the addresses.
//
DWORD dwCurrAddr = ntohl(pdwAddresses[0]);
for (DWORD i = 1; i < dwAddrCount; i++)
{
pdwAddresses[i] = htonl( ++dwCurrAddr );
}
return ERROR_SUCCESS;
}
DWORD
LocalRenewAddress(
IN BOOL fLocal,
IN LPMCAST_CLIENT_UID pRequestID,
IN PMCAST_LEASE_INFO pRenewRequest,
IN OUT PMCAST_LEASE_INFO pRenewResponse
)
/*++
Routine Description:
This routine renews multicast address(es) from the MDHCP server.
Arguments:
fLocal - if true, do not go to server
pRequestID - Unique identifier that was used when the address(es) were
obtained initially.
RequestIDLen - Length of the pRequestID buffer.
pRenewRequest - Pointer to the block containing all the parameters pertaining
to the renew request.
pRenewResponse - Pointer to the block which contains the response paramters for
the renew request.
Return Value:
The status of the operation.
--*/
{
if ( ! fLocal )
{
MCAST_LEASE_REQUEST RealRequest;
ConvertLeaseInfoToRequest(
pRenewRequest,
& RealRequest
);
//
// Tell the C API where to stick the returned addresses and how many
// we have space for.
//
pRenewResponse->pAddrBuf =
( (PBYTE) pRenewResponse ) + sizeof( MCAST_LEASE_INFO );
pRenewResponse->AddrCount = RealRequest.AddrCount;
return McastRenewAddress(AF_INET, // this means IPv4
pRequestID,
& RealRequest,
pRenewResponse);
}
//
// Local renewal...
//
//
// We always grant whatever renewal the user wants. Just copy the
// structure from the request to the response, keeping in mind
// that the pAddrBuf member has to change to avoid referencing
// the old structure.
//
// Note that we ASSUME that the response strucutre is big enough
// to hold the response including all the addresses, allocated
// CONTIGUOUSLY.
// note: assumes IPv4
//
CopyMemory( pRenewResponse,
pRenewRequest,
sizeof(MCAST_LEASE_INFO) +
sizeof(DWORD) * pRenewRequest->AddrCount
);
//
// The pAddrbuf member has to change to avoid referencing the old
// structure. Make it point to the end of this one.
//
pRenewResponse->pAddrBuf =
( (PBYTE) pRenewResponse ) + sizeof( MCAST_LEASE_INFO );
return ERROR_SUCCESS;
}
DWORD
LocalReleaseAddress(
IN BOOL fLocal,
IN LPMCAST_CLIENT_UID pRequestID,
IN PMCAST_LEASE_INFO pReleaseRequest
)
/*++
Routine Description:
This routine releases multicast address(es) from the MDHCP server.
Arguments:
pRequestID - Unique identifier that was used when the address(es) were
obtained initially.
RequestIDLen - Length of the pRequestID buffer.
pReleaseRequest - Pointer to the block containing all the parameters pertaining
to the release request.
Return Value:
The status of the operation.
--*/
{
if ( ! fLocal )
{
MCAST_LEASE_REQUEST RealRequest;
ConvertLeaseInfoToRequest(
pReleaseRequest,
& RealRequest
);
return McastReleaseAddress(AF_INET, // this means IPv4
pRequestID,
& RealRequest);
}
// locally, we don't care about releases.
return ERROR_SUCCESS;
}
// eof