windows-nt/Source/XPSP1/NT/net/rras/rtm/rtmp.h
2020-09-26 16:20:57 +08:00

490 lines
14 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
net\rtm\rtmp.h
Abstract:
Provate Interface for Routing Table Manager DLL
Author:
Vadim Eydelman
Revision History:
--*/
#if 0
#ifndef NT_INCLUDED
#include <nt.h>
#endif
#ifndef _NTRTL_
#include <ntrtl.h>
#endif
#ifndef _NTURTL_
#include <nturtl.h>
#endif
#ifndef _WINDEF_
#include <windef.h>
#endif
#ifndef _WINBASE_
#include <winbase.h>
#endif
#ifndef _WINREG_
#include <winreg.h>
#endif
#ifndef _ROUTING_RTM_
#include "rtm.h"
#endif
#ifndef _ROUTING_RMRTM_
#include "rmrtm.h"
#endif
#endif
/*++
*******************************************************************
S u p l e m e n t s t o R T M . H S t r u c t u r e s
*******************************************************************
--*/
// Basic route info, present in routes of all types
typedef struct {
ROUTE_HEADER;
} RTM_XX_ROUTE, *PRTM_XX_ROUTE;
#define XX_INTERFACE RR_InterfaceID
#define XX_PROTOCOL RR_RoutingProtocol
#define XX_METRIC RR_Metric
#define XX_TIMESTAMP RR_TimeStamp
#define XX_PSD RR_ProtocolSpecificData
/*++
*******************************************************************
S u p l e m e n t s t o N T R T L . H S t r u c t u r e s
*******************************************************************
--*/
#define InitializeListEntry(entry) InitializeListHead(entry)
#define IsListEntry(entry) (!IsListEmpty(entry))
#if DBG
#define ASSERTERR(exp) \
if (!(exp)) { \
DbgPrint("Get last error= %d\n", GetLastError ()); \
RtlAssert( #exp, __FILE__, __LINE__, NULL ); \
}
#else
#define ASSERTERR(exp)
#endif
#if DBG
#define ASSERTERRMSG(msg,exp) \
if (!(exp)) { \
DbgPrint("Get last error= %d\n", GetLastError ()); \
RtlAssert( #exp, __FILE__, __LINE__, msg ); \
}
#else
#define ASSERTERRMSG(msg,exp)
#endif
/*++
*******************************************************************
C o n f i g u r a t i o n C o n s t a n t s
*******************************************************************
--*/
// Size of interface index hash table
#define RTM_INTF_HASH_SIZE 31
// Maximum number of nodes in temp net number list that will
// triger an update (temp list is scaned when inserting the route)
#define RTM_TEMP_LIST_MAX_COUNT 16
// Maximum number of nodes in deleted list that will
// triger an update
#define RTM_DELETED_LIST_MAX_COUNT 16
// Maximum time between updates (if not triggered by the conditions above or
// client's query)
#define RTM_NET_NUMBER_UPDATE_PERIOD {(ULONG)(-60*1000*10000), -1L}
// Maximum number of pednign notification change messages
// the queue. If this number is exceeded because some client(s) are
// not dequeueing them, oldest message will be purged
#define RTM_MAX_ROUTE_CHANGE_MESSAGES 10000
/*++
*******************************************************************
D a t a T y p e s
*******************************************************************
--*/
// Types of nodes that can exist in the table
#define RTM_ENUMERATOR_FLAG 0x00000001
#define RTM_BEST_NODE_FLAG 0x00000002
#define RTM_ENABLED_NODE_FLAG 0x00000004
#define RTM_ANY_ENABLE_STATE ((DWORD)(~RTM_ENABLED_NODE_FLAG))
#define RTM_SORTED_NODE_FLAG 0x00000008
#define IsEnumerator(node) (node->RN_Flags&RTM_ENUMERATOR_FLAG)
#define IsBest(node) (node->RN_Flags&RTM_BEST_NODE_FLAG)
#define SetBest(node) node->RN_Flags|=RTM_BEST_NODE_FLAG
#define ResetBest(node) node->RN_Flags&=(~RTM_BEST_NODE_FLAG)
#define IsEnabled(node) (node->RN_Flags&RTM_ENABLED_NODE_FLAG)
#define IsSameEnableState(node,EnableFlag) \
((node->RN_Flags&RTM_ENABLED_NODE_FLAG)==EnableFlag)
#define SetEnable(node,enable) \
node->RN_Flags = enable \
? (node->RN_Flags|RTM_ENABLED_NODE_FLAG) \
: (node->RN_Flags&(~RTM_ENABLED_NODE_FLAG))
#define IsSorted(node) (node->RN_Flags&RTM_SORTED_NODE_FLAG)
#define SetSorted(node) node->RN_Flags|=RTM_SORTED_NODE_FLAG
#define RTM_NODE_FLAGS_INIT RTM_ENABLED_NODE_FLAG
#define RTM_ENUMERATOR_FLAGS_INIT RTM_ENUMERATOR_FLAG
// Each node will have the following links:
// Hash table link (routes in each basket are ordered by
// net number.interface.protocol.next_hop_address)
#define RTM_NET_NUMBER_HASH_LINK 0
// Deleted list link: used if entry cannot be deleted
// immediately because net number list is locked by the
// update thread. It is same as hash table link
// because one must first delete entry form the hash table
// before adding it to deleted list (there is no ordering
// in this list)
#define RTM_DELETED_LIST_LINK RTM_NET_NUMBER_HASH_LINK
#if RTM_USE_PROTOCOL_LISTS
// Link in the list of routes associated with a particular routing protocol
// (routes are grouped (not oredered) by the net number and
// ordered by protocol.next_hop_address inside of net number group
#define RTM_PROTOCOL_LIST_LINK (RTM_NET_NUMBER_HASH_LINK+1)
// Link in the list of routes associated with a particular interface
// (routes are grouped (not oredered) by the net number and
// ordered by interface.next_hop_address inside of net number group
#define RTM_INTERFACE_LIST_LINK (RTM_PROTOCOL_LIST_LINK+1)
#else
#define RTM_INTERFACE_LIST_LINK (RTM_NET_NUMBER_HASH_LINK+1)
#endif
// Link in the list ordered by net number.interface.protocol.next_hop_address
// There are two of these list. New routes are normaly inserted
// in temporary list that is periodically merged with master list
#define RTM_NET_NUMBER_LIST_LINK (RTM_INTERFACE_LIST_LINK+1)
// Link in list ordered by expiration time
#define RTM_EXPIRATION_QUEUE_LINK (RTM_NET_NUMBER_LIST_LINK+1)
// Total number of links for each node
#define RTM_NUM_OF_LINKS (RTM_EXPIRATION_QUEUE_LINK+1)
// Client count treshold that prevents client from entering RTM
// API's until table is initialized
#define RTM_CLIENT_STOP_TRESHHOLD (-10000)
// Event with link to store it in the stack
typedef struct _RTM_SYNC_OBJECT {
HANDLE RSO_Event;
SINGLE_LIST_ENTRY RSO_Link;
} RTM_SYNC_OBJECT, *PRTM_SYNC_OBJECT;
// Doubly linked list protected by the event that is
// assigned to the list on demand (when somebody is trying
// to access the list that is already in use)
typedef struct _RTM_SYNC_LIST {
PRTM_SYNC_OBJECT RSL_Sync; // Assigned event
LONG RSL_UseCount; // Number of user accessing or waiting
LIST_ENTRY RSL_Head; // List itself (head)
} RTM_SYNC_LIST, *PRTM_SYNC_LIST;
#if RTM_PROTOCOL_LIST_LINK
/* ****** Protocol lists no longer used ****** */
// Node of list of protocol lists
typedef struct _RTM_PROTOCOL_NODE {
LIST_ENTRY PN_Link; // Link in list of protocol lists
LIST_ENTRY PN_Head; // List of routes associated with
// a protocol
DWORD PN_RoutingProtocol; // Routing Protocol number
} RTM_PROTOCOL_NODE, *PRTM_PROTOCOL_NODE;
#endif
// Node of list of interface lists
typedef struct _RTM_INTERFACE_NODE {
LIST_ENTRY IN_Link; // Link in list of interface lists
LIST_ENTRY IN_Head; // List of routes associated with
// an interface
DWORD IN_InterfaceID; // Interface handle
} RTM_INTERFACE_NODE, *PRTM_INTERFACE_NODE;
// Node of Routing Table
typedef struct _RTM_ROUTE_NODE {
LIST_ENTRY RN_Links[RTM_NUM_OF_LINKS]; // Links in all lists
DWORD RN_Flags;
PRTM_SYNC_LIST RN_Hash; // Hash bucket this entry belongs to
DWORD RN_ExpirationTime; // System (Windows) Time in msec
RTM_XX_ROUTE RN_Route; // Route entry
} RTM_ROUTE_NODE, *PRTM_ROUTE_NODE;
// Node used to enumerate through any of the lists
typedef struct _RTM_ENUMERATOR {
LIST_ENTRY RE_Links[RTM_NUM_OF_LINKS]; // header is same as in
DWORD RE_Flags; // RTM_ROUTE_NODE
INT RE_Link; // Which link is used for enumeration
PLIST_ENTRY RE_Head; // Head of list through which we are
// enumerting
PRTM_SYNC_LIST RE_Lock; // Syncronization object protecting
// the this list
PRTM_SYNC_LIST RE_Hash; // Hash bucket this entry belongs to
DWORD RE_ProtocolFamily; // Table in which we are enumerating
DWORD RE_EnumerationFlags; // Which types of entries to limit
// enumeration to
RTM_XX_ROUTE RE_Route; // Criteria
} RTM_ENUMERATOR, *PRTM_ENUMERATOR;
// Node in route change message list
typedef struct _RTM_ROUTE_CHANGE_NODE {
LIST_ENTRY RCN_Link; // Link in the list
HANDLE RCN_ResponsibleClient; // Client that caused this change
// or null if route was aged out
ULONG RCN_ReferenceCount; // Initialized with total number
// of registered clients and decremented as messages are reported to
// each client until all clients are informed at which point the node
// can be deleted
DWORD RCN_Flags;
PRTM_ROUTE_NODE RCN_Route2;
RTM_XX_ROUTE RCN_Route1;
} RTM_ROUTE_CHANGE_NODE, *PRTM_ROUTE_CHANGE_NODE;
#define RTM_NODE_BASE_SIZE \
(FIELD_OFFSET(RTM_ROUTE_NODE,RN_Route) \
>FIELD_OFFSET(RTM_ROUTE_CHANGE_NODE,RCN_Route1)) \
? FIELD_OFFSET(RTM_ROUTE_NODE,RN_Route) \
: FIELD_OFFSET(RTM_ROUTE_CHANGE_NODE,RCN_Route1)
// Routing Manager Table
typedef struct _RTM_TABLE {
HANDLE RT_Heap; // Heap to allocate nodes from
LONG RT_APIclientCount; // Count of clients that are
// inside of RTM API calls
HANDLE RT_ExpirationTimer; // Nt timer handle
HANDLE RT_UpdateTimer; // Nt timer handle
DWORD RT_NumOfMessages; // Number of notification
// messages in the queue
ULONG RT_NetworkCount; // Total number of networks
// to which we have routes
DWORD RT_NetNumberTempCount; // How many entries are in
// net number temp list
DWORD RT_DeletedNodesCount; // How many entries are in
// deleted list
LONG RT_UpdateWorkerPending; // Sorted list update is
// being performed or scheduled
// if >=0
LONG RT_ExpirationWorkerPending; // Expiration queue check is
// being performed or scheduled
// if >=0
SINGLE_LIST_ENTRY RT_SyncObjectList; // Stack of events that can be
// used for synchronization
#if RTM_PROTOCOL_LIST_LINK
/* ****** Protocol lists no longer used ****** */
RTM_SYNC_LIST RT_ProtocolList; // List of protocol lists
#endif
RTM_SYNC_LIST RT_NetNumberMasterList; // Master net number list
RTM_SYNC_LIST RT_NetNumberTempList; // Temp net number list
RTM_SYNC_LIST RT_DeletedList; // List of deleted routes
RTM_SYNC_LIST RT_ExpirationQueue; // Expiration queue
RTM_SYNC_LIST RT_RouteChangeQueue;// List of route change messages
RTM_SYNC_LIST RT_ClientList; // List of registered clients
PRTM_SYNC_LIST RT_NetNumberHash; // Hash table
PRTM_SYNC_LIST RT_InterfaceHash; // Hash table of interface lists
RTM_PROTOCOL_FAMILY_CONFIG RT_Config; // Configuration params
CRITICAL_SECTION RT_Lock; // Table-wide lock
} RTM_TABLE, *PRTM_TABLE;
// Structure associated with each client
typedef struct _RTM_CLIENT {
LIST_ENTRY RC_Link; // Link in client list
DWORD RC_ProtocolFamily;
DWORD RC_RoutingProtocol;
DWORD RC_Flags;
HANDLE RC_NotificationEvent; // Event through which client
// is notified about route change
PLIST_ENTRY RC_PendingMessage; // Pointer to first message in
// the route change queue that was not reported
// to the client
} RTM_CLIENT, *PRTM_CLIENT;
#define RT_RouteSize RT_Config.RPFC_RouteSize
#define RT_HashTableSize RT_Config.RPFC_HashSize
#define NNM(Route) (((char *)Route)+sizeof (RTM_XX_ROUTE))
#define NetNumCmp(Table,Route1,Route2) \
(*Table->RT_Config.RPFC_NNcmp)(NNM(Route1),NNM(Route2))
#define NextHopCmp(Table,Route1,Route2) \
(*Table->RT_Config.RPFC_NHAcmp)(Route1,Route2)
#define FSDCmp(Table,Route1,Route2) \
(*Table->RT_Config.RPFC_FSDcmp)(Route1,Route2)
#define ValidateRoute(Table,Route) \
(*Table->RT_Config.RPFC_Validate)(Route)
#define MetricCmp(Table,Route1,Route2) \
(*Table->RT_Config.RPFC_RMcmp)(Route1,Route2)
#define EnterTableAPI(Table) \
((InterlockedIncrement(&(Table)->RT_APIclientCount)>0) \
? TRUE \
: (InterlockedDecrement (&(Table)->RT_APIclientCount), FALSE))
#define ExitTableAPI(Table) \
InterlockedDecrement(&(Table)->RT_APIclientCount)
/*++
*******************************************************************
I n t e r n a l F u n c t i o n P r o t o t y p e s
*******************************************************************
--*/
// Initializes sync list object
VOID
InitializeSyncList (
PRTM_SYNC_LIST list
);
#if DBG
#define EnterSyncList(table,list,wait) DoEnterSyncList(table,list,wait,__FILE__,__LINE__)
#else
#define EnterSyncList(table,list,wait) DoEnterSyncList(table,list,wait)
#endif
// Get mutually exclusive access to the sync list obect
// Returns TRUE if access if obtained, FALSE otherwise
BOOLEAN
DoEnterSyncList (
PRTM_TABLE table,
PRTM_SYNC_LIST list,
BOOLEAN wait
#if DBG
, LPSTR file,
ULONG line
#endif
);
// Release previously owned sync list object
VOID
LeaveSyncList (
PRTM_TABLE table,
PRTM_SYNC_LIST list
);
#define HashFunction(Table,Net) \
(*Table->RT_Config.RPFC_Hash)(Net)
#define IntfHashFunction(Table,InterfaceID) \
(InterfaceID%RTM_INTF_HASH_SIZE)
// Finds list of routes that are associated with given interface and returns
// pointer to its head
// Creates new list of none exists yet
PLIST_ENTRY
FindInterfaceList (
PRTM_SYNC_LIST intfHash,
DWORD Interface,
BOOL CreateNew
);
// Finds list of routes that are associated with given iprotocol and returns
// pointer to its head
// Creates new list of none exists yet
PLIST_ENTRY
FindProtocolList (
PRTM_TABLE Table,
DWORD RoutingProtocol,
BOOL CreateNew
);
// Adds node to temporary net number list (to be later merged with master list)
// Both lists are ordered by net number.interface.protocol.next hop address
VOID
AddNetNumberListNode (
PRTM_TABLE Table,
PRTM_ROUTE_NODE newNode
);
// Adds node to expiration time queue. (Queue is ordered by expiration time)
// Return TRUE if new node is the first in the queue
BOOL
AddExpirationQueueNode (
PRTM_TABLE Table,
PRTM_ROUTE_NODE newNode
);
#define MAXTICKS MAXULONG
#define IsLater(Time1,Time2) \
(Time1-Time2<MAXTICKS/2)
#define TimeDiff(Time1,Time2) \
(Time1-Time2)
#define IsPositiveTimeDiff(TimeDiff) \
(TimeDiff<MAXTICKS/2)
#if DBG
// Include debugging function prototypes
#ifndef _RTMDLG_
#include "rtmdlg.h"
#endif
#include <rtutils.h>
#include "rtmdbg.h"
#endif
typedef struct _MASK_ENTRY
{
DWORD dwMask;
DWORD dwCount;
} MASK_ENTRY, *PMASK_ENTRY;
//
// for IPv4 addresses
//
#define MAX_MASKS 32