📄 ip_intf.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//-***********************************************************************
//
// This file contains all of the code that sits under an IP interface
// and does the necessary multiplexing/demultiplexing for WAN connections.
//
//-***********************************************************************
#include "windows.h"
#include "cxport.h"
#include "types.h"
// IP Header files to bind to the LLIP interface
#include "ndis.h"
#include "ntddip.h"
#include "ip.h"
#include "llipif.h"
#include "tdiinfo.h"
#include "ipinfo.h"
#include "llinfo.h"
#include "tdistat.h"
#include "cellip.h"
#include "memory.h"
#include "afdfunc.h"
#include "cclib.h"
#include "iphlpapi.h"
// VJ Compression Include Files
#define _TCPIP_H_NOIP
#include "tcpip.h"
#include "vjcomp.h"
// PPP Include Files
#include "protocol.h"
#include "ppp.h"
#include "lcp.h"
#include "ipcp.h"
#include "ncp.h"
#include "mac.h"
#include "ip_intf.h"
#include "ipv6intf.h"
#include "crypt.h"
#include "pppserver.h"
#include "auth.h"
#include "util.h"
#include "debug.h"
#include <ndistapi.h>
#include <cenet.h>
// Function pointers into the upper layer IP stack
HMODULE g_hTcpStkModule;
IPRcvRtn IPRcv ;
IPTDCmpltRtn IPTDComplete ;
IPTxCmpltRtn IPSendComplete ;
IPStatusRtn IPStatus ;
IPRcvCmpltRtn IPRcvComplete ;
IPSetNTEAddrRtn IPSetNTEAddr ;
CEIPAddInterfaceRtn g_pfnIPAddInterface;
CEIPDelInterfaceRtn g_pfnIPDelInterface;
BOOL
GetIPProcAddresses(void)
//
// Initialize function pointers into tcpstk.dll for adding
// and removing interfaces.
//
{
BOOL bOk = TRUE;
DWORD dwResult;
if (g_hTcpStkModule == NULL)
{
dwResult = CXUtilGetProcAddresses(TEXT("tcpstk.dll"), &g_hTcpStkModule,
TEXT("CEIPAddInterface"), &g_pfnIPAddInterface,
TEXT("CEIPDelInterface"), &g_pfnIPDelInterface,
NULL);
if (dwResult != NO_ERROR)
{
RETAILMSG(1, (TEXT("PPP: ERROR: Can't find CEIPAddInterface or CEIPDelInterface in tcpstk.dll!\n")));
bOk = FALSE;
}
}
return bOk;
}
#define IS_BCAST(x) ((((ulong)(x)) & 0x000000ffL) == 0x000000ffL)
//
// Local Functions
//
static BOOL
IPConvertStringToAddress( WCHAR *AddressString, DWORD *AddressValue );
/******************************************************************************
@doc INTERNAL
@api ULONG | IPGetNetMask | Get the netmask for an address
@parm ULONG | Addr | an IP address
@rdesc ULONG | The netmask
********************************************************************/
ULONG
IPGetNetMask(ULONG Addr)
{
ULONG AddrType;
//
// Get the high byte of the address, which specifies the type
// (A, B, C, D, E) or IP address.
//
AddrType = Addr >> 24;
if (AddrType <= 127)
{
// Class A: Network address is upper 8 bits of an IP address
return 0xff000000;
}
else if (AddrType <= 191)
{
// Class B: Network address is upper 16 bits of an IP address
return 0xffff0000;
}
else
{
// Class C: Network address is upper 24 bits on an IP addres
// Don't sweat the wierd stuff (class D or E, ...)
return 0xffffff00;
}
}
#ifdef DEBUG
#define PROTOCOL_TCP 6 // from tcpipw\h\tcp.h
#define IP_VER_FLAG 0xF0 // from tcpipw\ip\ipdef.h
BOOL
DumpIP (BOOL Direction, PBYTE Buffer, DWORD Len)
{
IPHeader IPHdr;
TCPHeader TCPHdr;
if (Len < sizeof(IPHeader)) {
return FALSE;
}
memcpy ((char *)&IPHdr, Buffer, sizeof(IPHdr));
if (IPHdr.iph_protocol == PROTOCOL_TCP) {
memcpy ((char *)&TCPHdr, Buffer + (IPHdr.iph_verlen & 0x0F)*4, sizeof(TCPHeader));
NKDbgPrintfW (TEXT("%hs TCP %hs%hs%hs%hs%hs%hs, %d.%d.%d.%d(%d) => %d.%d.%d.%d(%d) Seq=%d-%d Ack=%d Win=%d\r\n"),
Direction ? "XMIT" : "RECV",
TCPHdr.tcp_flags & TCP_FLAG_URG ? "U" : ".",
TCPHdr.tcp_flags & TCP_FLAG_ACK ? "A" : ".",
TCPHdr.tcp_flags & TCP_FLAG_PUSH ? "P" : ".",
TCPHdr.tcp_flags & TCP_FLAG_RST ? "R" : ".",
TCPHdr.tcp_flags & TCP_FLAG_SYN ? "S" : ".",
TCPHdr.tcp_flags & TCP_FLAG_FIN ? "F" : ".",
IPHdr.iph_src & 0xFF,
(IPHdr.iph_src >> 8) & 0xFF,
(IPHdr.iph_src >> 16) & 0xFF,
(IPHdr.iph_src >> 24) & 0xFF,
net_short(TCPHdr.tcp_src),
IPHdr.iph_dest & 0xFF,
(IPHdr.iph_dest >> 8) & 0xFF,
(IPHdr.iph_dest >> 16) & 0xFF,
(IPHdr.iph_dest >> 24) & 0xFF,
net_short(TCPHdr.tcp_dest),
net_long(TCPHdr.tcp_seq),
net_long(TCPHdr.tcp_seq) + net_short(IPHdr.iph_length) -
((IPHdr.iph_verlen & 0x0F)*4 +
(net_short(TCPHdr.tcp_flags) >> 12)*4),
net_long(TCPHdr.tcp_ack),
net_short(TCPHdr.tcp_window));
return FALSE;
} else {
NKDbgPrintfW (TEXT("%hs IP ver=%d hlen=%d tos=0x%X len=%d id=%d offset=%d ttl=%d prot=%d xsum=%d Src=%d.%d.%d.%d Dest=%d.%d.%d.%d\r\n"),
Direction ? "XMIT" : "RECV",
(IPHdr.iph_verlen & IP_VER_FLAG) >> 4,
(IPHdr.iph_verlen & 0x0F)*4,
IPHdr.iph_tos,
net_short(IPHdr.iph_length),
net_short(IPHdr.iph_id), net_short(IPHdr.iph_offset),
IPHdr.iph_ttl, IPHdr.iph_protocol, net_short(IPHdr.iph_xsum),
IPHdr.iph_src & 0xFF,
(IPHdr.iph_src >> 8) & 0xFF,
(IPHdr.iph_src >> 16) & 0xFF,
(IPHdr.iph_src >> 24) & 0xFF,
IPHdr.iph_dest & 0xFF,
(IPHdr.iph_dest >> 8) & 0xFF,
(IPHdr.iph_dest >> 16) & 0xFF,
(IPHdr.iph_dest >> 24) & 0xFF);
}
return FALSE;
}
#endif
NDIS_STATUS
PppSendIPvX(
PVOID Context, // Pointer to ppp context.
PNDIS_PACKET Packet, // Pointer to packet to be transmitted.
DWORD ipProto) // 4 or 6
{
PPP_CONTEXT *pContext = (PPP_CONTEXT *)Context;
pppSession_t *s_p = (pppSession_t *)(pContext->Session);
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ASSERT(ipProto == 4 || ipProto == 6);
//
// Invoke packet debug extension if it is loaded.
//
if (g_pfnLogTxNdisPacket)
{
BOOL bDoSend;
bDoSend = g_pfnLogTxNdisPacket(L"PPP", pContext->AdapterName, ipProto == 4 ? L"IP" : L"IPV6", Packet);
if (!bDoSend)
return Status;
}
// Validate the session and make sure it doesn't go away until transmit is done
if (!PPPADDREF(s_p, REF_SENDIPVX))
{
Status = NDIS_STATUS_INVALID_PACKET;
}
else
{
// Protect the PPP Send
pppLock( s_p );
switch( s_p->Mode )
{
case PPPMODE_PPP:
// Route to IP Data Transmit
pppNcp_SendIPvX( s_p->ncpCntxt, Packet, ipProto == 4 ? NCP_IPCP : NCP_IPV6CP );
break;
case PPPMODE_SLIP:
pppSendNdisBufferChainViaSLIP( s_p, Packet->Private.Head );
break;
case PPPMODE_CSLIP:
// TBD - VJ Header compression
// TBD - Send the packet
break;
default:
ASSERT( 0 );
}
pppUnLock( s_p );
// Transmit complete, it's ok if the session gets deleted now
PPPDELREF(s_p, REF_SENDIPVX);
}
return Status;
}
// Transmit
//
// Function: Callout function for IP to tx data
//
NDIS_STATUS
Transmit( void *Context,
PNDIS_PACKET Packet,
IPAddr Destination,
RouteCacheEntry *RCE )
{
DEBUGMSG(ZONE_PPP, (TEXT( "PPP Transmit(%08X, %08X, %08X, %08X)\r\n" ),
Context, Packet, Destination, RCE ));
#ifdef DEBUG
if (dpCurSettings.ulZoneMask & 0xF0000000) {
char TempPacket[2048];
PNDIS_BUFFER pBuffer;
DWORD Length = 0;
PVOID VirtualAddress;
UINT BufferLength;
NdisQueryPacket(Packet, NULL, NULL, &pBuffer, NULL);
while (pBuffer)
{
NdisQueryBuffer(pBuffer, &VirtualAddress, &BufferLength);
if ((Length + BufferLength) > sizeof(TempPacket)) {
NKDbgPrintfW (TEXT("PPP:Transmit Packet too large, truncating at %d\r\n"), Length);
break;
}
memcpy (TempPacket+Length, VirtualAddress, BufferLength);
Length += BufferLength;
NdisGetNextBuffer(pBuffer, &pBuffer);
}
// Check top bit of zone mask.
// Turn this on via zo m NNN 0x80000000
if (dpCurSettings.ulZoneMask & 0x80000000) {
// Try to decode the first chunk
DumpIP (TRUE, TempPacket, Length);
}
if (dpCurSettings.ulZoneMask & 0x40000000) {
NKDbgPrintfW (TEXT("PPP:Transmit len=%d\r\n"), Length);
DumpMem(TempPacket, Length); // Dump packet contents
}
}
#endif
return PppSendIPvX(Context, Packet, 4);
}
// Receive
//
// Function: Send data up to IP
//
void
Receive(
void *session,
pppMsg_t *pMsg)
{
HANDLE threadId;
PPP_CONTEXT *pCurContext = (PPP_CONTEXT *)session;
DEBUGMSG( ZONE_PPP|ZONE_LOCK,
(TEXT("IPRcv LockWaitCnt=%d Locked=%d LockedCount=%d\r\n"),
pCurContext->Session->LockWaitCnt,
pCurContext->Session->Locked,
pCurContext->Session->SesCritSec.LockCount));
//
// Invoke packet debug extension if it is loaded.
//
if (g_pfnLogRxContigPacket)
{
BOOL bDoReceive;
bDoReceive = g_pfnLogRxContigPacket(L"PPP", pCurContext->AdapterName, L"IP", pMsg->data, pMsg->len);
if (!bDoReceive)
return;
}
// Print if lock count exceeds 1 as the receive
// path should only have the lock once.
if( pCurContext->Session->SesCritSec.LockCount > 1 )
{
DEBUGMSG( ZONE_ERROR, ( TEXT("IPRcv LockCount=%d\r\n"),
pCurContext->Session->SesCritSec.LockCount) );
}
threadId = (HANDLE )GetCurrentThreadId();
DEBUGMSG( ZONE_LOCK, (TEXT( "iprcv:Current thread Id 0x%x\n" ), threadId ));
DEBUGMSG( ZONE_LOCK, (TEXT( "iprcv:Lock Owner thread Id 0x%x\n" ),
pCurContext->Session->SesCritSec.OwnerThread ));
ASSERT( pCurContext->Session->SesCritSec.OwnerThread == threadId );
// Intercept any DHCP ACK packet containing domain name
if (pCurContext->Session->bDhcpTimerRunning)
{
if (PppDhcpRxPacket(pCurContext->Session, pMsg->data, pMsg->len))
{
return;
}
}
pppUnLock( pCurContext->Session );
#ifdef DEBUG
// Check top bit of zone mask.
// Turn this on via zo m NNN 0x80000000
if (dpCurSettings.ulZoneMask & 0x80000000) {
// Try to decode the first chunk
DumpIP (FALSE, pMsg->data, pMsg->len);
}
if (dpCurSettings.ulZoneMask & 0x40000000) {
NKDbgPrintfW (TEXT("PPP: Recieve Len=%d\r\n"), pMsg->len);
DumpMem(pMsg->data, pMsg->len); // Dump packet contents
}
#endif
//
// IPCP may be OPEN but the interface not registered if we
// RequireDataEncryption is set and CCP is not OPEN yet. In
// this case IPContext will be NULL until CCP enters the OPEN
// state and registers the interface with IP. Until the
// interface is registered IP packets are discarded.
//
if (pCurContext->IPContext != NULL)
{
IPRcv( pCurContext->IPContext, // IP's Context
pMsg->data, // The Packet
pMsg->len, // Data Size
pMsg->len, // Total Size
0, // Context1
0, // Context2
FALSE, // fBroadcast
NULL); // LINK
}
pppLock( pCurContext->Session );
}
void
ReceiveComplete(
void *session)
{
if (IPRcvComplete != NULL)
IPRcvComplete();
}
// XferData
//
// Function: Copy
//
NDIS_STATUS
XferData( void *Context,
NDIS_HANDLE MACContext,
uint MyOffset,
uint ByteOffset,
uint BytesWanted,
PNDIS_PACKET Packet,
uint *Transferred )
{
DEBUGMSG (ZONE_PPP, (
TEXT( "PPP XferData(%08X, %08X, %d, %d, %d, %08X, %08X)\r\n"),
Context, MACContext, MyOffset, ByteOffset,
BytesWanted, Packet, Transferred));
ASSERT( 0 );
return( NDIS_STATUS_SUCCESS );
}
void
Close( void *Context )
{
PPP_CONTEXT *pCurContext = (PPP_CONTEXT *)Context;
DEBUGMSG (ZONE_PPP, (TEXT("PPP Close(%08X)\r\n"), Context));
pCurContext->fOpen = FALSE;
return;
}
void
Invalidate( void *Context, RouteCacheEntry *RCE )
{
DEBUGMSG (ZONE_PPP, (TEXT("PPP Invalidate(%08X,%08X)\r\n"), Context, RCE));
// No action
return;
}
uint
AddAddr( void *Context, uint Type, IPAddr Address, IPMask Mask, PVOID pControlBlock )
{
DEBUGMSG( ZONE_PPP, (
TEXT( "PPP AddAddr(%08X,%d,%08X, %08X)\r\n"), Context,Type,Address,Mask));
return( TRUE );
}
uint
DeleteAddr( void *Context, uint Type, IPAddr Address, IPMask Mask )
{
DEBUGMSG (ZONE_PPP, (TEXT("PPP DeleteAddr(%08X,%d,%08X, %08X)\r\n"),
Context, Type, Address, Mask));
return( TRUE );
}
void
Open( void *Context )
{
DEBUGMSG (ZONE_PPP, (TEXT("PPP Open(%08X)\r\n"), Context));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -