//============================================================================ // Copyright (c) 1995, Microsoft Corporation // // File: table.h // // History: // Abolade Gbadegesin Aug-8-1995 Created. // // V Raman Oct-3-1996 // Added Deactivate Event to IF_TABLE_ENTRY // // V Raman Oct-27-1996 // Removed Deactivate Event in IF_TABLE_ENTRY // and made interface deactivation synchronous // // Contains structures and macros used for table management. //============================================================================ #ifndef _TABLE_H_ #define _TABLE_H_ #define GETMODE_EXACT 0 #define GETMODE_FIRST 1 #define GETMODE_NEXT 2 // // TYPE DEFINITIONS FOR INTERFACE MANAGEMENT // // // struct: IF_TABLE_ENTRY // // declares the components of an interface table entry // // typedef struct _IF_TABLE_ENTRY { LIST_ENTRY ITE_LinkByAddress; LIST_ENTRY ITE_LinkByIndex; LIST_ENTRY ITE_HTLinkByIndex; NET_INTERFACE_TYPE ITE_Type; DWORD ITE_Index; DWORD ITE_Flags; HANDLE ITE_FullOrDemandUpdateTimer; IPRIP_IF_STATS ITE_Stats; PIPRIP_IF_CONFIG ITE_Config; PIPRIP_IF_BINDING ITE_Binding; SOCKET *ITE_Sockets; } IF_TABLE_ENTRY, *PIF_TABLE_ENTRY; #define ITEFLAG_ENABLED ((DWORD)0x00000001) #define ITEFLAG_BOUND ((DWORD)0x00000002) #define ITEFLAG_FULL_UPDATE_PENDING ((DWORD)0x00000004) #define ITEFLAG_FULL_UPDATE_INQUEUE ((DWORD)0x00000008) #define IF_IS_ENABLED(i) \ ((i)->ITE_Flags & ITEFLAG_ENABLED) #define IF_IS_BOUND(i) \ ((i)->ITE_Flags & ITEFLAG_BOUND) #define IF_IS_ACTIVE(i) \ (IF_IS_BOUND(i) && IF_IS_ENABLED(i)) #define IF_IS_DISABLED(i) !IF_IS_ENABLED(i) #define IF_IS_UNBOUND(i) !IF_IS_BOUND(i) #define IF_IS_INACTIVE(i) !IF_IS_ACTIVE(i) #define IF_FULL_UPDATE_PENDING(i) \ ((i)->ITE_Flags & ITEFLAG_FULL_UPDATE_PENDING) #define IF_FULL_UPDATE_INQUEUE(i) \ ((i)->ITE_Flags & ITEFLAG_FULL_UPDATE_INQUEUE) // // macros and definitions used by interface tables // #define IF_HASHTABLE_SIZE 29 #define IF_HASHVALUE(i) ((i) % IF_HASHTABLE_SIZE) // // struct: IF_TABLE // // declares the structure of an interface table. consists of a hash-table // of IF_TABLE_ENTRY structures hashed on interface index, and a list // of all activated interfaces ordered by IP address // // The IT_CS section is used to synchronize the generation of updates; // it is acquired when updates are started and finished on interfaces // in this table, and thus it protects the flags field. // // The IT_RWL section is used to synchronize modifications to the table; // it must be acquired exclusively when entries are being added or deleted // from the table, and when the states of entries are being changed. // (e.g. binding, unbinding, enabling and disabling entries). // // IT_RWL must be acquired non-exclusively on all other acceses. // // When IT_RWL and IT_CS must both be acquired, IT_RWL must be acquired first. // typedef struct _IF_TABLE { DWORD IT_Created; DWORD IT_Flags; LARGE_INTEGER IT_LastUpdateTime; HANDLE IT_FinishTriggeredUpdateTimer; HANDLE IT_FinishFullUpdateTimer; CRITICAL_SECTION IT_CS; READ_WRITE_LOCK IT_RWL; LIST_ENTRY IT_ListByAddress; LIST_ENTRY IT_ListByIndex; LIST_ENTRY IT_HashTableByIndex[IF_HASHTABLE_SIZE]; } IF_TABLE, *PIF_TABLE; // // constants and macros used for the flags field // #define IPRIP_FLAG_FULL_UPDATE_PENDING ((DWORD)0x00000001) #define IPRIP_FLAG_TRIGGERED_UPDATE_PENDING ((DWORD)0x00000002) #define IPRIP_FULL_UPDATE_PENDING(t) \ ((t)->IT_Flags & IPRIP_FLAG_FULL_UPDATE_PENDING) #define IPRIP_TRIGGERED_UPDATE_PENDING(t) \ ((t)->IT_Flags & IPRIP_FLAG_TRIGGERED_UPDATE_PENDING) DWORD CreateIfTable( PIF_TABLE pTable ); DWORD DeleteIfTable( PIF_TABLE pTable ); DWORD CreateIfEntry( PIF_TABLE pTable, DWORD dwIndex, NET_INTERFACE_TYPE dwIfType, PIPRIP_IF_CONFIG pConfig, PIF_TABLE_ENTRY *ppEntry ); DWORD DeleteIfEntry( PIF_TABLE pIfTable, DWORD dwIndex ); DWORD ValidateIfConfig( PIPRIP_IF_CONFIG pic ); DWORD CreateIfSocket( PIF_TABLE_ENTRY pITE ); DWORD DeleteIfSocket( PIF_TABLE_ENTRY pITE ); DWORD BindIfEntry( PIF_TABLE pTable, DWORD dwIndex, PIP_ADAPTER_BINDING_INFO pBinding ); DWORD UnBindIfEntry( PIF_TABLE pTable, DWORD dwIndex ); DWORD EnableIfEntry( PIF_TABLE pTable, DWORD dwIndex ); DWORD ConfigureIfEntry( PIF_TABLE pTable, DWORD dwIndex, PIPRIP_IF_CONFIG pConfig ); DWORD DisableIfEntry( PIF_TABLE pTable, DWORD dwIndex ); PIF_TABLE_ENTRY GetIfByIndex( PIF_TABLE pTable, DWORD dwIndex ); PIF_TABLE_ENTRY GetIfByAddress( PIF_TABLE pTable, DWORD dwAddress, DWORD dwGetMode, PDWORD pdwErr ); PIF_TABLE_ENTRY GetIfByListIndex( PIF_TABLE pTable, DWORD dwAddress, DWORD dwGetMode, PDWORD pdwErr ); #define IF_TABLE_CREATED(pTable) ((pTable)->IT_Created == 0x12345678) // // TYPE DEFINITIONS FOR THE PEER STATISTICS HASH TABLE // // // struct: PEER_TABLE_ENTRY // // declares the structure of each entry in the peer table // typedef struct _PEER_TABLE_ENTRY { LIST_ENTRY PTE_LinkByAddress; LIST_ENTRY PTE_HTLinkByAddress; DWORD PTE_Address; IPRIP_PEER_STATS PTE_Stats; } PEER_TABLE_ENTRY, *PPEER_TABLE_ENTRY; // // macros and definitions used by peer statistics tables // #define PEER_HASHTABLE_SIZE 29 #define PEER_HASHVALUE(a) \ (((a) + \ ((a) >> 8) + \ ((a) >> 16) + \ ((a) >> 24)) % PEER_HASHTABLE_SIZE) // // struct: PEER_TABLE // // this table contains the entries for keeping statistics about each peer. // it consists of a hash-table of peer stats (for fast direct access to // a specific entry) and a list of peer stats entries ordered by address // (for easy enumeration via MibGetNext) // typedef struct _PEER_TABLE { READ_WRITE_LOCK PT_RWL; DWORD PT_Created; LIST_ENTRY PT_ListByAddress; LIST_ENTRY PT_HashTableByAddress[PEER_HASHTABLE_SIZE]; } PEER_TABLE, *PPEER_TABLE; DWORD CreatePeerTable( PPEER_TABLE pTable ); DWORD DeletePeerTable( PPEER_TABLE pTable ); DWORD CreatePeerEntry( PPEER_TABLE pTable, DWORD dwAddress, PPEER_TABLE_ENTRY *ppEntry ); DWORD DeletePeerEntry( PPEER_TABLE pTable, DWORD dwAddress ); PPEER_TABLE_ENTRY GetPeerByAddress( PPEER_TABLE pTable, DWORD dwAddress, DWORD dwGetMode, PDWORD pdwErr ); #define PEER_TABLE_CREATED(pTable) ((pTable)->PT_Created == 0x12345678) // // TYPE DEFINITIONS FOR THE ROUTE TABLE USED FOR NETWORK SUMMARY // // // struct: ROUTE_TABLE_ENTRY // // declares the structure of each entry in the route table // typedef struct _ROUTE_TABLE_ENTRY { LIST_ENTRY RTE_Link; DWORD RTE_TTL; DWORD RTE_HoldTTL; RIP_IP_ROUTE RTE_Route; } ROUTE_TABLE_ENTRY, *PROUTE_TABLE_ENTRY; // // declares the structure of the protocol specific data // // // macros and definitions used by the route table // // // These flags are used in the ProtocolSpecificData array // to distinguish routes pending expiration from routes pending removal, // and to store the route tag for each route. // The first DWORD in the PSD_Data array is treated here as a byte-array; // the first two bytes are used to store the route tag; // the third byte is used to store the route flag // #define PSD(route) (route)->RR_ProtocolSpecificData.PSD_Data #define PSD_TAG0 0 #define PSD_TAG1 1 #define PSD_FLAG 2 #define ROUTEFLAG_SUMMARY ((BYTE)0x03) #define SETROUTEFLAG(route, flag) (((PBYTE)&PSD(route))[PSD_FLAG] = (flag)) #define GETROUTEFLAG(route) ((PBYTE)&PSD(route))[PSD_FLAG] #define SETROUTETAG(route, tag) \ ((PBYTE)&PSD(route))[PSD_TAG0] = LOBYTE(tag), \ ((PBYTE)&PSD(route))[PSD_TAG1] = HIBYTE(tag) #define GETROUTETAG(route) \ MAKEWORD(((PBYTE)&PSD(route))[PSD_TAG0],((PBYTE)&PSD(route))[PSD_TAG1]) #define SETROUTEMETRIC(route, metric) \ (route)->RR_FamilySpecificData.FSD_Metric1 = (metric) #define GETROUTEMETRIC(route) \ (route)->RR_FamilySpecificData.FSD_Metric1 #define COMPUTE_ROUTE_METRIC(route) \ (route)->RR_FamilySpecificData.FSD_Metric = \ (route)->RR_FamilySpecificData.FSD_Metric1 // // Macros to manipulate entity specific info in RTMv2 routes // #define ESD(route) (route)->EntitySpecificInfo #define ESD_TAG0 0 #define ESD_TAG1 1 #define ESD_FLAG 2 #define SETRIPFLAG(route, flag) (((PBYTE)&ESD(route))[ESD_FLAG] = (flag)) #define GETRIPFLAG(route) ((PBYTE)&ESD(route))[ESD_FLAG] #define SETRIPTAG(route, tag) \ ((PBYTE)&ESD(route))[ESD_TAG0] = LOBYTE(tag), \ ((PBYTE)&ESD(route))[ESD_TAG1] = HIBYTE(tag) #define GETRIPTAG(route) \ MAKEWORD(((PBYTE)&ESD(route))[ESD_TAG0],((PBYTE)&ESD(route))[ESD_TAG1]) #define ROUTE_HASHTABLE_SIZE 29 #define ROUTE_HASHVALUE(a) \ (((a) + \ ((a) >> 8) + \ ((a) >> 16) + \ ((a) >> 24)) % ROUTE_HASHTABLE_SIZE) // // struct: ROUTE_TABLE // // declares the structure of a route table, which consists of a hash-table // of routes hashed on the destination network. Note that no synchronization // is included since this structure is only used during full-updates, to // store summary routes, and at most one thread may be sending a full-update // at any given time. // typedef struct _ROUTE_TABLE { DWORD RT_Created; LIST_ENTRY RT_HashTableByNetwork[ROUTE_HASHTABLE_SIZE]; } ROUTE_TABLE, *PROUTE_TABLE; DWORD CreateRouteTable( PROUTE_TABLE pTable ); DWORD DeleteRouteTable( PROUTE_TABLE pTable ); DWORD WriteSummaryRoutes( PROUTE_TABLE pTable, HANDLE hRtmHandle ); DWORD CreateRouteEntry( PROUTE_TABLE pTable, PRIP_IP_ROUTE pRoute, DWORD dwTTL, DWORD dwHoldTTL ); DWORD DeleteRouteEntry( PROUTE_TABLE pTable, PRIP_IP_ROUTE pRoute ); PROUTE_TABLE_ENTRY GetRouteByRoute( PROUTE_TABLE pTable, PRIP_IP_ROUTE pRoute ); #define ROUTE_TABLE_CREATED(pTable) ((pTable)->RT_Created == 0x12345678) // // TYPE DEFINITIONS FOR BINDING TABLE // // // struct: BINDING_TABLE_ENTRY // // this entry contains a single binding. // a binding entry consists of an IP address, a network number (found // using the network class mask, not the subnet mask), // and a subnet mask. // All of the above are available when an interface is bound. // When a route arrives and its mask is to be guessed, its network number // can be computed (using the routes network class mask); we then search // the binding table for matching networks, and for each one we compare // (stored subnet mask) AND (interface IP address) // to // (stored subnet mask) AND (incoming route IP address). // When we find a match, (stored subnet mask) is our guess. // typedef struct _BINDING_TABLE_ENTRY { DWORD BTE_Address; DWORD BTE_Network; DWORD BTE_Netmask; LIST_ENTRY BTE_Link; } BINDING_TABLE_ENTRY, *PBINDING_TABLE_ENTRY; #define BINDING_HASHTABLE_SIZE 29 #define BINDING_HASHVALUE(a) \ (((a) + \ ((a) >> 8) + \ ((a) >> 16) + \ ((a) >> 24)) % BINDING_HASHTABLE_SIZE) // // struct: BINDING_TABLE // // this table is used to store binding information that is used to guess // the subnet masks of incoming routes. it contains the bindings of all // interfaces which have been added to IPRIP, in an array to speed up access // typedef struct _BINDING_TABLE { READ_WRITE_LOCK BT_RWL; DWORD BT_Created; LIST_ENTRY BT_HashTableByNetwork[BINDING_HASHTABLE_SIZE]; } BINDING_TABLE, *PBINDING_TABLE; #define BINDING_TABLE_CREATED(b) ((b)->BT_Created == 0x12345678) DWORD CreateBindingTable( PBINDING_TABLE pTable ); DWORD DeleteBindingTable( PBINDING_TABLE pTable ); DWORD CreateBindingEntry( PBINDING_TABLE pTable, PIPRIP_IF_BINDING pib ); DWORD DeleteBindingEntry( PBINDING_TABLE pTable, PIPRIP_IF_BINDING pib ); DWORD GuessSubnetMask( DWORD dwAddress, PDWORD pdwNetclassMask ); DWORD AddRtmRoute( RTM_ENTITY_HANDLE hRtmHandle, PRIP_IP_ROUTE prir, RTM_NEXTHOP_HANDLE hNextHop OPTIONAL, DWORD dwTimeOut, DWORD dwHoldTime, BOOL bActive ); DWORD GetRouteInfo( IN RTM_ROUTE_HANDLE hRoute, IN PRTM_ROUTE_INFO pInRouteInfo OPTIONAL, IN PRTM_DEST_INFO pInDestInfo OPTIONAL, OUT PRIP_IP_ROUTE pRoute ); #endif // _TABLE_H_