|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
routing\ip\locate.c
Abstract:
The LocateXXXRow Functions are passed a variable sized array of indices, a count of the number of indices passed and the type of search that needs to be executed. There are three types of searches: Locate the first item (ACCESS_GET_FIRST) Locate the next item (ACCESS_GET_NEXT) Locate the exact item (ACCESS_GET, ACCESS_SET, ACCESS_CREATE_ENTRY ACCESS_DELETE_ENTRY)
The functions fill in the index of the corresponding row and return
NO_ERROR if an item matching the indices and criterion was found ERROR_NO_DATA if no item is found ERROR_INVALID_INDEX ERROR_NO_MORE_ITEMS
The general search algorithm is this:
If the table is empty return ERROR_NO_DATA If the query is a LOCATE_FIRST return the first row Build the index as follows:
Set the Index to all 0s From the number of indices passed figure out how much of the index can be built keeping the rest 0. If the query is a LOCATE_EXACT then the complete index must be given. This check is, however, supposed to be done by the caller If the full index has not been given, the index is deemed to be modified (Again this can only happen in the LOCATE_NEXT case). Once the index is created, a search is done. We try for an exact match with the index. For all queries other than LOCATE_NEXT there is no problem. For LOCATE_NEXT there are two cases:
If the complete index was given and we get an exact match, then we return the next entry. If we dont get an exact match we return the next higher entry If an incomplete index was given and we modified it by padding 0s, and if an exact match is found, then we return the matching entry (Of course if an exact match is not found just return the next higher entry)
ALL THESE FUNCTION ARE CALLED WITH THE LOCK OF THE RESPECTIVE CACHE HELD ATLEAST AS READER Revision History:
Amritansh Raghav 6/8/95 Created
--*/
#include "allinc.h"
#define LOCAL_ADDR 0
#define LOCAL_PORT 1
#define REM_ADDR 2
#define REM_PORT 3
DWORD LocateIfRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, ICB **ppicb, BOOL bNoClient ) { PLIST_ENTRY currentList,startIndex,stopIndex ; DWORD dwIndex = 0; BOOL fNext, fModified; PICB pIf; *ppicb = NULL; if(g_ulNumInterfaces is 0) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; }
if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; }
if(dwQueryType is ACCESS_GET_FIRST) { if(bNoClient) { for(currentList = ICBList.Flink; currentList isnot &ICBList; currentList = currentList->Flink) { //
// Find the first one which is not internal loopback
// or client
//
pIf = CONTAINING_RECORD (currentList, ICB, leIfLink); if(pIf->ritType is ROUTER_IF_TYPE_CLIENT) { continue; }
*ppicb = pIf;
break; } } else { *ppicb = CONTAINING_RECORD(ICBList.Flink, ICB, leIfLink); }
if(*ppicb) { return NO_ERROR; } else { return ERROR_NO_DATA; } }
fModified = TRUE; if(dwNumIndices > 0) { dwIndex = pdwIndex[0]; fModified = FALSE; }
//
// Should we take the match or the next entry in case of an exact match?
//
fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = ICBList.Flink; stopIndex = &ICBList; for(currentList = startIndex; currentList isnot stopIndex; currentList = currentList->Flink) { *ppicb = CONTAINING_RECORD(currentList, ICB, leIfLink) ;
if(bNoClient and ((*ppicb)->ritType is ROUTER_IF_TYPE_CLIENT)) { //
// Go to the next one
//
continue; } if((dwIndex is (*ppicb)->dwIfIndex) and !fNext) { //
// Found it
//
return NO_ERROR; } if(dwIndex < (*ppicb)->dwIfIndex) { if(dwQueryType is ACCESS_GET_NEXT) { return NO_ERROR; } else { //
// Since the list is ordered we wont find this index further on
//
*ppicb = NULL; return ERROR_INVALID_INDEX; } } }
return ERROR_NO_MORE_ITEMS; }
DWORD LocateIpAddrRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, PDWORD pdwRetIndex ) { DWORD dwIpAddr; DWORD dwResult, startIndex, stopIndex; LONG lCompare; DWORD i; BOOL fNext, fModified; if((g_IpInfo.pAddrTable is NULL) or (g_IpInfo.pAddrTable->dwNumEntries is 0)) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; } if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; } if(dwQueryType is ACCESS_GET_FIRST) { *pdwRetIndex = 0; return NO_ERROR; } if(dwNumIndices > 0) { dwIpAddr = pdwIndex[0]; fModified = FALSE; } else { dwIpAddr = 0; fModified = TRUE; } fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = 0; stopIndex = g_IpInfo.pAddrTable->dwNumEntries; for(i = startIndex; i < stopIndex; i++) { lCompare = InetCmp(dwIpAddr, g_IpInfo.pAddrTable->table[i].dwAddr, lCompare); if((lCompare is 0) and !fNext) { *pdwRetIndex = i; return NO_ERROR; } if(lCompare < 0) { if(dwQueryType is ACCESS_GET_NEXT) { *pdwRetIndex = i; return NO_ERROR; } else { return ERROR_INVALID_INDEX; } } }
return ERROR_NO_MORE_ITEMS; }
DWORD LocateIpForwardRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, PDWORD pdwRetIndex ) { DWORD rgdwIpForwardIndex[4]; DWORD dwResult,startIndex, stopIndex; LONG lCompare; DWORD i; BOOL fNext,fModified; if((g_IpInfo.pForwardTable is NULL) or (g_IpInfo.pForwardTable->dwNumEntries is 0)) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; }
if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; } if(dwQueryType is ACCESS_GET_FIRST) { *pdwRetIndex = 0; return NO_ERROR; } // Quick way to copy the valid part of index
// TBD: just might want to asssert the sizes
ZeroMemory(rgdwIpForwardIndex, 4*sizeof(DWORD)); memcpy(rgdwIpForwardIndex, pdwIndex, dwNumIndices * sizeof(DWORD));
//
// We have modified it if the index is not the exact size
//
if(dwNumIndices isnot 4) { fModified = TRUE; } else { fModified = FALSE; } fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = 0; stopIndex = g_IpInfo.pForwardTable->dwNumEntries; for(i = startIndex; i < stopIndex; i++) { lCompare = IpForwardCmp(rgdwIpForwardIndex[0], rgdwIpForwardIndex[1], rgdwIpForwardIndex[2], rgdwIpForwardIndex[3], g_IpInfo.pForwardTable->table[i].dwForwardDest, g_IpInfo.pForwardTable->table[i].dwForwardProto, g_IpInfo.pForwardTable->table[i].dwForwardPolicy, g_IpInfo.pForwardTable->table[i].dwForwardNextHop); if((lCompare is 0) and !fNext) { *pdwRetIndex = i; return NO_ERROR; } if(lCompare < 0) { if(dwQueryType is ACCESS_GET_NEXT) { *pdwRetIndex = i; return NO_ERROR; } else { return ERROR_INVALID_INDEX; } } } return ERROR_NO_MORE_ITEMS; }
DWORD LocateIpNetRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, PDWORD pdwRetIndex ) { DWORD dwResult,i; LONG lCompare; DWORD dwIpNetIfIndex,dwIpNetIpAddr; BOOL fNext, fModified; DWORD startIndex,stopIndex; if((g_IpInfo.pNetTable is NULL) or (g_IpInfo.pNetTable->dwNumEntries is 0)) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; }
if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; } if(dwQueryType is ACCESS_GET_FIRST) { *pdwRetIndex = 0; return NO_ERROR; }
switch(dwNumIndices) { case 0: { dwIpNetIfIndex = 0; dwIpNetIpAddr = 0; fModified = TRUE; break; } case 1: { dwIpNetIfIndex = pdwIndex[0]; dwIpNetIpAddr = 0; fModified = TRUE; break; } case 2: { dwIpNetIfIndex = pdwIndex[0]; dwIpNetIpAddr = pdwIndex[1]; fModified = FALSE; break; } default: { return ERROR_INVALID_INDEX; } } fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = 0; stopIndex = g_IpInfo.pNetTable->dwNumEntries; for(i = startIndex; i < stopIndex; i++) { lCompare = IpNetCmp(dwIpNetIfIndex, dwIpNetIpAddr, g_IpInfo.pNetTable->table[i].dwIndex, g_IpInfo.pNetTable->table[i].dwAddr); if((lCompare is 0) and !fNext) { *pdwRetIndex = i; return NO_ERROR; } if(lCompare < 0) { if(dwQueryType is ACCESS_GET_NEXT) { *pdwRetIndex = i; return NO_ERROR; } else { return ERROR_INVALID_INDEX; } } } return ERROR_NO_MORE_ITEMS; }
DWORD LocateUdpRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, PDWORD pdwRetIndex ) { DWORD i; LONG lCompare; DWORD rgdwLocal[2]; BOOL fNext, fModified; DWORD startIndex, stopIndex; if((g_UdpInfo.pUdpTable is NULL) or (g_UdpInfo.pUdpTable->dwNumEntries is 0)) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; }
if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; } if(dwQueryType is ACCESS_GET_FIRST) { *pdwRetIndex = 0; return NO_ERROR; } rgdwLocal[0] = 0; rgdwLocal[1] = 0; fModified = TRUE; switch(dwNumIndices) { case 0: { break; } case 1: { rgdwLocal[LOCAL_ADDR] = pdwIndex[0]; break; } case 2: { fModified = FALSE; rgdwLocal[LOCAL_ADDR] = pdwIndex[0]; rgdwLocal[LOCAL_PORT] = pdwIndex[1]; break; } } fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = 0; stopIndex = g_UdpInfo.pUdpTable->dwNumEntries; for(i = startIndex; i < stopIndex; i++) { lCompare = UdpCmp(rgdwLocal[LOCAL_ADDR], rgdwLocal[LOCAL_PORT], g_UdpInfo.pUdpTable->table[i].dwLocalAddr, g_UdpInfo.pUdpTable->table[i].dwLocalPort); if((lCompare is 0) and !fNext) { *pdwRetIndex = i; return NO_ERROR; } if(lCompare < 0) { if(dwQueryType is ACCESS_GET_NEXT) { *pdwRetIndex = i; return NO_ERROR; } else { return ERROR_INVALID_INDEX; } } } return ERROR_NO_MORE_ITEMS; }
DWORD LocateTcpRow( DWORD dwQueryType, DWORD dwNumIndices, PDWORD pdwIndex, PDWORD pdwRetIndex ) { LONG lCompare; DWORD rgdwAddr[4]; BOOL fNext, fModified; DWORD startIndex, stopIndex,i; if((g_TcpInfo.pTcpTable is NULL) or (g_TcpInfo.pTcpTable->dwNumEntries is 0)) { if(EXACT_MATCH(dwQueryType)) { return ERROR_INVALID_INDEX; }
if(dwQueryType is ACCESS_GET_FIRST) { return ERROR_NO_DATA; }
return ERROR_NO_MORE_ITEMS; } if(dwQueryType is ACCESS_GET_FIRST) { *pdwRetIndex = 0; return NO_ERROR; } //
// Quick way to copy the valid part of index
// BUG might want to asssert the sizes
//
ZeroMemory(rgdwAddr, 4*sizeof(DWORD)); memcpy(rgdwAddr, pdwIndex, dwNumIndices * sizeof(DWORD));
//
// We have modified it if the index is not the exact size
//
if(dwNumIndices isnot 4) { fModified = TRUE; } else { fModified = FALSE; } fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE); startIndex = 0; stopIndex = g_TcpInfo.pTcpTable->dwNumEntries; for(i = startIndex; i < stopIndex; i++) { lCompare = TcpCmp(rgdwAddr[LOCAL_ADDR], rgdwAddr[LOCAL_PORT], rgdwAddr[REM_ADDR], rgdwAddr[REM_PORT], g_TcpInfo.pTcpTable->table[i].dwLocalAddr, g_TcpInfo.pTcpTable->table[i].dwLocalPort, g_TcpInfo.pTcpTable->table[i].dwRemoteAddr, g_TcpInfo.pTcpTable->table[i].dwRemotePort); if((lCompare is 0) and !fNext) { *pdwRetIndex = i; return NO_ERROR; } if(lCompare < 0) { if(dwQueryType is ACCESS_GET_NEXT) { *pdwRetIndex = i; return NO_ERROR; } else { return ERROR_INVALID_INDEX; } } } return ERROR_NO_MORE_ITEMS; }
|