📄 ip_intf.c
字号:
// What would we do here?
return;
}
int
QueryInfo
( void *IFContext,
TDIObjectID *ID,
PNDIS_BUFFER Buffer,
uint *Size,
void *Context )
{
PPP_CONTEXT *pCurContext = (PPP_CONTEXT *)IFContext;
pppSession_t *s_p = pCurContext->Session;
PLCPContext lcp_p = (PLCPContext)s_p->lcpCntxt;
uint Offset = 0;
uint BufferSize = *Size;
uchar InfoBuff[ sizeof( IFEntry ) ];
uint Entity;
uint Instance;
DEBUGMSG (ZONE_PPP, (
TEXT( "PPP QueryInfo( %08X, %08X, %08X, %08X, %08X )\r\n"),
IFContext, ID, Buffer, Size ) );
Entity = ID->toi_entity.tei_entity;
Instance = ID->toi_entity.tei_instance;
// We support only Interface MIBs - no address xlation -
// pretty much like a loopback i/f (per Henry circa 1994).
if( (Entity != IF_ENTITY) || (Instance != pCurContext->ifinst) )
{
return( TDI_INVALID_REQUEST );
}
if( ID->toi_type != INFO_TYPE_PROVIDER )
{
return( TDI_INVALID_PARAMETER );
}
*Size = 0 ; // a safe initialization.
if( ID->toi_class == INFO_CLASS_GENERIC )
{
if( ID->toi_id == ENTITY_TYPE_ID )
{
// Identify what type we are.
if( BufferSize >= sizeof( uint ) )
{
*(uint *)&InfoBuff[ 0 ] =
(Entity == AT_ENTITY) ? AT_ARP : IF_MIB;
(void )CopyFlatToNdis(Buffer, InfoBuff, sizeof(uint), &Offset);
*Size = sizeof(uint);
return( TDI_SUCCESS );
}
else
{
return( TDI_BUFFER_TOO_SMALL );
}
}
// That's the only generic request supported.
return( TDI_INVALID_PARAMETER );
}
if( ID->toi_class != INFO_CLASS_PROTOCOL )
{
return( TDI_INVALID_PARAMETER );
}
// Asking for interface level information.
// Do we support what he's asking for.
if( ID->toi_id == IF_MIB_STATS_ID )
{
// We should probably fill get some statistics for it.
IFEntry *IFE = (IFEntry *)InfoBuff;
if( BufferSize < IFE_FIXED_SIZE )
{
return( TDI_BUFFER_TOO_SMALL );
}
// Buffer can hold the fixeded part. Build
// the IFEntry structure, and copy it in.
IFE->if_index = pCurContext->index;
IFE->if_type = IF_TYPE_PPP;
IFE->if_physaddrlen = ARP_802_ADDR_LENGTH;
switch( s_p->Mode )
{
case PPPMODE_PPP:
// Use the negotiated peer MRU
IFE->if_mtu = lcp_p->peer.MRU;
break;
case PPPMODE_SLIP:
case PPPMODE_CSLIP:
IFE->if_mtu = SLIP_DEFAULT_MTU;
break;
default: ASSERT( 0 );
}
DEBUGMSG (ZONE_PPP, ( TEXT( "PPP QueryInfo +pppMac_GetCallSpeed\n")));
pppMac_GetCallSpeed(s_p->macCntxt, &IFE->if_speed);
DEBUGMSG (ZONE_PPP, ( TEXT( "PPP QueryInfo -pppMac_GetCallSpeed\n")));
CTEMemSet( IFE->if_physaddr, 0, ARP_802_ADDR_LENGTH );
//
// Since PPP dynamically registers/deregisters adapters,
// it can only be queried by TCP/IP when it is "UP".
//
IFE->if_adminstatus = IF_STATUS_UP;
IFE->if_operstatus = IF_STATUS_UP;
IFE->if_lastchange = 0;
// Get the MAC layers stats
// Rx Statistics
IFE->if_inoctets = s_p->Stats.BytesRcvd;
IFE->if_inucastpkts = s_p->Stats.FramesRcvd;
IFE->if_innucastpkts = 0;
IFE->if_indiscards = s_p->Stats.CRCErrors;
IFE->if_inerrors = s_p->Stats.TimeoutErrors +
s_p->Stats.AlignmentErrors +
s_p->Stats.SerialOverrunErrors +
s_p->Stats.FramingErrors +
s_p->Stats.BufferOverrunErrors;
IFE->if_inunknownprotos = 0;
// Tx Statistics
IFE->if_outoctets = s_p->Stats.BytesSent;
IFE->if_outucastpkts = s_p->Stats.FramesRcvd;
IFE->if_outnucastpkts = 0;
IFE->if_outdiscards = 0;
IFE->if_outerrors = 0;
IFE->if_outqlen = 0; // no queue
IFE->if_descrlen = 0;
Buffer = CopyFlatToNdis( Buffer, (uchar *)IFE, IFE_FIXED_SIZE, &Offset);
// We should copy a description over....
*Size = IFE_FIXED_SIZE;
DEBUGMSG (ZONE_PPP, ( TEXT( "PPP -QueryInfo SUCCESS\n")));
return TDI_SUCCESS;
}
return( TDI_INVALID_PARAMETER );
}
int
SetInfo( void *Context, TDIObjectID *ID, void *Buffer, uint Size )
{
DEBUGMSG (ZONE_PPP, (TEXT("PPP SetInfo(%08X, %08X, %08X, %d)\r\n"),
Context, ID, Buffer, Size));
return( TRUE );
}
int
GetEList(void *Context, TDIEntityID *EntityList, uint *Count)
{
PPP_CONTEXT *pCurContext = (PPP_CONTEXT *)Context;
uint ECount;
uint MyIFBase;
uint i;
TDIEntityID *pEntity = NULL;
int Status = TRUE;
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
DEBUGMSG (ZONE_PPP, (TEXT("PPP GetEList(%08X,%08X,%08X)\r\n"),
Context, EntityList, Count));
ECount = *Count;
// Walk down the list, looking for existing AT or IF entities, and
// adjust our base instance accordingly.
MyIFBase = 0;
for (i = 0; i < ECount; i++, EntityList++)
{
if (EntityList->tei_entity == IF_ENTITY)
{
if ( EntityList->tei_instance == pCurContext->ifinst &&
EntityList->tei_instance != INVALID_ENTITY_INSTANCE ) {
pEntity = EntityList;
break;
} else {
MyIFBase = MAX(MyIFBase, EntityList->tei_instance + 1);
}
}
}
if (pEntity) {
if (! pCurContext->fOpen)
pEntity->tei_instance = (DWORD)INVALID_ENTITY_INSTANCE;
} else {
if (pCurContext->fOpen) {
// EntityList points to the start of where we want to begin filling in.
// Make sure we have enough room. We need one for the ICMP instance,
// and one for the CL_NL instance.
if ((ECount + 1) > MAX_TDI_ENTITIES)
{
Status = FALSE;
} else {
// At this point we've figure out our base instance. Save for later use.
pCurContext->ifinst = MyIFBase;
// Now fill it in.
EntityList->tei_entity = IF_ENTITY;
EntityList->tei_instance = MyIFBase;
*Count += 1;
}
}
}
return( Status );
}
LONG
RegSetIPAddrMultiSzValue(
HKEY hKey,
PTCHAR tszValueName,
...)
//
// Set a registry value which is a MULTI_SZ list of IP addresses.
//
// The variable parameters to this function are a NULL terminated list of
// pdwIPAddrs to convert to strings to build the multi_sz.
//
// NOTE: Does not set addresses with a value of 0. If not addresses are
// set, the registry value is deleted.
//
// @alert: if memory allocation fails, registry value is not deleted
//
{
TCHAR *ptszMultiIpAddr = NULL, *tszCur = NULL;
DWORD dwIPAddr, *pdwIPAddr;
va_list ArgList;
LONG lResult;
HLOCAL hMem = NULL;
#ifndef BLOCK_LENGTH
#undef BLOCK_LENGTH
#endif /* BLOCK_LENGTH */
#define BLOCK_LENGTH (0x100)
INT nContentLength = 0;
INT nAllocatedLength = BLOCK_LENGTH;
va_start (ArgList, tszValueName);
hMem = LocalAlloc(LMEM_ZEROINIT, nAllocatedLength * sizeof(TCHAR)); // ref: +alloc
if (!hMem)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
ptszMultiIpAddr = LocalLock(hMem); // ref: +lock
tszCur = ptszMultiIpAddr;
// Build the multi_sz
while (pdwIPAddr = va_arg(ArgList, PDWORD))
{
dwIPAddr = *pdwIPAddr;
if (dwIPAddr)
{
/* since the function accepts variable list of pdwIPAddrs, it's
necessary to reallocate the memory holding the string. BLOCK_LENGTH
is basically (max IP adddress length (string) + safe length) and it
can be fine tuned to the exact specifications */
if ((nContentLength > 0) && ((nAllocatedLength - nContentLength) > BLOCK_LENGTH))
{
HLOCAL hTmp = NULL;
LocalUnlock(hMem); // ref: -lock
hTmp = LocalReAlloc(hMem, (nAllocatedLength + BLOCK_LENGTH) *
sizeof(TCHAR), (LMEM_MODIFY | LMEM_MOVEABLE)); // ref: *alloc
if (!hTmp)
{
LocalFree(hMem); // ref: -alloc
return ERROR_NOT_ENOUGH_MEMORY;
}
else
{
nAllocatedLength += BLOCK_LENGTH;
}
hMem = hTmp;
ptszMultiIpAddr = LocalLock(hMem); // ref: +lock
tszCur = (ptszMultiIpAddr + nContentLength); // set tszCur to current location
}
tszCur += _stprintf (tszCur, TEXT("%d.%d.%d.%d\0"),
(dwIPAddr >> 24) & 0xFF, (dwIPAddr >> 16) & 0xFF,
(dwIPAddr >> 8) & 0xFF, dwIPAddr & 0xFF) + 1;
nContentLength = (tszCur - ptszMultiIpAddr);
}
}
va_end(ArgList);
if (tszCur > ptszMultiIpAddr)
{
// We have 1 or more nonzero IP addresses
//
// Add the extra terminator to denote end of the multi_sz
*tszCur++ = TEXT('\0');
DEBUGMSG (ZONE_PPP, (TEXT("PPP: Setting multi_sz list for %s - 1=%s\n"), tszValueName, ptszMultiIpAddr));
lResult = RegSetValueEx (hKey, tszValueName, 0, REG_MULTI_SZ, (char *)ptszMultiIpAddr, (tszCur - ptszMultiIpAddr) * sizeof(TCHAR));
}
else
{
DEBUGMSG (ZONE_PPP, (TEXT("PPP: Deleting registry value %s - all IP addresses for it are 0\n"), tszValueName));
lResult = RegDeleteValue(hKey, tszValueName);
}
if (hMem)
{
LocalUnlock(hMem); // ref: -lock
LocalFree(hMem); // ref: -alloc
}
#ifndef BLOCK_LENGTH
#undef BLOCK_LENGTH
#endif /* BLOCK_LENGTH */
return lResult;
}
const WCHAR TcpipParametersKey[] = L"Comm\\Tcpip\\Parms";
BOOL
PPPSetAdapterIPRegistrySettings(
IN PPP_CONTEXT *pContext,
IN OUT PNDIS_STRING pConfigName,
OUT PDWORD pdwDefaultGateway)
//
// Set the adapter's IP registry values based upon the IPCP negotiated values.
//
/*
[HKEY_LOCAL_MACHINE\Comm\<adapter name/#>\Parms\TcpIp]
"EnableDHCP" = dword:0
"DefaultGateway" = multi_sz:"<IPCP peer ip addr>"
"UseZeroBroadcast" = dword:0
"IpAddress" = multi_sz:"<IPCP negotiated ip address>"
"Subnetmask" = multi_sz:"<derived from IP address>"
"DNS" = multi_sz:"<IPCP assigned primary DNS server address>","<DNS secondary>"
"WINS" = multi_sz:"<IPCP assigned primary WINS>","<WINS secondary>"
*/
{
pppSession_t *s_p = pContext->Session;
ncpCntxt_t *ncp_p = s_p->ncpCntxt;
ipcpCntxt_t *ipcp_p = (ipcpCntxt_t *)ncp_p->protocol[ 1 ].context;
HKEY hKey;
LONG hRes;
DWORD zero = 0;
DWORD dwSubNetMask, dwIPAddr, dwDefaultGatewayIPAddr,
dwAddDefaultGateway, dwDontAddDefaultGateway;
WCHAR Buffer[MAX_PATH];
if (s_p->szDomain[0] != 0)
{
memset(Buffer, 0, sizeof(Buffer));
MultiByteToWideChar(CP_OEMCP, 0, &s_p->szDomain[0], -1, Buffer, MAX_PATH);
//
// Set system-wide DNSDomain name
//
hRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TcpipParametersKey, 0, 0, &hKey);
if (ERROR_SUCCESS == hRes)
{
RegSetValueEx (hKey, TEXT("DNSDomain"), 0, REG_SZ, (PBYTE)&Buffer[0], (wcslen(Buffer) + 1) * sizeof(WCHAR));
RegCloseKey(hKey);
}
}
//
// Set the per adapter TcpIp parameters.
//
_stprintf(pConfigName->Buffer, TEXT("Comm\\%s\\Parms\\TcpIp"), &pContext->AdapterName[0]);
pConfigName->Length = wcslen(pConfigName->Buffer) * sizeof(WCHAR);
ASSERT(pConfigName->Length < pConfigName->MaximumLength);
hRes = RegCreateKeyEx (HKEY_LOCAL_MACHINE, pConfigName->Buffer, 0, NULL,
REG_OPTION_NON_VOLATILE, 0, NULL,
&hKey, NULL);
if (hRes != ERROR_SUCCESS)
{
DEBUGMSG (ZONE_ERROR, (TEXT("PPP: Unable to create reg key '%s'\n"), pConfigName->Buffer));
return FALSE;
}
//
// Set the TCP/IP domain for this adapter if we obtained a domain
// via DHCP over PPP.
//
if (s_p->szDomain[0] != 0)
{
RegSetValueEx (hKey, TEXT("Domain"), 0, REG_SZ, (PBYTE)&Buffer[0], (wcslen(Buffer) + 1) * sizeof(WCHAR));
} else {
RegDeleteValue (hKey, TEXT("Domain"));
}
// Don't run DHCP over the PPP link, the IP address is set by the IPCP negotiation
RegSetValueEx (hKey, TEXT("EnableDHCP"), 0, REG_DWORD, (char *)&(zero), sizeof(DWORD));
RegSetValueEx (hKey, TEXT("UseZeroBroadcast"), 0, REG_DWORD, (char *)&(zero), sizeof(DWORD));
//
// Only want to set up default routes (gateways) if we are a RAS client
// and the RASENTRY option is set.
//
dwAddDefaultGateway = !s_p->bIsServer && (s_p->dwAlwaysAddDefaultRoute || (s_p->rasEntry.dwfOptions & RASEO_RemoteDefaultGateway));
dwDontAddDefaultGateway = !dwAddDefaultGateway;
RegSetValueEx (hKey, TEXT("DontAddDefaultGateway"), 0, REG_DWORD, (char *)&dwDontAddDefaultGateway, sizeof(DWORD));
switch( s_p->Mode )
{
case PPPMODE_PPP:
dwIPAddr = ipcp_p->local.ipAddress;
dwDefaultGatewayIPAddr = ipcp_p->peer.ipAddress;
//
// If the server did not tell us its IP address, generate
// a default gateway address based upon our address.
//
// If the server told us that its address is the same as
// our address, that's strange and really confuses our routing
// tables, so replace it with a fake address instead.
//
if (dwDefaultGatewayIPAddr == 0 || dwDefaultGatewayIPAddr == dwIPAddr)
{
dwDefaultGatewayIPAddr = dwIPAddr;
DEBUGMSG(ZONE_WARN, (TEXT("PPP: Server did not tell us its IP address, using own IP as default gateway\n")));
}
break;
case PPPMODE_SLIP:
case PPPMODE_CSLIP:
dwIPAddr = *(PDWORD)&s_p->rasEntry.ipaddr;
//
// We need to have a default gateway assigned so that IP will add a default route to the route
// table. The IP address of the default gateway doesn't matter so long as it is on the same
// subnet as the SLIP adapter's IP address. Since SLIP has no mechanism to tell us what our
// SLIP peer's IP address is, we just fudge an address on the same subnet. The gateway's IP
// address will get passed into our send handler by IP when the default route kicks in, but
// PPP just ignores this address as PPP only has one place to send IP packets to. On a LAN
// adapter, the gateway's MAC address would get put into the LAN packet.
//
dwDefaultGatewayIPAddr = dwIPAddr;
break;
}
if (s_p->bIsServer)
{
dwSubNetMask = PPPServerGetSessionIPMask(s_p);
}
else
{
// Just derive the subnet from the IP address (class A, B, or C)
dwSubNetMask = IPGetNetMask( dwIPAddr );
}
//
// If we are adding a default route, make sure that the peer's IP address is
// within the same subnet as our IP address. Otherwise, with the peer IP outside
// the subnet, the routing table will be configured such that PPP interface may
// not be used to send packets matching the PPP default route!
//
if ((dwIPAddr & dwSubNetMask) != (dwDefaultGatewayIPAddr & dwSubNetMask))
{
DEBUGMSG(ZONE_WARN, (L"PPP: Peer IP addr %x outside our subnet %x/%x, using own IP as gateway\n", dwDefaultGatewayIPAddr, dwIPAddr, dwSubNetMask));
dwDefaultGatewayIPAddr = dwIPAddr;
}
if ((s_p->rasEntry.dwfOptions & RASEO_RemoteDefaultGateway)
&& !(s_p->dwAlwaysAddSubnetRoute))
{
//
// We are adding a default route for this PPP interface, and don't
// want a subnet route as well.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -