/*++ 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 \ // #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 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 #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__