📄 option.c
字号:
DWORD cbOptData= *pcbOptData;
DWORD peerRequestedIPAddress;
static BYTE IPAddrZero[4] = {0,0,0,0};
if (pOptData == NULL)
{
//
// The peer did not send us its IP address in a Config-Request, and we want it to.
// So, we send a NAK with a 0 address.
//
*ppOptData = &IPAddrZero[0];
*pcbOptData = 4;
}
else
{
//
// The generic option handling code should have rejected any illegal sized option.
//
ASSERT(cbOptData == 4);
IPADDR_TO_DWORD(peerRequestedIPAddress, pOptData);
if (pSession->bIsServer)
{
if (pContext->peer.ipAddress == 0)
{
//
// Get the IP address (static or DHCP) allocated
// for the client side when the line was enabled
//
pContext->peer.ipAddress = PPPServerGetSessionClientIPAddress(pSession);
}
DEBUGMSG(ZONE_NCP, (TEXT("PPP: Server assigning IP Address %u.%u.%u.%u to client\n"), IPADDROUT(pContext->peer.ipAddress)));
if (pContext->peer.ipAddress == 0)
{
// Unable to obtain an IP address for the client
*pCode = PPP_CONFIGURE_REJ;
}
else
{
//
// If we are a server, then we will only allow the client to use
// the IP address we assign. If the client requests any other
// address (including 0), we NAK and tell him the address to use.
//
if (peerRequestedIPAddress == pContext->peer.ipAddress)
{
*pCode = PPP_CONFIGURE_ACK;
}
else
{
DWORD_TO_IPADDR(&pContext->optDataIPAddress[0], pContext->peer.ipAddress);
*pCode = PPP_CONFIGURE_NAK;
*ppOptData = &pContext->optDataIPAddress[0];
}
}
}
else
{
//
// If we are a client, then we will allow the server to use any
// address it wants, except 0.
//
pContext->peer.ipAddress = peerRequestedIPAddress;
if (peerRequestedIPAddress != 0)
{
*pCode = PPP_CONFIGURE_ACK;
}
else
{
RASPENTRY *pRasEntry = &pSession->rasEntry;
if (pContext->local.ipAddress == 0)
{
memcpy( &pContext->local.ipAddress, &pRasEntry->ipaddr, 4 );
}
DWORD_TO_IPADDR(&pContext->optDataIPAddress[0], pContext->local.ipAddress);
pContext->optDataIPAddress[3] += 1;
*pCode = PPP_CONFIGURE_NAK;
*ppOptData = &pContext->optDataIPAddress[0];
DEBUGMSG( ZONE_IPCP, (TEXT( "PPP: Server Trying to use 0.0.0.0 IP ADDRESS, PROB W95, substituting...: 0x%X\r\n" ), pContext->local.ipAddress + 1 ) );
}
}
}
return dwResult;
}
///////////// Name Server Address configuration callbacks //////////////
DWORD
ipcpBuildNSAddressOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pOptData,
OUT PDWORD pcbOptData)
//
// Called to fill in the data for a name server IP Address option
// that is part of a configure-request we will send to the peer.
//
{
PIPCPContext pContext = (PIPCPContext)context;
pppSession_t *pSession = pContext->session;
DWORD dwResult = NO_ERROR;
PBYTE pAddr;
switch( pInfo->pDescriptor->type)
{
case IPCP_OPT_DNS_IP_ADDR: pAddr = (PBYTE)&pSession->rasEntry.ipaddrDns; break;
case IPCP_OPT_WINS_IP_ADDR: pAddr = (PBYTE)&pSession->rasEntry.ipaddrWins; break;
case IPCP_OPT_DNS_BACKUP_IP_ADDR: pAddr = (PBYTE)&pSession->rasEntry.ipaddrDnsAlt; break;
case IPCP_OPT_WINS_BACKUP_IP_ADDR: pAddr = (PBYTE)&pSession->rasEntry.ipaddrWinsAlt;break;
default: ASSERT(FALSE); return ERROR_INVALID_PARAMETER;
}
//
// This is a kludge to support ActiveSync. ActiveSync silently drops 0.0.0.0 name
// server addresses from its ACK messages without REJecting them. It will NAK the
// DNS address. So, after receiving a NAK for one or more name server addresses
// do not send 0.0.0.0 name server addresses in any subsequent config-requests.
//
if (pContext->bNakReceived && *(PDWORD)pAddr == 0)
{
dwResult = ERROR_PPP_SKIP_OPTION;
}
else
{
// RASIPADDR is stored LSB first, option is MSB first
pOptData[0] = pAddr[3];
pOptData[1] = pAddr[2];
pOptData[2] = pAddr[1];
pOptData[3] = pAddr[0];
*pcbOptData = 4;
}
return dwResult;
}
DWORD
ipcpAckNSAddressOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer ACKs a name server IP address option
// that we sent in a CR.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
// This is where we should commit to using the name server addresses...
// Currently they are committed in the Nak callback.
return dwResult;
}
DWORD
ipcpNakNSAddressOptionCb(
IN PVOID context,
IN OUT struct OptionInfo *pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer NAKs a name server IP address option
// that we sent in a CR.
//
{
PIPCPContext pContext = (PIPCPContext)context;
pppSession_t *pSession = pContext->session;
DWORD dwResult = NO_ERROR;
DWORD ipAddrNameServer;
//
// We only send a configure-request with name server address options
// if we are configured as a client.
//
ASSERT(!pSession->bIsServer);
//
// The generic option handling code should have rejected any illegal sized option.
//
ASSERT(cbOptData == 4);
IPADDR_TO_DWORD(ipAddrNameServer, pOptData);
pContext->bNakReceived = TRUE;
if (ipAddrNameServer == 0 || ipAddrNameServer == 0xFFFFFFFF)
{
//
// IP address is 0 or the broadcast address, neither of which
// is valid. We will ignore it and do no further negotiation
// of this option (treat it as if the peer had REJected it instead).
//
pInfo->onsLocal = ONS_Rejected;
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - Server NAKed option %hs with Invalid IPAddr=%x\n"),
pInfo->pDescriptor->szName, ipAddrNameServer));
}
else
{
PVOID pAddr;
//
// IP address seems reasonable. Save it for use in subsequent config-request
//
switch( pInfo->pDescriptor->type)
{
case IPCP_OPT_DNS_IP_ADDR: pAddr = &pSession->rasEntry.ipaddrDns; break;
case IPCP_OPT_WINS_IP_ADDR: pAddr = &pSession->rasEntry.ipaddrWins; break;
case IPCP_OPT_DNS_BACKUP_IP_ADDR: pAddr = &pSession->rasEntry.ipaddrDnsAlt; break;
case IPCP_OPT_WINS_BACKUP_IP_ADDR: pAddr = &pSession->rasEntry.ipaddrWinsAlt;break;
default: ASSERT(FALSE); pAddr = NULL; break;
}
if (pAddr)
memcpy( pAddr, &ipAddrNameServer, sizeof( DWORD ) );
}
return dwResult;
}
DWORD
ipcpRequestNSAddressCb(
IN OUT PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pCode,
IN OUT PBYTE *ppOptData,
IN OUT PDWORD pcbOptData)
//
// Called when we receive an IPCP configure request containing
// DNS or WINS primary or secondary IP Address option. If the IP address is 0, then
// the peer is requesting that we NAK with an IP address for it
// to use.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
PBYTE pOptData = *ppOptData;
DWORD cbOptData= *pcbOptData;
DWORD peerRequestedNameServerAddress;
DWORD ipAddrNameServer;
//
// The generic option handling code will reject this option unless we are a server,
// per our call to PppFsmOptionsAdd.
//
ASSERT(pContext->session->bIsServer);
//
// The generic option handling code should have rejected any illegal sized option.
//
ASSERT(cbOptData == 4);
IPADDR_TO_DWORD(peerRequestedNameServerAddress, pOptData);
//
// If we are a server then the client requests the addresses of the name
// servers by sending them in a CR with values of 0
//
if (peerRequestedNameServerAddress == 0)
{
//
// Get IP address of appropriate name server
//
switch(pInfo->pDescriptor->type)
{
case IPCP_OPT_DNS_IP_ADDR:
ipAddrNameServer = g_dwDNSIpAddr[0];
break;
case IPCP_OPT_DNS_BACKUP_IP_ADDR:
ipAddrNameServer = g_dwDNSIpAddr[1];
break;
case IPCP_OPT_WINS_IP_ADDR:
ipAddrNameServer = g_dwWINSIpAddr[0];
break;
case IPCP_OPT_WINS_BACKUP_IP_ADDR:
ipAddrNameServer = g_dwWINSIpAddr[1];
break;
default:
ASSERT(FALSE);
ipAddrNameServer = 0;
break;
}
//
// If we don't have a valid name server, reject the option.
// Otherwise, NAK and tell the client the name server address.
//
if (ipAddrNameServer == 0)
{
*pCode = PPP_CONFIGURE_REJ;
}
else
{
DWORD_TO_IPADDR(&pContext->optDataIPAddress[0], ipAddrNameServer);
*pCode = PPP_CONFIGURE_NAK;
*ppOptData = &pContext->optDataIPAddress[0];
}
}
else
{
// Presumably the client is sending the name server address
// that we previously NAKed with. Regardless, accept the name
// server IP address the client has chosen.
*pCode = PPP_CONFIGURE_ACK;
}
return dwResult;
}
//
// Constant information describing IPCP options:
//
OptionDescriptor ipcpIPCompressionOptionDescriptor =
{
IPCP_OPT_IPCOMPRESSION, // type == IP-Compression-Protocol
OPTION_VARIABLE_LENGTH, // can be 2 or more octets
"IP-Compression-Protocol", // name
ipcpBuildIPCompressionOptionCb,
ipcpAckIPCompressionOptionCb,
ipcpNakIPCompressionOptionCb,
NULL, // no special reject handling
ipcpRequestIPCompressionCb,
ipCompressionOptionToStringCb // debug routine
};
OptionDescriptor ipcpIPAddressOptionDescriptor =
{
IPCP_OPT_IPADDRESS, // type == IP-Address
4, // always exactly 4 octets
"IP-Address", // name
ipcpBuildIPAddressOptionCb,
ipcpAckIPAddressOptionCb,
ipcpNakIPAddressOptionCb,
ipcpRejIPAddressOptionCb,
ipcpRequestIPAddressCb,
ipAddressOptionToStringCb // debug routine
};
OptionDescriptor ipcpDNSAddressOptionDescriptor =
{
IPCP_OPT_DNS_IP_ADDR, // type == DNS-Address
4, // always exactly 4 octets
"DNS-Address", // name
ipcpBuildNSAddressOptionCb,
ipcpAckNSAddressOptionCb,
ipcpNakNSAddressOptionCb,
NULL, // no special reject handling
ipcpRequestNSAddressCb,
ipAddressOptionToStringCb // debug routine
};
OptionDescriptor ipcpWINSAddressOptionDescriptor =
{
IPCP_OPT_WINS_IP_ADDR, // type == WINS-Address
4, // always exactly 4 octets
"WINS-Address", // name
ipcpBuildNSAddressOptionCb,
ipcpAckNSAddressOptionCb,
ipcpNakNSAddressOptionCb,
NULL, // no special reject handling
ipcpRequestNSAddressCb,
ipAddressOptionToStringCb // debug routine
};
OptionDescriptor ipcpDNSBackupAddressOptionDescriptor =
{
IPCP_OPT_DNS_BACKUP_IP_ADDR, // type == DNS-Backup-Address
4, // always exactly 4 octets
"DNS-Backup-Address", // name
ipcpBuildNSAddressOptionCb,
ipcpAckNSAddressOptionCb,
ipcpNakNSAddressOptionCb,
NULL, // no special reject handling
ipcpRequestNSAddressCb,
ipAddressOptionToStringCb // debug routine
};
OptionDescriptor ipcpWINSBackupAddressOptionDescriptor =
{
IPCP_OPT_WINS_BACKUP_IP_ADDR, // type == WINS-Backup-Address
4, // always exactly 4 octets
"WINS-Backup-Address", // name
ipcpBuildNSAddressOptionCb,
ipcpAckNSAddressOptionCb,
ipcpNakNSAddressOptionCb,
NULL, // no special reject handling
ipcpRequestNSAddressCb,
ipAddressOptionToStringCb // debug routine
};
DWORD
ipcpOptionInit(
PIPCPContext pContext)
//
// This function is called once during session initialization
// to build the list of options that are supported.
//
{
DWORD dwResult;
pppSession_t *pSession = pContext->session;
RASPENTRY *pRasEntry = &pSession->rasEntry;
OptionRequireLevel orlIPCompressionLocal,
orlIPCompressionPeer,
orlNSLocal,
orlNSPeer;
orlIPCompressionLocal = ORL_Unsupported;
orlIPCompressionPeer = ORL_Unsupported;
if(pRasEntry->dwfOptions & RASEO_IpHeaderCompression )
{
//
// Negotiate IP header compression - ie Request header compression
// in our CR and accept it in our peer's CR.
//
orlIPCompressionLocal = ORL_Wanted;
orlIPCompressionPeer = ORL_Allowed;
}
orlNSLocal = ORL_Unsupported;
orlNSPeer = ORL_Unsupported;
if (pSession->bIsServer)
{
//
// If we are a server, then we want to allow clients to obtain DNS
// and WINS server addresses from us.
//
orlNSPeer = ORL_Allowed;
}
else
{
//
// If we are a client, then we want to try to obtain DNS and WINS
// server addresses from the server, if:
// bAlwaysRequestDNSandWINS registry flag is set, OR
// static DNS/WINS addresses were not set
//
if (pSession->dwAlwaysRequestDNSandWINS
|| (pRasEntry->dwfOptions & RASEO_SpecificNameServers) == 0)
{
orlNSLocal = ORL_Wanted;
}
}
dwResult = PppFsmOptionsAdd(pContext->pFsm,
&ipcpIPCompressionOptionDescriptor, orlIPCompressionLocal, orlIPCompressionPeer,
&ipcpIPAddressOptionDescriptor, ORL_Wanted, ORL_Allowed,
&ipcpDNSAddressOptionDescriptor, orlNSLocal, orlNSPeer,
&ipcpWINSAddressOptionDescriptor, orlNSLocal, orlNSPeer,
&ipcpDNSBackupAddressOptionDescriptor, orlNSLocal, orlNSPeer,
&ipcpWINSBackupAddressOptionDescriptor,orlNSLocal, orlNSPeer,
NULL);
return dwResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -