Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

724 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\locate.c
  5. Abstract:
  6. The LocateXXXRow Functions are passed a variable sized array of
  7. indices, a count of the number of indices passed and the type of search
  8. that needs to be executed. There are three types of searches:
  9. Locate the first item (ACCESS_GET_FIRST)
  10. Locate the next item (ACCESS_GET_NEXT)
  11. Locate the exact item (ACCESS_GET, ACCESS_SET, ACCESS_CREATE_ENTRY
  12. ACCESS_DELETE_ENTRY)
  13. The functions fill in the index of the corresponding row and return
  14. NO_ERROR if an item matching the indices and criterion was found
  15. ERROR_NO_DATA if no item is found
  16. ERROR_INVALID_INDEX
  17. ERROR_NO_MORE_ITEMS
  18. The general search algorithm is this:
  19. If the table is empty
  20. return ERROR_NO_DATA
  21. If the query is a LOCATE_FIRST
  22. return the first row
  23. Build the index as follows:
  24. Set the Index to all 0s
  25. From the number of indices passed figure out how much of the index
  26. can be built keeping the rest 0.
  27. If the query is a LOCATE_EXACT then the complete index must be given.
  28. This check is, however, supposed to be done by the caller
  29. If the full index has not been given, the index is deemed to be
  30. modified (Again this can only happen in the LOCATE_NEXT case).
  31. Once the index is created, a search is done.
  32. We try for an exact match with the index. For all queries other than
  33. LOCATE_NEXT there is no problem.
  34. For LOCATE_NEXT there are two cases:
  35. If the complete index was given and we get an exact match, then we
  36. return the next entry.
  37. If we dont get an exact match we return the next higher entry
  38. If an incomplete index was given and we modified it by padding 0s,
  39. and if an exact match is found, then we return the matching entry
  40. (Of course if an exact match is not found just return the next
  41. higher entry)
  42. ALL THESE FUNCTION ARE CALLED WITH THE LOCK OF THE RESPECTIVE CACHE
  43. HELD ATLEAST AS READER
  44. Revision History:
  45. Amritansh Raghav 6/8/95 Created
  46. --*/
  47. #include "allinc.h"
  48. #define LOCAL_ADDR 0
  49. #define LOCAL_PORT 1
  50. #define REM_ADDR 2
  51. #define REM_PORT 3
  52. DWORD
  53. LocateIfRow(
  54. DWORD dwQueryType,
  55. DWORD dwNumIndices,
  56. PDWORD pdwIndex,
  57. ICB **ppicb,
  58. BOOL bNoClient
  59. )
  60. {
  61. PLIST_ENTRY currentList,startIndex,stopIndex ;
  62. DWORD dwIndex = 0;
  63. BOOL fNext, fModified;
  64. PICB pIf;
  65. *ppicb = NULL;
  66. if(g_ulNumInterfaces is 0)
  67. {
  68. if(EXACT_MATCH(dwQueryType))
  69. {
  70. return ERROR_INVALID_INDEX;
  71. }
  72. if(dwQueryType is ACCESS_GET_FIRST)
  73. {
  74. return ERROR_NO_DATA;
  75. }
  76. return ERROR_NO_MORE_ITEMS;
  77. }
  78. if(dwQueryType is ACCESS_GET_FIRST)
  79. {
  80. if(bNoClient)
  81. {
  82. for(currentList = ICBList.Flink;
  83. currentList isnot &ICBList;
  84. currentList = currentList->Flink)
  85. {
  86. //
  87. // Find the first one which is not internal loopback
  88. // or client
  89. //
  90. pIf = CONTAINING_RECORD (currentList, ICB, leIfLink);
  91. if(pIf->ritType is ROUTER_IF_TYPE_CLIENT)
  92. {
  93. continue;
  94. }
  95. *ppicb = pIf;
  96. break;
  97. }
  98. }
  99. else
  100. {
  101. *ppicb = CONTAINING_RECORD(ICBList.Flink,
  102. ICB,
  103. leIfLink);
  104. }
  105. if(*ppicb)
  106. {
  107. return NO_ERROR;
  108. }
  109. else
  110. {
  111. return ERROR_NO_DATA;
  112. }
  113. }
  114. fModified = TRUE;
  115. if(dwNumIndices > 0)
  116. {
  117. dwIndex = pdwIndex[0];
  118. fModified = FALSE;
  119. }
  120. //
  121. // Should we take the match or the next entry in case of an exact match?
  122. //
  123. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  124. startIndex = ICBList.Flink;
  125. stopIndex = &ICBList;
  126. for(currentList = startIndex;
  127. currentList isnot stopIndex;
  128. currentList = currentList->Flink)
  129. {
  130. *ppicb = CONTAINING_RECORD(currentList,
  131. ICB,
  132. leIfLink) ;
  133. if(bNoClient and
  134. ((*ppicb)->ritType is ROUTER_IF_TYPE_CLIENT))
  135. {
  136. //
  137. // Go to the next one
  138. //
  139. continue;
  140. }
  141. if((dwIndex is (*ppicb)->dwIfIndex) and !fNext)
  142. {
  143. //
  144. // Found it
  145. //
  146. return NO_ERROR;
  147. }
  148. if(dwIndex < (*ppicb)->dwIfIndex)
  149. {
  150. if(dwQueryType is ACCESS_GET_NEXT)
  151. {
  152. return NO_ERROR;
  153. }
  154. else
  155. {
  156. //
  157. // Since the list is ordered we wont find this index further on
  158. //
  159. *ppicb = NULL;
  160. return ERROR_INVALID_INDEX;
  161. }
  162. }
  163. }
  164. return ERROR_NO_MORE_ITEMS;
  165. }
  166. DWORD
  167. LocateIpAddrRow(
  168. DWORD dwQueryType,
  169. DWORD dwNumIndices,
  170. PDWORD pdwIndex,
  171. PDWORD pdwRetIndex
  172. )
  173. {
  174. DWORD dwIpAddr;
  175. DWORD dwResult, startIndex, stopIndex;
  176. LONG lCompare;
  177. DWORD i;
  178. BOOL fNext, fModified;
  179. if((g_IpInfo.pAddrTable is NULL) or
  180. (g_IpInfo.pAddrTable->dwNumEntries is 0))
  181. {
  182. if(EXACT_MATCH(dwQueryType))
  183. {
  184. return ERROR_INVALID_INDEX;
  185. }
  186. if(dwQueryType is ACCESS_GET_FIRST)
  187. {
  188. return ERROR_NO_DATA;
  189. }
  190. return ERROR_NO_MORE_ITEMS;
  191. }
  192. if(dwQueryType is ACCESS_GET_FIRST)
  193. {
  194. *pdwRetIndex = 0;
  195. return NO_ERROR;
  196. }
  197. if(dwNumIndices > 0)
  198. {
  199. dwIpAddr = pdwIndex[0];
  200. fModified = FALSE;
  201. }
  202. else
  203. {
  204. dwIpAddr = 0;
  205. fModified = TRUE;
  206. }
  207. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  208. startIndex = 0;
  209. stopIndex = g_IpInfo.pAddrTable->dwNumEntries;
  210. for(i = startIndex; i < stopIndex; i++)
  211. {
  212. lCompare = InetCmp(dwIpAddr,
  213. g_IpInfo.pAddrTable->table[i].dwAddr,
  214. lCompare);
  215. if((lCompare is 0) and !fNext)
  216. {
  217. *pdwRetIndex = i;
  218. return NO_ERROR;
  219. }
  220. if(lCompare < 0)
  221. {
  222. if(dwQueryType is ACCESS_GET_NEXT)
  223. {
  224. *pdwRetIndex = i;
  225. return NO_ERROR;
  226. }
  227. else
  228. {
  229. return ERROR_INVALID_INDEX;
  230. }
  231. }
  232. }
  233. return ERROR_NO_MORE_ITEMS;
  234. }
  235. DWORD
  236. LocateIpForwardRow(
  237. DWORD dwQueryType,
  238. DWORD dwNumIndices,
  239. PDWORD pdwIndex,
  240. PDWORD pdwRetIndex
  241. )
  242. {
  243. DWORD rgdwIpForwardIndex[4];
  244. DWORD dwResult,startIndex, stopIndex;
  245. LONG lCompare;
  246. DWORD i;
  247. BOOL fNext,fModified;
  248. if((g_IpInfo.pForwardTable is NULL) or
  249. (g_IpInfo.pForwardTable->dwNumEntries is 0))
  250. {
  251. if(EXACT_MATCH(dwQueryType))
  252. {
  253. return ERROR_INVALID_INDEX;
  254. }
  255. if(dwQueryType is ACCESS_GET_FIRST)
  256. {
  257. return ERROR_NO_DATA;
  258. }
  259. return ERROR_NO_MORE_ITEMS;
  260. }
  261. if(dwQueryType is ACCESS_GET_FIRST)
  262. {
  263. *pdwRetIndex = 0;
  264. return NO_ERROR;
  265. }
  266. // Quick way to copy the valid part of index
  267. // TBD: just might want to asssert the sizes
  268. ZeroMemory(rgdwIpForwardIndex,
  269. 4*sizeof(DWORD));
  270. memcpy(rgdwIpForwardIndex,
  271. pdwIndex,
  272. dwNumIndices * sizeof(DWORD));
  273. //
  274. // We have modified it if the index is not the exact size
  275. //
  276. if(dwNumIndices isnot 4)
  277. {
  278. fModified = TRUE;
  279. }
  280. else
  281. {
  282. fModified = FALSE;
  283. }
  284. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  285. startIndex = 0;
  286. stopIndex = g_IpInfo.pForwardTable->dwNumEntries;
  287. for(i = startIndex; i < stopIndex; i++)
  288. {
  289. lCompare =
  290. IpForwardCmp(rgdwIpForwardIndex[0],
  291. rgdwIpForwardIndex[1],
  292. rgdwIpForwardIndex[2],
  293. rgdwIpForwardIndex[3],
  294. g_IpInfo.pForwardTable->table[i].dwForwardDest,
  295. g_IpInfo.pForwardTable->table[i].dwForwardProto,
  296. g_IpInfo.pForwardTable->table[i].dwForwardPolicy,
  297. g_IpInfo.pForwardTable->table[i].dwForwardNextHop);
  298. if((lCompare is 0) and !fNext)
  299. {
  300. *pdwRetIndex = i;
  301. return NO_ERROR;
  302. }
  303. if(lCompare < 0)
  304. {
  305. if(dwQueryType is ACCESS_GET_NEXT)
  306. {
  307. *pdwRetIndex = i;
  308. return NO_ERROR;
  309. }
  310. else
  311. {
  312. return ERROR_INVALID_INDEX;
  313. }
  314. }
  315. }
  316. return ERROR_NO_MORE_ITEMS;
  317. }
  318. DWORD
  319. LocateIpNetRow(
  320. DWORD dwQueryType,
  321. DWORD dwNumIndices,
  322. PDWORD pdwIndex,
  323. PDWORD pdwRetIndex
  324. )
  325. {
  326. DWORD dwResult,i;
  327. LONG lCompare;
  328. DWORD dwIpNetIfIndex,dwIpNetIpAddr;
  329. BOOL fNext, fModified;
  330. DWORD startIndex,stopIndex;
  331. if((g_IpInfo.pNetTable is NULL) or
  332. (g_IpInfo.pNetTable->dwNumEntries is 0))
  333. {
  334. if(EXACT_MATCH(dwQueryType))
  335. {
  336. return ERROR_INVALID_INDEX;
  337. }
  338. if(dwQueryType is ACCESS_GET_FIRST)
  339. {
  340. return ERROR_NO_DATA;
  341. }
  342. return ERROR_NO_MORE_ITEMS;
  343. }
  344. if(dwQueryType is ACCESS_GET_FIRST)
  345. {
  346. *pdwRetIndex = 0;
  347. return NO_ERROR;
  348. }
  349. switch(dwNumIndices)
  350. {
  351. case 0:
  352. {
  353. dwIpNetIfIndex = 0;
  354. dwIpNetIpAddr = 0;
  355. fModified = TRUE;
  356. break;
  357. }
  358. case 1:
  359. {
  360. dwIpNetIfIndex = pdwIndex[0];
  361. dwIpNetIpAddr = 0;
  362. fModified = TRUE;
  363. break;
  364. }
  365. case 2:
  366. {
  367. dwIpNetIfIndex = pdwIndex[0];
  368. dwIpNetIpAddr = pdwIndex[1];
  369. fModified = FALSE;
  370. break;
  371. }
  372. default:
  373. {
  374. return ERROR_INVALID_INDEX;
  375. }
  376. }
  377. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  378. startIndex = 0;
  379. stopIndex = g_IpInfo.pNetTable->dwNumEntries;
  380. for(i = startIndex; i < stopIndex; i++)
  381. {
  382. lCompare = IpNetCmp(dwIpNetIfIndex,
  383. dwIpNetIpAddr,
  384. g_IpInfo.pNetTable->table[i].dwIndex,
  385. g_IpInfo.pNetTable->table[i].dwAddr);
  386. if((lCompare is 0) and !fNext)
  387. {
  388. *pdwRetIndex = i;
  389. return NO_ERROR;
  390. }
  391. if(lCompare < 0)
  392. {
  393. if(dwQueryType is ACCESS_GET_NEXT)
  394. {
  395. *pdwRetIndex = i;
  396. return NO_ERROR;
  397. }
  398. else
  399. {
  400. return ERROR_INVALID_INDEX;
  401. }
  402. }
  403. }
  404. return ERROR_NO_MORE_ITEMS;
  405. }
  406. DWORD
  407. LocateUdpRow(
  408. DWORD dwQueryType,
  409. DWORD dwNumIndices,
  410. PDWORD pdwIndex,
  411. PDWORD pdwRetIndex
  412. )
  413. {
  414. DWORD i;
  415. LONG lCompare;
  416. DWORD rgdwLocal[2];
  417. BOOL fNext, fModified;
  418. DWORD startIndex, stopIndex;
  419. if((g_UdpInfo.pUdpTable is NULL) or
  420. (g_UdpInfo.pUdpTable->dwNumEntries is 0))
  421. {
  422. if(EXACT_MATCH(dwQueryType))
  423. {
  424. return ERROR_INVALID_INDEX;
  425. }
  426. if(dwQueryType is ACCESS_GET_FIRST)
  427. {
  428. return ERROR_NO_DATA;
  429. }
  430. return ERROR_NO_MORE_ITEMS;
  431. }
  432. if(dwQueryType is ACCESS_GET_FIRST)
  433. {
  434. *pdwRetIndex = 0;
  435. return NO_ERROR;
  436. }
  437. rgdwLocal[0] = 0;
  438. rgdwLocal[1] = 0;
  439. fModified = TRUE;
  440. switch(dwNumIndices)
  441. {
  442. case 0:
  443. {
  444. break;
  445. }
  446. case 1:
  447. {
  448. rgdwLocal[LOCAL_ADDR] = pdwIndex[0];
  449. break;
  450. }
  451. case 2:
  452. {
  453. fModified = FALSE;
  454. rgdwLocal[LOCAL_ADDR] = pdwIndex[0];
  455. rgdwLocal[LOCAL_PORT] = pdwIndex[1];
  456. break;
  457. }
  458. }
  459. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  460. startIndex = 0;
  461. stopIndex = g_UdpInfo.pUdpTable->dwNumEntries;
  462. for(i = startIndex; i < stopIndex; i++)
  463. {
  464. lCompare = UdpCmp(rgdwLocal[LOCAL_ADDR],
  465. rgdwLocal[LOCAL_PORT],
  466. g_UdpInfo.pUdpTable->table[i].dwLocalAddr,
  467. g_UdpInfo.pUdpTable->table[i].dwLocalPort);
  468. if((lCompare is 0) and !fNext)
  469. {
  470. *pdwRetIndex = i;
  471. return NO_ERROR;
  472. }
  473. if(lCompare < 0)
  474. {
  475. if(dwQueryType is ACCESS_GET_NEXT)
  476. {
  477. *pdwRetIndex = i;
  478. return NO_ERROR;
  479. }
  480. else
  481. {
  482. return ERROR_INVALID_INDEX;
  483. }
  484. }
  485. }
  486. return ERROR_NO_MORE_ITEMS;
  487. }
  488. DWORD
  489. LocateTcpRow(
  490. DWORD dwQueryType,
  491. DWORD dwNumIndices,
  492. PDWORD pdwIndex,
  493. PDWORD pdwRetIndex
  494. )
  495. {
  496. LONG lCompare;
  497. DWORD rgdwAddr[4];
  498. BOOL fNext, fModified;
  499. DWORD startIndex, stopIndex,i;
  500. if((g_TcpInfo.pTcpTable is NULL) or
  501. (g_TcpInfo.pTcpTable->dwNumEntries is 0))
  502. {
  503. if(EXACT_MATCH(dwQueryType))
  504. {
  505. return ERROR_INVALID_INDEX;
  506. }
  507. if(dwQueryType is ACCESS_GET_FIRST)
  508. {
  509. return ERROR_NO_DATA;
  510. }
  511. return ERROR_NO_MORE_ITEMS;
  512. }
  513. if(dwQueryType is ACCESS_GET_FIRST)
  514. {
  515. *pdwRetIndex = 0;
  516. return NO_ERROR;
  517. }
  518. //
  519. // Quick way to copy the valid part of index
  520. // BUG might want to asssert the sizes
  521. //
  522. ZeroMemory(rgdwAddr,
  523. 4*sizeof(DWORD));
  524. memcpy(rgdwAddr,
  525. pdwIndex,
  526. dwNumIndices * sizeof(DWORD));
  527. //
  528. // We have modified it if the index is not the exact size
  529. //
  530. if(dwNumIndices isnot 4)
  531. {
  532. fModified = TRUE;
  533. }
  534. else
  535. {
  536. fModified = FALSE;
  537. }
  538. fNext = (dwQueryType is ACCESS_GET_NEXT) and (fModified is FALSE);
  539. startIndex = 0;
  540. stopIndex = g_TcpInfo.pTcpTable->dwNumEntries;
  541. for(i = startIndex; i < stopIndex; i++)
  542. {
  543. lCompare = TcpCmp(rgdwAddr[LOCAL_ADDR],
  544. rgdwAddr[LOCAL_PORT],
  545. rgdwAddr[REM_ADDR],
  546. rgdwAddr[REM_PORT],
  547. g_TcpInfo.pTcpTable->table[i].dwLocalAddr,
  548. g_TcpInfo.pTcpTable->table[i].dwLocalPort,
  549. g_TcpInfo.pTcpTable->table[i].dwRemoteAddr,
  550. g_TcpInfo.pTcpTable->table[i].dwRemotePort);
  551. if((lCompare is 0) and !fNext)
  552. {
  553. *pdwRetIndex = i;
  554. return NO_ERROR;
  555. }
  556. if(lCompare < 0)
  557. {
  558. if(dwQueryType is ACCESS_GET_NEXT)
  559. {
  560. *pdwRetIndex = i;
  561. return NO_ERROR;
  562. }
  563. else
  564. {
  565. return ERROR_INVALID_INDEX;
  566. }
  567. }
  568. }
  569. return ERROR_NO_MORE_ITEMS;
  570. }