📄 pppserver.c
字号:
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
PPPServerLineConfiguration_t *pLine;
BOOL bInUse;
// Determine if the address is in use by an existing PPP Server line
bInUse = FALSE;
for (pLine = (PPPServerLineConfiguration_t *)(pConfig->LineList.Flink);
pLine != (PPPServerLineConfiguration_t *)(&pConfig->LineList);
pLine = (PPPServerLineConfiguration_t *)pLine->listEntry.Flink)
{
if (ipAddr == pLine->IPAddrInfo[SERVER_INDEX].IPAddr
|| ipAddr == pLine->IPAddrInfo[CLIENT_INDEX].IPAddr)
{
// Address in use, try another.
bInUse = TRUE;
break;
}
}
return bInUse;
}
BOOL
PPPServerIPAddrInUseOnNet(
DWORD dwIpAddr)
//
// Determine whether the specified IP address is assigned to some
// other adapter on our device, or some other device on the subnet.
//
// dwIpAddr will be in format 0xDDCCBBAA where the ip address is A.B.C.D
//
{
BOOL bInUse = FALSE;
DWORD dwResult;
BYTE macAddr[6];
DWORD cbMacAddr;
PMIB_IPADDRTABLE pTable;
PMIB_IPADDRROW pRow;
DWORD i;
//
// Check to see if the address is in use on the local device.
//
dwResult = PPPServerGetIPAddrTable(&pTable, NULL);
if (dwResult == NO_ERROR)
{
// Search the table for an interface with a matching IpAddr
for (i = 0; i < pTable->dwNumEntries; i++)
{
pRow = &pTable->table[i];
if (pRow->dwAddr == dwIpAddr)
{
bInUse = TRUE;
break;
}
}
LocalFree(pTable);
}
//
// If not in use on local device, check to see if some external
// device is using it.
//
if (!bInUse && g_pfnSendARP)
{
cbMacAddr = sizeof(macAddr);
dwResult = g_pfnSendARP(dwIpAddr, 0, (PULONG)(&macAddr[0]), &cbMacAddr);
if (dwResult == NO_ERROR && cbMacAddr > 0)
{
bInUse = TRUE;
}
}
DEBUGMSG(ZONE_TRACE, (TEXT("PPP: ARP for %x, inUse=%d\n"), dwIpAddr, bInUse));
return bInUse;
}
//** PPPServerDhcpSetNTE
//
// Routine to identify which NTE is currently being DHCP'ed. We take as input
// an nte_context. If the context is less than the max NTE context, we look
// for a matching NTE and if we find him we save a pointer. If we don't we
// fail. If the context > max NTE context we're disabling DHCPing, and
// we NULL out the save pointer.
//
// Input: Context - NTE context value.
// (will be 0x1FFFF if clearing NTE)
//
// Returns: TRUE if we succeed, FALSE if we don't.
//
uint
PPPServerDhcpSetNTECb(
IN uint Context,
OPTIONAL OUT PVOID *ppNTE,
OPTIONAL char *pAddr,
OPTIONAL OUT DWORD *cAddr)
{
uint bSuccess = TRUE;
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: +PPPServerDhcpSetNTECb(%x)\n"), Context));
#if 0 // Don't currently support this feature
if (g_pfnCESetDHCPNTEByName)
{
PWSTR wszDeviceName;
if (Context == 0x1ffff)
{
// Clearing DHCP NTE
bSuccess = g_pfnCESetDHCPNTEByName(NULL);
}
else
{
wszDeviceName = pConfig->wszDhcpInterface;
if (wszDeviceName[0])
{
bSuccess = g_pfnCESetDHCPNTEByName(wszDeviceName);
}
}
}
DEBUGMSG(!bSuccess && ZONE_ERROR, (TEXT("PPP: WARNING: PPPServerDhcpSetNTECb(%x) failed\n"), Context));
#endif
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: -PPPServerDhcpSetNTECb(%x) bSuccess=%d\n"), Context, bSuccess));
return bSuccess;
}
//* PPPServerDhcpSetAddr - Set the IP address of an NTE.
//
// Wrapper routine for IPpSetNTEAddr
//
// Input: Context - Context of NTE to alter.
// Addr - IP address to set.
// Mask - Subnet mask for Addr.
//
// Returns: IP_SUCCESS if we changed the address
//
uint
PPPServerDhcpSetAddrCb(
IN ushort Context,
OUT void *NTEp,
IN IPAddr Addr,
IN IPMask Mask,
IN IPAddr GWAddr)
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
uint Result = IP_SUCCESS;
PPPServerLineConfiguration_t *pLine;
DWORD type; // SERVER_INDEX or CLIENT_INDEX
DWORD OldIPAddr, OldMask;
BOOL bDhcpCompleted = TRUE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: +PPPServerDhcpSetAddrCb(%x) Addr=%x Mask=%x GW=%x\n"), Context, Addr, Mask, GWAddr));
//
// Find the IPAddrInfo for the Context
//
PPPServerFindIPInfoByIndex(Context, &pLine, &type);
if (pLine == NULL)
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING: PPPServerDhcpSetAddrCb(%x) Addr=%x Mask=%x GW=%x *NO LINE*\n"), Context, Addr, Mask, GWAddr));
Result = IP_DEVICE_DOES_NOT_EXIST;
}
else
{
OldIPAddr = pLine->IPAddrInfo[type].IPAddr;
OldMask = pLine->IPAddrInfo[type].IPMask;
pLine->IPAddrInfo[type].IPAddr = ntohl(Addr);
pLine->IPAddrInfo[type].IPMask = ntohl(Mask);
pLine->IPAddrInfo[type].GWAddr = ntohl(GWAddr);
if (Addr == 0)
{
if (pLine->IPAddrInfo[type].bDhcpCollision)
{
//
// DHCP calls us immediately after we report a collision
// to take away the address that we rejected. We don't want
// to signal the lease process is done in that case.
//
pLine->IPAddrInfo[type].bDhcpCollision = FALSE;
bDhcpCompleted = FALSE; // DHCP will try again to get a lease
}
else
{
//
// If we lost the lease unexpectedly then we want to shut the line down.
// If we gave up the lease (disabled the line ourselves by setting the
// global or local line enable flags off), then we don't need to do
// anything.
//
if (pConfig->bEnable)
{
DEBUGMSG(ZONE_WARN, (L"PPPSERVER: WARNING - DHCP Lease Failure, shutting down line\n"));
PPPServerLineDisable(pLine);
}
}
// Stop using the address, the lease is not available
if (OldIPAddr)
{
// Tell IP to stop handling proxy ARP requests for the address.
ArpProxyManagerIssueRequest(OldIPAddr, FALSE);
}
}
else
{
// Lease obtained
if (PPPServerIPAddrInUseOnNet(Addr))
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING: DHCP assigned Addr=%x is already IN USE by another device\n"), Addr));
Result = IP_DUPLICATE_ADDRESS;
bDhcpCompleted = FALSE; // DHCP will try again to get a lease
pLine->IPAddrInfo[type].bDhcpCollision = TRUE;
pLine->IPAddrInfo[type].dwDhcpCollisionCount++;
}
else
{
// Configure IP to handle ARP requests for the address
Result = ArpProxyManagerIssueRequest(ntohl(Addr), TRUE);
}
}
//
// We are done unless the address was a duplicate in which case
// the attempt to get a lease continues.
//
if (bDhcpCompleted)
{
DEBUGMSG(ZONE_PPP, (L"PPP: SIGNALLING DHCP LEASE REQUEST COMPLETED Result=%d.\n", Result));
SetEvent(pLine->IPAddrInfo[type].hEvent);
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: -PPPServerDhcpSetAddrCb(%x) Result=%d\n"), Context, Result));
return Result;
}
void
PPPServerRegisterWithDhcp()
//
// Obtain and register hooks into the dhcp library
//
{
PFNDhcpRegister pfnDhcpRegister;
//
// If the DHCP dll is not currently loaded, try to load it
//
if (g_hDhcpMod == NULL)
{
g_hDhcpMod = LoadLibrary(TEXT("dhcp.dll"));
}
if (g_hDhcpMod && !g_pDhcpProtocolContext)
{
// Get handle to DhcpRegister
pfnDhcpRegister = (PFNDhcpRegister)GetProcAddress(g_hDhcpMod, TEXT("DhcpRegister"));
if (pfnDhcpRegister)
{
g_pDhcpProtocolContext = pfnDhcpRegister(L"PPP", PPPServerDhcpSetNTECb, PPPServerDhcpSetAddrCb, &g_pfnDhcpNotify);
if (g_pDhcpProtocolContext)
{
DEBUGMSG (ZONE_INIT, (TEXT("PPP: registered w/ DHCP\n")));
}
else
{
DEBUGMSG (ZONE_ERROR, (TEXT("PPP: DhcpRegister failed\n")));
}
}
}
}
////////////////////////////////////
// Auto IP address allocation support
////////////////////////////////////
DWORD
PPPServerLineGenerateAutoIpAddrs(
PPPServerLineConfiguration_t *pLine)
//
// Generate random IP addresses on the AutoIP subnet that are not in use.
//
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
DWORD dwResult = NO_ERROR;
DWORD type;
DWORD randomIpAddr;
DWORD dwTriesRemaining;
for (type = SERVER_INDEX; type <= CLIENT_INDEX; type++)
{
for (dwTriesRemaining = 10; dwTriesRemaining; dwTriesRemaining--)
{
// A host id of all 0's or all 1's is not allowed
do
CeGenRandom(sizeof(randomIpAddr), (PBYTE)&randomIpAddr);
while (((randomIpAddr & ~pConfig->dwAutoIpSubnetMask) == 0)
|| ((randomIpAddr & ~pConfig->dwAutoIpSubnetMask) == ~pConfig->dwAutoIpSubnetMask));
randomIpAddr &= ~pConfig->dwAutoIpSubnetMask;
randomIpAddr |= pConfig->dwAutoIpSubnet;
if (!PPPServerUsingIpAddr(randomIpAddr)
&& !PPPServerIPAddrInUseOnNet(htonl(randomIpAddr)))
// random address is available, we'll use it
break;
}
if (dwTriesRemaining == 0)
{
dwResult = ERROR_NO_IP_ADDRESSES;
break;
}
pLine->IPAddrInfo[type].IPAddr = randomIpAddr;
pLine->IPAddrInfo[type].IPMask = pConfig->dwAutoIpSubnetMask;
// Configure IP to handle ARP requests for the address
dwResult = ArpProxyManagerIssueRequest(randomIpAddr, TRUE);
}
return dwResult;
}
////////////////////////////////////
// Static IP address allocation support
////////////////////////////////////
DWORD
PPPServerGetFreeStaticIpAddress()
//
// Find an unused address in the static IP pool and return it.
// Return 0 if no free address is found.
//
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
DWORD ipAddr;
DWORD i;
for (i = 0; TRUE; i++)
{
if (i == pConfig->dwStaticIpAddrCount)
{
// All addresses in static pool are in use
ipAddr = 0;
break;
}
ipAddr = pConfig->dwStaticIpAddrStart + i;
//
// If the address is not in use, we are done.
//
if (!PPPServerUsingIpAddr(ipAddr))
{
break;
}
// Otherwise, keep looking for a free one
}
return ipAddr;
}
VOID
PPPServerLineReleaseIPAddresses(
PPPServerLineConfiguration_t *pLine)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: +PPPServerLineReleaseIPAddresses\n")));
//
// Static addresses are implicitly released when the line
// is disabled.
//
// DHCP addresses need to be explicitly released.
//
if (pLine->bUsingDhcpAddress)
{
PPPServerLineReleaseDHCPAddrs(pLine);
pLine->bUsingDhcpAddress = FALSE;
}
// Make sure any ARP proxying is terminated
ArpProxyManagerIssueRequest(pLine->IPAddrInfo[SERVER_INDEX].IPAddr, FALSE);
ArpProxyManagerIssueRequest(pLine->IPAddrInfo[CLIENT_INDEX].IPAddr, FALSE);
pLine->IPAddrInfo[SERVER_INDEX].IPAddr = 0;
pLine->IPAddrInfo[SERVER_INDEX].Index = 0;
pLine->IPAddrInfo[CLIENT_INDEX].IPAddr = 0;
pLine->IPAddrInfo[CLIENT_INDEX].Index = 0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: -PPPServerLineReleaseIPAddresses\n")));
}
DWORD
PPPServerLineGetIPAddresses(
PPPServerLineConfiguration_t *pLine)
//
// Obtain IP addresses for the server and client sides
// of a PPP connection.
//
// Return:
// SUCCESS if it works,
// ERROR_NO_IP_ADDRESS if no addresses were assigned
//
{
PPPServerConfiguration_t *pConfig = &PPPServerConfig;
DWORD dwResult = ERROR_NO_IP_ADDRESSES;
BYTE MacAddress[6];
BOOL bSuccess;
DEBUGMSG(ZONE_FUNCTION, (TEXT("PPP: +PPPServerLineGetIPAddresses\n")));
ASSERT(pLine->IPAddrInfo[SERVER_INDEX].IPAddr == 0);
ASSERT(pLine->IPAddrInfo[CLIENT_INDEX].IPAddr == 0);
if (pConfig->bUseDhcpAddresses)
{
if (g_pDhcpProtocolContext == NULL)
{
// The DHCP service is not available
}
else
{
//
// Get the MAC address of a DHCP enabled LAN
// adapter in the system. Also find out the interface index for
//
bSuccess = PPPServerGetUniqueMacAddress(MacAddress, sizeof(MacAddress), &pLine->dwDhcpIfIndex);
if (bSuccess)
{
//
// Build the client HW address to use with DHCP
//
PPPServerLineBuildClientHWAddrs(pLine, MacAddress, sizeof(MacAddress));
//
// Issue the request to DHCP to assign the client
// and server IP addresses
//
dwResult = PPPServerLineRequestDHCPAddrs(pLine);
if (dwResult == SUCCESS)
{
pLine->bUsingDhcpAddress = TRUE;
}
}
}
}
else if (pConfig->bUseAutoIpAddresses)
{
// Auto IP address assignment
pLine->bUsingDhcpAddress = FALSE;
dwResult = PPPServerLineGenerateAutoIpAddrs(pLine);
}
else
{
// Static IP address assignment
pLine->bUsingDhcpAddress = FALSE;
pLine->IPAddrInfo[SERVER_INDEX].IPAddr = PPPServerGetFreeStaticIpAddress();
pLine->IPAddrInfo[SERVER_INDEX].IPMask = IPGetNetMask(pLine->IPAddrInfo[SERVER_INDEX].IPAddr);
pLine->IPAddrInfo[CLIENT_INDEX].IPAddr = PPPServerGetFreeStaticIpAddress();
pLine->IPAddrInfo[CLIENT_INDEX].IPMask = IPGetNetMask(pLine->IPAddrInfo[CLIENT_INDEX].IPAddr);
if (pLine->IPAddrInfo[SERVER_INDEX].IPAddr
&& pLine->IPAddrInfo[CLIENT_INDEX].IPAddr)
{
dwResult = SUCCESS;
}
else
{
// No static IP addresses available
}
}
#ifdef DEBUG
if (dwResult == SUCCESS)
{
DEBU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -