You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
746 lines
18 KiB
746 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
wanarp2\ipinip.h
|
|
|
|
Abstract:
|
|
|
|
Main header file for the IP in IP encapsulation driver
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#ifndef __WANARP_WANARP_H__
|
|
#define __WANARP_WANARP_H___
|
|
|
|
//
|
|
// Symbolic link into DOS space
|
|
//
|
|
|
|
#define WIN32_WANARP_SYMBOLIC_LINK L"\\DosDevices\\WanArp"
|
|
|
|
|
|
//
|
|
// ARP name (for IP). Also goes into LLInterface
|
|
//
|
|
|
|
#define WANARP_ARP_NAME WANARP_SERVICE_NAME_W
|
|
|
|
//
|
|
// Name for NDIS. NDIS requires us to have a TCPIP_ in front of the name
|
|
//
|
|
|
|
#define WANARP_NDIS_NAME L"TCPIP_WANARP"
|
|
|
|
|
|
//
|
|
// Need to prefix all our device names with this when we give name to
|
|
// IP. We assume that the name we cat is of type \<Name>
|
|
//
|
|
|
|
#define TCPIP_IF_PREFIX L"\\DEVICE"
|
|
|
|
//
|
|
// The prefix for the registry key
|
|
//
|
|
|
|
#define TCPIP_REG_PREFIX L"\\Tcpip\\Parameters\\Interfaces\\"
|
|
|
|
//
|
|
// Length of a GUID
|
|
//
|
|
|
|
#define GUID_STR_LEN (38)
|
|
|
|
//
|
|
// We look like an 802.x ARP interface
|
|
//
|
|
|
|
#define ARP_802_ADDR_LENGTH 6
|
|
|
|
//
|
|
// Macro for building a 802.3 hw address given an index.
|
|
// We do this since our adapters do not have a real net card associated with
|
|
// them
|
|
//
|
|
|
|
#define HW_NAME_SEED "\0SExx\0"
|
|
|
|
#define BuildHardwareAddrFromIndex(addr,index) { \
|
|
RtlCopyMemory(addr, HW_NAME_SEED, 6); \
|
|
addr[3] = (uchar) index >> 8; \
|
|
addr[4] = (uchar) index; \
|
|
}
|
|
|
|
//
|
|
// The default speed and MTU. We change the MTU when we get a better estimate
|
|
// but the speed remains the same
|
|
//
|
|
|
|
#define WANARP_DEFAULT_MTU 1500
|
|
#define WANARP_DEFAULT_SPEED 28000
|
|
|
|
#define MEDIA_802_3 0 // index of media
|
|
|
|
#define WANARP_LOOKAHEAD_SIZE 128 // A reasonable lookahead size
|
|
#define MIN_ETYPE 0x600 // Minimum valid Ethertype
|
|
|
|
|
|
#define ARP_ETYPE_IP 0x800 // Standard ETYPE
|
|
|
|
//
|
|
// Max number of packets a connection can have pending
|
|
//
|
|
|
|
#define WANARP_MAX_PENDING_PACKETS 32
|
|
|
|
//
|
|
// Initial size of packet pool
|
|
//
|
|
|
|
#define WAN_PACKET_POOL_COUNT 64
|
|
|
|
//
|
|
// Max outstanding packets:
|
|
// Allow 64 connections to be maxed out pending, and 64 others to have
|
|
// 2 packets outstanding
|
|
//
|
|
|
|
#define WAN_PACKET_POOL_OVERFLOW ((WANARP_MAX_PENDING_PACKETS * 64) + (2 * 64))
|
|
|
|
#define CompareUnicodeStrings(S1,S2) \
|
|
(((S1)->Length == (S2)->Length) && \
|
|
(RtlCompareMemory((S1)->Buffer, \
|
|
(S2)->Buffer, \
|
|
(S2)->Length) == (S2)->Length))
|
|
|
|
|
|
#define MIN(a,b) ((a) < (b)?a:b)
|
|
|
|
//
|
|
// Functions which are called at passive but acquire spinlocks
|
|
//
|
|
|
|
#define PASSIVE_ENTRY() PAGED_CODE()
|
|
#define PASSIVE_EXIT() PAGED_CODE()
|
|
|
|
//
|
|
// Nifty macro for printing IP Addresses
|
|
//
|
|
|
|
#define PRINT_IPADDR(x) \
|
|
((x)&0x000000FF),(((x)&0x0000FF00)>>8),(((x)&0x00FF0000)>>16),(((x)&0xFF000000)>>24)
|
|
|
|
//
|
|
// 0.0.0.0 is an invalid address
|
|
//
|
|
|
|
#define INVALID_IP_ADDRESS 0x00000000
|
|
|
|
#define IsUnicastAddr(X) ((DWORD)((X) & 0x000000F0) < (DWORD)(0x000000E0))
|
|
#define IsClassDAddr(X) (((X) & 0x000000F0) == 0x000000E0)
|
|
|
|
//
|
|
// IPv4 header
|
|
//
|
|
|
|
#include <packon.h>
|
|
|
|
typedef struct _IP_HEADER
|
|
{
|
|
BYTE byVerLen; // Version and length.
|
|
BYTE byTos; // Type of service.
|
|
WORD wLength; // Total length of datagram.
|
|
WORD wId; // Identification.
|
|
WORD wFlagOff; // Flags and fragment offset.
|
|
BYTE byTtl; // Time to live.
|
|
BYTE byProtocol; // Protocol.
|
|
WORD wXSum; // Header checksum.
|
|
DWORD dwSrc; // Source address.
|
|
DWORD dwDest; // Destination address.
|
|
}IP_HEADER, *PIP_HEADER;
|
|
|
|
#define LengthOfIpHeader(X) (ULONG)((((X)->byVerLen) & 0x0F)<<2)
|
|
|
|
typedef struct _ETH_HEADER
|
|
{
|
|
//
|
|
// 6 byte destination address
|
|
//
|
|
|
|
BYTE rgbyDestAddr[ARP_802_ADDR_LENGTH];
|
|
|
|
//
|
|
// 6 byte source address
|
|
//
|
|
|
|
BYTE rgbySourceAddr[ARP_802_ADDR_LENGTH];
|
|
|
|
//
|
|
// 2 byte type
|
|
//
|
|
|
|
WORD wType;
|
|
|
|
}ETH_HEADER, *PETH_HEADER;
|
|
|
|
#include <packoff.h>
|
|
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// Reference history structure.
|
|
//
|
|
|
|
typedef struct _REF_HIST_ENTRY
|
|
{
|
|
//
|
|
// time of reference operation
|
|
//
|
|
|
|
LARGE_INTEGER liChangeTime;
|
|
|
|
//
|
|
// Refcount after reference operation
|
|
//
|
|
|
|
LONG lRefCount;
|
|
|
|
//
|
|
// File where reference operation was invoked
|
|
//
|
|
|
|
DWORD dwFileSig;
|
|
|
|
//
|
|
// Line where reference operation was invoked
|
|
//
|
|
|
|
DWORD dwLine;
|
|
|
|
} REF_HIST_ENTRY, *PREF_HIST_ENTRY;
|
|
|
|
|
|
#define MAX_REF_HISTORY 16
|
|
|
|
#endif
|
|
|
|
|
|
#define CS_DISCONNECTING 0x00
|
|
#define CS_CONNECTING 0x01
|
|
#define CS_CONNECTED 0x02
|
|
|
|
#if DBG
|
|
|
|
#define CS_IP_DELETED_LINK 0xf0
|
|
|
|
#endif
|
|
|
|
//
|
|
// The CONN_ENTRY structure defines a connection. There is only one
|
|
// CONN_ENTRY for each dial out or router connection. However, on the
|
|
// server adapter, we can have multiple CONN_ENYTRYs - one for each dial
|
|
// in client. The fields of a CONN_ENTRY are all READ-ONLY except
|
|
// for ulSpeed, ulMtu, pAdapter and byState.
|
|
// REFCOUNTS: A CONN_ENTRY is refcounted once when the connection is
|
|
// created (LinkUp) and then once for every send. It is deref'ed
|
|
// on every SendComplete and then again on CloseLink.
|
|
//
|
|
|
|
typedef struct _CONN_ENTRY
|
|
{
|
|
//
|
|
// Back pointer to owning adapter
|
|
//
|
|
|
|
struct _ADAPTER *pAdapter;
|
|
|
|
//
|
|
// Connection information
|
|
//
|
|
|
|
DWORD dwLocalAddr;
|
|
DWORD dwLocalMask;
|
|
DWORD dwRemoteAddr;
|
|
|
|
//
|
|
// IP's context for this link. Only used for DU_CALLIN connections
|
|
//
|
|
|
|
PVOID pvIpLinkContext;
|
|
|
|
//
|
|
// Pointer to the lock to use when locking this connection.
|
|
// For clients, this is a pointer to rlLock, while for others
|
|
// this points to the adapter's lock entry
|
|
//
|
|
|
|
PRT_LOCK prlLock;
|
|
|
|
//
|
|
// The lock for this entry. Only used for DU_CALLIN
|
|
//
|
|
|
|
RT_LOCK rlLock;
|
|
|
|
//
|
|
// Refcount
|
|
//
|
|
|
|
LONG lRefCount;
|
|
|
|
//
|
|
// The MTU and speed for this connection
|
|
//
|
|
|
|
ULONG ulMtu;
|
|
ULONG ulSpeed;
|
|
|
|
//
|
|
// The usage (CALLIN, CALLOUT or ROUTER) for the connection
|
|
//
|
|
|
|
DIAL_USAGE duUsage;
|
|
|
|
//
|
|
// The slot index in the connection table
|
|
//
|
|
|
|
ULONG ulSlotIndex;
|
|
|
|
//
|
|
// Precanned header for this connection
|
|
//
|
|
|
|
ETH_HEADER ehHeader;
|
|
|
|
//
|
|
// Flag which determines whether to filter netbios packets or not
|
|
//
|
|
|
|
BOOLEAN bFilterNetBios;
|
|
|
|
BYTE byState;
|
|
|
|
#if DBG
|
|
|
|
DWORD dwTotalRefOps;
|
|
|
|
REF_HIST_ENTRY rheHistory[MAX_REF_HISTORY];
|
|
|
|
#endif
|
|
|
|
} CONN_ENTRY, *PCONN_ENTRY;
|
|
|
|
#include "ref.h"
|
|
|
|
#define InitConnEntryRefCount(p) InitStructureRefCount("ConnEntry", (p), 0)
|
|
|
|
#if DBG
|
|
|
|
#define ReferenceConnEntry(p) \
|
|
{ \
|
|
REF_HIST_ENTRY __rheTemp; \
|
|
InterlockedIncrement((PLONG)&((p)->dwTotalRefOps)); \
|
|
KeQuerySystemTime(&(__rheTemp.liChangeTime)); \
|
|
__rheTemp.lRefCount = ReferenceStructure("ConnEntry", (p)); \
|
|
__rheTemp.dwFileSig = __FILE_SIG__; \
|
|
__rheTemp.dwLine = __LINE__; \
|
|
(p)->rheHistory[((p)->dwTotalRefOps) % MAX_REF_HISTORY] = \
|
|
__rheTemp; \
|
|
}
|
|
|
|
#define DereferenceConnEntry(p) \
|
|
{ \
|
|
REF_HIST_ENTRY __rheTemp; \
|
|
InterlockedIncrement((PLONG)&((p)->dwTotalRefOps)); \
|
|
KeQuerySystemTime(&(__rheTemp.liChangeTime)); \
|
|
__rheTemp.dwFileSig = __FILE_SIG__; \
|
|
__rheTemp.dwLine = __LINE__; \
|
|
if((__rheTemp.lRefCount = \
|
|
InterlockedDecrement(&((p)->lRefCount))) == 0) \
|
|
{ \
|
|
(p)->rheHistory[((p)->dwTotalRefOps) % MAX_REF_HISTORY] =\
|
|
__rheTemp; \
|
|
WanpDeleteConnEntry((p)); \
|
|
} \
|
|
else \
|
|
{ \
|
|
(p)->rheHistory[((p)->dwTotalRefOps) % MAX_REF_HISTORY] =\
|
|
__rheTemp; \
|
|
} \
|
|
}
|
|
|
|
#else
|
|
|
|
#define ReferenceConnEntry(p) ReferenceStructure("ConnEntry", (p))
|
|
#define DereferenceConnEntry(p) DereferenceStructure("ConnEntry", (p) ,WanpDeleteConnEntry)
|
|
|
|
#endif
|
|
|
|
#define AS_FREE 0x00
|
|
#define AS_REMOVING 0x01
|
|
#define AS_ADDING 0x02
|
|
#define AS_ADDED 0x03
|
|
#define AS_UNMAPPING 0x04
|
|
#define AS_MAPPING 0x05
|
|
#define AS_MAPPED 0x06
|
|
|
|
//
|
|
// There are two conditions where an adapter is in AS_MAPPED state yet has
|
|
// no connection entry:
|
|
// (i) A Server Adapter is mapped, but has a connection table
|
|
// (ii) If a demand dial attempt finds an added adapter, it maps it but
|
|
// doesnt create the CONN_ENTRY till LinkUp
|
|
//
|
|
|
|
|
|
//
|
|
// REFCOUNTS: An ADAPTER is referenced once on creation since it lies on
|
|
// a list and once when it added to IP. It is referenced when it
|
|
// is mapped to an interface since the interface has a pointer to it.
|
|
// It is also referenced once for each connection.
|
|
// ADAPTERs are dereferenced when they are unmapped from an interface (at
|
|
// linkdown or connection failure). They are deref'ed when a CONN_ENTRY
|
|
// is finally cleaned out (not at linkdown - rather when the CONN_ENTRY's
|
|
// ref goes to 0). They are deref'ed when they are removed from the
|
|
// list to be deleted. We also deref them when we get a CloseAdapter from
|
|
// IP
|
|
//
|
|
|
|
typedef struct _ADAPTER
|
|
{
|
|
//
|
|
// Link in the list of adapters on this machine
|
|
//
|
|
|
|
LIST_ENTRY leAdapterLink;
|
|
|
|
//
|
|
// The connection entry for this adapter. Not used for the Server
|
|
// Adapter since it has many connections on it
|
|
//
|
|
|
|
PCONN_ENTRY pConnEntry;
|
|
|
|
//
|
|
// Name of the binding
|
|
//
|
|
|
|
UNICODE_STRING usConfigKey;
|
|
|
|
//
|
|
// Name of the device
|
|
//
|
|
|
|
UNICODE_STRING usDeviceNameW;
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// Same thing, only in asciiz so that we can print it easily
|
|
//
|
|
|
|
ANSI_STRING asDeviceNameA;
|
|
|
|
#endif
|
|
|
|
//
|
|
// Lock that protects the adapter
|
|
//
|
|
|
|
RT_LOCK rlLock;
|
|
|
|
//
|
|
// The reference count for the structure
|
|
// Keep this and the lock together to make the cache happy
|
|
//
|
|
|
|
LONG lRefCount;
|
|
|
|
//
|
|
// The index given to us by IP
|
|
//
|
|
|
|
DWORD dwAdapterIndex;
|
|
|
|
#if DBG
|
|
|
|
DWORD dwRequestedIndex;
|
|
|
|
#endif
|
|
|
|
//
|
|
// TDI entity magic
|
|
//
|
|
|
|
DWORD dwIfInstance;
|
|
DWORD dwATInstance;
|
|
|
|
//
|
|
// The state of this adapter
|
|
//
|
|
|
|
BYTE byState;
|
|
|
|
//
|
|
// The Guid for the adapter
|
|
//
|
|
|
|
GUID Guid;
|
|
|
|
//
|
|
// IP's context for this adapter
|
|
//
|
|
|
|
PVOID pvIpContext;
|
|
|
|
//
|
|
// The interface that is adapter is mapped to
|
|
//
|
|
|
|
struct _UMODE_INTERFACE *pInterface;
|
|
|
|
//
|
|
// The pending packet queue length
|
|
//
|
|
|
|
ULONG ulQueueLen;
|
|
|
|
//
|
|
// Queue of pending packets
|
|
//
|
|
|
|
LIST_ENTRY lePendingPktList;
|
|
|
|
//
|
|
// Queue of header buffers for the pending packets
|
|
//
|
|
|
|
LIST_ENTRY lePendingHdrList;
|
|
|
|
//
|
|
// The next two members are used to synchronize state changes for
|
|
// the adapter. There are two kinds of notifications needed. When a
|
|
// thread is modifying the state using functions which are completed
|
|
// asynchronously, it needs to wait for the completion routine to run
|
|
// The completion routine uses the pkeChangeEvent to notify the original
|
|
// thread.
|
|
// Also while this change is in progress, other threads may be interested
|
|
// in getting access to the data structure once the state has been
|
|
// modified. They add WAN_EVENT_NODE to the EventList and the original
|
|
// thread then goes about notifying each of the waiters
|
|
//
|
|
|
|
PKEVENT pkeChangeEvent;
|
|
LIST_ENTRY leEventList;
|
|
|
|
BYTE rgbyHardwareAddr[ARP_802_ADDR_LENGTH];
|
|
|
|
}ADAPTER, *PADAPTER;
|
|
|
|
#define InitAdapterRefCount(p) InitStructureRefCount("Adapter", (p), 1)
|
|
#define ReferenceAdapter(p) ReferenceStructure("Adapter", (p))
|
|
#define DereferenceAdapter(p) DereferenceStructure("Adapter", (p), WanpDeleteAdapter)
|
|
|
|
typedef struct _UMODE_INTERFACE
|
|
{
|
|
//
|
|
// Link on the list of interfaces
|
|
//
|
|
|
|
LIST_ENTRY leIfLink;
|
|
|
|
//
|
|
// Pointer to adapter when mapped
|
|
//
|
|
|
|
PADAPTER pAdapter;
|
|
|
|
//
|
|
// The (user mode) interface index
|
|
//
|
|
|
|
DWORD dwIfIndex;
|
|
|
|
//
|
|
// The reserved index for this interface
|
|
//
|
|
|
|
DWORD dwRsvdAdapterIndex;
|
|
|
|
//
|
|
// The lock for the interface
|
|
//
|
|
|
|
RT_LOCK rlLock;
|
|
|
|
//
|
|
// The reference count for the structure
|
|
// Keep this and the lock together to make the cache happy
|
|
//
|
|
|
|
LONG lRefCount;
|
|
|
|
//
|
|
// The GUID for the interface. This is setup at add interface time
|
|
// for router interfaces and at lineup for callouts
|
|
//
|
|
|
|
GUID Guid;
|
|
|
|
//
|
|
// The usage (CALLIN, CALLOUT or ROUTER)
|
|
//
|
|
|
|
DIAL_USAGE duUsage;
|
|
|
|
//
|
|
// Count of packets pending. Used to cap the max number of packets
|
|
// copied when a connection is being brought up
|
|
//
|
|
|
|
ULONG ulPacketsPending;
|
|
|
|
//
|
|
// The admin and operational states.
|
|
//
|
|
|
|
DWORD dwAdminState;
|
|
DWORD dwOperState;
|
|
|
|
//
|
|
// Last time the state changed. We dont do anything with this right now
|
|
//
|
|
|
|
DWORD dwLastChange;
|
|
|
|
//
|
|
// Sundry MIB-II statistics for the interface
|
|
//
|
|
|
|
ULONG ulInOctets;
|
|
ULONG ulInUniPkts;
|
|
ULONG ulInNonUniPkts;
|
|
ULONG ulInDiscards;
|
|
ULONG ulInErrors;
|
|
ULONG ulInUnknownProto;
|
|
ULONG ulOutOctets;
|
|
ULONG ulOutUniPkts;
|
|
ULONG ulOutNonUniPkts;
|
|
ULONG ulOutDiscards;
|
|
ULONG ulOutErrors;
|
|
|
|
}UMODE_INTERFACE, *PUMODE_INTERFACE;
|
|
|
|
#define InitInterfaceRefCount(p) InitStructureRefCount("Interface", (p), 1)
|
|
#define ReferenceInterface(p) ReferenceStructure("Interface", (p))
|
|
#define DereferenceInterface(p) DereferenceStructure("Interface", (p), WanpDeleteInterface)
|
|
|
|
typedef struct _ADDRESS_CONTEXT
|
|
{
|
|
//
|
|
// The next RCE in the chain
|
|
//
|
|
|
|
RouteCacheEntry *pNextRce;
|
|
|
|
PCONN_ENTRY pOwningConn;
|
|
|
|
}ADDRESS_CONTEXT, *PADDRESS_CONTEXT;
|
|
|
|
//
|
|
// Context for an asynchronous NdisRequest
|
|
//
|
|
|
|
typedef
|
|
VOID
|
|
(* PFNWANARP_REQUEST_COMPLETION_HANDLER)(
|
|
NDIS_HANDLE nhHandle,
|
|
struct _WANARP_NDIS_REQUEST_CONTEXT *pRequestContext,
|
|
NDIS_STATUS nsStatus
|
|
);
|
|
|
|
#pragma warning(disable:4201)
|
|
|
|
typedef struct _WANARP_NDIS_REQUEST_CONTEXT
|
|
{
|
|
//
|
|
// The request sent to NDIS
|
|
// Ndis returns a pointer to this in our completion routine; we
|
|
// use CONTAINING_RECORD to get a pointer to the context structure
|
|
//
|
|
|
|
NDIS_REQUEST NdisRequest;
|
|
|
|
//
|
|
// The completion routine to call when NDIS is done processing the
|
|
// request. If NULL, then we stop
|
|
//
|
|
|
|
PFNWANARP_REQUEST_COMPLETION_HANDLER pfnCompletionRoutine;
|
|
|
|
union
|
|
{
|
|
BYTE rgbyProtocolId[ARP_802_ADDR_LENGTH];
|
|
ULONG ulLookahead;
|
|
ULONG ulPacketFilter;
|
|
TRANSPORT_HEADER_OFFSET TransportHeaderOffset;
|
|
};
|
|
|
|
}WANARP_NDIS_REQUEST_CONTEXT, *PWANARP_NDIS_REQUEST_CONTEXT;
|
|
|
|
#pragma warning(default:4201)
|
|
|
|
//
|
|
// Our resource (which doesnt allow recursive access)
|
|
//
|
|
|
|
typedef struct _WAN_RESOURCE
|
|
{
|
|
//
|
|
// Number of people waiting on the resource ( + 1 if one is using
|
|
// the resource)
|
|
//
|
|
|
|
LONG lWaitCount;
|
|
|
|
KEVENT keEvent;
|
|
}WAN_RESOURCE, *PWAN_RESOURCE;
|
|
|
|
//
|
|
// List of events
|
|
//
|
|
|
|
typedef struct _WAN_EVENT_NODE
|
|
{
|
|
LIST_ENTRY leEventLink;
|
|
KEVENT keEvent;
|
|
|
|
}WAN_EVENT_NODE, *PWAN_EVENT_NODE;
|
|
|
|
//
|
|
// Define alignment macros to align structure sizes and pointers up and down.
|
|
//
|
|
|
|
#define ALIGN_DOWN(length, type) \
|
|
((ULONG)(length) & ~(sizeof(type) - 1))
|
|
|
|
#define ALIGN_UP(length, type) \
|
|
(ALIGN_DOWN(((ULONG)(length) + sizeof(type) - 1), type))
|
|
|
|
#define ALIGN_DOWN_POINTER(address, type) \
|
|
((PVOID)((ULONG_PTR)(address) & ~((ULONG_PTR)sizeof(type) - 1)))
|
|
|
|
#define ALIGN_UP_POINTER(address, type) \
|
|
(ALIGN_DOWN_POINTER(((ULONG_PTR)(address) + sizeof(type) - 1), type))
|
|
|
|
#endif // __WANARP_WANARP_H__
|