//**************************************************************************** // // Microsoft Windows NT RIP // // Copyright 1995-96 // // // Revision History // // // 2/26/95 Gurdeep Singh Pall Picked up from JBallard's team // // // Description: Globals, headers, defines. // //**************************************************************************** #define CLASSA_ADDR(a) (( (*((uchar *)&(a))) & 0x80) == 0) #define CLASSB_ADDR(a) (( (*((uchar *)&(a))) & 0xc0) == 0x80) #define CLASSC_ADDR(a) (( (*((uchar *)&(a))) & 0xe0) == 0xc0) #define CLASSD_ADDR(a) (( (*((uchar *)&(a))) & 0xf0) == 0xe0) #define CLASSE_ADDR(a) ((( (*((uchar *)&(a))) & 0xf0) == 0xf0) && \ ((a) != 0xffffffff)) #define CLASSA_MASK 0x000000ff #define CLASSB_MASK 0x0000ffff #define CLASSC_MASK 0x00ffffff #define CLASSD_MASK 0x000000e0 #define CLASSE_MASK 0xffffffff #define IP_LOOPBACK_ADDR(x) (((x) & 0xff) == 0x7f) #define IS_BROADCAST_ADDR(a) \ ((a) == INADDR_BROADCAST || \ (CLASSA_ADDR(a) && (((a) & ~CLASSA_MASK) == ~CLASSA_MASK)) || \ (CLASSB_ADDR(a) && (((a) & ~CLASSB_MASK) == ~CLASSB_MASK)) || \ (CLASSC_ADDR(a) && (((a) & ~CLASSC_MASK) == ~CLASSC_MASK))) #define HOSTADDR_MASK 0xffffffff #define NETCLASS_MASK(a) \ (CLASSA_ADDR(a) ? CLASSA_MASK : \ (CLASSB_ADDR(a) ? CLASSB_MASK : \ (CLASSC_ADDR(a) ? CLASSC_MASK : \ (CLASSD_ADDR(a) ? CLASSD_MASK : CLASSE_MASK)))) #define HASH_TABLE_SIZE 101 #define NEW_ENTRY 0x0001 #define TIMEOUT_TIMER 0x0002 #define GARBAGE_TIMER 0x0004 #define ROUTE_CHANGE 0x0008 #define ROUTE_UPDATE 0x0010 #define ROUTE_ZOMBIE 0x0020 #define ROUTE_HOST 0x0040 #define ADDRFLAG_DISABLED 0x01 #define RIP_MESSAGE_SIZE 512 #define RIP_SERVICE "IPRIP" // // definitions for IPRIP packet fields // #define RIP_REQUEST 1 #define RIP_RESPONSE 2 #define RIP_PORT 520 #define METRIC_INFINITE 16 #define RIP_MULTIADDR ((DWORD)0x090000E0) // // authentication definitions // #define RIP_MAX_AUTHKEY_SIZE 16 #define RIP_AUTHTYPE_NONE 1 #define RIP_AUTHTYPE_SIMPLE_PASSWORD 2 #define RIP_AUTHTYPE_MD5 3 #define ADDRFAMILY_AUTHENT 0xFFFF #define MAX_ADDRESS_COUNT 128 #define DHCP_ADDR_CHANGE_EVENT "DHCPNEWIPADDRESS" #define RIP_STATS_TABLE_NAME "IPRIP Statistics" #define RIP_DUMP_ROUTES_NAME "IPRIP Dump Routes" #define RIP_DUMP_REPLY "Dump Routes Reply" #define RIP_DUMP_REQUEST "Dump Routes Request" //----------------------------------------------------------------------- // type definitions //----------------------------------------------------------------------- // the following struct is used to store information about routes // see the comment for the RIP_GLOBALS for more information about // accessing these. All addresses and masks are in network order. typedef struct _HASH_TABLE_ENTRY { struct _HASH_TABLE_ENTRY *next; struct _HASH_TABLE_ENTRY *prev; DWORD dwIndex; DWORD dwDestaddr; DWORD dwNetmask; DWORD dwNexthop; DWORD dwMetric; // the metric is in host order DWORD dwFlag; LONG lTimeout; DWORD dwProtocol; } HASH_TABLE_ENTRY, *LPHASH_TABLE_ENTRY; // the following two types are templates used on network packets. // therefore, we require bytes to be packed. // rgatta : changing reserved fields to unions for RIPv2 compatibility #pragma pack(1) typedef struct { BYTE chCommand; BYTE chVersion; WORD wReserved; } RIP_HEADER, *LPRIP_HEADER; typedef struct { WORD wAddrFamily; union { WORD wReserved; WORD wRoutetag; }; DWORD dwAddress; union { DWORD dwReserved1; DWORD dwSubnetmask; }; union { DWORD dwReserved2; DWORD dwNexthop; }; DWORD dwMetric; } RIP_ENTRY, *LPRIP_ENTRY; typedef struct { WORD wAddrFamily; WORD wAuthType; BYTE AuthKey[RIP_MAX_AUTHKEY_SIZE]; } RIP_AUTHENT_ENTRY, *LPRIP_AUTHENT_ENTRY; #pragma pack() // this struct is used to save operational parameters // read from the registry. There is a single instance // for the process, so for read/write access to the fields, // first acquire the parameters lock by calling RIP_LOCK_PARAMS(), // and release it by calling RIP_UNLOCK_PARAMS() typedef struct { DWORD dwSilentRIP; DWORD dwAcceptHost; DWORD dwAnnounceHost; DWORD dwLoggingLevel; DWORD dwAcceptDefault; DWORD dwAnnounceDefault; DWORD dwSplitHorizon; DWORD dwPoisonReverse; DWORD dwRouteTimeout; DWORD dwGarbageTimeout; DWORD dwUpdateFrequency; DWORD dwTriggeredUpdates; DWORD dwMaxTriggerFrequency; DWORD dwOverwriteStaticRoutes; DWORD dwMaxTimedOpsInterval; } RIP_PARAMETERS, *LPRIP_PARAMETERS; #ifdef ROUTE_FILTERS typedef struct { DWORD dwCount; DWORD pdwFilter[1]; } RIP_FILTERS, *PRIP_FILTERS; #endif // this struct is used to save statistics for each RIP interface // All writes to these fields are done using InterlockedIncrement, // by whichever thread is holding the address table lock. // Interlocking is called for because these variables are in // file-mapped memory, and may be read by other processes. // Thus, it is important that all the fields here are DWORDs typedef struct { DWORD dwAddress; DWORD dwSendFailures; DWORD dwReceiveFailures; DWORD dwRequestsSent; DWORD dwResponsesSent; DWORD dwRequestsReceived; DWORD dwResponsesReceived; DWORD dwBadPacketsReceived; DWORD dwBadRouteResponseEntries; DWORD dwTriggeredUpdatesSent; } RIP_ADDRESS_STATISTICS, *LPRIP_ADDRESS_STATISTICS; typedef struct { DWORD dwAddrCount; DWORD dwRouteCount; DWORD dwSystemAddRouteFailures; DWORD dwSystemDeleteRouteFailures; DWORD dwRoutesAddedToSystemTable; DWORD dwRoutesDeletedFromSystemTable; RIP_ADDRESS_STATISTICS lpAddrStats[MAX_ADDRESS_COUNT]; } RIP_STATISTICS, *LPRIP_STATISTICS; // The following struct contains information stored for each IP address // in use by RIP. For information on the field lpstats, see above typedef struct { SOCKET sock; DWORD dwFlag; DWORD dwIndex; DWORD dwAddress; DWORD dwNetmask; LPRIP_ADDRESS_STATISTICS lpstats; } RIP_ADDRESS, *LPRIP_ADDRESS; // The following struct contains several variables // used in more than one thread. All changes to the first three // are made using the InterlockedExchange function, so they can // be safely read directly. // For read/write access to dwAddrCount and lpAddrTable, first acquire the // address table lock by calling RIP_LOCK_ADDRTABLE(), and then release it // by calling RIP_UNLOCK_ADDRTABLE() // For read/write access to lpRouteTable, first acquire the route table lock // by calling RIP_LOCK_ROUTETABLE(), and release it by calling // RIP_UNLOCK_ROUTETABLE(). // For nested locking, the following rules apply: // 1. When getting both the address table lock and the parameters lock // always call RIP_LOCK_ADDRTABLE() before RIP_LOCK_PARAMS() // 2. When getting both the address table lock and the route table lock // always call RIP_LOCK_ADDRTABLE() before RIP_LOCK_ROUTETABLE() // 3. When getting both the route table lock and the parameters lock, // always call RIP_LOCK_ROUTETABLE() before RIP_LOCK_PARAMS() // 4. Never hold more than two of the above locks simultaneously typedef struct { DWORD dwRouteChanged; DWORD dwLastTriggeredUpdate; DWORD dwMillisecsTillFullUpdate; HANDLE hTCPDriver; DWORD dwAddrCount; RIP_ADDRESS lpAddrTable[MAX_ADDRESS_COUNT]; LPRIP_STATISTICS lpStatsTable; HASH_TABLE_ENTRY *lpRouteTable[HASH_TABLE_SIZE]; } RIP_GLOBALS, *LPRIP_GLOBALS; //----------------------------------------------------------------------- // string for product type/version verfication //----------------------------------------------------------------------- #define REGKEY_PRODUCT_OPTION TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions") #define REGVAL_PRODUCT_TYPE TEXT("ProductType") #define WINNT_WORKSTATION TEXT("WinNt") //----------------------------------------------------------------------- // strings used for registry access //----------------------------------------------------------------------- #define REGKEY_RIP_LINKAGE "System\\CurrentControlSet\\Services" \ "\\IpRip\\Linkage" #define REGKEY_RIP_DISABLED "System\\CurrentControlSet\\Services" \ "\\IpRip\\Linkage\\Disabled" #define REGVAL_BIND "Bind" #define REGVAL_ENABLEDHCP "EnableDHCP" #define REGVAL_DHCPIPADDRESS "DhcpIPAddress" #define REGVAL_IPADDRESS "IPAddress" #define REGVAL_DHCPNETMASK "DhcpSubnetMask" #define REGVAL_NETMASK "SubnetMask" #define REGKEY_SERVICES "System\\CurrentControlSet\\Services" #define REGKEY_PARAMETERS "\\Parameters" #define REGKEY_TCPIP "\\TCPIP" #define REGKEY_TCPIP_PARAMS "SYSTEM\\CurrentControlSet\\Services" \ "\\TCPIP\\Parameters" #define REGKEY_RIP_PARAMS "SYSTEM\\CurrentControlSet\\Services" \ "\\IpRip\\Parameters" #define REGVAL_ACCEPT_HOST "AcceptHostRoutes" #define REGVAL_ANNOUNCE_HOST "AnnounceHostRoutes" #define REGVAL_ACCEPT_DEFAULT "AcceptDefaultRoutes" #define REGVAL_ANNOUNCE_DEFAULT "AnnounceDefaultRoutes" #define REGVAL_SPLITHORIZON "EnableSplitHorizon" #define REGVAL_POISONREVERSE "EnablePoisonedReverse" #define REGVAL_LOGGINGLEVEL "LoggingLevel" #define REGVAL_ROUTETIMEOUT "RouteTimeout" #define REGVAL_GARBAGETIMEOUT "GarbageTimeout" #define REGVAL_UPDATEFREQUENCY "UpdateFrequency" #define REGVAL_TRIGGEREDUPDATES "EnableTriggeredUpdates" #define REGVAL_TRIGGERFREQUENCY "MaxTriggeredUpdateFrequency" #define REGVAL_OVERWRITESTATIC "OverwriteStaticRoutes" #define REGVAL_MAXTIMEDOPSINTERVAL "MaxTimedOpsInterval" #define REGVAL_IP_ENABLEROUTER "IPEnableRouter" #define REGVAL_SILENTRIP "SilentRIP" #ifdef ROUTE_FILTERS #define REGVAL_ANNOUCE_FILTERS "AnnounceRouteFilters" #define REGVAL_ACCEPT_FILTERS "AcceptRouteFilters" #endif #define LOGLEVEL_NONE 0 #define LOGLEVEL_ERROR 1 #define LOGLEVEL_WARNING 2 #define LOGLEVEL_INFORMATION 3 // all values pertaining to time are in milliseconds, // but are read as seconds from the registry #define DEF_SILENTRIP 0 #define DEF_ACCEPT_HOST 0 #define DEF_ANNOUNCE_HOST 0 #define DEF_ACCEPT_DEFAULT 0 #define DEF_ANNOUNCE_DEFAULT 0 #define DEF_SPLITHORIZON 1 #define DEF_POISONREVERSE 1 #define DEF_GETROUTEFREQUENCY (60 * 1000) #define DEF_LOGGINGLEVEL LOGLEVEL_ERROR #define DEF_ROUTETIMEOUT (180 * 1000) #define DEF_LOCALROUTETIMEOUT (90 * 1000) #define DEF_GARBAGETIMEOUT (120 * 1000) #define DEF_UPDATEFREQUENCY (30 * 1000) #define DEF_TRIGGEREDUPDATES 1 #define DEF_TRIGGERFREQUENCY (5 * 1000) #define DEF_OVERWRITESTATIC 0 #define DEF_MAXTIMEDOPSINTERVAL (10 * 1000) #define MIN_LOGGINGLEVEL LOGLEVEL_NONE #define MIN_ROUTETIMEOUT (15 * 1000) #define MIN_GARBAGETIMEOUT (15 * 1000) #define MIN_UPDATEFREQUENCY (15 * 1000) #define MIN_TRIGGERFREQUENCY (1 * 1000) #define MAX_LOGGINGLEVEL LOGLEVEL_INFORMATION #define MAX_ROUTETIMEOUT ((60 * 60 * 24 * 3) * 1000) #define MAX_GARBAGETIMEOUT ((60 * 60 * 24 * 3) * 1000) #define MAX_UPDATEFREQUENCY ((60 * 60 * 24) * 1000) #define MAX_TRIGGERFREQUENCY ((60 * 60 * 24) * 1000) #define STOP_REASON_QUIT 0 #define STOP_REASON_ADDRCHANGE 1 //----------------------------------------------------------------------- // global data declarations //----------------------------------------------------------------------- extern RIP_PARAMETERS g_params; extern RIP_GLOBALS g_ripcfg; #ifdef ROUTE_FILTERS extern PRIP_FILTERS g_prfAnnounceFilters; extern PRIP_FILTERS g_prfAcceptFilters; extern CRITICAL_SECTION g_csAccFilters; extern CRITICAL_SECTION g_csAnnFilters; #endif extern CRITICAL_SECTION g_csRoutes; extern CRITICAL_SECTION g_csParameters; extern CRITICAL_SECTION g_csAddrtables; extern DWORD g_dwTraceID; extern HANDLE g_stopEvent; extern HANDLE g_addressChangeEvent; extern HANDLE g_netEvent; extern HANDLE g_triggerEvent; extern HANDLE g_hUpdateThread; #ifndef CHICAGO extern HMODULE g_hmodule; #endif //----------------------------------------------------------------------- // macro functions //----------------------------------------------------------------------- #define HASH_VALUE(ad) (((ad & 0xff) + \ ((ad >> 8) & 0xff) + \ ((ad >> 16) & 0xff) + \ ((ad >> 24) & 0xff)) % HASH_TABLE_SIZE) #define RIP_CREATE_ROUTETABLE_LOCK() InitializeCriticalSection(&g_csRoutes) #define RIP_DESTROY_ROUTETABLE_LOCK() DeleteCriticalSection(&g_csRoutes) #define RIP_LOCK_ROUTETABLE() EnterCriticalSection(&g_csRoutes) #define RIP_UNLOCK_ROUTETABLE() LeaveCriticalSection(&g_csRoutes) #define RIP_CREATE_PARAMS_LOCK() InitializeCriticalSection(&g_csParameters) #define RIP_DESTROY_PARAMS_LOCK() DeleteCriticalSection(&g_csParameters) #define RIP_LOCK_PARAMS() EnterCriticalSection(&g_csParameters) #define RIP_UNLOCK_PARAMS() LeaveCriticalSection(&g_csParameters) #define RIP_CREATE_ADDRTABLE_LOCK() InitializeCriticalSection(&g_csAddrtables) #define RIP_DESTROY_ADDRTABLE_LOCK() DeleteCriticalSection(&g_csAddrtables) #define RIP_LOCK_ADDRTABLE() EnterCriticalSection(&g_csAddrtables) #define RIP_UNLOCK_ADDRTABLE() LeaveCriticalSection(&g_csAddrtables) #ifdef ROUTE_FILTERS #define RIP_CREATE_ANNOUNCE_FILTERS_LOCK() \ InitializeCriticalSection( &g_csAnnFilters ) #define RIP_DESTROY_ANNOUNCE_FILTERS_LOCK() \ DeleteCriticalSection( &g_csAnnFilters ) #define RIP_LOCK_ANNOUNCE_FILTERS() \ EnterCriticalSection( &g_csAnnFilters ) #define RIP_UNLOCK_ANNOUNCE_FILTERS() \ LeaveCriticalSection( &g_csAnnFilters ) #define RIP_CREATE_ACCEPT_FILTERS_LOCK() \ InitializeCriticalSection( &g_csAccFilters ) #define RIP_DESTROY_ACCEPT_FILTERS_LOCK() \ DeleteCriticalSection( &g_csAccFilters ) #define RIP_LOCK_ACCEPT_FILTERS() \ EnterCriticalSection( &g_csAccFilters ) #define RIP_UNLOCK_ACCEPT_FILTERS() \ LeaveCriticalSection( &g_csAccFilters ) #endif //----------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------- DWORD UpdateThread(LPVOID lpvParam); ULONG AddressChangeNotificationThread(LPVOID lpvParam); VOID serviceHandlerFunction(DWORD dwControl); VOID FAR PASCAL serviceMainFunction(IN DWORD dwNumServicesArgs, IN LPSTR *lpServiceArgVectors); DWORD InitializeRouteTable(); VOID CleanupRouteTable(); VOID CheckRouteTableEntries(); LPHASH_TABLE_ENTRY GetRouteTableEntry(DWORD dwIndex, DWORD dwDestaddr, DWORD dwNetmask); BOOL RouteTableEntryExists(DWORD dwIndex, DWORD dwDestaddr); VOID DumpRouteTableEntries(BOOL bChangesOnly); VOID ProcessRouteTableChanges(BOOL bTriggered); VOID ClearChangeFlags(); DWORD SubnetMask(DWORD dwAddress); DWORD NetclassMask(DWORD dwAddress); INT LoadRouteTable(BOOL bFirstTime); DWORD UpdateSystemRouteTable(LPHASH_TABLE_ENTRY rt_entry, BOOL bAdd); VOID dbgprintf(LPSTR szFormat, ...); DWORD LoadParameters(); DWORD InitializeAddressTable(BOOL bFirstTime); DWORD InitializeStatsTable(); VOID CleanupStatsTable(); BOOL IsHostAddress(DWORD dwAddress); BOOL IsLocalAddr(DWORD dwAddress); BOOL IsDisabledLocalAddress(DWORD dwAddress); BOOL IsBroadcastAddress(DWORD dwAddress); DWORD BroadcastRouteTableRequests(); DWORD BroadcastRouteTableContents(BOOL bTriggered, BOOL bChangesOnly); VOID TransmitRouteTableContents(LPRIP_ADDRESS lpaddr, LPSOCKADDR_IN lpdestaddr, BOOL bChangesOnly); VOID InitUpdateBuffer(BYTE buffer[], LPRIP_ENTRY *lplpentry, LPDWORD lpdwSize); VOID AddUpdateEntry(BYTE buffer[], LPRIP_ENTRY *lplpentry, LPDWORD lpdwSize, LPRIP_ADDRESS lpaddr, LPSOCKADDR_IN lpdestaddr, DWORD dwAddress, DWORD dwMetric); VOID FinishUpdateBuffer(BYTE buffer[], LPDWORD lpdwSize, LPRIP_ADDRESS lpaddr, LPSOCKADDR_IN lpdestaddr); VOID ProcessRIPRequest(LPRIP_ADDRESS lpaddr, LPSOCKADDR_IN lpsrcaddr, BYTE buffer[], int length); VOID ProcessRIPResponse(LPRIP_ADDRESS lpaddr, LPSOCKADDR_IN lpsrcaddr, BYTE buffer[], int length); DWORD ProcessResponse(RIP_ADDRESS *lpAddress); DWORD ProcessRIPEntry(LPRIP_ADDRESS lpaddr, IN_ADDR srcaddr, LPRIP_ENTRY rip_entry, BYTE chVersion); DWORD ProcessRIPQuery(LPRIP_ADDRESS lpaddr, LPRIP_ENTRY rip_entry); VOID DoTimedOperations(DWORD dwMillisecsSinceLastCall); /* add option to disable triggered updates */ /* pass socket address to process_rip_entry and process_rip_query */ /* add index field to rt_entry */ VOID RIPServiceStop(); VOID RipLogError(DWORD dwMsgID, WORD wNumString, LPSTR *lplpStrings, DWORD dwErr); VOID RipLogWarning(DWORD dwMsgID, WORD wNumString, LPSTR *lplpStrings, DWORD dwErr); VOID RipLogInformation(DWORD dwMsgID, WORD wNumString, LPSTR *lplpStrings, DWORD dwErr); #ifdef ROUTE_FILTERS PRIP_FILTERS LoadFilters( IN HKEY hKeyParams, IN LPSTR lpszKeyName ); #endif //----------------------------------------------------------------------------- // // WIN 95 String resources // //----------------------------------------------------------------------------- #ifdef CHICAGO #define IDS_STRING_BASE 4096 #define IDS_APP_NAME IDS_STRING_BASE + 0 #define IDS_TITLE_BAR IDS_STRING_BASE + 1 #define IDS_HELP_TEXT1 IDS_STRING_BASE + 6 #define IDS_HELP_TEXT2 IDS_STRING_BASE + 7 #define IP_ADDRESS_RELOAD_INTR 120 // // SYNOPSIS: One debug statememt in time can save nine. // Last modified Time-stamp: <25-Nov-96 17:49> // History: // MohsinA, 14-Nov-96. // void DbgPrintf( char * format, ... ); #endif