Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1439 lines
34 KiB

/*
Copyright (c) 1998, Microsoft Corporation, all rights reserved
Description:
History:
*/
#include "rassrvr_.h"
// This flag indicates if netbios options are to be preserved for
// the ras server adapter or not.
BOOL g_fDisableNetbiosOverTcpip = FALSE;
extern BOOL HelperInitialized;
BOOL WINAPI ShutdownHandlerRoutine ( DWORD dwCtrlType )
{
if ( CTRL_SHUTDOWN_EVENT == dwCtrlType )
{
TraceHlp("ShutdownHandlerRoutine. Got Shutdown Event. Releasing DhcpAddresses");
//uninitialize Dhcp addresses here.
RasDhcpUninitialize();
return TRUE;
}
return FALSE;
}
/*
Returns:
Notes:
*/
DWORD
RasSrvrInitialize(
IN MPRADMINGETIPADDRESSFORUSER* pfnMprGetAddress,
IN MPRADMINRELEASEIPADDRESS* pfnMprReleaseAddress
)
{
DNS_STATUS DnsStatus;
HINSTANCE hInstance;
DWORD dwErr = NO_ERROR;
TraceHlp("RasSrvrInitialize");
g_fDisableNetbiosOverTcpip = FALSE;
//
// Read the key that tells whether to disable netbios over ip
//
{
HKEY hkeyRASIp;
dwErr = RegOpenKeyExA(
HKEY_LOCAL_MACHINE, REGKEY_RAS_IP_PARAM_A, 0,
KEY_READ, &hkeyRASIp);
if(NO_ERROR == dwErr)
{
DWORD dwSize = sizeof(DWORD) , dwData = 0, dwType;
dwErr = RegQueryValueExA(
hkeyRASIp,
"DisableNetbiosOverTcpip",
NULL, &dwType, (BYTE *) &dwData,
&dwSize);
if( (NO_ERROR == dwErr)
&& (dwType == REG_DWORD))
{
g_fDisableNetbiosOverTcpip = !!(dwData);
}
RegCloseKey(hkeyRASIp);
dwErr = NO_ERROR;
}
}
TraceHlp("DisableNetbt = %d", g_fDisableNetbiosOverTcpip);
// Keep a ref count in HelperUninitialize, and call HelperUninitialize
// once for each time you call HelperInitialize.
dwErr = HelperInitialize(&hInstance);
if (NO_ERROR != dwErr)
{
// goto LDone; Don't do this. The CriticalSections are not available.
return(dwErr);
}
EnterCriticalSection(&RasSrvrCriticalSection);
if (RasSrvrRunning)
{
goto LDone;
}
//Set the control handler for the process here
if ( !SetProcessShutdownParameters( 510 , SHUTDOWN_NORETRY ) )
{
TraceHlp("SetProcessShutdownParameters failed and returned 0x%x. This is not a fatal error so continuing on with server start", GetLastError());
}
else
{
if ( !SetConsoleCtrlHandler( ShutdownHandlerRoutine, TRUE ) )
{
TraceHlp("SetConsoleCtrlHandler failed and returned 0x%x. This is not a fatal error so continuing on with server start", GetLastError());
}
}
dwErr = rasSrvrInitAdapterName();
if (NO_ERROR != dwErr)
{
goto LDone;
}
dwErr = MprAdminMIBServerConnect(NULL, &RasSrvrHMIBServer);
if (NO_ERROR != dwErr)
{
TraceHlp("MprAdminMIBServerConnect failed and returned 0x%x", dwErr);
goto LDone;
}
pfnMprAdminGetIpAddressForUser = pfnMprGetAddress;
pfnMprAdminReleaseIpAddress = pfnMprReleaseAddress;
DnsStatus = DnsDhcpSrvRegisterInit(
NULL, // no creds
0 // no special queue length limit
);
if (DNSDHCP_SUCCESS != DnsStatus)
{
dwErr = DnsStatus;
TraceHlp("DnsDhcpSrvRegisterInit failed and returned 0x%x", dwErr);
goto LDone;
}
HelperChangeNotification();
dwErr = RasSrvrStart();
if (NO_ERROR != dwErr)
{
TraceHlp("RasSrvrStart failed and returned 0x%x", dwErr);
goto LDone;
}
RasSrvrRunning = TRUE;
LDone:
//
// Moved this up above RasSrvrUninitialize based on the
// comment in that function. We should not call RasSrvrStop
// when holding this critical section.
//
LeaveCriticalSection(&RasSrvrCriticalSection);
if (NO_ERROR != dwErr)
{
RasSrvrUninitialize();
}
return(dwErr);
}
/*
Returns:
VOID
Notes:
*/
VOID
RasSrvrUninitialize(
VOID
)
{
AINODE* pAiNode;
DNS_STATUS DnsStatus;
DWORD dwErr;
TraceHlp("RasSrvrUninitialize");
RasSrvrRunning = FALSE;
/*
Don't call RasSrvrStop when you have RasSrvrCriticalSection. It will call
RasDhcpUninitialize, which will call RasDhcpTimerUninitialize, which will
wait till all the timer work itemss are done. The timer work item could be
rasDhcpAllocateAddress or rasDhcpRenewLease, both of which can call
RasSrvrDhcpCallback, which tries to acquire RasSrvrCriticalSection.
*/
SetConsoleCtrlHandler(ShutdownHandlerRoutine, FALSE);
RasSrvrStop(FALSE /* fParametersChanged */);
EnterCriticalSection(&RasSrvrCriticalSection);
if (NULL != RasSrvrHMIBServer)
{
MprAdminMIBServerDisconnect(RasSrvrHMIBServer);
RasSrvrHMIBServer = NULL;
}
pfnMprAdminGetIpAddressForUser = NULL;
pfnMprAdminReleaseIpAddress = NULL;
DnsStatus = DnsDhcpSrvRegisterTerm();
if (DNSDHCP_SUCCESS != DnsStatus)
{
TraceHlp("DnsDhcpSrvRegisterTerm failed and returned 0x%x",
DnsStatus);
}
if (NULL != PDisableDhcpInformServer)
{
PDisableDhcpInformServer();
}
g_fDisableNetbiosOverTcpip = FALSE;
LeaveCriticalSection(&RasSrvrCriticalSection);
}
/*
Returns:
Notes:
*/
DWORD
RasSrvrStart(
VOID
)
{
DWORD dwErr;
TraceHlp("RasSrvrStart");
EnterCriticalSection(&RasSrvrCriticalSection);
if (HelperRegVal.fUseDhcpAddressing)
{
dwErr = RasDhcpInitialize();
}
else
{
dwErr = RasStatInitialize();
}
LeaveCriticalSection(&RasSrvrCriticalSection);
return(dwErr);
}
/*
Returns:
VOID
Notes:
*/
VOID
RasSrvrStop(
IN BOOL fParametersChanged
)
{
AINODE* pAiNode;
CHAR szIpAddress[MAXIPSTRLEN + 1];
CHAR* sz;
DWORD dwNumBytes;
DWORD dwErr;
WANARP_MAP_SERVER_ADAPTER_INFO info;
TraceHlp("RasSrvrStop");
RasDhcpUninitialize();
EnterCriticalSection(&RasSrvrCriticalSection);
if ( fParametersChanged
&& (0 != RasSrvrNboServerIpAddress))
{
AbcdSzFromIpAddress(RasSrvrNboServerIpAddress, szIpAddress);
sz = szIpAddress;
LogEvent(EVENTLOG_WARNING_TYPE, ROUTERLOG_SRV_ADDR_CHANGED, 1,
(CHAR**)&sz);
}
if (!fParametersChanged)
{
while (NULL != RasSrvrAcquiredIpAddresses)
{
RasSrvrReleaseAddress(
RasSrvrAcquiredIpAddresses->nboIpAddr,
RasSrvrAcquiredIpAddresses->wszUserName,
RasSrvrAcquiredIpAddresses->wszPortName,
TRUE);
// Assert: the list decreases by one node in each iteration.
}
}
RasStatUninitialize();
RasStatSetRoutes(RasSrvrNboServerIpAddress, FALSE);
RasTcpSetProxyArp(RasSrvrNboServerIpAddress, FALSE);
rasSrvrSetIpAddressInRegistry(0, 0);
dwErr = PDhcpNotifyConfigChange(NULL, g_rgwcAdapterName, TRUE,
0, 0, 0, IgnoreFlag);
if (NO_ERROR != dwErr)
{
TraceHlp("DhcpNotifyConfigChange failed and returned %d", dwErr);
}
if (RasSrvrAdapterMapped)
{
// Ask wanarp to unmap the adapter
info.fMap = 0;
if(!DeviceIoControl(HelperWanArpHandle,
IOCTL_WANARP_MAP_SERVER_ADAPTER,
&info,
sizeof(WANARP_MAP_SERVER_ADAPTER_INFO),
&info,
sizeof(WANARP_MAP_SERVER_ADAPTER_INFO),
&dwNumBytes,
NULL))
{
dwErr = GetLastError();
TraceHlp("Error %d unmapping server adapter", dwErr);
}
TraceHlp("RasSrvrAdapterUnMapped");
RasSrvrAdapterMapped = FALSE;
}
RasSrvrNboServerIpAddress = 0;
RasSrvrNboServerSubnetMask = 0;
LeaveCriticalSection(&RasSrvrCriticalSection);
/*
Don't call RasDhcpUninitialize when you have RasSrvrCriticalSection. It
will call RasDhcpTimerUninitialize, which will wait till all the timer work
itemss are done. The timer work item could be rasDhcpAllocateAddress or
rasDhcpRenewLease, both of which can call RasSrvrDhcpCallback, which tries
to acquire RasSrvrCriticalSection.
*/
//RasDhcpUninitialize();
}
/*
Returns:
Description:
*/
DWORD
RasSrvrAcquireAddress(
IN HPORT hPort,
IN IPADDR nboIpAddressRequested,
OUT IPADDR* pnboIpAddressAllocated,
IN WCHAR* wszUserName,
IN WCHAR* wszPortName
)
{
IPADDR nboIpAddr;
IPADDR nboIpMask;
IPADDR nboIpAddrObtained = 0;
IPADDR nboIpAddrFromDll = 0;
BOOL fNotifyDll = FALSE;
BOOL fEasyNet = FALSE;
WCHAR* wszUserNameTemp = NULL;
WCHAR* wszPortNameTemp = NULL;
AINODE* pAiNode = NULL;
DWORD dwErr = NO_ERROR;
TraceHlp("RasSrvrAcquireAddress(hPort: 0x%x, IP address: 0x%x, "
"UserName: %ws, PortName: %ws)",
hPort, nboIpAddressRequested, wszUserName, wszPortName);
EnterCriticalSection(&RasSrvrCriticalSection);
dwErr = rasSrvrGetAddressForServerAdapter();
if (NO_ERROR != dwErr)
{
goto LDone;
}
if (nboIpAddressRequested == RasSrvrNboServerIpAddress)
{
// The server's address is being requested. Forget the request.
nboIpAddressRequested = 0;
}
nboIpAddr = nboIpAddressRequested;
dwErr = rasSrvrAcquireAddressEx(hPort, &nboIpAddr, &nboIpMask, &fEasyNet);
if ( (NO_ERROR != dwErr)
&& (0 != nboIpAddr))
{
// We couldn't get the address we wanted. Let us get any other
// address.
nboIpAddr = 0;
dwErr = rasSrvrAcquireAddressEx(hPort, &nboIpAddr, &nboIpMask,
&fEasyNet);
}
if (NO_ERROR == dwErr)
{
RTASSERT(0 != nboIpAddr);
nboIpAddrObtained = nboIpAddr;
}
else
{
RTASSERT(0 == nboIpAddr);
goto LDone;
}
if (NULL != pfnMprAdminGetIpAddressForUser)
{
nboIpAddrFromDll = nboIpAddrObtained;
dwErr = pfnMprAdminGetIpAddressForUser(wszUserName, wszPortName,
&nboIpAddrFromDll, &fNotifyDll);
if (NO_ERROR != dwErr)
{
TraceHlp("MprAdminGetIpAddressForUser(%ws, %ws, 0x%x) failed "
"and returned %d",
wszUserName, wszPortName, nboIpAddrFromDll, dwErr);
goto LDone;
}
if ( (0 == nboIpAddrFromDll)
|| (RasSrvrNboServerIpAddress == nboIpAddrFromDll))
{
// We can't give the server's address.
TraceHlp("3rd party DLL wants to hand out bad address 0x%x",
nboIpAddrFromDll);
dwErr = ERROR_NOT_FOUND;
goto LDone;
}
if (nboIpAddrObtained != nboIpAddrFromDll)
{
TraceHlp("3rd party DLL wants to hand out address 0x%x",
nboIpAddrFromDll);
// We have to make sure that nboIpAddrFromDll is available.
// The DLL changed what we had got from Dhcp or Static. Release the
// old address.
if (HelperRegVal.fUseDhcpAddressing)
{
RasDhcpReleaseAddress(nboIpAddrObtained);
}
else
{
RasStatReleaseAddress(nboIpAddrObtained);
}
nboIpAddrObtained = 0;
fEasyNet = FALSE;
nboIpAddr = nboIpAddrFromDll;
dwErr = rasSrvrAcquireAddressEx(hPort, &nboIpAddr, &nboIpMask,
&fEasyNet);
if (NO_ERROR != dwErr)
{
goto LDone;
}
nboIpAddrObtained = nboIpAddr;
}
}
wszUserNameTemp = _wcsdup(wszUserName);
if (NULL == wszUserNameTemp)
{
dwErr = ERROR_OUTOFMEMORY;
TraceHlp("_strdup failed and returned %d", dwErr);
goto LDone;
}
wszPortNameTemp = _wcsdup(wszPortName);
if (NULL == wszPortNameTemp)
{
dwErr = ERROR_OUTOFMEMORY;
TraceHlp("_strdup failed and returned %d", dwErr);
goto LDone;
}
pAiNode = LocalAlloc(LPTR, sizeof(AINODE));
if (NULL == pAiNode)
{
dwErr = GetLastError();
TraceHlp("LocalAlloc failed and returned %d", dwErr);
goto LDone;
}
pAiNode->hPort = hPort;
pAiNode->fFlags = fNotifyDll ? AINODE_FLAG_NOTIFY_DLL : 0;
pAiNode->fFlags |= fEasyNet ? AINODE_FLAG_EASYNET : 0;
pAiNode->wszUserName = wszUserNameTemp;
pAiNode->wszPortName = wszPortNameTemp;
pAiNode->pNext = RasSrvrAcquiredIpAddresses;
RasSrvrAcquiredIpAddresses = pAiNode;
pAiNode->nboIpAddr = *pnboIpAddressAllocated = nboIpAddrObtained;
LDone:
if (NO_ERROR != dwErr)
{
if (fNotifyDll)
{
pfnMprAdminReleaseIpAddress(wszUserName, wszPortName,
&nboIpAddrFromDll);
}
if (0 != nboIpAddrObtained)
{
if (HelperRegVal.fUseDhcpAddressing)
{
RasDhcpReleaseAddress(nboIpAddrObtained);
}
else
{
RasStatReleaseAddress(nboIpAddrObtained);
}
}
free(wszUserNameTemp);
free(wszPortNameTemp);
}
LeaveCriticalSection(&RasSrvrCriticalSection);
return(dwErr);
}
/*
Returns:
Description:
*/
VOID
RasSrvrReleaseAddress(
IN IPADDR nboIpAddress,
IN WCHAR* wszUserName,
IN WCHAR* wszPortName,
IN BOOL fDeregister
)
{
DNS_STATUS DnsStatus;
REGISTER_HOST_ENTRY HostAddr;
AINODE* pAiNode = NULL;
DWORD dwErr;
TraceHlp("RasSrvrReleaseAddress(IP address: 0x%x, "
"UserName: %ws, PortName: %ws)",
nboIpAddress, wszUserName, wszPortName);
EnterCriticalSection(&RasSrvrCriticalSection);
if (fDeregister)
{
HostAddr.dwOptions = REGISTER_HOST_PTR;
HostAddr.Addr.ipAddr = nboIpAddress;
DnsStatus = DnsDhcpSrvRegisterHostName(
HostAddr,
NULL,
600,
DYNDNS_DELETE_ENTRY | DYNDNS_REG_FORWARD,
NULL,
NULL,
NULL,
0 );
if (DNSDHCP_SUCCESS != DnsStatus)
{
TraceHlp("DnsDhcpSrvRegisterHostName_A(0x%x) failed: 0x%x",
nboIpAddress, DnsStatus);
}
}
pAiNode = rasSrvrFindAiNode(nboIpAddress, TRUE /* fRemoveFromList */);
if (NULL == pAiNode)
{
TraceHlp("Couldn't find address 0x%x in Acquired Ip Addresses list",
nboIpAddress);
goto LDone;
}
if (HelperRegVal.fUseDhcpAddressing)
{
RasDhcpReleaseAddress(nboIpAddress);
}
else
{
RasStatReleaseAddress(nboIpAddress);
}
if (pAiNode->fFlags & AINODE_FLAG_NOTIFY_DLL)
{
pfnMprAdminReleaseIpAddress(wszUserName, wszPortName, &nboIpAddress);
}
if (pAiNode->fFlags & AINODE_FLAG_ACTIVATED)
{
if (!(pAiNode->fFlags & AINODE_FLAG_EASYNET))
{
RasTcpSetProxyArp(nboIpAddress, FALSE);
}
dwErr = rasSrvrGetAddressForServerAdapter();
if (NO_ERROR != dwErr)
{
TraceHlp("Couldn't get address for server adapter");
goto LDone;
}
RasTcpSetRoute(nboIpAddress,
nboIpAddress,
HOST_MASK,
RasSrvrNboServerIpAddress,
FALSE,
1,
TRUE);
}
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
rasSrvrFreeAiNode(pAiNode);
}
/*
Returns:
Description:
Look up the DNS server, WINS server, and "this server" addresses.
*/
DWORD
RasSrvrQueryServerAddresses(
IN OUT IPINFO* pIpInfo
)
{
DWORD dwNumBytes;
IPADDR nboWins1 = 0;
IPADDR nboWins2 = 0;
IPADDR nboDns1 = 0;
IPADDR nboDns2 = 0;
DWORD dwErr = NO_ERROR;
TraceHlp("RasSrvrQueryServerAddresses");
EnterCriticalSection(&RasSrvrCriticalSection);
dwErr = rasSrvrGetAddressForServerAdapter();
if (NO_ERROR != dwErr)
{
goto LDone;
}
// Ignore errors; its OK not to be able to give DNS or WINS server
// addresses
GetPreferredAdapterInfo(NULL, &nboDns1, &nboDns2, &nboWins1,
&nboWins2, NULL);
if (TRUE == HelperRegVal.fSuppressWINSNameServers)
{
nboWins1 = 0;
nboWins2 = 0;
}
else if (0 != HelperRegVal.nboWINSNameServer1)
{
nboWins1 = HelperRegVal.nboWINSNameServer1;
nboWins2 = HelperRegVal.nboWINSNameServer2;
}
if (TRUE == HelperRegVal.fSuppressDNSNameServers)
{
nboDns1 = 0;
nboDns2 = 0;
}
else if (0 != HelperRegVal.nboDNSNameServer1)
{
nboDns1 = HelperRegVal.nboDNSNameServer1;
nboDns2 = HelperRegVal.nboDNSNameServer2;
}
pIpInfo->nboDNSAddress = nboDns1;
pIpInfo->nboDNSAddressBackup = nboDns2;
pIpInfo->nboWINSAddress = nboWins1;
pIpInfo->nboWINSAddressBackup = nboWins2;
pIpInfo->nboServerIpAddress = RasSrvrNboServerIpAddress;
pIpInfo->nboServerSubnetMask = RasSrvrNboServerSubnetMask;
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
return(dwErr);
}
/*
Returns:
Description:
Does two things - RasTcpSetRoute and RasTcpSetProxyArp.
*/
DWORD
RasSrvrActivateIp(
IN IPADDR nboIpAddress,
IN DWORD dwUsage
)
{
AINODE* pAiNode;
DWORD dwErr = NO_ERROR;
TraceHlp("RasSrvrActivateIp(IpAddr = 0x%x, dwUsage = %d)",
nboIpAddress, dwUsage);
EnterCriticalSection(&RasSrvrCriticalSection);
pAiNode = rasSrvrFindAiNode(nboIpAddress, FALSE /* fRemoveFromList */);
if (NULL == pAiNode)
{
TraceHlp("Couldn't find address 0x%x in Acquired Ip Addresses list",
nboIpAddress);
dwErr = ERROR_IP_CONFIGURATION;
goto LDone;
}
pAiNode->fFlags |= AINODE_FLAG_ACTIVATED;
RasTcpSetProxyArp(nboIpAddress, TRUE);
if (dwUsage != DU_ROUTER)
{
// Add a route to the route table. Router connections get
// added by router manager
dwErr = rasSrvrGetAddressForServerAdapter();
if (NO_ERROR != dwErr)
{
// Don't return an error, because we have done RasTcpSetProxyArp.
dwErr = NO_ERROR;
TraceHlp("Couldn't get address for server adapter");
goto LDone;
}
RasTcpSetRoute(nboIpAddress,
nboIpAddress,
HOST_MASK,
RasSrvrNboServerIpAddress,
TRUE,
1,
TRUE);
}
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
return(dwErr);
}
/*
Returns:
VOID
Description:
Called by dhcp address code when the lease for a given address expires.
nboIpAddr = 0 indicates the server's IP address.
*/
VOID
RasSrvrDhcpCallback(
IN IPADDR nboIpAddr
)
{
AINODE* pAiNode = NULL;
CHAR szIpAddress[MAXIPSTRLEN + 1];
CHAR* sz;
DWORD dwErr = NO_ERROR;
TraceHlp("RasSrvrDhcpCallback(0x%x)", nboIpAddr);
EnterCriticalSection(&RasSrvrCriticalSection);
if ( (0 == nboIpAddr)
&& (0 == RasSrvrNboServerIpAddress))
{
// The server hasn't got an IP address yet. Its lease hasn't really
// expired. We are just simulating it.
goto LDone;
}
if ( (0 == nboIpAddr)
|| (nboIpAddr == RasSrvrNboServerIpAddress))
{
TraceHlp("******** SERVER ADDRESS (0x%x) LEASE EXPIRED ********",
RasSrvrNboServerIpAddress);
AbcdSzFromIpAddress(RasSrvrNboServerIpAddress, szIpAddress);
sz = szIpAddress;
// Log that the server adapter address lease was lost
LogEvent(EVENTLOG_WARNING_TYPE, ROUTERLOG_SRV_ADDR_CHANGED, 1,
(CHAR**)&sz);
// Unroute all the connected clients
while (NULL != RasSrvrAcquiredIpAddresses)
{
RasSrvrReleaseAddress(
RasSrvrAcquiredIpAddresses->nboIpAddr,
RasSrvrAcquiredIpAddresses->wszUserName,
RasSrvrAcquiredIpAddresses->wszPortName,
TRUE);
// Assert: the list decreases by one node in each iteration.
}
RasTcpSetProxyArp(RasSrvrNboServerIpAddress, FALSE);
rasSrvrSetIpAddressInRegistry(0, 0);
dwErr = PDhcpNotifyConfigChange(NULL, g_rgwcAdapterName, TRUE,
0, 0, 0, IgnoreFlag);
if (NO_ERROR != dwErr)
{
TraceHlp("DhcpNotifyConfigChange failed and returned %d", dwErr);
}
RasSrvrNboServerIpAddress = 0;
RasSrvrNboServerSubnetMask = 0;
}
else
{
pAiNode = rasSrvrFindAiNode(nboIpAddr, TRUE /* fRemoveFromList */);
if (NULL != pAiNode)
{
TraceHlp("******** CLIENT ADDRESS (0x%x) LEASE EXPIRED ********",
nboIpAddr);
AbcdSzFromIpAddress(nboIpAddr, szIpAddress);
sz = szIpAddress;
// Log that the client's address lease could not be renewed
LogEvent(EVENTLOG_WARNING_TYPE, ROUTERLOG_CLIENT_ADDR_LEASE_LOST, 1,
(CHAR**)&sz);
RasSrvrReleaseAddress(nboIpAddr, pAiNode->wszUserName,
pAiNode->wszPortName, TRUE);
}
}
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
rasSrvrFreeAiNode(pAiNode);
}
/*
Returns:
VOID
Description:
*/
VOID
RasSrvrEnableRouter(
BOOL fEnable
)
{
DWORD dwErr;
DEFINE_MIB_BUFFER(pSetInfo, MIB_IPSTATS, pSetStats);
TraceHlp("RasSrvrEnableRouter(%d)", fEnable);
EnterCriticalSection(&RasSrvrCriticalSection);
pSetInfo->dwId = IP_STATS;
pSetStats->dwForwarding = fEnable? MIB_IP_FORWARDING: MIB_IP_NOT_FORWARDING;
pSetStats->dwDefaultTTL = MIB_USE_CURRENT_TTL;
dwErr = MprAdminMIBEntrySet(
RasSrvrHMIBServer,
PID_IP,
IPRTRMGR_PID,
(VOID*)pSetInfo,
MIB_INFO_SIZE(MIB_IPSTATS));
if (NO_ERROR != dwErr)
{
TraceHlp("MprAdminMIBEntrySet failed with error %x", dwErr);
}
LeaveCriticalSection(&RasSrvrCriticalSection);
}
/*
Returns:
VOID
Description:
*/
VOID
RasSrvrAdapterUnmapped(
VOID
)
{
if (HelperInitialized)
{
EnterCriticalSection(&RasSrvrCriticalSection);
RasSrvrAdapterMapped = FALSE;
TraceHlp("RasSrvrAdapterUnMapped");
LeaveCriticalSection(&RasSrvrCriticalSection);
}
}
/*
Returns:
VOID
Description:
*/
DWORD
rasSrvrInitAdapterName(
VOID
)
{
DWORD dwNumBytes;
WANARP_ADD_INTERFACE_INFO info;
DWORD dwErr = NO_ERROR;
info.dwUserIfIndex = WANARP_INVALID_IFINDEX;
info.bCallinInterface = TRUE;
if (!DeviceIoControl(HelperWanArpHandle,
IOCTL_WANARP_ADD_INTERFACE,
&info,
sizeof(WANARP_ADD_INTERFACE_INFO),
&info,
sizeof(WANARP_ADD_INTERFACE_INFO),
&dwNumBytes,
NULL))
{
dwErr = GetLastError();
TraceHlp("rasSrvrInitAdapterName: Error %d getting server name",
dwErr);
goto LDone;
}
wcsncpy(g_rgwcAdapterName, info.rgwcDeviceName, WANARP_MAX_DEVICE_NAME_LEN);
// The RAS server adapter must not be registered with DNS. (These API's are
// called in IpcpProjectionNotification also.)
DnsDisableAdapterDomainNameRegistration(g_rgwcAdapterName);
DnsDisableDynamicRegistration(g_rgwcAdapterName);
LDone:
return(dwErr);
}
/*
Returns:
Description:
*/
AINODE*
rasSrvrFindAiNode(
IN IPADDR nboIpAddr,
IN BOOL fRemoveFromList
)
{
AINODE* pNode;
AINODE* pNodePrev;
EnterCriticalSection(&RasSrvrCriticalSection);
for (pNode = RasSrvrAcquiredIpAddresses, pNodePrev = pNode;
NULL != pNode;
pNodePrev = pNode, pNode = pNode->pNext)
{
if (pNode->nboIpAddr == nboIpAddr)
{
break;
}
}
if (!fRemoveFromList)
{
goto LDone;
}
if (NULL == pNode)
{
goto LDone;
}
if (pNode == pNodePrev)
{
RTASSERT(pNode == RasSrvrAcquiredIpAddresses);
RasSrvrAcquiredIpAddresses = pNode->pNext;
goto LDone;
}
pNodePrev->pNext = pNode->pNext;
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
return(pNode);
}
/*
Returns:
Description:
*/
VOID
rasSrvrFreeAiNode(
IN AINODE* pNode
)
{
if (NULL != pNode)
{
free(pNode->wszUserName);
free(pNode->wszPortName);
LocalFree(pNode);
}
}
/*
Returns:
Description:
*/
DWORD
rasSrvrSetIpAddressInRegistry(
IN IPADDR nboIpAddr,
IN IPADDR nboIpMask
)
{
TCPIP_INFO* pTcpipInfo = NULL;
DWORD dwErr = NO_ERROR;
dwErr = LoadTcpipInfo(&pTcpipInfo, g_rgwcAdapterName,
TRUE /* fAdapterOnly */);
if (NO_ERROR != dwErr)
{
TraceHlp("LoadTcpipInfo(%ws) failed and returned %d",
g_rgwcAdapterName, dwErr);
goto LDone;
}
AbcdWszFromIpAddress(nboIpAddr, pTcpipInfo->wszIPAddress);
AbcdWszFromIpAddress(nboIpMask, pTcpipInfo->wszSubnetMask);
if(g_fDisableNetbiosOverTcpip)
{
TraceHlp("rasSrvrSetIpAddressInRegistry: Netbios disabled");
pTcpipInfo->fDisableNetBIOSoverTcpip = TRUE;
}
pTcpipInfo->fChanged = TRUE;
dwErr = SaveTcpipInfo(pTcpipInfo);
if (dwErr != NO_ERROR)
{
TraceHlp("SaveTcpipInfo(%ws) failed and returned %d",
g_rgwcAdapterName, dwErr);
goto LDone;
}
LDone:
FreeTcpipInfo(&pTcpipInfo);
return(dwErr);
}
/*
Returns:
Notes:
*/
DWORD
rasSrvrAcquireAddressEx(
IN HPORT hPort,
IN OUT IPADDR* pnboIpAddr,
IN OUT IPADDR* pnboIpMask,
OUT BOOL* pfEasyNet
)
{
BOOL fExitWhile;
BOOL fAnyAddress;
AINODE* pAiNode;
DWORD dwErr = NO_ERROR;
EnterCriticalSection(&RasSrvrCriticalSection);
if (NULL != pfEasyNet)
{
*pfEasyNet = FALSE;
}
fAnyAddress = (0 == *pnboIpAddr);
fExitWhile = FALSE;
while (!fExitWhile)
{
dwErr = NO_ERROR;
if (fAnyAddress)
{
if (HelperRegVal.fUseDhcpAddressing)
{
dwErr = RasDhcpAcquireAddress(hPort, pnboIpAddr, pnboIpMask,
pfEasyNet);
}
else
{
dwErr = RasStatAcquireAddress(hPort, pnboIpAddr, pnboIpMask);
}
}
if (NO_ERROR != dwErr)
{
goto LDone;
}
for (pAiNode = RasSrvrAcquiredIpAddresses; NULL != pAiNode;
pAiNode = pAiNode->pNext)
{
if (pAiNode->nboIpAddr == *pnboIpAddr)
{
// This address is in use
if (fAnyAddress)
{
// Ask for another address
goto LWhileEnd;
}
else
{
TraceHlp("Address 0x%x is already in use", *pnboIpAddr);
dwErr = ERROR_PPP_REQUIRED_ADDRESS_REJECTED;
goto LDone;
}
}
}
dwErr = NO_ERROR;
fExitWhile = TRUE;
LWhileEnd:
;
}
LDone:
LeaveCriticalSection(&RasSrvrCriticalSection);
if ( fAnyAddress
&& (NO_ERROR != dwErr))
{
LogEvent(EVENTLOG_WARNING_TYPE, ROUTERLOG_NO_IP_ADDRESS, 0, NULL);
}
return(dwErr);
}
/*
Returns:
Description:
*/
DWORD
rasSrvrGetAddressForServerAdapter(
VOID
)
{
IPADDR nboIpAddr = 0;
IPADDR nboIpMask;
CHAR szIpAddress[MAXIPSTRLEN + 1];
CHAR* sz;
BOOL fAddrAcquired = FALSE;
BOOL fAdapterMapped = FALSE;
DWORD dwNumBytes;
DWORD dwErrTemp;
DWORD dwErr = NO_ERROR;
WANARP_MAP_SERVER_ADAPTER_INFO info;
TraceHlp("rasSrvrGetAddressForServerAdapter");
EnterCriticalSection(&RasSrvrCriticalSection);
if (!RasSrvrAdapterMapped)
{
// First time - ask wanarp to map the adapter
info.fMap = 1;
info.dwAdapterIndex = (DWORD)-1;
if(!DeviceIoControl(HelperWanArpHandle,
IOCTL_WANARP_MAP_SERVER_ADAPTER,
&info,
sizeof(WANARP_MAP_SERVER_ADAPTER_INFO),
&info,
sizeof(WANARP_MAP_SERVER_ADAPTER_INFO),
&dwNumBytes,
NULL))
{
dwErr = GetLastError();
TraceHlp("Error %d mapping server adapter", dwErr);
goto LDone;
}
TraceHlp("RasSrvrAdapterMapped");
RasSrvrAdapterMapped = TRUE;
fAdapterMapped = TRUE;
}
if (0 != RasSrvrNboServerIpAddress)
{
if (!fAdapterMapped)
{
goto LDone;
}
}
else
{
dwErr = rasSrvrAcquireAddressEx((HPORT) ULongToPtr(((ULONG) SERVER_HPORT)),
&nboIpAddr, &nboIpMask, NULL);
if (NO_ERROR != dwErr)
{
goto LDone;
}
fAddrAcquired = TRUE;
RasSrvrNboServerIpAddress = nboIpAddr;
RasSrvrNboServerSubnetMask = HOST_MASK;
}
dwErr = rasSrvrSetIpAddressInRegistry(
RasSrvrNboServerIpAddress, RasSrvrNboServerSubnetMask);
if (NO_ERROR != dwErr)
{
goto LDone;
}
dwErr = PDhcpNotifyConfigChange(NULL, g_rgwcAdapterName, TRUE, 0,
RasSrvrNboServerIpAddress,
RasSrvrNboServerSubnetMask,
IgnoreFlag);
if (NO_ERROR != dwErr)
{
TraceHlp("DhcpNotifyConfigChange(%ws) failed and returned %d",
g_rgwcAdapterName, dwErr);
goto LDone;
}
/*
It looks like the default subnet route no longer gets added.
// Now delete the default subnet route added as a result of setting the
// adapter's IP address and subnet mask
RasTcpSetRoute(RasSrvrNboServerIpAddress & RasSrvrNboServerSubnetMask,
RasSrvrNboServerIpAddress,
RasSrvrNboServerSubnetMask,
RasSrvrNboServerIpAddress,
FALSE,
1,
TRUE);
*/
RasTcpSetProxyArp(RasSrvrNboServerIpAddress, TRUE);
if (!HelperRegVal.fUseDhcpAddressing)
{
RasStatSetRoutes(RasSrvrNboServerIpAddress, TRUE);
}
AbcdSzFromIpAddress(RasSrvrNboServerIpAddress, szIpAddress);
sz = szIpAddress;
LogEvent(EVENTLOG_INFORMATION_TYPE, ROUTERLOG_SRV_ADDR_ACQUIRED, 1,
(CHAR**)&sz);
TraceHlp("Acquired IP address 0x%x(%s) and subnet mask 0x%x for the server",
RasSrvrNboServerIpAddress, szIpAddress, RasSrvrNboServerSubnetMask);
LDone:
if (NO_ERROR != dwErr)
{
// Some cleanup is required here. We must release the
// address if RasSrvrNboServerIpAddress != 0 and get rid of the
// variable fAddrAcquired.
if (fAddrAcquired)
{
if (HelperRegVal.fUseDhcpAddressing)
{
RasDhcpReleaseAddress(nboIpAddr);
}
else
{
RasStatReleaseAddress(nboIpAddr);
}
RasTcpSetProxyArp(RasSrvrNboServerIpAddress, FALSE);
}
RasSrvrNboServerIpAddress = RasSrvrNboServerSubnetMask = 0;
rasSrvrSetIpAddressInRegistry(0, 0);
dwErrTemp = PDhcpNotifyConfigChange(NULL, g_rgwcAdapterName, TRUE,
0, 0, 0, IgnoreFlag);
if (NO_ERROR != dwErrTemp)
{
TraceHlp("DhcpNotifyConfigChange failed and returned %d",
dwErrTemp);
}
}
LeaveCriticalSection(&RasSrvrCriticalSection);
return(dwErr);
}