📄 pppserver.c
字号:
}
DWORD
PPPServerLineAdd(
IN PRASCNTL_SERVERLINE pBufIn,
IN DWORD dwLenIn)
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
PPPServerLineConfiguration_t *pLine;
DWORD dwRetVal = SUCCESS;
if ((pBufIn == NULL)
|| (dwLenIn < sizeof(RASCNTL_SERVERLINE)))
{
dwRetVal = ERROR_INVALID_PARAMETER;
}
else
{
EnterCriticalSection( &PPPServerCritSec );
pLine = PPPServerFindOrCreateLineConfig(&pConfig->LineList, &pBufIn->rasDevInfo);
if (pLine)
{
PPPServerWriteLineConfigurationRegistrySettings(pLine);
}
LeaveCriticalSection( &PPPServerCritSec );
}
return dwRetVal;
}
DWORD
PPPServerLineRemove(
IN PPPServerLineConfiguration_t *pLine)
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
DWORD dwRetVal;
dwRetVal = PPPServerLineDisable(pLine);
PPPServerRemoveLineConfigurationRegistrySettings(pLine);
PPPServerDestroyLineConfig(&pConfig->LineList, pLine);
return dwRetVal;
}
#ifdef DEBUG
#define ENUM_TO_SZ_CASE(name) case(name): return #name
char *
GetRASConnectionStateName(
RASCONNSTATE state)
{
switch (state)
{
ENUM_TO_SZ_CASE(RASCS_OpenPort);
ENUM_TO_SZ_CASE(RASCS_PortOpened);
ENUM_TO_SZ_CASE(RASCS_ConnectDevice);
ENUM_TO_SZ_CASE(RASCS_DeviceConnected);
ENUM_TO_SZ_CASE(RASCS_AllDevicesConnected);
ENUM_TO_SZ_CASE(RASCS_Authenticate);
ENUM_TO_SZ_CASE(RASCS_AuthNotify);
ENUM_TO_SZ_CASE(RASCS_AuthRetry);
ENUM_TO_SZ_CASE(RASCS_AuthCallback);
ENUM_TO_SZ_CASE(RASCS_AuthChangePassword);
ENUM_TO_SZ_CASE(RASCS_AuthProject);
ENUM_TO_SZ_CASE(RASCS_AuthLinkSpeed);
ENUM_TO_SZ_CASE(RASCS_AuthAck);
ENUM_TO_SZ_CASE(RASCS_ReAuthenticate);
ENUM_TO_SZ_CASE(RASCS_Authenticated);
ENUM_TO_SZ_CASE(RASCS_PrepareForCallback);
ENUM_TO_SZ_CASE(RASCS_WaitForModemReset);
ENUM_TO_SZ_CASE(RASCS_WaitForCallback);
ENUM_TO_SZ_CASE(RASCS_Projected);
ENUM_TO_SZ_CASE(RASCS_Interactive);
ENUM_TO_SZ_CASE(RASCS_RetryAuthentication);
ENUM_TO_SZ_CASE(RASCS_CallbackSetByCaller);
ENUM_TO_SZ_CASE(RASCS_PasswordExpired);
ENUM_TO_SZ_CASE(RASCS_Connected);
ENUM_TO_SZ_CASE(RASCS_Disconnected);
default: return "???";
}
}
#endif
////////////////////////////////////
// DHCP address allocation support
////////////////////////////////////
HINSTANCE g_hDhcpMod = NULL;
PDHCP_PROTOCOL_CONTEXT g_pDhcpProtocolContext = NULL;
PFN_DHCP_NOTIFY g_pfnDhcpNotify;
DWORD
PPPServerGetAdapterIndex(
LPWSTR AdapterName,
PULONG IfIndex)
{
DWORD dwResult = ERROR_NOT_SUPPORTED;
if (g_pfnGetAdapterIndex)
{
dwResult = g_pfnGetAdapterIndex(AdapterName, IfIndex);
}
return dwResult;
}
DWORD
PPPServerCreateIpForwardEntry(
PMIB_IPFORWARDROW pRoute)
{
DWORD dwResult = ERROR_NOT_SUPPORTED;
if (g_pfnCreateIpForwardEntry)
{
dwResult = g_pfnCreateIpForwardEntry(pRoute);
}
return dwResult;
}
DWORD
PPPServerDeleteIpForwardEntry(
PMIB_IPFORWARDROW pRoute)
{
DWORD dwResult = ERROR_NOT_SUPPORTED;
if (g_pfnDeleteIpForwardEntry)
{
dwResult = g_pfnDeleteIpForwardEntry(pRoute);
}
return dwResult;
}
DWORD
PPPServerBuildRoute(
IN PPPServerLineConfiguration_t *pLine,
OUT PMIB_IPFORWARDROW pRoute)
{
DWORD ClientIPAddr;
ClientIPAddr = pLine->IPAddrInfo[CLIENT_INDEX].IPAddr;
ClientIPAddr = htonl(ClientIPAddr);
pRoute->dwForwardDest = ClientIPAddr;
pRoute->dwForwardMask = 0xFFFFFFFF; // Only forward exact matches of the client IP address
pRoute->dwForwardNextHop = ClientIPAddr;
pRoute->dwForwardPolicy = 0;
pRoute->dwForwardIfIndex = pLine->dwIfIndex;
pRoute->dwForwardType = 3; // The next hop is the final destination (local route)
pRoute->dwForwardProto = PROTO_IP_NETMGMT; // Routes added by "route add" or through SNMP
pRoute->dwForwardAge = 0;
pRoute->dwForwardNextHopAS = 0;
pRoute->dwForwardMetric1 = 1;
pRoute->dwForwardMetric2 = -1;
pRoute->dwForwardMetric3 = -1;
pRoute->dwForwardMetric4 = -1;
pRoute->dwForwardMetric5 = -1;
return NO_ERROR;
}
void
PPPServerAddRouteToClient(
pppSession_t *pSession)
//
// Add a route that will cause received packets with an IP
// address equal to that of the client to be sent through
// the PPP server interface.
//
{
DWORD dwResult = ERROR_DEVICENAME_NOT_FOUND;
MIB_IPFORWARDROW route;
PPPServerLineConfiguration_t *pLine;
pLine = PPPServerFindLineWithSession(pSession);
if (pLine)
{
dwResult = PPPServerGetAdapterIndex(pSession->context->AdapterName, &pLine->dwIfIndex);
if (dwResult == NO_ERROR)
{
dwResult = PPPServerBuildRoute(pLine, &route);
if (dwResult == NO_ERROR)
{
dwResult = PPPServerCreateIpForwardEntry(&route);
}
}
}
}
void
PPPServerDeleteRouteToClient(
pppSession_t *pSession)
//
// Delete a route to a client previously created by PPPServerAddRouteToClient.
//
{
DWORD dwResult = ERROR_DEVICENAME_NOT_FOUND;
MIB_IPFORWARDROW route;
PPPServerLineConfiguration_t *pLine;
pLine = PPPServerFindLineWithSession(pSession);
if (pLine)
{
dwResult = PPPServerBuildRoute(pLine, &route);
if (dwResult == NO_ERROR)
{
dwResult = PPPServerDeleteIpForwardEntry(&route);
}
}
}
BOOL
PPPServerGetUniqueMacAddress(
OUT BYTE *pMacAddress,
IN UINT cbMacAddress,
OUT PDWORD pdwIfIndex)
//
// Find the MAC address of a LAN adapter installed in the server
// to use to generate unique client hardware IDs for getting DHCP
// leases for PPP connections.
//
// Return the MAC address and the interface index for its adapter.
//
{
BOOL bSuccess = FALSE;
memset(pMacAddress, 0, cbMacAddress);
bSuccess = utilFindEUI(0, TRUE, pMacAddress, (1<<cbMacAddress), &cbMacAddress, pdwIfIndex);
return bSuccess;
}
VOID
PPPServerFindIPInfoByIndex(
DWORD Index,
PPPServerLineConfiguration_t **ppLine,
PDWORD pInfoType)
//
// Find the line with IP Info having the specified Index
// Return NULL if no match found.
//
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
PPPServerLineConfiguration_t *pLine;
DWORD type;
*ppLine = NULL;
for (pLine = (PPPServerLineConfiguration_t *)(pConfig->LineList.Flink);
pLine != (PPPServerLineConfiguration_t *)(&pConfig->LineList);
pLine = (PPPServerLineConfiguration_t *)pLine->listEntry.Flink)
{
for (type = SERVER_INDEX; type <= CLIENT_INDEX; type++)
{
if (Index == pLine->IPAddrInfo[type].Index)
{
*ppLine = pLine;
*pInfoType = type;
break;
}
}
if (*ppLine)
break;
}
}
VOID
PPPServerLineAssignUnusedIndices(
PPPServerLineConfiguration_t *pLine)
//
// Assign lowest available unused index values for the server and client IP info structures
// These indexes become the last 4 bytes of the unique client hw address identifiers that
// are used to reserve DHCP addresses.
//
{
DWORD index;
PPPServerLineConfiguration_t *pLineUsingIndex;
DWORD type, typeUsingIndex;
//
// We should have freed and zeroed any prior in use indices
//
ASSERT(pLine->IPAddrInfo[SERVER_INDEX].Index == 0);
ASSERT(pLine->IPAddrInfo[CLIENT_INDEX].Index == 0);
index = 0x8001;
type = SERVER_INDEX;
while (type <= CLIENT_INDEX)
{
PPPServerFindIPInfoByIndex(index, &pLineUsingIndex, &typeUsingIndex);
if (pLineUsingIndex == NULL)
{
// index is not in use, assign it
pLine->IPAddrInfo[type].Index = index;
type++;
}
index++;
// There should not be too many of these in use in practice
ASSERT(index <= 0xFFFF);
}
}
#define RAS_PREPEND_SIZE strlen(RAS_PREPEND)
VOID
PPPServerLineBuildClientHWAddrs(
PPPServerLineConfiguration_t *pLine,
BYTE *pMacAddr,
DWORD cbMacAddr)
//
// Build the client hardware addresses to be used to acquire DHCP leases.
//
// The address takes the form:
//
// 4 Bytes: "RAS "
// 8 Bytes: <MacAddress> (0 padded on the front)
// 4 Bytes: <Index>
//
{
DWORD type, index;
BYTE *pHWAddr;
PPPServerLineAssignUnusedIndices(pLine);
if (cbMacAddr > 8)
cbMacAddr = 8;
for (type = SERVER_INDEX; type <= CLIENT_INDEX; type++)
{
//
// "RAS " part
//
pHWAddr = &pLine->IPAddrInfo[type].DhcpClientHWAddress[0];
memcpy(pHWAddr, RAS_PREPEND, RAS_PREPEND_SIZE);
pHWAddr += RAS_PREPEND_SIZE;
//
// <MacAddress> part
//
memset(pHWAddr, 0, 8);
memcpy(pHWAddr + (8 - cbMacAddr), pMacAddr, cbMacAddr);
pHWAddr += 8;
//
// <Index> part
//
index = pLine->IPAddrInfo[type].Index;
index = htonl(index);
memcpy(pHWAddr, (BYTE *)&index, sizeof(index));
}
}
TCHAR cLineTypeSuffix[2] =
{
TEXT('s'), // SERVER_INDEX
TEXT('c') // CLIENT_INDEX
};
DWORD
PPPServerLineRequestDHCPAddrs(
PPPServerLineConfiguration_t *pLine)
//
// Issue requests to DHCP to assign IP addresses for the line
//
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
TCHAR tszAdapterName[RAS_MaxDeviceName+1+1];
DWORD dwResult;
DWORD type;
DWORD dwCollisionCount;
DWORD dhcpTimeouts;
for (type = SERVER_INDEX; type <= CLIENT_INDEX; type++)
{
// tszAdapterName has to be unique for the Dhcp lease,
// e.g. "VPN1s" for serverside, "VPN1c" for clientside
_stprintf(tszAdapterName, TEXT("%s%c"), pLine->rasDevInfo.szDeviceName, cLineTypeSuffix[type]);
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: DHCP_REQUEST_ADDRESS for %s\n"), tszAdapterName));
ResetEvent(pLine->IPAddrInfo[type].hEvent);
dwResult = g_pfnDhcpNotify(
DHCP_REQUEST_ADDRESS,
g_pDhcpProtocolContext,
tszAdapterName,
pLine, // Nte
pLine->IPAddrInfo[type].Index,
pLine->IPAddrInfo[type].DhcpClientHWAddress,
sizeof(pLine->IPAddrInfo[type].DhcpClientHWAddress));
if (dwResult != DHCP_SUCCESS)
{
DEBUGMSG(ZONE_ERROR, (TEXT("PPP: DHCP_REQUEST_ADDRESS failed, error=%x\n"), dwResult));
break;
}
else
{
// Wait for DHCP to get the lease
for (dhcpTimeouts = 0; dhcpTimeouts <= pConfig->DhcpMaxTimeouts; dhcpTimeouts++)
{
dwCollisionCount = pLine->IPAddrInfo[type].dwDhcpCollisionCount;
LeaveCriticalSection( &PPPServerCritSec );
DEBUGMSG(ZONE_PPP, (L"PPPSERVER: Wait for DHCP lease...\n"));
dwResult = WaitForSingleObject(pLine->IPAddrInfo[type].hEvent, pConfig->DhcpTimeoutMs);
DEBUGMSG(ZONE_PPP, (L"PPPSERVER: Lease request completed, result=%d.\n", dwResult));
EnterCriticalSection( &PPPServerCritSec );
// If didn't time out or had no activity, we are done
if (dwResult != WAIT_TIMEOUT
|| dwCollisionCount == pLine->IPAddrInfo[type].dwDhcpCollisionCount)
{
break;
}
}
if (dwResult == WAIT_TIMEOUT)
{
// No response from DHCP to our request with 30 seconds
DEBUGMSG(ZONE_ERROR, (L"PPPSERVER: ERROR - DHCP Lease request timeout\n"));
dwResult = ERROR_NO_IP_ADDRESSES;
break;
}
if (pLine->IPAddrInfo[type].IPAddr == 0)
{
// DHCP failed to obtain a lease.
dwResult = ERROR_NO_IP_ADDRESSES;
DEBUGMSG(ZONE_ERROR, (L"PPPSERVER: ERROR - DHCP Lease request failure\n"));
break;
}
dwResult = NO_ERROR;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: DHCP_REQUEST_ADDRESS for %s RESULT=%d\n"), tszAdapterName, dwResult));
}
DEBUGMSG(ZONE_ERROR && dwResult, (TEXT("PPP: PPPServerLineRequestDHCPAddrs FAILED result=%d\n"), dwResult));
return dwResult;
}
DWORD
PPPServerLineReleaseDHCPAddrs(
PPPServerLineConfiguration_t *pLine)
//
// Issue requests to DHCP to release IP addresses for the line
//
{
TCHAR tszAdapterName[RAS_MaxDeviceName+1+1];
DWORD dwResult;
DWORD type;
for (type = SERVER_INDEX; type <= CLIENT_INDEX; type++)
{
_stprintf(tszAdapterName, TEXT("%s%c"), pLine->rasDevInfo.szDeviceName, cLineTypeSuffix[type]);
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: DHCP_REQUEST_RELEASE for %s\n"), tszAdapterName));
dwResult = g_pfnDhcpNotify(
DHCP_REQUEST_RELEASE,
g_pDhcpProtocolContext,
tszAdapterName,
NULL, // Nte
0,
NULL,
0);
}
return dwResult;
}
BOOL
PPPServerUsingIpAddr(
DWORD ipAddr)
//
// ipAddr should be in the format 0xAABBCCDD
//
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -