Leaked source code of windows server 2003
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.

5724 lines
146 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\rtrmgr\access.c
  5. Abstract:
  6. All the "access" functions take similar arguments:
  7. dwQueryType This is the type of the query and can be
  8. ACCESS_GET
  9. ACCESS_GET_FIRST,
  10. ACCESS_GET_NEXT,
  11. ACCESS_SET,
  12. ACCESS_CREATE_ENTRY,
  13. ACCESS_DELETE_ENTRY
  14. dwInEntrySize Size of the input buffer. The information
  15. in the input buffer is dependent on the query type and
  16. the information being queried. The input buffer stores
  17. the QueryInfo which is a variable sized structure taking
  18. an array of instance ids. The dwInEntrySize is used to
  19. figure out how many instance ids are in the array (since
  20. and explicit count is not given)
  21. pInEntry Pointer to the input buffer. This is a MIB_OPAQUE_QUERY
  22. structure which contains an integer (dwType) which
  23. indicates the object being queried (which is not used
  24. since the demuxing based on that has already been done)
  25. and a variable length array of integer instance ids
  26. The instance id must be completely specified in case of
  27. ACCESS_GET,
  28. ACCESS_SET,
  29. ACCESS_CREATE_ENTRY,
  30. ACCESS_DELETE_ENTRY
  31. but for the rest only the first 'n' components of
  32. the instance id may be specified.
  33. pOutEntrySize Pointer to the size of the output buffer. If this is 0
  34. the caller is querying us for the size of buffer needed
  35. If the supplied buffer size is too small, we set this
  36. to the minimum required size and return
  37. ERROR_INSUFFICIENT_BUFFER;
  38. pOutEntry The output buffer which is a MIB_OPAQUE_INFO structure.
  39. The function fills in the dwTyoe to indicate the object
  40. being returned. That type is used to cast the opaque
  41. variable sized buffer following the type
  42. pbCache Pointer to BOOL which is set to TRUE if the corresponding
  43. cache was updated. This is not used currently, but may
  44. be used later for optimizations
  45. Revision History:
  46. Amritansh Raghav 7/8/95 Created
  47. --*/
  48. #include "allinc.h"
  49. DWORD
  50. SetIpForwardRow(
  51. PMIB_IPFORWARDROW pOldIpForw,
  52. PMIB_IPFORWARDROW pNewIpForw
  53. );
  54. DWORD
  55. DeleteIpForwardRow(
  56. PMIB_IPFORWARDROW pIpForw
  57. );
  58. DWORD
  59. AccessMcastMfeStatsInternal(
  60. DWORD dwQueryType,
  61. DWORD dwInEntrySize,
  62. PMIB_OPAQUE_QUERY pInEntry,
  63. PDWORD pOutEntrySize,
  64. PMIB_OPAQUE_INFO pOutEntry,
  65. PBOOL pbCache,
  66. DWORD dwStatsFlag
  67. );
  68. DWORD
  69. AccessIfNumber(
  70. DWORD dwQueryType,
  71. DWORD dwInEntrySize,
  72. PMIB_OPAQUE_QUERY pInEntry,
  73. PDWORD pOutEntrySize,
  74. PMIB_OPAQUE_INFO pOutEntry,
  75. PBOOL pbCache
  76. )
  77. /*++
  78. Routine Description
  79. Retrieves the number of interfaces
  80. Locks
  81. None since g_IfInfo.dwNumberOfInterfaces is InterlockXxx()ed
  82. Arguments
  83. dwQueryType ACCESS_GET
  84. dwInEntrySize Dont care
  85. pInEntry Dont care
  86. pOutEntrySize Minimum: MAX_MIB_OFFSET + sizeof(MIB_IFNUMBER)
  87. Return Value
  88. NO_ERROR
  89. --*/
  90. {
  91. PMIB_IFNUMBER pIfNumber;
  92. DWORD dwNumInterfaces;
  93. TraceEnter("AccessIfNumber");
  94. pIfNumber = (PMIB_IFNUMBER)(pOutEntry->rgbyData);
  95. if(dwQueryType isnot ACCESS_GET)
  96. {
  97. TraceLeave("AccessIfNumber");
  98. return ERROR_INVALID_PARAMETER;
  99. }
  100. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IFNUMBER))
  101. {
  102. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFNUMBER);
  103. TraceLeave("AccessIfNumber");
  104. return ERROR_INSUFFICIENT_BUFFER;
  105. }
  106. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFNUMBER);
  107. //
  108. // The variable is only inc/dec using interlocked ops
  109. // so we dont need to take a lock here
  110. //
  111. pIfNumber->dwValue = g_ulNumInterfaces;
  112. pOutEntry->dwId = IF_NUMBER;
  113. *pbCache = TRUE;
  114. TraceLeave("AccessIfNumber");
  115. return NO_ERROR;
  116. }
  117. DWORD
  118. AccessIfTable(
  119. DWORD dwQueryType,
  120. DWORD dwInEntrySize,
  121. PMIB_OPAQUE_QUERY pInEntry,
  122. PDWORD pOutEntrySize,
  123. PMIB_OPAQUE_INFO pOutEntry,
  124. PBOOL pbCache
  125. )
  126. /*++
  127. Routine Description
  128. Retrieves the Interface table
  129. Locks
  130. Takes ICB list lock as READER
  131. Arguments
  132. dwQueryType ACCESS_GET
  133. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IFTABLE)
  134. Return Value
  135. NO_ERROR
  136. --*/
  137. {
  138. PMIB_IFTABLE pIfTable;
  139. DWORD count;
  140. PLIST_ENTRY currentList;
  141. PICB picb;
  142. DWORD dwNumInterfaces, dwResult;
  143. TraceEnter("AccessIfTable");
  144. pIfTable = (PMIB_IFTABLE)(pOutEntry->rgbyData);
  145. if(dwQueryType isnot ACCESS_GET)
  146. {
  147. TraceLeave("AccessIfTable");
  148. return ERROR_INVALID_PARAMETER;
  149. }
  150. do
  151. {
  152. ENTER_READER(ICB_LIST);
  153. dwNumInterfaces = g_ulNumNonClientInterfaces;
  154. if(dwNumInterfaces is 0)
  155. {
  156. Trace0(MIB,"AccessIfTable: No valid entries found");
  157. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IFTABLE))
  158. {
  159. dwResult = ERROR_INSUFFICIENT_BUFFER;
  160. }
  161. else
  162. {
  163. pIfTable->dwNumEntries = 0;
  164. pOutEntry->dwId = IF_TABLE;
  165. dwResult = NO_ERROR;
  166. }
  167. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFTABLE);
  168. break;
  169. }
  170. if(*pOutEntrySize < MAX_MIB_OFFSET + SIZEOF_IFTABLE(dwNumInterfaces))
  171. {
  172. *pOutEntrySize = MAX_MIB_OFFSET + SIZEOF_IFTABLE(dwNumInterfaces);
  173. dwResult = ERROR_INSUFFICIENT_BUFFER;
  174. break;
  175. }
  176. pOutEntry->dwId = IF_TABLE;
  177. *pOutEntrySize = MAX_MIB_OFFSET + SIZEOF_IFTABLE(dwNumInterfaces);
  178. for(currentList = ICBList.Flink, count = 0 ;
  179. currentList isnot &ICBList;
  180. currentList = currentList->Flink)
  181. {
  182. picb = CONTAINING_RECORD (currentList, ICB, leIfLink) ;
  183. //
  184. // NOTE WE DO NOT RETURN ANY CLIENT INTERFACES
  185. //
  186. if((picb->ritType is ROUTER_IF_TYPE_CLIENT) or
  187. ((picb->ritType is ROUTER_IF_TYPE_INTERNAL) and
  188. (picb->bBound is FALSE)))
  189. {
  190. continue;
  191. }
  192. dwResult = GetInterfaceStatistics(picb,
  193. pIfTable->table + count);
  194. if(dwResult is NO_ERROR)
  195. {
  196. count++;
  197. }
  198. else
  199. {
  200. Trace2(ERR,
  201. "AccessIfTable: Error %d getting statistics for %S",
  202. dwResult,
  203. picb->pwszName);
  204. }
  205. }
  206. pIfTable->dwNumEntries = count;
  207. dwResult = NO_ERROR;
  208. }while(FALSE);
  209. EXIT_LOCK(ICB_LIST);
  210. *pbCache = TRUE;
  211. TraceLeave("AccessIfTable");
  212. return dwResult;
  213. }
  214. DWORD
  215. AccessIfRow(
  216. DWORD dwQueryType,
  217. DWORD dwInEntrySize,
  218. PMIB_OPAQUE_QUERY pInEntry,
  219. PDWORD pOutEntrySize,
  220. PMIB_OPAQUE_INFO pOutEntry,
  221. PBOOL pbCache
  222. )
  223. /*++
  224. Routine Description:
  225. Function used to set or retrieve an IFRow
  226. Locks
  227. ICB List lock are READER in caces of queries, WRITER in case of SETs
  228. Arguments
  229. dwQueryType Can be anything other than ACCESS_DELETE_ENTRY or
  230. ACCESS_CREATE_ENTRY. The only field that can be Set is
  231. the adminStatus
  232. pInEntry Interface index in the rgdwVarIndex field.
  233. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IFROW)
  234. For sets, the OutEntry contains the row to set
  235. Return Value:
  236. NO_ERROR
  237. --*/
  238. {
  239. PICB picb;
  240. PMIB_IFROW pIfRow;
  241. DWORD dwNumIndices, dwResult;
  242. BOOL bUpdateDIM = FALSE;
  243. HANDLE hDimInterface;
  244. TraceEnter("AccessIfRow");
  245. pIfRow = (PMIB_IFROW)(pOutEntry->rgbyData);
  246. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IFROW))
  247. {
  248. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFROW);
  249. TraceLeave("AccessIfRow");
  250. return ERROR_INSUFFICIENT_BUFFER;
  251. }
  252. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFROW);
  253. pOutEntry->dwId = IF_ROW;
  254. do
  255. {
  256. if(dwQueryType is ACCESS_SET)
  257. {
  258. ENTER_WRITER(ICB_LIST);
  259. }
  260. else
  261. {
  262. ENTER_READER(ICB_LIST);
  263. }
  264. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  265. dwResult = LocateIfRow(dwQueryType,
  266. dwNumIndices,
  267. pInEntry->rgdwVarIndex,
  268. &picb,
  269. FALSE);
  270. if(dwResult is NO_ERROR)
  271. {
  272. switch(dwQueryType)
  273. {
  274. case ACCESS_GET:
  275. case ACCESS_GET_NEXT:
  276. case ACCESS_GET_FIRST:
  277. {
  278. dwResult = GetInterfaceStatistics(picb,pIfRow);
  279. break;
  280. }
  281. case ACCESS_SET:
  282. {
  283. //
  284. // Save the interface handle, so that is can used outside
  285. // the interface locks
  286. //
  287. hDimInterface = picb->hDIMHandle;
  288. dwResult = SetInterfaceStatistics(picb,pIfRow,&bUpdateDIM);
  289. break;
  290. }
  291. default:
  292. {
  293. Trace1(MIB,
  294. "AccessIfRow: Wrong query type %d",dwQueryType);
  295. dwResult = ERROR_INVALID_PARAMETER;
  296. break;
  297. }
  298. }
  299. }
  300. }while(FALSE);
  301. EXIT_LOCK(ICB_LIST);
  302. //
  303. // If the AdminStatus of the interface has been changed,
  304. // update its status with DIM
  305. //
  306. if(bUpdateDIM)
  307. {
  308. EnableInterfaceWithDIM(
  309. hDimInterface,
  310. PID_IP,
  311. (pIfRow->dwAdminStatus == IF_ADMIN_STATUS_UP) ? TRUE : FALSE
  312. );
  313. }
  314. *pbCache = TRUE;
  315. TraceLeave("AccessIfRow");
  316. return dwResult;
  317. }
  318. DWORD
  319. AccessIcmpStats(
  320. DWORD dwQueryType,
  321. DWORD dwInEntrySize,
  322. PMIB_OPAQUE_QUERY pInEntry,
  323. PDWORD pOutEntrySize,
  324. PMIB_OPAQUE_INFO pOutEntry,
  325. PBOOL pbCache
  326. )
  327. /*++
  328. Routine Description:
  329. Function used to get ICMP statistics
  330. Locks
  331. None, since the stats are not cached
  332. Arguments
  333. dwQueryType ACCESS_GET
  334. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_ICMP)
  335. Return Value:
  336. NO_ERROR or some error code defined in iprtrmib
  337. --*/
  338. {
  339. PMIB_ICMP pIcmp;
  340. DWORD dwResult;
  341. TraceEnter("AccessIcmpStats");
  342. pIcmp = (PMIB_ICMP)(pOutEntry->rgbyData);
  343. if(dwQueryType isnot ACCESS_GET)
  344. {
  345. TraceLeave("AccessIcmpStats");
  346. return ERROR_INVALID_PARAMETER;
  347. }
  348. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_ICMP))
  349. {
  350. dwResult = ERROR_INSUFFICIENT_BUFFER;
  351. }
  352. else
  353. {
  354. pOutEntry->dwId = ICMP_STATS;
  355. dwResult = GetIcmpStatsFromStack(pIcmp);
  356. }
  357. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_ICMP);
  358. *pbCache = TRUE;
  359. TraceLeave("AccessIcmpStats");
  360. return dwResult;
  361. }
  362. DWORD
  363. AccessUdpStats(
  364. DWORD dwQueryType,
  365. DWORD dwInEntrySize,
  366. PMIB_OPAQUE_QUERY pInEntry,
  367. PDWORD pOutEntrySize,
  368. PMIB_OPAQUE_INFO pOutEntry,
  369. PBOOL pbCache
  370. )
  371. /*++
  372. Routine Description:
  373. Function used to get UDP statistics
  374. Locks
  375. None, since the stats are not cached
  376. Arguments
  377. dwQueryType ACCESS_GET
  378. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_UDPSTATS)
  379. Return Value:
  380. NO_ERROR or some error code defined in iprtrmib
  381. --*/
  382. {
  383. PMIB_UDPSTATS pUdpStats;
  384. DWORD dwResult;
  385. TraceEnter("AccessUdpStats");
  386. pUdpStats = (PMIB_UDPSTATS)(pOutEntry->rgbyData);
  387. if(dwQueryType isnot ACCESS_GET)
  388. {
  389. TraceLeave("AccessUdpStats");
  390. return ERROR_INVALID_PARAMETER;
  391. }
  392. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_UDPSTATS))
  393. {
  394. dwResult = ERROR_INSUFFICIENT_BUFFER;
  395. }
  396. else
  397. {
  398. pOutEntry->dwId = UDP_STATS;
  399. *pbCache = TRUE;
  400. dwResult = GetUdpStatsFromStack(pUdpStats);
  401. }
  402. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_UDPSTATS);
  403. TraceLeave("AccessUdpStats");
  404. return dwResult;
  405. }
  406. DWORD
  407. AccessUdpTable(
  408. DWORD dwQueryType,
  409. DWORD dwInEntrySize,
  410. PMIB_OPAQUE_QUERY pInEntry,
  411. PDWORD pOutEntrySize,
  412. PMIB_OPAQUE_INFO pOutEntry,
  413. PBOOL pbCache
  414. )
  415. /*++
  416. Routine Description:
  417. Function used to get UDP Table
  418. Locks
  419. UDP Cache lock as READER
  420. Arguments
  421. dwQueryType ACCESS_GET
  422. pOutEntrySize MAX_MIB_OFFSET + SIZEOF_UDPTABLE(NumUdpEntries)
  423. Return Value:
  424. NO_ERROR
  425. --*/
  426. {
  427. PMIB_UDPTABLE pUdpTable = (PMIB_UDPTABLE)(pOutEntry->rgbyData);
  428. DWORD i,dwResult;
  429. TraceEnter("AccessUdpTable");
  430. if(dwQueryType isnot ACCESS_GET)
  431. {
  432. TraceLeave("AccessUdpTable");
  433. return ERROR_INVALID_PARAMETER;
  434. }
  435. dwResult = UpdateCache(UDPCACHE,pbCache);
  436. if(dwResult isnot NO_ERROR)
  437. {
  438. Trace1(MIB,
  439. "AccessUdpTable: Couldnt update Udp Cache. Error %d",dwResult);
  440. TraceLeave("AccessUdpTable");
  441. return dwResult;
  442. }
  443. do
  444. {
  445. ENTER_READER(UDPCACHE);
  446. if((g_UdpInfo.pUdpTable is NULL) or
  447. (g_UdpInfo.pUdpTable->dwNumEntries is 0))
  448. {
  449. Trace0(MIB,"AccessUdpTable: No valid entries found");
  450. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_UDPTABLE))
  451. {
  452. dwResult = ERROR_INSUFFICIENT_BUFFER;
  453. }
  454. else
  455. {
  456. pOutEntry->dwId = UDP_TABLE;
  457. pUdpTable->dwNumEntries = 0;
  458. dwResult = NO_ERROR;
  459. }
  460. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_UDPTABLE);
  461. break;
  462. }
  463. if(*pOutEntrySize <
  464. MAX_MIB_OFFSET + SIZEOF_UDPTABLE(g_UdpInfo.pUdpTable->dwNumEntries))
  465. {
  466. *pOutEntrySize =
  467. MAX_MIB_OFFSET + SIZEOF_UDPTABLE(g_UdpInfo.pUdpTable->dwNumEntries);
  468. dwResult = ERROR_INSUFFICIENT_BUFFER;
  469. break;
  470. }
  471. *pOutEntrySize =
  472. MAX_MIB_OFFSET + SIZEOF_UDPTABLE(g_UdpInfo.pUdpTable->dwNumEntries);
  473. pOutEntry->dwId = UDP_TABLE;
  474. for(i = 0; i < g_UdpInfo.pUdpTable->dwNumEntries; i++)
  475. {
  476. pUdpTable->table[i] = g_UdpInfo.pUdpTable->table[i];
  477. }
  478. pUdpTable->dwNumEntries = g_UdpInfo.pUdpTable->dwNumEntries;
  479. dwResult = NO_ERROR;
  480. }while(FALSE);
  481. EXIT_LOCK(UDPCACHE);
  482. TraceLeave("AccessUdpTable");
  483. return dwResult;
  484. }
  485. DWORD
  486. AccessUdpRow(
  487. DWORD dwQueryType,
  488. DWORD dwInEntrySize,
  489. PMIB_OPAQUE_QUERY pInEntry,
  490. PDWORD pOutEntrySize,
  491. PMIB_OPAQUE_INFO pOutEntry,
  492. PBOOL pbCache
  493. )
  494. /*++
  495. Routine Description:
  496. Function used to retrieve a UDP Row
  497. Locks
  498. Takes the UDP Cache lock as READER
  499. Arguments
  500. dwQueryType Can be ACCESS_GET, ACCESS_GET_NEXT or ACCESS_GET_FIRST
  501. pInEntry LocalAddr & LocalPort for the row filled in the
  502. rgdwVarIndex field.
  503. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_UDPROW);
  504. Return Value:
  505. NO_ERROR or some error code defined in iprtrmib
  506. --*/
  507. {
  508. PMIB_UDPROW pUdpRow;
  509. DWORD dwResult, dwIndex, dwNumIndices;
  510. TraceEnter("AccessUdpRow");
  511. pUdpRow = (PMIB_UDPROW)(pOutEntry->rgbyData);
  512. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_UDPROW))
  513. {
  514. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_UDPROW);
  515. TraceLeave("AccessUdpRow");
  516. return ERROR_INSUFFICIENT_BUFFER;
  517. }
  518. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_UDPROW);
  519. pOutEntry->dwId = UDP_ROW;
  520. if((dwResult = UpdateCache(UDPCACHE,pbCache)) isnot NO_ERROR)
  521. {
  522. Trace1(MIB,
  523. "AccessUdpRow: Couldnt update Udp Cache. Error %d", dwResult);
  524. TraceLeave("AccessUdpRow");
  525. return dwResult;
  526. }
  527. do
  528. {
  529. ENTER_READER(UDPCACHE);
  530. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  531. dwResult = LocateUdpRow(dwQueryType,
  532. dwNumIndices,
  533. pInEntry->rgdwVarIndex,
  534. &dwIndex);
  535. if(dwResult is NO_ERROR)
  536. {
  537. *pUdpRow = g_UdpInfo.pUdpTable->table[dwIndex];
  538. dwResult = NO_ERROR;
  539. }
  540. }while(FALSE);
  541. EXIT_LOCK(UDPCACHE);
  542. TraceLeave("AccessUdpRow");
  543. return dwResult;
  544. }
  545. DWORD
  546. AccessTcpStats(
  547. DWORD dwQueryType,
  548. DWORD dwInEntrySize,
  549. PMIB_OPAQUE_QUERY pInEntry,
  550. PDWORD pOutEntrySize,
  551. PMIB_OPAQUE_INFO pOutEntry,
  552. PBOOL pbCache
  553. )
  554. /*++
  555. Routine Description:
  556. Function used to get TCP statistics
  557. Locks
  558. None, since the stats are not cached
  559. Arguments
  560. dwQueryType ACCESS_GET
  561. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_TCPSTATS)
  562. Return Value:
  563. NO_ERROR or some error code defined in iprtrmib
  564. --*/
  565. {
  566. PMIB_TCPSTATS pTcpStats;
  567. DWORD dwResult;
  568. TraceEnter("AccessTcpStats");
  569. pTcpStats = (PMIB_TCPSTATS)(pOutEntry->rgbyData);
  570. if(dwQueryType isnot ACCESS_GET)
  571. {
  572. TraceLeave("AccessTcpStats");
  573. return ERROR_INVALID_PARAMETER;
  574. }
  575. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_TCPSTATS))
  576. {
  577. dwResult = ERROR_INSUFFICIENT_BUFFER;
  578. }
  579. else
  580. {
  581. pOutEntry->dwId = TCP_STATS;
  582. *pbCache = TRUE;
  583. dwResult = GetTcpStatsFromStack(pTcpStats);
  584. }
  585. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_TCPSTATS);
  586. TraceLeave("AccessTcpStats");
  587. return dwResult;
  588. }
  589. DWORD
  590. AccessTcpTable(
  591. DWORD dwQueryType,
  592. DWORD dwInEntrySize,
  593. PMIB_OPAQUE_QUERY pInEntry,
  594. PDWORD pOutEntrySize,
  595. PMIB_OPAQUE_INFO pOutEntry,
  596. PBOOL pbCache
  597. )
  598. /*++
  599. Routine Description:
  600. Function used to get TCP Table
  601. Locks
  602. TCP Cache lock as READER
  603. Arguments
  604. dwQueryType ACCESS_GET
  605. pOutEntrySize MAX_MIB_OFFSET + SIZEOF_TCPTABLE(NumTcpEntries)
  606. Return Value:
  607. NO_ERROR
  608. --*/
  609. {
  610. PMIB_TCPTABLE pTcpTable;
  611. DWORD i, dwResult;
  612. TraceEnter("AccessTcpTable");
  613. pTcpTable = (PMIB_TCPTABLE)(pOutEntry->rgbyData);
  614. if(dwQueryType isnot ACCESS_GET)
  615. {
  616. return ERROR_INVALID_PARAMETER;
  617. }
  618. if((dwResult = UpdateCache(TCPCACHE,pbCache)) isnot NO_ERROR)
  619. {
  620. Trace1(MIB,
  621. "AccessTcpTable: Couldnt update Tcp Cache. Error %d",
  622. dwResult);
  623. TraceLeave("AccessTcpTable");
  624. return dwResult;
  625. }
  626. do
  627. {
  628. ENTER_READER(TCPCACHE);
  629. if((g_TcpInfo.pTcpTable is NULL) or
  630. (g_TcpInfo.pTcpTable->dwNumEntries is 0))
  631. {
  632. Trace0(MIB,"AccessTcpTable: No valid entries found");
  633. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_TCPTABLE))
  634. {
  635. dwResult = ERROR_INSUFFICIENT_BUFFER;
  636. }
  637. else
  638. {
  639. pOutEntry->dwId = TCP_TABLE;
  640. pTcpTable->dwNumEntries = 0;
  641. dwResult = NO_ERROR;
  642. }
  643. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_TCPTABLE);
  644. break;
  645. }
  646. if(*pOutEntrySize <
  647. MAX_MIB_OFFSET + SIZEOF_TCPTABLE(g_TcpInfo.pTcpTable->dwNumEntries))
  648. {
  649. *pOutEntrySize =
  650. MAX_MIB_OFFSET + SIZEOF_TCPTABLE(g_TcpInfo.pTcpTable->dwNumEntries);
  651. dwResult = ERROR_INSUFFICIENT_BUFFER;
  652. break;
  653. }
  654. pOutEntry->dwId = TCP_TABLE;
  655. *pOutEntrySize =
  656. MAX_MIB_OFFSET + SIZEOF_TCPTABLE(g_TcpInfo.pTcpTable->dwNumEntries);
  657. for(i = 0; i < g_TcpInfo.pTcpTable->dwNumEntries; i++)
  658. {
  659. pTcpTable->table[i] = g_TcpInfo.pTcpTable->table[i];
  660. }
  661. pTcpTable->dwNumEntries = g_TcpInfo.pTcpTable->dwNumEntries;
  662. dwResult = NO_ERROR;
  663. }while(FALSE);
  664. EXIT_LOCK(TCPCACHE);
  665. TraceLeave("AccessTcpTable");
  666. return dwResult;
  667. }
  668. DWORD
  669. AccessTcpRow(
  670. DWORD dwQueryType,
  671. DWORD dwInEntrySize,
  672. PMIB_OPAQUE_QUERY pInEntry,
  673. PDWORD pOutEntrySize,
  674. PMIB_OPAQUE_INFO pOutEntry,
  675. PBOOL pbCache
  676. )
  677. /*++
  678. Routine Description:
  679. Function used to retrieve or set a TCP Row
  680. Locks
  681. Takes the TCP Cache lock as READER for queries and as a WRITER for
  682. Sets
  683. Arguments
  684. dwQueryType Can be anything except ACCESS_DELETE_ENTRY and
  685. ACCESS_CREATE_ENTRY.
  686. For ACCESS_SET, the state is the only thing that can
  687. be set and it can only be set to TCP_DELETE_TCB
  688. pInEntry LocalAddr, LocalPort, RemoteAddr, RemotePort for the
  689. row filled in the rgdwVarIndex field.
  690. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_TCPROW);
  691. For Sets, the OutEntry contains the row to set
  692. Return Value:
  693. NO_ERROR or some error code defined in iprtrmib
  694. --*/
  695. {
  696. DWORD dwResult, dwNumIndices, dwIndex;
  697. PMIB_TCPROW pTcpRow;
  698. TraceEnter("AccessTcpRow");
  699. pTcpRow = (PMIB_TCPROW)(pOutEntry->rgbyData);
  700. if(dwQueryType isnot ACCESS_DELETE_ENTRY)
  701. {
  702. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_TCPROW))
  703. {
  704. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_TCPROW);
  705. TraceLeave("AccessTcpRow");
  706. return ERROR_INSUFFICIENT_BUFFER;
  707. }
  708. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_TCPROW);
  709. pOutEntry->dwId = TCP_ROW;
  710. }
  711. if((dwResult = UpdateCache(TCPCACHE,pbCache)) isnot NO_ERROR)
  712. {
  713. Trace1(MIB,
  714. "AccessTcpRow: Couldnt update Tcp Cache. Error %d",
  715. dwResult);
  716. TraceLeave("AccessTcpRow");
  717. return dwResult;
  718. }
  719. do
  720. {
  721. if(dwQueryType is ACCESS_SET)
  722. {
  723. ENTER_WRITER(TCPCACHE);
  724. }
  725. else
  726. {
  727. ENTER_READER(TCPCACHE);
  728. }
  729. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  730. dwResult = LocateTcpRow(dwQueryType,
  731. dwNumIndices,
  732. pInEntry->rgdwVarIndex,
  733. &dwIndex);
  734. if(dwResult is NO_ERROR)
  735. {
  736. switch(dwQueryType)
  737. {
  738. case ACCESS_GET:
  739. case ACCESS_GET_NEXT:
  740. case ACCESS_GET_FIRST:
  741. {
  742. *pTcpRow = g_TcpInfo.pTcpTable->table[dwIndex];
  743. dwResult = NO_ERROR;
  744. break;
  745. }
  746. case ACCESS_SET:
  747. {
  748. //
  749. // The only thing you can do is set it to a state and that
  750. // too only to TCP_DELETE_TCB
  751. //
  752. if(pTcpRow->dwState isnot TCP_DELETE_TCB)
  753. {
  754. Trace1(ERR,
  755. "AccessTcpRow: TCP State can only be set to delete. Tried to set to %d",
  756. pTcpRow->dwState);
  757. dwResult = ERROR_INVALID_DATA;
  758. break;
  759. }
  760. dwResult = SetTcpEntryToStack(pTcpRow);
  761. if(dwResult is NO_ERROR)
  762. {
  763. g_TcpInfo.pTcpTable->table[dwIndex].dwState =
  764. pTcpRow->dwState;
  765. }
  766. break;
  767. }
  768. default:
  769. {
  770. Trace1(ERR,
  771. "AccessTcpRow: Query type %d is wrong",
  772. dwQueryType);
  773. dwResult = ERROR_INVALID_PARAMETER;
  774. break;
  775. }
  776. }
  777. }
  778. }while(FALSE);
  779. EXIT_LOCK(TCPCACHE);
  780. TraceLeave("AccessTcpRow");
  781. return dwResult;
  782. }
  783. DWORD
  784. AccessIpStats(
  785. DWORD dwQueryType,
  786. DWORD dwInEntrySize,
  787. PMIB_OPAQUE_QUERY pInEntry,
  788. PDWORD pOutEntrySize,
  789. PMIB_OPAQUE_INFO pOutEntry,
  790. PBOOL pbCache
  791. )
  792. /*++
  793. Routine Description:
  794. Function used to get IP statistics
  795. Locks
  796. None, since the stats are not cached
  797. Arguments
  798. dwQueryType ACCESS_GET or ACCESS_SET
  799. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPSTATS)
  800. Return Value:
  801. NO_ERROR or some error code defined in iprtrmib
  802. --*/
  803. {
  804. PMIB_IPSTATS pIpStats;
  805. DWORD dwResult;
  806. TraceEnter("AccessIpStats");
  807. pIpStats = (PMIB_IPSTATS)(pOutEntry->rgbyData);
  808. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPSTATS))
  809. {
  810. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPSTATS);
  811. TraceLeave("AccessIpStats");
  812. return ERROR_INSUFFICIENT_BUFFER;
  813. }
  814. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPSTATS);
  815. pOutEntry->dwId = IP_STATS;
  816. switch(dwQueryType)
  817. {
  818. case ACCESS_GET:
  819. {
  820. //
  821. // Since we need to write the number of routes addresses etc
  822. // Update the two caches
  823. //
  824. UpdateCache(IPADDRCACHE,pbCache);
  825. UpdateCache(IPFORWARDCACHE,pbCache);
  826. dwResult = GetIpStatsFromStack(pIpStats);
  827. pIpStats->dwNumIf = g_ulNumInterfaces;
  828. pIpStats->dwNumRoutes = 0;
  829. if(g_IpInfo.pForwardTable)
  830. {
  831. pIpStats->dwNumRoutes = g_IpInfo.pForwardTable->dwNumEntries;
  832. }
  833. pIpStats->dwNumAddr = 0;
  834. if(g_IpInfo.pAddrTable)
  835. {
  836. pIpStats->dwNumAddr = g_IpInfo.pAddrTable->dwNumEntries;
  837. }
  838. TraceLeave("AccessIpStats");
  839. return dwResult;
  840. }
  841. case ACCESS_SET:
  842. {
  843. MIB_IPSTATS CurrentIpStats;
  844. DWORD dwErr;
  845. dwErr = GetIpStatsFromStack(&CurrentIpStats);
  846. if(dwErr isnot NO_ERROR)
  847. {
  848. Trace1(ERR,
  849. "AccessIpStats: Couldnt get IPSNMP info from stack to initiate set. Error %d",
  850. dwErr);
  851. return dwErr;
  852. }
  853. //
  854. // See what the current forwarding status is. We allow one to go
  855. // Forward -> notForward but not the other way.
  856. //
  857. if(pIpStats->dwDefaultTTL isnot MIB_USE_CURRENT_TTL)
  858. {
  859. if(pIpStats->dwDefaultTTL > 255)
  860. {
  861. Trace0(ERR,"AccessIpStats: Cant set TTL > 255");
  862. TraceLeave("AccessIpStats");
  863. return ERROR_INVALID_DATA;
  864. }
  865. dwErr = SetIpStatsToStack(pIpStats);
  866. if(dwErr isnot NO_ERROR)
  867. {
  868. Trace1(ERR,
  869. "AccessIpStats: Error %d setting TTL in stack",
  870. dwErr);
  871. }
  872. }
  873. if(pIpStats->dwForwarding isnot MIB_USE_CURRENT_FORWARDING)
  874. {
  875. if((pIpStats->dwForwarding isnot MIB_IP_FORWARDING) and
  876. (pIpStats->dwForwarding isnot MIB_IP_NOT_FORWARDING))
  877. {
  878. Trace1(ERR,
  879. "AccessIpStats: Fwding state %d is invalid",
  880. pIpStats->dwForwarding);
  881. return ERROR_INVALID_DATA;
  882. }
  883. //
  884. // See if its to switch off forwarding
  885. //
  886. EnterCriticalSection(&g_csFwdState);
  887. g_bEnableFwdRequest = (pIpStats->dwForwarding is MIB_IP_FORWARDING);
  888. Trace1(GLOBAL,
  889. "AccessIpStats: Signalling worker to %s forwarding",
  890. g_bEnableFwdRequest ? "enable" : "disable");
  891. SetEvent(g_hSetForwardingEvent);
  892. LeaveCriticalSection(&g_csFwdState);
  893. }
  894. TraceLeave("AccessIpStats");
  895. return dwErr;
  896. }
  897. default:
  898. {
  899. Trace1(ERR,
  900. "AccessIpStats: Query type %d is wrong",
  901. dwQueryType);
  902. return ERROR_INVALID_PARAMETER;
  903. }
  904. }
  905. }
  906. DWORD
  907. AccessIpAddrTable(
  908. DWORD dwQueryType,
  909. DWORD dwInEntrySize,
  910. PMIB_OPAQUE_QUERY pInEntry,
  911. PDWORD pOutEntrySize,
  912. PMIB_OPAQUE_INFO pOutEntry,
  913. PBOOL pbCache
  914. )
  915. /*++
  916. Routine Description:
  917. Function used to get IP Address Table
  918. Locks
  919. IP Address Cache lock as READER
  920. Arguments
  921. dwQueryType ACCESS_GET
  922. pOutEntrySize MAX_MIB_OFFSET + SIZEOF_IPADDRTABLE(NumIpAddrEntries)
  923. Return Value:
  924. NO_ERROR
  925. --*/
  926. {
  927. PMIB_IPADDRTABLE pIpAddrTable;
  928. DWORD dwResult, i;
  929. TraceEnter("AccessIpAddrTable");
  930. pIpAddrTable = (PMIB_IPADDRTABLE)(pOutEntry->rgbyData);
  931. if(dwQueryType isnot ACCESS_GET)
  932. {
  933. TraceLeave("AccessIpAddrTable");
  934. return ERROR_INVALID_PARAMETER;
  935. }
  936. if((dwResult = UpdateCache(IPADDRCACHE,pbCache)) isnot NO_ERROR)
  937. {
  938. Trace1(MIB,
  939. "AccessIpAddrTable: Error %d updating IpAddr Cache",
  940. dwResult);
  941. TraceLeave("AccessIpAddrTable");
  942. return dwResult;
  943. }
  944. do
  945. {
  946. ENTER_READER(IPADDRCACHE);
  947. if((g_IpInfo.pAddrTable is NULL) or
  948. (g_IpInfo.pAddrTable->dwNumEntries is 0))
  949. {
  950. Trace0(MIB,"No valid entries found");
  951. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPADDRTABLE))
  952. {
  953. dwResult = ERROR_INSUFFICIENT_BUFFER;
  954. }
  955. else
  956. {
  957. pOutEntry->dwId = IP_ADDRTABLE;
  958. pIpAddrTable->dwNumEntries = 0;
  959. dwResult = NO_ERROR;
  960. }
  961. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPADDRTABLE);
  962. break;
  963. }
  964. if(*pOutEntrySize <
  965. MAX_MIB_OFFSET + SIZEOF_IPADDRTABLE(g_IpInfo.pAddrTable->dwNumEntries))
  966. {
  967. *pOutEntrySize = MAX_MIB_OFFSET +
  968. SIZEOF_IPADDRTABLE(g_IpInfo.pAddrTable->dwNumEntries);
  969. dwResult = ERROR_INSUFFICIENT_BUFFER;
  970. break;
  971. }
  972. pOutEntry->dwId = IP_ADDRTABLE;
  973. *pOutEntrySize = MAX_MIB_OFFSET +
  974. SIZEOF_IPADDRTABLE(g_IpInfo.pAddrTable->dwNumEntries);
  975. for(i = 0; i < g_IpInfo.pAddrTable->dwNumEntries; i ++)
  976. {
  977. pIpAddrTable->table[i] = g_IpInfo.pAddrTable->table[i];
  978. }
  979. pIpAddrTable->dwNumEntries = g_IpInfo.pAddrTable->dwNumEntries;
  980. dwResult = NO_ERROR;
  981. }while(FALSE);
  982. EXIT_LOCK(IPADDRCACHE);
  983. TraceLeave("AccessIpAddrTable");
  984. return dwResult;
  985. }
  986. DWORD
  987. AccessIpForwardNumber(
  988. DWORD dwQueryType,
  989. DWORD dwInEntrySize,
  990. PMIB_OPAQUE_QUERY pInEntry,
  991. PDWORD pOutEntrySize,
  992. PMIB_OPAQUE_INFO pOutEntry,
  993. PBOOL pbCache
  994. )
  995. {
  996. PMIB_IPFORWARDNUMBER pNum;
  997. DWORD dwResult;
  998. TraceEnter("AccessIpForwardNumber");
  999. pNum = (PMIB_IPFORWARDNUMBER)pOutEntry;
  1000. if(dwQueryType isnot ACCESS_GET)
  1001. {
  1002. TraceLeave("AccessIpForwardNumber");
  1003. return ERROR_INVALID_PARAMETER;
  1004. }
  1005. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDNUMBER))
  1006. {
  1007. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDNUMBER);
  1008. TraceLeave("AccessIpForwardNumber");
  1009. return ERROR_INSUFFICIENT_BUFFER;
  1010. }
  1011. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDNUMBER);
  1012. if((dwResult = UpdateCache(IPFORWARDCACHE,pbCache)) isnot NO_ERROR)
  1013. {
  1014. Trace1(MIB,
  1015. "AccessIpForwardNumber: Couldnt update IpForward Cache. Error %d",
  1016. dwResult);
  1017. TraceLeave("AccessIpForwardNumber");
  1018. return dwResult;
  1019. }
  1020. ENTER_READER(IPFORWARDCACHE);
  1021. pNum->dwValue = 0;
  1022. if(g_IpInfo.pForwardTable)
  1023. {
  1024. pNum->dwValue = g_IpInfo.pForwardTable->dwNumEntries;
  1025. }
  1026. pOutEntry->dwId = IP_FORWARDNUMBER;
  1027. *pbCache = TRUE;
  1028. EXIT_LOCK(IPFORWARDCACHE);
  1029. TraceLeave("AccessIpForwardNumber");
  1030. return NO_ERROR;
  1031. }
  1032. DWORD
  1033. AccessIpForwardTable(
  1034. DWORD dwQueryType,
  1035. DWORD dwInEntrySize,
  1036. PMIB_OPAQUE_QUERY pInEntry,
  1037. PDWORD pOutEntrySize,
  1038. PMIB_OPAQUE_INFO pOutEntry,
  1039. PBOOL pbCache
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. Function used to get IFTable
  1044. Arguments
  1045. dwQueryType Can only be ACCESS_GET
  1046. dwInEntrySize Size of pInEntry in bytes
  1047. pInEntry Nothing important since the whole table is retrieved
  1048. pOutEntrySize IN: Size of pOutEntry in bytes
  1049. OUT:Size of information filled in OR size of memory needed
  1050. pOutEntry Points to information filled into an MIB_IFTABLE structure
  1051. pbCache Unused
  1052. Return Value:
  1053. NO_ERROR or some error code defined in iprtrmib
  1054. --*/
  1055. {
  1056. PMIB_IPFORWARDTABLE pIpForwardTable;
  1057. DWORD i,dwResult;
  1058. TraceEnter("AccessIpForwardTable");
  1059. pIpForwardTable = (PMIB_IPFORWARDTABLE)(pOutEntry->rgbyData);
  1060. if(dwQueryType isnot ACCESS_GET)
  1061. {
  1062. TraceLeave("AccessIpForwardTable");
  1063. return ERROR_INVALID_PARAMETER;
  1064. }
  1065. if((dwResult = UpdateCache(IPFORWARDCACHE,pbCache)) isnot NO_ERROR)
  1066. {
  1067. Trace1(MIB,
  1068. "AccessIpForwardTable: Couldnt update IpForward Cache. Error %d",
  1069. dwResult);
  1070. TraceLeave("AccessIpForwardTable");
  1071. return dwResult;
  1072. }
  1073. do
  1074. {
  1075. ENTER_READER(IPFORWARDCACHE);
  1076. if((g_IpInfo.pForwardTable is NULL) or
  1077. (g_IpInfo.pForwardTable->dwNumEntries is 0))
  1078. {
  1079. Trace0(MIB,"No valid entries found");
  1080. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDTABLE))
  1081. {
  1082. dwResult = ERROR_INSUFFICIENT_BUFFER;
  1083. }
  1084. else
  1085. {
  1086. pOutEntry->dwId = IP_FORWARDTABLE;
  1087. pIpForwardTable->dwNumEntries = 0;
  1088. dwResult = NO_ERROR;
  1089. }
  1090. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDTABLE);
  1091. break;
  1092. }
  1093. if(*pOutEntrySize < MAX_MIB_OFFSET + SIZEOF_IPFORWARDTABLE(g_IpInfo.pForwardTable->dwNumEntries))
  1094. {
  1095. *pOutEntrySize = MAX_MIB_OFFSET + SIZEOF_IPFORWARDTABLE(g_IpInfo.pForwardTable->dwNumEntries);
  1096. dwResult = ERROR_INSUFFICIENT_BUFFER;
  1097. break;
  1098. }
  1099. pOutEntry->dwId = IP_FORWARDTABLE;
  1100. *pOutEntrySize = MAX_MIB_OFFSET + SIZEOF_IPFORWARDTABLE(g_IpInfo.pForwardTable->dwNumEntries);
  1101. for(i = 0; i < g_IpInfo.pForwardTable->dwNumEntries; i ++)
  1102. {
  1103. pIpForwardTable->table[i] = g_IpInfo.pForwardTable->table[i];
  1104. }
  1105. pIpForwardTable->dwNumEntries = g_IpInfo.pForwardTable->dwNumEntries;
  1106. dwResult = NO_ERROR;
  1107. }while(FALSE);
  1108. EXIT_LOCK(IPFORWARDCACHE);
  1109. TraceLeave("AccessIpForwardTable");
  1110. return dwResult;
  1111. }
  1112. DWORD
  1113. AccessIpNetTable(
  1114. DWORD dwQueryType,
  1115. DWORD dwInEntrySize,
  1116. PMIB_OPAQUE_QUERY pInEntry,
  1117. PDWORD pOutEntrySize,
  1118. PMIB_OPAQUE_INFO pOutEntry,
  1119. PBOOL pbCache
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Function used to get ARP Table
  1124. Locks
  1125. IP Net Cache lock as READER
  1126. Arguments
  1127. dwQueryType ACCESS_GET or ACCESS_DELETE_ENTRY
  1128. dwInEntrySize (only for delete)
  1129. pOutEntrySize MAX_MIB_OFFSET + SIZEOF_IPNETTABLE(NumArpEntries)
  1130. Return Value:
  1131. NO_ERROR
  1132. --*/
  1133. {
  1134. PMIB_IPNETTABLE pIpNetTable;
  1135. DWORD i,dwResult;
  1136. TraceEnter("AccessIpNetTable");
  1137. pIpNetTable = (PMIB_IPNETTABLE)(pOutEntry->rgbyData);
  1138. if((dwQueryType isnot ACCESS_GET) and
  1139. (dwQueryType isnot ACCESS_DELETE_ENTRY))
  1140. {
  1141. TraceLeave("AccessIpNetTable");
  1142. return ERROR_INVALID_PARAMETER;
  1143. }
  1144. if(dwQueryType is ACCESS_GET)
  1145. {
  1146. dwResult = UpdateCache(IPNETCACHE,pbCache);
  1147. if(dwResult isnot NO_ERROR)
  1148. {
  1149. Trace1(MIB,
  1150. "AccessIpNetTable: Couldnt update IpNet Cache. Error %d",
  1151. dwResult);
  1152. TraceLeave("AccessIpNetTable");
  1153. return dwResult;
  1154. }
  1155. }
  1156. else
  1157. {
  1158. DWORD dwIfIndex;
  1159. PICB pIcb;
  1160. if(dwInEntrySize < sizeof(MIB_OPAQUE_QUERY))
  1161. {
  1162. TraceLeave("AccessIpNetTable");
  1163. return ERROR_INVALID_PARAMETER;
  1164. }
  1165. dwIfIndex = pInEntry->rgdwVarIndex[0];
  1166. ENTER_READER(ICB_LIST);
  1167. pIcb = InterfaceLookupByIfIndex(dwIfIndex);
  1168. if((pIcb is NULL) or
  1169. (pIcb->bBound is FALSE))
  1170. {
  1171. EXIT_LOCK(ICB_LIST);
  1172. TraceLeave("AccessIpNetTable");
  1173. return ERROR_INVALID_INDEX;
  1174. }
  1175. dwIfIndex = pIcb->dwIfIndex;
  1176. EXIT_LOCK(ICB_LIST);
  1177. dwResult = FlushIpNetTableFromStack(dwIfIndex);
  1178. TraceLeave("AccessIpNetTable");
  1179. return dwResult;
  1180. }
  1181. do
  1182. {
  1183. ENTER_READER(IPNETCACHE);
  1184. if((g_IpInfo.pNetTable is NULL) or
  1185. (g_IpInfo.pNetTable->dwNumEntries is 0))
  1186. {
  1187. Trace0(MIB,"No valid entries found");
  1188. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPNETTABLE))
  1189. {
  1190. dwResult = ERROR_INSUFFICIENT_BUFFER;
  1191. }
  1192. else
  1193. {
  1194. pOutEntry->dwId = IP_NETTABLE;
  1195. pIpNetTable->dwNumEntries = 0;
  1196. dwResult = NO_ERROR;
  1197. }
  1198. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPNETTABLE);
  1199. break;
  1200. }
  1201. if(*pOutEntrySize <
  1202. MAX_MIB_OFFSET + SIZEOF_IPNETTABLE(g_IpInfo.pNetTable->dwNumEntries))
  1203. {
  1204. *pOutEntrySize = MAX_MIB_OFFSET +
  1205. SIZEOF_IPNETTABLE(g_IpInfo.pNetTable->dwNumEntries);
  1206. dwResult = ERROR_INSUFFICIENT_BUFFER;
  1207. break;
  1208. }
  1209. pOutEntry->dwId = IP_NETTABLE;
  1210. *pOutEntrySize =
  1211. MAX_MIB_OFFSET + SIZEOF_IPNETTABLE(g_IpInfo.pNetTable->dwNumEntries);
  1212. for(i = 0; i < g_IpInfo.pNetTable->dwNumEntries; i ++)
  1213. {
  1214. pIpNetTable->table[i] = g_IpInfo.pNetTable->table[i];
  1215. }
  1216. pIpNetTable->dwNumEntries = g_IpInfo.pNetTable->dwNumEntries;
  1217. dwResult = NO_ERROR;
  1218. }while(FALSE);
  1219. EXIT_LOCK(IPNETCACHE);
  1220. TraceLeave("AccessIpNetTable");
  1221. return dwResult;
  1222. }
  1223. DWORD
  1224. AccessIpAddrRow(
  1225. DWORD dwQueryType,
  1226. DWORD dwInEntrySize,
  1227. PMIB_OPAQUE_QUERY pInEntry,
  1228. PDWORD pOutEntrySize,
  1229. PMIB_OPAQUE_INFO pOutEntry,
  1230. PBOOL pbCache
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. Function used to retrieve a IP Address Row
  1235. Locks
  1236. Takes the IP Address Cache lock as READER
  1237. Arguments
  1238. dwQueryType Can be ACCESS_GET, ACCESS_GET_NEXT or ACCESS_GET_FIRST
  1239. pInEntry Address for the row filled in the rgdwVarIndex field.
  1240. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPADDRROW)
  1241. Return Value:
  1242. NO_ERROR or some error code defined in iprtrmib
  1243. --*/
  1244. {
  1245. DWORD dwResult, dwNumIndices, dwIndex;
  1246. PMIB_IPADDRROW pIpAddrRow;
  1247. TraceEnter("AccessIpAddrRow");
  1248. pIpAddrRow = (PMIB_IPADDRROW)(pOutEntry->rgbyData);
  1249. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPADDRROW))
  1250. {
  1251. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPADDRROW);
  1252. TraceLeave("AccessIpAddrRow");
  1253. return ERROR_INSUFFICIENT_BUFFER;
  1254. }
  1255. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPADDRROW);
  1256. pOutEntry->dwId = IP_ADDRROW;
  1257. if((dwResult = UpdateCache(IPADDRCACHE,pbCache)) isnot NO_ERROR)
  1258. {
  1259. Trace1(MIB,
  1260. "AccessIpAddrRow: Couldnt update Ip Addr Cache. Error %d",
  1261. dwResult);
  1262. TraceLeave("AccessIpAddrRow");
  1263. return dwResult;
  1264. }
  1265. do
  1266. {
  1267. ENTER_READER(IPADDRCACHE);
  1268. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  1269. dwResult = LocateIpAddrRow(dwQueryType,
  1270. dwNumIndices,
  1271. pInEntry->rgdwVarIndex,
  1272. &dwIndex);
  1273. if(dwResult is NO_ERROR)
  1274. {
  1275. *pIpAddrRow = g_IpInfo.pAddrTable->table[dwIndex];
  1276. dwResult = NO_ERROR;
  1277. }
  1278. }while(FALSE);
  1279. EXIT_LOCK(IPADDRCACHE);
  1280. TraceLeave("AccessIpAddrRow");
  1281. return dwResult;
  1282. }
  1283. DWORD
  1284. AccessIpForwardRow(
  1285. DWORD dwQueryType,
  1286. DWORD dwInEntrySize,
  1287. PMIB_OPAQUE_QUERY pInEntry,
  1288. PDWORD pOutEntrySize,
  1289. PMIB_OPAQUE_INFO pOutEntry,
  1290. PBOOL pbCache
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. Function used to retrieve or set a route (IP Forward Row)
  1295. Locks
  1296. Takes the IP Forward Cache lock as READER for queries, WRITER for sets
  1297. Arguments
  1298. dwQueryType All permitted
  1299. pInEntry Dest, Proto, Policy and NextHop for the row filled in the
  1300. rgdwVarIndex field.
  1301. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDROW). For Sets the
  1302. OutBuffer has the row to set
  1303. Return Value:
  1304. NO_ERROR or some error code defined in iprtrmib
  1305. --*/
  1306. {
  1307. DWORD dwResult,dwNumIndices,dwIndex;
  1308. PMIB_IPFORWARDROW pIpForwardRow;
  1309. TraceEnter("AccessIpForwardRow");
  1310. pIpForwardRow = (PMIB_IPFORWARDROW)(pOutEntry->rgbyData);
  1311. if(dwQueryType isnot ACCESS_DELETE_ENTRY)
  1312. {
  1313. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDROW))
  1314. {
  1315. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDROW);
  1316. TraceLeave("AccessIpForwardRow");
  1317. return ERROR_INSUFFICIENT_BUFFER;
  1318. }
  1319. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPFORWARDROW);
  1320. pOutEntry->dwId = IP_FORWARDROW;
  1321. }
  1322. if((dwResult = UpdateCache(IPFORWARDCACHE,pbCache)) isnot NO_ERROR)
  1323. {
  1324. Trace1(MIB,
  1325. "AccessIpForwardRow: Error %d updating IpForward Cache",
  1326. dwResult);
  1327. TraceLeave("AccessIpForwardRow");
  1328. return dwResult;
  1329. }
  1330. do
  1331. {
  1332. if(dwQueryType > ACCESS_GET_NEXT)
  1333. {
  1334. ENTER_WRITER(IPFORWARDCACHE);
  1335. }
  1336. else
  1337. {
  1338. ENTER_READER(IPFORWARDCACHE);
  1339. }
  1340. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  1341. dwResult = LocateIpForwardRow(dwQueryType,
  1342. dwNumIndices,
  1343. pInEntry->rgdwVarIndex,
  1344. &dwIndex);
  1345. if(dwResult is NO_ERROR)
  1346. {
  1347. switch(dwQueryType)
  1348. {
  1349. case ACCESS_GET:
  1350. case ACCESS_GET_NEXT:
  1351. case ACCESS_GET_FIRST:
  1352. {
  1353. *pIpForwardRow = g_IpInfo.pForwardTable->table[dwIndex];
  1354. break;
  1355. }
  1356. case ACCESS_SET:
  1357. {
  1358. dwResult =
  1359. SetIpForwardRow(&(g_IpInfo.pForwardTable->table[dwIndex]),
  1360. pIpForwardRow);
  1361. if(dwResult is NO_ERROR)
  1362. {
  1363. g_IpInfo.pForwardTable->table[dwIndex] = *pIpForwardRow;
  1364. }
  1365. break;
  1366. }
  1367. case ACCESS_DELETE_ENTRY:
  1368. {
  1369. dwResult =
  1370. DeleteIpForwardRow(&(g_IpInfo.pForwardTable->table[dwIndex]));
  1371. if(dwResult is NO_ERROR)
  1372. {
  1373. g_LastUpdateTable[IPFORWARDCACHE] = 0;
  1374. }
  1375. break;
  1376. }
  1377. case ACCESS_CREATE_ENTRY:
  1378. {
  1379. //
  1380. //
  1381. // This is the case where you have tried to create a
  1382. // route which matches an existing entry
  1383. //
  1384. dwResult = ERROR_ALREADY_EXISTS;
  1385. break;
  1386. }
  1387. }
  1388. }
  1389. else
  1390. {
  1391. if((dwQueryType is ACCESS_CREATE_ENTRY) or
  1392. (dwQueryType is ACCESS_SET))
  1393. {
  1394. //
  1395. // Cannot set PROTO_IP_LOCAL routes (other protos will
  1396. // be weeded out when we search for the RTM handle)
  1397. //
  1398. if(pIpForwardRow->dwForwardProto is PROTO_IP_LOCAL)
  1399. {
  1400. dwResult = ERROR_INVALID_PARAMETER;
  1401. break;
  1402. }
  1403. dwResult = SetIpForwardRow(NULL,
  1404. pIpForwardRow);
  1405. //
  1406. // Since its too much hassle to create, malloc (possibly)
  1407. // sorted insert we make just invalidate the route cache
  1408. //
  1409. if(dwResult is NO_ERROR)
  1410. {
  1411. g_LastUpdateTable[IPFORWARDCACHE] = 0;
  1412. }
  1413. }
  1414. }
  1415. }while(FALSE);
  1416. EXIT_LOCK(IPFORWARDCACHE);
  1417. TraceLeave("AccessIpForwardRow");
  1418. return dwResult;
  1419. }
  1420. DWORD
  1421. AccessIpNetRow(
  1422. DWORD dwQueryType,
  1423. DWORD dwInEntrySize,
  1424. PMIB_OPAQUE_QUERY pInEntry,
  1425. PDWORD pOutEntrySize,
  1426. PMIB_OPAQUE_INFO pOutEntry,
  1427. PBOOL pbCache
  1428. )
  1429. /*++
  1430. Routine Description:
  1431. Function used to retrieve or set an ARP entry (IP Net Row)
  1432. Locks
  1433. Takes the IP Net Cache lock as READER for queries, as WRITER for sets
  1434. Arguments
  1435. dwQueryType All permitted
  1436. pInEntry IfIndex and IPAddress for the row filled in the
  1437. rgdwVarIndex field.
  1438. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPNETROW);
  1439. For Sets, the OutEntry contains the row to set
  1440. Return Value:
  1441. NO_ERROR or some error code defined in iprtrmib
  1442. --*/
  1443. {
  1444. DWORD dwResult, dwNumIndices, dwIndex;
  1445. PMIB_IPNETROW pIpNetRow;
  1446. PICB pIcb;
  1447. TraceEnter("AccessIpNetRow");
  1448. pIpNetRow = (PMIB_IPNETROW)(pOutEntry->rgbyData);
  1449. if(dwQueryType isnot ACCESS_DELETE_ENTRY)
  1450. {
  1451. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPNETROW))
  1452. {
  1453. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPNETROW);
  1454. TraceLeave("AccessIpNetRow");
  1455. return ERROR_INSUFFICIENT_BUFFER;
  1456. }
  1457. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPNETROW);
  1458. pOutEntry->dwId = IP_NETROW;
  1459. }
  1460. if((dwResult = UpdateCache(IPNETCACHE,pbCache)) isnot NO_ERROR)
  1461. {
  1462. Trace1(MIB,
  1463. "AccessIpNetRow: Couldnt update Ip Addr Cache. Error %d",
  1464. dwResult);
  1465. TraceLeave("AccessIpNetRow");
  1466. return dwResult;
  1467. }
  1468. do
  1469. {
  1470. if(dwQueryType > ACCESS_GET_NEXT)
  1471. {
  1472. ENTER_WRITER(IPNETCACHE);
  1473. }
  1474. else
  1475. {
  1476. ENTER_READER(IPNETCACHE);
  1477. }
  1478. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  1479. dwResult = LocateIpNetRow(dwQueryType,
  1480. dwNumIndices,
  1481. pInEntry->rgdwVarIndex,
  1482. &dwIndex);
  1483. if(dwResult is NO_ERROR)
  1484. {
  1485. switch(dwQueryType)
  1486. {
  1487. case ACCESS_GET:
  1488. case ACCESS_GET_NEXT:
  1489. case ACCESS_GET_FIRST:
  1490. {
  1491. *pIpNetRow = g_IpInfo.pNetTable->table[dwIndex];
  1492. break;
  1493. }
  1494. case ACCESS_SET:
  1495. {
  1496. if((pIpNetRow->dwType isnot MIB_IPNET_TYPE_DYNAMIC) and
  1497. (pIpNetRow->dwType isnot MIB_IPNET_TYPE_STATIC))
  1498. {
  1499. dwResult = ERROR_INVALID_DATA;
  1500. break;
  1501. }
  1502. //
  1503. // Need to map the interface index to the adapter index
  1504. //
  1505. ENTER_READER(ICB_LIST);
  1506. pIcb = InterfaceLookupByIfIndex(pIpNetRow->dwIndex);
  1507. if((pIcb is NULL) or
  1508. (!pIcb->bBound))
  1509. {
  1510. //
  1511. // Could not find interface
  1512. //
  1513. dwResult = ERROR_INVALID_INDEX;
  1514. EXIT_LOCK(ICB_LIST);
  1515. break;
  1516. }
  1517. EXIT_LOCK(ICB_LIST);
  1518. //
  1519. // No need to force cache updates
  1520. //
  1521. dwResult = SetIpNetEntryToStack(pIpNetRow, FALSE);
  1522. if(dwResult is NO_ERROR)
  1523. {
  1524. g_IpInfo.pNetTable->table[dwIndex] = *pIpNetRow;
  1525. }
  1526. break;
  1527. }
  1528. case ACCESS_DELETE_ENTRY:
  1529. {
  1530. MIB_IPNETROW tempRow;
  1531. g_IpInfo.pNetTable->table[dwIndex].dwType =
  1532. MIB_IPNET_TYPE_INVALID;
  1533. tempRow = g_IpInfo.pNetTable->table[dwIndex];
  1534. dwResult = SetIpNetEntryToStack(&tempRow,
  1535. FALSE);
  1536. if(dwResult is NO_ERROR)
  1537. {
  1538. g_LastUpdateTable[IPNETCACHE] = 0;
  1539. }
  1540. break;
  1541. }
  1542. case ACCESS_CREATE_ENTRY:
  1543. {
  1544. dwResult = ERROR_ALREADY_EXISTS;
  1545. break;
  1546. }
  1547. }
  1548. }
  1549. else
  1550. {
  1551. if((dwQueryType is ACCESS_CREATE_ENTRY) or
  1552. (dwQueryType is ACCESS_SET))
  1553. {
  1554. ENTER_READER(ICB_LIST);
  1555. pIcb = InterfaceLookupByIfIndex(pIpNetRow->dwIndex);
  1556. if((pIcb is NULL) or
  1557. (!pIcb->bBound))
  1558. {
  1559. //
  1560. // Could not find interface
  1561. //
  1562. dwResult = ERROR_INVALID_INDEX;
  1563. EXIT_LOCK(ICB_LIST);
  1564. break;
  1565. }
  1566. EXIT_LOCK(ICB_LIST);
  1567. dwResult = SetIpNetEntryToStack(pIpNetRow,
  1568. FALSE);
  1569. if(dwResult is NO_ERROR)
  1570. {
  1571. g_LastUpdateTable[IPNETCACHE] = 0;
  1572. }
  1573. }
  1574. }
  1575. }while(FALSE);
  1576. EXIT_LOCK(IPNETCACHE);
  1577. TraceLeave("AccessIpNetRow");
  1578. return dwResult;
  1579. }
  1580. //
  1581. // The ACCESS_SETs and ACCESS_CREATEs require a bit more work in that the
  1582. // values have to be written back to the stack. The actual code for setting
  1583. // to stack (or RTM) is elsewhere, the following functions are merely
  1584. // wrappers around the actual calls
  1585. //
  1586. DWORD
  1587. SetIpForwardRow(
  1588. PMIB_IPFORWARDROW pOldIpForw,
  1589. PMIB_IPFORWARDROW pNewIpForw
  1590. )
  1591. {
  1592. DWORD i, dwResult, dwMask;
  1593. HANDLE hRtmHandle;
  1594. PICB pIcb;
  1595. TraceEnter("SetIpForwardRow");
  1596. hRtmHandle = NULL;
  1597. for(i = 0;
  1598. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  1599. i++)
  1600. {
  1601. if(pNewIpForw->dwForwardProto is g_rgRtmHandles[i].dwProtoId)
  1602. {
  1603. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  1604. break;
  1605. }
  1606. }
  1607. if(hRtmHandle is NULL)
  1608. {
  1609. Trace1(ERR,
  1610. "SetIpForwardRow: Protocol %d not valid",
  1611. pNewIpForw->dwForwardProto);
  1612. TraceLeave("SetIpForwardRow");
  1613. return ERROR_INVALID_PARAMETER;
  1614. }
  1615. if((pNewIpForw->dwForwardDest & pNewIpForw->dwForwardMask) isnot pNewIpForw->dwForwardDest)
  1616. {
  1617. Trace2(ERR,
  1618. "SetIpForwardRow: Dest %d.%d.%d.%d and Mask %d.%d.%d.%d wrong",
  1619. PRINT_IPADDR(pNewIpForw->dwForwardDest),
  1620. PRINT_IPADDR(pNewIpForw->dwForwardMask));
  1621. TraceLeave("SetIpForwardRow");
  1622. return ERROR_INVALID_PARAMETER;
  1623. }
  1624. if(((DWORD)(pNewIpForw->dwForwardDest & 0x000000FF)) >= (DWORD)0x000000E0)
  1625. {
  1626. //
  1627. // This will catch the CLASS D/E and all 1's bcast
  1628. //
  1629. Trace1(ERR,
  1630. "SetIpForwardRow: Dest %d.%d.%d.%d is invalid",
  1631. PRINT_IPADDR(pNewIpForw->dwForwardDest));
  1632. TraceLeave("SetIpForwardRow");
  1633. return ERROR_INVALID_PARAMETER;
  1634. }
  1635. #if 0
  1636. // Removed this since metric=0 is legal for routes to the loopback
  1637. // interface.
  1638. if(pNewIpForw->dwForwardMetric1 is 0)
  1639. {
  1640. Trace0(ERR,
  1641. "SetIpForwardRow: Metric1 cant be 0");
  1642. TraceLeave("SetIpForwardRow");
  1643. return ERROR_INVALID_PARAMETER;
  1644. }
  1645. #endif
  1646. //
  1647. // If we are changing values, we need to blow the old row away.
  1648. // Just a quirk of how
  1649. // RTM and our stack works
  1650. //
  1651. if(pOldIpForw isnot NULL)
  1652. {
  1653. dwResult = DeleteIpForwardRow(pOldIpForw);
  1654. if(dwResult isnot NO_ERROR)
  1655. {
  1656. Trace1(MIB,
  1657. "SetIpForwardRow: Unable to delete route from RTM. Error %d",
  1658. dwResult);
  1659. TraceLeave("SetIpForwardRow");
  1660. return ERROR_CAN_NOT_COMPLETE;
  1661. }
  1662. UpdateStackRoutesToRestoreList(pOldIpForw, IRNO_FLAG_DELETE);
  1663. }
  1664. if(pNewIpForw->dwForwardProto isnot PROTO_IP_NETMGMT)
  1665. {
  1666. pNewIpForw->dwForwardAge = INFINITE;
  1667. }
  1668. //
  1669. // Add the RTM route from the ip forward entry
  1670. //
  1671. ENTER_READER(ICB_LIST);
  1672. dwMask = GetBestNextHopMaskGivenIndex(pNewIpForw->dwForwardIfIndex,
  1673. pNewIpForw->dwForwardNextHop);
  1674. pIcb = InterfaceLookupByIfIndex(pNewIpForw->dwForwardIfIndex);
  1675. if(pIcb is NULL)
  1676. {
  1677. EXIT_LOCK(ICB_LIST);
  1678. Trace1(ERR,
  1679. "SetIpForwardRow: I/f 0x%x doesnt exist",
  1680. pNewIpForw->dwForwardIfIndex);
  1681. TraceLeave("SetIpForwardRow");
  1682. return ERROR_INVALID_PARAMETER;
  1683. }
  1684. if(IsIfP2P(pIcb->ritType))
  1685. {
  1686. pNewIpForw->dwForwardNextHop = 0;
  1687. }
  1688. EXIT_LOCK(ICB_LIST);
  1689. dwResult = AddRtmRoute(hRtmHandle,
  1690. ConvertMibRouteToRouteInfo(pNewIpForw),
  1691. IP_VALID_ROUTE | IP_STACK_ROUTE,
  1692. dwMask,
  1693. pNewIpForw->dwForwardAge,
  1694. NULL);
  1695. if(dwResult isnot NO_ERROR)
  1696. {
  1697. Trace1(MIB,
  1698. "SetIpForwardRow: Could not set route to RTM: Dest %x\n",
  1699. pNewIpForw->dwForwardDest) ;
  1700. }
  1701. else
  1702. {
  1703. UpdateStackRoutesToRestoreList(pNewIpForw, IRNO_FLAG_ADD);
  1704. }
  1705. TraceLeave("SetIpForwardRow");
  1706. return dwResult;
  1707. }
  1708. DWORD
  1709. DeleteIpForwardRow(
  1710. PMIB_IPFORWARDROW pIpForw
  1711. )
  1712. {
  1713. DWORD i, dwResult;
  1714. HANDLE hRtmHandle;
  1715. hRtmHandle = NULL;
  1716. for(i = 0;
  1717. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  1718. i++)
  1719. {
  1720. if(pIpForw->dwForwardProto is g_rgRtmHandles[i].dwProtoId)
  1721. {
  1722. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  1723. break;
  1724. }
  1725. }
  1726. if(hRtmHandle is NULL)
  1727. {
  1728. Trace1(ERR,
  1729. "DeleteIpForwardRow: Protocol %d not valid",
  1730. pIpForw->dwForwardProto);
  1731. return ERROR_INVALID_PARAMETER;
  1732. }
  1733. //
  1734. // Delete the RTM route corr. to the ip forward entry
  1735. //
  1736. dwResult = DeleteRtmRoute(hRtmHandle,
  1737. ConvertMibRouteToRouteInfo(pIpForw));
  1738. if(dwResult isnot NO_ERROR)
  1739. {
  1740. Trace1(MIB,
  1741. "DeleteIpForwardRow: RtmDeleteRoute returned %d", dwResult);
  1742. }
  1743. else
  1744. {
  1745. UpdateStackRoutesToRestoreList(pIpForw, IRNO_FLAG_DELETE);
  1746. }
  1747. return dwResult;
  1748. }
  1749. DWORD
  1750. AccessMcastMfe(
  1751. DWORD dwQueryType,
  1752. DWORD dwInEntrySize,
  1753. PMIB_OPAQUE_QUERY pInEntry,
  1754. PDWORD pOutEntrySize,
  1755. PMIB_OPAQUE_INFO pOutEntry,
  1756. PBOOL pbCache
  1757. )
  1758. /*++
  1759. Routine Description
  1760. This
  1761. Locks
  1762. None
  1763. Arguments
  1764. None
  1765. Return Value
  1766. None
  1767. --*/
  1768. {
  1769. DWORD dwResult,dwNumIndices,dwIndex;
  1770. DWORD dwOutBufferSize, dwNumMfes;
  1771. MIB_IPMCAST_MFE mimInMfe;
  1772. TraceEnter("AccessMcastMfe");
  1773. #if 1
  1774. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  1775. switch(dwQueryType)
  1776. {
  1777. case ACCESS_GET:
  1778. {
  1779. //
  1780. // The in index better be a good size
  1781. // The user must specify Group, Source and SrcMask. The
  1782. // SrcMask is not used and MUST be 0xFFFFFFFF
  1783. //
  1784. if(dwNumIndices < 3)
  1785. {
  1786. TraceLeave("AccessMcastMfe");
  1787. return ERROR_INVALID_INDEX;
  1788. }
  1789. ZeroMemory(&mimInMfe, sizeof(mimInMfe));
  1790. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  1791. mimInMfe.dwSource = pInEntry->rgdwVarIndex[1];
  1792. //
  1793. // NOTE: Change when doing source aggregation
  1794. //
  1795. mimInMfe.dwSrcMask = 0xFFFFFFFF;
  1796. dwOutBufferSize =
  1797. (*pOutEntrySize < MAX_MIB_OFFSET)? 0 : (*pOutEntrySize - MAX_MIB_OFFSET);
  1798. dwResult = MgmGetMfe(
  1799. &mimInMfe, &dwOutBufferSize, pOutEntry->rgbyData
  1800. );
  1801. if (dwResult == ERROR_INSUFFICIENT_BUFFER)
  1802. {
  1803. *pOutEntrySize = MAX_MIB_OFFSET + dwOutBufferSize;
  1804. }
  1805. break;
  1806. }
  1807. case ACCESS_GET_FIRST:
  1808. {
  1809. PMIB_MFE_TABLE pMfeTable;
  1810. //
  1811. // We always gets chunks of 1KB
  1812. //
  1813. if(*pOutEntrySize < MIB_MFE_BUFFER_SIZE)
  1814. {
  1815. *pOutEntrySize = MIB_MFE_BUFFER_SIZE;
  1816. return ERROR_INSUFFICIENT_BUFFER;
  1817. }
  1818. //
  1819. // MGM wants a flat buffer for MFEs. We however return a
  1820. // MIB_MFE_TABLE to the user that starts (in the worst case) after
  1821. // MAX_MIB_OFFSET bytes of the input buffer
  1822. //
  1823. #define _MIN_SIZE \
  1824. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_MFE_TABLE,table[0]))
  1825. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  1826. #undef _MIN_SIZE
  1827. pMfeTable = (PMIB_MFE_TABLE)pOutEntry->rgbyData;
  1828. pMfeTable->dwNumEntries = 0;
  1829. // pMfe = (PMIB_IPMCAST_MFE)(pMfeTable->table);
  1830. dwNumMfes = 0;
  1831. dwResult = MgmGetFirstMfe(
  1832. &dwOutBufferSize, (PBYTE)pMfeTable->table,
  1833. &dwNumMfes
  1834. );
  1835. //
  1836. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  1837. //
  1838. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  1839. if((dwResult is ERROR_MORE_DATA) or
  1840. (dwResult is ERROR_NO_MORE_ITEMS))
  1841. {
  1842. pMfeTable->dwNumEntries = dwNumMfes;
  1843. dwResult = NO_ERROR;
  1844. }
  1845. break;
  1846. }
  1847. case ACCESS_GET_NEXT:
  1848. {
  1849. PMIB_MFE_TABLE pMfeTable;
  1850. //
  1851. // For this, too we always get chunks of 1K pages
  1852. //
  1853. if(*pOutEntrySize < MIB_MFE_BUFFER_SIZE)
  1854. {
  1855. *pOutEntrySize = MIB_MFE_BUFFER_SIZE;
  1856. return ERROR_INSUFFICIENT_BUFFER;
  1857. }
  1858. #define _MIN_SIZE \
  1859. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_MFE_TABLE,table[0]))
  1860. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  1861. #undef _MIN_SIZE
  1862. pMfeTable = (PMIB_MFE_TABLE)pOutEntry->rgbyData;
  1863. pMfeTable->dwNumEntries = 0;
  1864. // pMfe = (PMIB_IPMCAST_MFE)(pMfeTable->table);
  1865. dwNumMfes = 0;
  1866. //
  1867. // Set up the "first" mfe
  1868. //
  1869. ZeroMemory(&mimInMfe, sizeof(mimInMfe));
  1870. //
  1871. // NOTE: Change when doing source aggregation
  1872. //
  1873. mimInMfe.dwSrcMask = 0xFFFFFFFF;
  1874. switch(dwNumIndices)
  1875. {
  1876. case 0:
  1877. {
  1878. break;
  1879. }
  1880. case 1:
  1881. {
  1882. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  1883. break;
  1884. }
  1885. default:
  1886. {
  1887. //
  1888. // 2 or more indices
  1889. //
  1890. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  1891. mimInMfe.dwSource = pInEntry->rgdwVarIndex[1];
  1892. break;
  1893. }
  1894. }
  1895. dwResult = MgmGetNextMfe(
  1896. &mimInMfe, &dwOutBufferSize, (PBYTE)pMfeTable->table,
  1897. &dwNumMfes
  1898. );
  1899. //
  1900. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  1901. //
  1902. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  1903. if((dwResult is ERROR_MORE_DATA) or
  1904. (dwResult is ERROR_NO_MORE_ITEMS))
  1905. {
  1906. pMfeTable->dwNumEntries = dwNumMfes;
  1907. dwResult = NO_ERROR;
  1908. }
  1909. break;
  1910. }
  1911. case ACCESS_SET:
  1912. {
  1913. //
  1914. // Validate the MFE size
  1915. //
  1916. if(dwInEntrySize < SIZEOF_BASIC_MFE)
  1917. {
  1918. }
  1919. //dwResult = SetMfe(pMfe);
  1920. break;
  1921. }
  1922. case ACCESS_DELETE_ENTRY:
  1923. {
  1924. break;
  1925. }
  1926. case ACCESS_CREATE_ENTRY:
  1927. {
  1928. //
  1929. //
  1930. // This is the case where you have tried to create a route which
  1931. // matches an existing entry
  1932. //
  1933. dwResult = ERROR_ALREADY_EXISTS;
  1934. break;
  1935. }
  1936. }
  1937. #endif
  1938. TraceLeave("AccessMcastMfe");
  1939. //return dwResult;
  1940. return NO_ERROR;
  1941. }
  1942. DWORD
  1943. AccessMcastMfeStats(
  1944. DWORD dwQueryType,
  1945. DWORD dwInEntrySize,
  1946. PMIB_OPAQUE_QUERY pInEntry,
  1947. PDWORD pOutEntrySize,
  1948. PMIB_OPAQUE_INFO pOutEntry,
  1949. PBOOL pbCache
  1950. )
  1951. {
  1952. return AccessMcastMfeStatsInternal(
  1953. dwQueryType,
  1954. dwInEntrySize,
  1955. pInEntry,
  1956. pOutEntrySize,
  1957. pOutEntry,
  1958. pbCache,
  1959. MGM_MFE_STATS_0
  1960. );
  1961. }
  1962. DWORD
  1963. AccessMcastMfeStatsEx(
  1964. DWORD dwQueryType,
  1965. DWORD dwInEntrySize,
  1966. PMIB_OPAQUE_QUERY pInEntry,
  1967. PDWORD pOutEntrySize,
  1968. PMIB_OPAQUE_INFO pOutEntry,
  1969. PBOOL pbCache
  1970. )
  1971. {
  1972. return AccessMcastMfeStatsInternal(
  1973. dwQueryType,
  1974. dwInEntrySize,
  1975. pInEntry,
  1976. pOutEntrySize,
  1977. pOutEntry,
  1978. pbCache,
  1979. MGM_MFE_STATS_1
  1980. );
  1981. }
  1982. DWORD
  1983. AccessMcastMfeStatsInternal(
  1984. DWORD dwQueryType,
  1985. DWORD dwInEntrySize,
  1986. PMIB_OPAQUE_QUERY pInEntry,
  1987. PDWORD pOutEntrySize,
  1988. PMIB_OPAQUE_INFO pOutEntry,
  1989. PBOOL pbCache,
  1990. DWORD dwStatsFlag
  1991. )
  1992. /*++
  1993. Routine Description
  1994. This
  1995. Locks
  1996. None
  1997. Arguments
  1998. None
  1999. Return Value
  2000. None
  2001. --*/
  2002. {
  2003. DWORD dwResult = NO_ERROR,dwNumIndices,dwIndex;
  2004. DWORD dwOutBufferSize, dwNumMfes;
  2005. MIB_IPMCAST_MFE mimInMfe;
  2006. TraceEnter("AccessMcastMfeStatsInternal");
  2007. #if 1
  2008. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2009. switch(dwQueryType)
  2010. {
  2011. case ACCESS_GET:
  2012. {
  2013. //
  2014. // The in index better be a good size
  2015. // The user must specify Group, Source and SrcMask. The
  2016. // SrcMask is not used and MUST be 0xFFFFFFFF
  2017. //
  2018. if(dwNumIndices < 3)
  2019. {
  2020. TraceLeave("AccessMcastMfeStatsInternal");
  2021. return ERROR_INVALID_INDEX;
  2022. }
  2023. ZeroMemory(&mimInMfe, sizeof(mimInMfe));
  2024. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  2025. mimInMfe.dwSource = pInEntry->rgdwVarIndex[1];
  2026. //
  2027. // NOTE: Change when doing source aggregation
  2028. //
  2029. mimInMfe.dwSrcMask = 0xFFFFFFFF;
  2030. dwOutBufferSize =
  2031. (*pOutEntrySize < MAX_MIB_OFFSET)? 0 : (*pOutEntrySize - MAX_MIB_OFFSET);
  2032. dwResult = MgmGetMfeStats(
  2033. &mimInMfe, &dwOutBufferSize,
  2034. pOutEntry->rgbyData, dwStatsFlag
  2035. );
  2036. if (dwResult == ERROR_INSUFFICIENT_BUFFER)
  2037. {
  2038. *pOutEntrySize = MAX_MIB_OFFSET + dwOutBufferSize;
  2039. }
  2040. break;
  2041. }
  2042. case ACCESS_GET_FIRST:
  2043. {
  2044. PMIB_MFE_STATS_TABLE pMfeStatsTable;
  2045. //
  2046. // We always get chunks of 1KB
  2047. //
  2048. if (*pOutEntrySize < MIB_MFE_BUFFER_SIZE)
  2049. {
  2050. *pOutEntrySize = MIB_MFE_BUFFER_SIZE;
  2051. return ERROR_INSUFFICIENT_BUFFER;
  2052. }
  2053. //
  2054. // MGM wants a flat buffer for MFEs. We however return a
  2055. // MIB_MFE_TABLE to the user that starts (in the worst case) after
  2056. // MAX_MIB_OFFSET bytes of the input buffer
  2057. //
  2058. #define _MIN_SIZE \
  2059. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_MFE_STATS_TABLE,table[0]))
  2060. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2061. #undef _MIN_SIZE
  2062. pMfeStatsTable = (PMIB_MFE_STATS_TABLE)pOutEntry->rgbyData;
  2063. pMfeStatsTable->dwNumEntries = 0;
  2064. // pMfeStats = (PMIB_IPMCAST_MFE_STATS)(pMfeStatsTable->table);
  2065. dwNumMfes = 0;
  2066. dwResult = MgmGetFirstMfeStats(
  2067. &dwOutBufferSize, (PBYTE)pMfeStatsTable->table,
  2068. &dwNumMfes, dwStatsFlag
  2069. );
  2070. //
  2071. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2072. //
  2073. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2074. if((dwResult is ERROR_MORE_DATA) or
  2075. (dwResult is ERROR_NO_MORE_ITEMS))
  2076. {
  2077. pMfeStatsTable->dwNumEntries = dwNumMfes;
  2078. dwResult = NO_ERROR;
  2079. }
  2080. break;
  2081. }
  2082. case ACCESS_GET_NEXT:
  2083. {
  2084. PMIB_MFE_STATS_TABLE pMfeStatsTable;
  2085. //
  2086. // For this, too we always get chunks of 1K pages
  2087. //
  2088. if (*pOutEntrySize < MIB_MFE_BUFFER_SIZE)
  2089. {
  2090. *pOutEntrySize = MIB_MFE_BUFFER_SIZE;
  2091. return ERROR_INSUFFICIENT_BUFFER;
  2092. }
  2093. #define _MIN_SIZE \
  2094. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_MFE_TABLE,table[0]))
  2095. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2096. #undef _MIN_SIZE
  2097. pMfeStatsTable = (PMIB_MFE_STATS_TABLE)pOutEntry->rgbyData;
  2098. pMfeStatsTable->dwNumEntries = 0;
  2099. //pMfeStats = (PIPMCAST_MFE_STATS)(pMfeStatsTable->table);
  2100. dwNumMfes = 0;
  2101. //
  2102. // Set up the "first" mfe
  2103. //
  2104. ZeroMemory(&mimInMfe, sizeof(mimInMfe));
  2105. //
  2106. // NOTE: Change when doing source aggregation
  2107. //
  2108. mimInMfe.dwSrcMask = 0xFFFFFFFF;
  2109. switch(dwNumIndices)
  2110. {
  2111. case 0:
  2112. {
  2113. break;
  2114. }
  2115. case 1:
  2116. {
  2117. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  2118. break;
  2119. }
  2120. default:
  2121. {
  2122. //
  2123. // 2 or more indices
  2124. //
  2125. mimInMfe.dwGroup = pInEntry->rgdwVarIndex[0];
  2126. mimInMfe.dwSource = pInEntry->rgdwVarIndex[1];
  2127. break;
  2128. }
  2129. }
  2130. dwResult = MgmGetNextMfeStats(
  2131. &mimInMfe, &dwOutBufferSize,
  2132. (PBYTE)pMfeStatsTable->table, &dwNumMfes,
  2133. dwStatsFlag
  2134. );
  2135. //
  2136. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2137. //
  2138. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2139. if((dwResult is ERROR_MORE_DATA) or
  2140. (dwResult is ERROR_NO_MORE_ITEMS))
  2141. {
  2142. pMfeStatsTable->dwNumEntries = dwNumMfes;
  2143. dwResult = NO_ERROR;
  2144. }
  2145. break;
  2146. }
  2147. case ACCESS_SET:
  2148. {
  2149. //
  2150. // Validate the MFE size
  2151. //
  2152. if(dwInEntrySize < SIZEOF_BASIC_MFE)
  2153. {
  2154. }
  2155. //dwResult = SetMfe(pMfe);
  2156. break;
  2157. }
  2158. case ACCESS_DELETE_ENTRY:
  2159. {
  2160. break;
  2161. }
  2162. case ACCESS_CREATE_ENTRY:
  2163. {
  2164. //
  2165. //
  2166. // This is the case where you have tried to create a route which
  2167. // matches an existing entry
  2168. //
  2169. dwResult = ERROR_ALREADY_EXISTS;
  2170. break;
  2171. }
  2172. }
  2173. #endif
  2174. TraceLeave("AccessMcastMfeStatsInternal");
  2175. return dwResult;
  2176. }
  2177. DWORD
  2178. AccessMcastIfStats(
  2179. DWORD dwQueryType,
  2180. DWORD dwInEntrySize,
  2181. PMIB_OPAQUE_QUERY pInEntry,
  2182. PDWORD pOutEntrySize,
  2183. PMIB_OPAQUE_INFO pOutEntry,
  2184. PBOOL pbCache
  2185. )
  2186. /*++
  2187. Routine Description
  2188. Retrieves the IP Multicast Interface table
  2189. Locks
  2190. Takes ICB list lock as READER
  2191. Arguments
  2192. dwQueryType ACCESS_GET
  2193. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IFTABLE)
  2194. Return Value
  2195. None
  2196. --*/
  2197. {
  2198. PICB picb;
  2199. PMIB_IPMCAST_IF_ENTRY pIfRow;
  2200. DWORD dwNumIndices, dwResult;
  2201. TraceEnter("AccessMcastIfTable");
  2202. pIfRow = (PMIB_IPMCAST_IF_ENTRY)(pOutEntry->rgbyData);
  2203. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_IF_ENTRY))
  2204. {
  2205. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_IF_ENTRY);
  2206. TraceLeave("AccessMcastIfTable");
  2207. return ERROR_INSUFFICIENT_BUFFER;
  2208. }
  2209. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_IF_ENTRY);
  2210. pOutEntry->dwId = MCAST_IF_ENTRY;
  2211. do
  2212. {
  2213. if(dwQueryType is ACCESS_SET)
  2214. {
  2215. ENTER_WRITER(ICB_LIST);
  2216. }
  2217. else
  2218. {
  2219. ENTER_READER(ICB_LIST);
  2220. }
  2221. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2222. dwResult = LocateIfRow(dwQueryType,
  2223. dwNumIndices,
  2224. pInEntry->rgdwVarIndex,
  2225. &picb,
  2226. FALSE);
  2227. if(dwResult is NO_ERROR)
  2228. {
  2229. switch(dwQueryType)
  2230. {
  2231. case ACCESS_GET:
  2232. case ACCESS_GET_NEXT:
  2233. case ACCESS_GET_FIRST:
  2234. {
  2235. dwResult = GetInterfaceMcastStatistics(picb,pIfRow);
  2236. break;
  2237. }
  2238. case ACCESS_SET:
  2239. {
  2240. dwResult = SetInterfaceMcastStatistics(picb,pIfRow);
  2241. break;
  2242. }
  2243. default:
  2244. {
  2245. Trace1(MIB,
  2246. "AccessIfRow: Wrong query type %d",dwQueryType);
  2247. dwResult = ERROR_INVALID_PARAMETER;
  2248. break;
  2249. }
  2250. }
  2251. }
  2252. }while(FALSE);
  2253. EXIT_LOCK(ICB_LIST);
  2254. *pbCache = TRUE;
  2255. TraceLeave("AccessMcastIfTable");
  2256. return dwResult;
  2257. }
  2258. DWORD
  2259. AccessMcastStats(
  2260. DWORD dwQueryType,
  2261. DWORD dwInEntrySize,
  2262. PMIB_OPAQUE_QUERY pInEntry,
  2263. PDWORD pOutEntrySize,
  2264. PMIB_OPAQUE_INFO pOutEntry,
  2265. PBOOL pbCache
  2266. )
  2267. /*++
  2268. Routine Description
  2269. Retrieves the IP Multicast scalar information
  2270. Arguments
  2271. dwQueryType ACCESS_GET
  2272. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_GLOBAL)
  2273. Return Value
  2274. None
  2275. --*/
  2276. {
  2277. PMIB_IPMCAST_GLOBAL pMcastStats;
  2278. DWORD dwResult;
  2279. TraceEnter("AccessMcastStats");
  2280. if (dwQueryType isnot ACCESS_GET) {
  2281. TraceLeave("AccessMcastStats");
  2282. return ERROR_INVALID_PARAMETER;
  2283. }
  2284. pMcastStats = (PMIB_IPMCAST_GLOBAL)(pOutEntry->rgbyData);
  2285. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_GLOBAL))
  2286. {
  2287. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_GLOBAL);
  2288. TraceLeave("AccessMcastStats");
  2289. return ERROR_INSUFFICIENT_BUFFER;
  2290. }
  2291. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_GLOBAL);
  2292. pOutEntry->dwId = MCAST_GLOBAL;
  2293. dwResult = NO_ERROR;
  2294. // Retrieve statistics
  2295. pMcastStats->dwEnable = (g_hMcastDevice isnot NULL)? 1 : 2;
  2296. return dwResult;
  2297. }
  2298. DWORD
  2299. AccessMcastBoundary(
  2300. DWORD dwQueryType,
  2301. DWORD dwInEntrySize,
  2302. PMIB_OPAQUE_QUERY pInEntry,
  2303. PDWORD pOutEntrySize,
  2304. PMIB_OPAQUE_INFO pOutEntry,
  2305. PBOOL pbCache
  2306. )
  2307. /*++
  2308. Routine Description
  2309. Retrieves multicast boundary information
  2310. Arguments
  2311. dwQueryType ACCESS_GET
  2312. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_BOUNDARY)
  2313. Return Value
  2314. None
  2315. --*/
  2316. {
  2317. DWORD dwResult = NO_ERROR,dwNumIndices,dwIndex;
  2318. DWORD dwOutBufferSize, dwNumBoundaries;
  2319. MIB_IPMCAST_BOUNDARY imInBoundary;
  2320. TraceEnter("AccessMcastBoundary");
  2321. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2322. switch(dwQueryType)
  2323. {
  2324. case ACCESS_GET:
  2325. {
  2326. //
  2327. // The in index better be a good size
  2328. // The user must specify IfIndex, Group, GrpMask.
  2329. //
  2330. if(dwNumIndices < 3)
  2331. {
  2332. TraceLeave("AccessMcastBoundary");
  2333. return ERROR_INVALID_INDEX;
  2334. }
  2335. //
  2336. // We always get chunks of 1KB
  2337. //
  2338. if (*pOutEntrySize < MIB_BOUNDARY_BUFFER_SIZE)
  2339. {
  2340. *pOutEntrySize = MIB_BOUNDARY_BUFFER_SIZE;
  2341. return ERROR_INSUFFICIENT_BUFFER;
  2342. }
  2343. ZeroMemory(&imInBoundary, sizeof(imInBoundary));
  2344. imInBoundary.dwIfIndex = pInEntry->rgdwVarIndex[0];
  2345. imInBoundary.dwGroupAddress = pInEntry->rgdwVarIndex[1];
  2346. imInBoundary.dwGroupMask = pInEntry->rgdwVarIndex[2];
  2347. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2348. ? 0
  2349. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2350. dwResult = RmGetBoundary(&imInBoundary,
  2351. &dwOutBufferSize,
  2352. pOutEntry->rgbyData);
  2353. break;
  2354. }
  2355. case ACCESS_GET_FIRST:
  2356. {
  2357. #ifdef USE_BOUNDARY_TABLE
  2358. PMIB_IPMCAST_BOUNDARY_TABLE pBoundaryTable;
  2359. #endif
  2360. PMIB_IPMCAST_BOUNDARY pBoundary;
  2361. //
  2362. // We always get chunks of 1KB
  2363. //
  2364. if (*pOutEntrySize < MIB_BOUNDARY_BUFFER_SIZE)
  2365. {
  2366. *pOutEntrySize = MIB_BOUNDARY_BUFFER_SIZE;
  2367. return ERROR_INSUFFICIENT_BUFFER;
  2368. }
  2369. #ifdef USE_BOUNDARY_TABLE
  2370. //
  2371. // RM wants a flat buffer for boundaries. We however return a
  2372. // MIB_IPMCAST_BOUNDARY_TABLE to the user that starts (in the worst case)
  2373. // after MAX_MIB_OFFSET bytes of the input buffer
  2374. //
  2375. #define _MIN_SIZE \
  2376. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_IPMCAST_BOUNDARY_TABLE,table[0]))
  2377. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2378. #undef _MIN_SIZE
  2379. pBoundaryTable = (PMIB_IPMCAST_BOUNDARY_TABLE)pOutEntry->rgbyData;
  2380. pBoundaryTable->dwNumEntries = 0;
  2381. pBoundary = (PMIB_IPMCAST_BOUNDARY)(pBoundaryTable->table);
  2382. #else
  2383. pBoundary = (PMIB_IPMCAST_BOUNDARY)pOutEntry->rgbyData;
  2384. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2385. ? 0
  2386. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2387. #endif
  2388. dwNumBoundaries = 1; // get one
  2389. dwResult = RmGetFirstBoundary(&dwOutBufferSize,
  2390. (PBYTE)pBoundary,
  2391. &dwNumBoundaries);
  2392. //
  2393. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2394. //
  2395. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2396. #ifdef USE_BOUNDARY_TABLE
  2397. if((dwResult is ERROR_MORE_DATA) or
  2398. (dwResult is ERROR_NO_MORE_ITEMS))
  2399. {
  2400. pBoundaryTable->dwNumEntries = dwNumBoundaries;
  2401. dwResult = NO_ERROR;
  2402. }
  2403. #endif
  2404. break;
  2405. }
  2406. case ACCESS_GET_NEXT:
  2407. {
  2408. PMIB_IPMCAST_BOUNDARY pBoundary;
  2409. #ifdef USE_BOUNDARY_TABLE
  2410. PMIB_IPMCAST_BOUNDARY_TABLE pBoundaryTable;
  2411. #endif
  2412. //
  2413. // For this, too we always get chunks of 1K pages
  2414. //
  2415. if (*pOutEntrySize < MIB_BOUNDARY_BUFFER_SIZE)
  2416. {
  2417. *pOutEntrySize = MIB_BOUNDARY_BUFFER_SIZE;
  2418. return ERROR_INSUFFICIENT_BUFFER;
  2419. }
  2420. #ifdef USE_BOUNDARY_TABLE
  2421. #define _MIN_SIZE \
  2422. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_IPMCAST_BOUNDARY_TABLE,table[0]))
  2423. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2424. #undef _MIN_SIZE
  2425. pBoundaryTable = (PMIB_IPMCAST_BOUNDARY_TABLE)pOutEntry->rgbyData;
  2426. pBoundaryTable->dwNumEntries = 0;
  2427. pBoundary = (PMIB_IPMCAST_BOUNDARY)(pBoundaryTable->table);
  2428. #else
  2429. pBoundary = (PMIB_IPMCAST_BOUNDARY)pOutEntry->rgbyData;
  2430. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2431. ? 0
  2432. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2433. #endif
  2434. dwNumBoundaries = 1; // get one
  2435. //
  2436. // Set up the "first" boundary
  2437. //
  2438. ZeroMemory(&imInBoundary, sizeof(imInBoundary));
  2439. switch(dwNumIndices)
  2440. {
  2441. case 0:
  2442. {
  2443. break;
  2444. }
  2445. case 1:
  2446. {
  2447. imInBoundary.dwIfIndex = pInEntry->rgdwVarIndex[0];
  2448. break;
  2449. }
  2450. case 2:
  2451. {
  2452. imInBoundary.dwIfIndex = pInEntry->rgdwVarIndex[0];
  2453. imInBoundary.dwGroupAddress = pInEntry->rgdwVarIndex[1];
  2454. break;
  2455. }
  2456. default:
  2457. {
  2458. //
  2459. // 3 or more indices
  2460. //
  2461. imInBoundary.dwIfIndex = pInEntry->rgdwVarIndex[0];
  2462. imInBoundary.dwGroupAddress = pInEntry->rgdwVarIndex[1];
  2463. imInBoundary.dwGroupMask = pInEntry->rgdwVarIndex[2];
  2464. break;
  2465. }
  2466. }
  2467. dwResult = RmGetNextBoundary(&imInBoundary,
  2468. &dwOutBufferSize,
  2469. (PBYTE)pBoundary,
  2470. &dwNumBoundaries);
  2471. //
  2472. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2473. //
  2474. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2475. #ifdef USE_BOUNDARY_TABLE
  2476. if((dwResult is ERROR_MORE_DATA) or
  2477. (dwResult is ERROR_NO_MORE_ITEMS))
  2478. {
  2479. pBoundaryTable->dwNumEntries = dwNumBoundaries;
  2480. dwResult = NO_ERROR;
  2481. }
  2482. #endif
  2483. break;
  2484. }
  2485. case ACCESS_SET:
  2486. {
  2487. PMIB_IPMCAST_BOUNDARY pBound;
  2488. PICB picb;
  2489. //
  2490. // Validate the buffer size
  2491. //
  2492. if (*pOutEntrySize < sizeof(MIB_IPMCAST_BOUNDARY)) {
  2493. return ERROR_INVALID_INDEX;
  2494. }
  2495. //
  2496. // Make sure the ifIndex is a valid one
  2497. //
  2498. dwResult = LocateIfRow(dwQueryType,
  2499. 1,
  2500. (PDWORD)pOutEntry->rgbyData,
  2501. &picb,
  2502. FALSE);
  2503. if (dwResult isnot NO_ERROR)
  2504. return dwResult;
  2505. pBound = (PMIB_IPMCAST_BOUNDARY)(pOutEntry->rgbyData);
  2506. if (pBound->dwStatus == ROWSTATUS_CREATEANDGO) {
  2507. dwResult = SNMPAddBoundaryToInterface(pBound->dwIfIndex,
  2508. pBound->dwGroupAddress, pBound->dwGroupMask);
  2509. } else if (pBound->dwStatus == ROWSTATUS_DESTROY) {
  2510. dwResult =SNMPDeleteBoundaryFromInterface(pBound->dwIfIndex,
  2511. pBound->dwGroupAddress, pBound->dwGroupMask);
  2512. }
  2513. break;
  2514. }
  2515. case ACCESS_DELETE_ENTRY:
  2516. {
  2517. break;
  2518. }
  2519. case ACCESS_CREATE_ENTRY:
  2520. {
  2521. //
  2522. //
  2523. // This is the case where you have tried to create a boundary which
  2524. // matches an existing entry
  2525. //
  2526. dwResult = ERROR_ALREADY_EXISTS;
  2527. break;
  2528. }
  2529. default:
  2530. {
  2531. dwResult = ERROR_INVALID_PARAMETER;
  2532. break;
  2533. }
  2534. }
  2535. TraceLeave("AccessMcastBoundary");
  2536. return dwResult;
  2537. }
  2538. DWORD
  2539. AccessMcastScope(
  2540. DWORD dwQueryType,
  2541. DWORD dwInEntrySize,
  2542. PMIB_OPAQUE_QUERY pInEntry,
  2543. PDWORD pOutEntrySize,
  2544. PMIB_OPAQUE_INFO pOutEntry,
  2545. PBOOL pbCache
  2546. )
  2547. /*++
  2548. Routine Description
  2549. Retrieves multicast scope information
  2550. Arguments
  2551. dwQueryType ACCESS_GET
  2552. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPMCAST_SCOPE)
  2553. Return Value
  2554. None
  2555. --*/
  2556. {
  2557. DWORD dwResult = NO_ERROR,
  2558. dwNumIndices,dwIndex;
  2559. DWORD dwOutBufferSize, dwNumScopes;
  2560. MIB_IPMCAST_SCOPE imInScope;
  2561. TraceEnter("AccessMcastScope");
  2562. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2563. switch(dwQueryType)
  2564. {
  2565. case ACCESS_GET:
  2566. {
  2567. //
  2568. // The in index better be a good size
  2569. // The user must specify Group, GrpMask.
  2570. //
  2571. if(dwNumIndices < 2)
  2572. {
  2573. TraceLeave("AccessMcastScope");
  2574. return ERROR_INVALID_INDEX;
  2575. }
  2576. //
  2577. // We always get chunks of 1KB
  2578. //
  2579. if (*pOutEntrySize < MIB_SCOPE_BUFFER_SIZE)
  2580. {
  2581. *pOutEntrySize = MIB_SCOPE_BUFFER_SIZE;
  2582. return ERROR_INSUFFICIENT_BUFFER;
  2583. }
  2584. ZeroMemory(&imInScope, sizeof(imInScope));
  2585. imInScope.dwGroupAddress = pInEntry->rgdwVarIndex[0];
  2586. imInScope.dwGroupMask = pInEntry->rgdwVarIndex[1];
  2587. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2588. ? 0
  2589. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2590. dwResult = RmGetScope(&imInScope,
  2591. &dwOutBufferSize,
  2592. pOutEntry->rgbyData);
  2593. break;
  2594. }
  2595. case ACCESS_GET_FIRST:
  2596. {
  2597. #ifdef USE_SCOPE_TABLE
  2598. PMIB_IPMCAST_SCOPE_TABLE pScopeTable;
  2599. #endif
  2600. PMIB_IPMCAST_SCOPE pScope;
  2601. //
  2602. // We always get chunks of 1KB
  2603. //
  2604. if (*pOutEntrySize < MIB_SCOPE_BUFFER_SIZE)
  2605. {
  2606. *pOutEntrySize = MIB_SCOPE_BUFFER_SIZE;
  2607. return ERROR_INSUFFICIENT_BUFFER;
  2608. }
  2609. #ifdef USE_SCOPE_TABLE
  2610. //
  2611. // RM wants a flat buffer for scopes. We however return a
  2612. // MIB_IPMCAST_SCOPE_TABLE to the user that starts (in the worst case)
  2613. // after MAX_MIB_OFFSET bytes of the input buffer
  2614. //
  2615. #define _MIN_SIZE \
  2616. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_IPMCAST_SCOPE_TABLE,table[0]))
  2617. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2618. #undef _MIN_SIZE
  2619. pScopeTable = (PMIB_IPMCAST_SCOPE_TABLE)pOutEntry->rgbyData;
  2620. pScopeTable->dwNumEntries = 0;
  2621. pScope = (PMIB_IPMCAST_SCOPE)(pScopeTable->table);
  2622. #else
  2623. pScope = (PMIB_IPMCAST_SCOPE)pOutEntry->rgbyData;
  2624. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2625. ? 0
  2626. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2627. #endif
  2628. dwNumScopes = 1; // get one
  2629. dwResult = RmGetFirstScope(&dwOutBufferSize,
  2630. (PBYTE)pScope,
  2631. &dwNumScopes);
  2632. //
  2633. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2634. //
  2635. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2636. #ifdef USE_SCOPE_TABLE
  2637. if((dwResult is ERROR_MORE_DATA) or
  2638. (dwResult is ERROR_NO_MORE_ITEMS))
  2639. {
  2640. pScopeTable->dwNumEntries = dwNumScopes;
  2641. dwResult = NO_ERROR;
  2642. }
  2643. #endif
  2644. break;
  2645. }
  2646. case ACCESS_GET_NEXT:
  2647. {
  2648. PMIB_IPMCAST_SCOPE pScope;
  2649. #ifdef USE_SCOPE_TABLE
  2650. PMIB_IPMCAST_SCOPE_TABLE pScopeTable;
  2651. #endif
  2652. //
  2653. // For this, too we always get chunks of 1K pages
  2654. //
  2655. if (*pOutEntrySize < MIB_SCOPE_BUFFER_SIZE)
  2656. {
  2657. *pOutEntrySize = MIB_SCOPE_BUFFER_SIZE;
  2658. return ERROR_INSUFFICIENT_BUFFER;
  2659. }
  2660. #ifdef USE_SCOPE_TABLE
  2661. #define _MIN_SIZE \
  2662. (MAX_MIB_OFFSET + FIELD_OFFSET(MIB_IPMCAST_SCOPE_TABLE,table[0]))
  2663. dwOutBufferSize = *pOutEntrySize - _MIN_SIZE;
  2664. #undef _MIN_SIZE
  2665. pScopeTable = (PMIB_IPMCAST_Scope_TABLE)pOutEntry->rgbyData;
  2666. pScopeTable->dwNumEntries = 0;
  2667. pScope = (PMIB_IPMCAST_SCOPE)(pScopeTable->table);
  2668. #else
  2669. pScope = (PMIB_IPMCAST_SCOPE)pOutEntry->rgbyData;
  2670. dwOutBufferSize = (*pOutEntrySize < MAX_MIB_OFFSET)
  2671. ? 0
  2672. : (*pOutEntrySize - MAX_MIB_OFFSET);
  2673. #endif
  2674. dwNumScopes = 1; // get one
  2675. //
  2676. // Set up the "first" scope
  2677. //
  2678. ZeroMemory(&imInScope, sizeof(imInScope));
  2679. switch(dwNumIndices)
  2680. {
  2681. case 0:
  2682. {
  2683. break;
  2684. }
  2685. case 1:
  2686. {
  2687. imInScope.dwGroupAddress = pInEntry->rgdwVarIndex[0];
  2688. break;
  2689. }
  2690. default:
  2691. {
  2692. //
  2693. // 2 or more indices
  2694. //
  2695. imInScope.dwGroupAddress = pInEntry->rgdwVarIndex[0];
  2696. imInScope.dwGroupMask = pInEntry->rgdwVarIndex[1];
  2697. break;
  2698. }
  2699. }
  2700. dwResult = RmGetNextScope(&imInScope,
  2701. &dwOutBufferSize,
  2702. (PBYTE)pScope,
  2703. &dwNumScopes);
  2704. //
  2705. // We should NEVER get back ERROR_INSUFFICIENT_BUFFER
  2706. //
  2707. IpRtAssert(dwResult isnot ERROR_INSUFFICIENT_BUFFER);
  2708. #ifdef USE_SCOPE_TABLE
  2709. if((dwResult is ERROR_MORE_DATA) or
  2710. (dwResult is ERROR_NO_MORE_ITEMS))
  2711. {
  2712. pScopeTable->dwNumEntries = dwNumScopes;
  2713. dwResult = NO_ERROR;
  2714. }
  2715. #endif
  2716. break;
  2717. }
  2718. case ACCESS_SET:
  2719. {
  2720. PMIB_IPMCAST_SCOPE pScope;
  2721. //
  2722. // Validate the buffer size
  2723. //
  2724. if (*pOutEntrySize < sizeof(MIB_IPMCAST_SCOPE)) {
  2725. return ERROR_INVALID_INDEX;
  2726. }
  2727. pScope = (PMIB_IPMCAST_SCOPE)(pOutEntry->rgbyData);
  2728. if ( !pScope->dwStatus )
  2729. {
  2730. dwResult = SNMPSetScope( pScope->dwGroupAddress,
  2731. pScope->dwGroupMask,
  2732. pScope->snNameBuffer
  2733. );
  2734. } else if (pScope->dwStatus == ROWSTATUS_CREATEANDGO)
  2735. {
  2736. PSCOPE_ENTRY pNew;
  2737. dwResult = SNMPAddScope( pScope->dwGroupAddress,
  2738. pScope->dwGroupMask,
  2739. pScope->snNameBuffer,
  2740. &pNew
  2741. );
  2742. }
  2743. else if (pScope->dwStatus == ROWSTATUS_DESTROY)
  2744. {
  2745. dwResult = SNMPDeleteScope( pScope->dwGroupAddress,
  2746. pScope->dwGroupMask
  2747. );
  2748. }
  2749. else
  2750. {
  2751. return ERROR_INVALID_PARAMETER;
  2752. }
  2753. break;
  2754. }
  2755. case ACCESS_DELETE_ENTRY:
  2756. {
  2757. break;
  2758. }
  2759. case ACCESS_CREATE_ENTRY:
  2760. {
  2761. //
  2762. //
  2763. // This is the case where you have tried to create a scope which
  2764. // matches an existing entry
  2765. //
  2766. dwResult = ERROR_ALREADY_EXISTS;
  2767. break;
  2768. }
  2769. }
  2770. TraceLeave("AccessMcastScope");
  2771. return dwResult;
  2772. }
  2773. DWORD
  2774. AccessBestIf(
  2775. DWORD dwQueryType,
  2776. DWORD dwInEntrySize,
  2777. PMIB_OPAQUE_QUERY pInEntry,
  2778. PDWORD pOutEntrySize,
  2779. PMIB_OPAQUE_INFO pOutEntry,
  2780. PBOOL pbCache
  2781. )
  2782. /*++
  2783. Routine Description
  2784. This function services the BEST_IF var id
  2785. Locks
  2786. Takes the ICB_LIST as READER to map from adapter to interface index
  2787. Arguments
  2788. dwQueryType Can only be ACCESS_GET
  2789. pInEntry Destination address filled in the rgdwVarIndex field.
  2790. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_BEST_IF)
  2791. Return Value
  2792. None
  2793. --*/
  2794. {
  2795. DWORD dwNumIndices, dwResult;
  2796. DWORD dwIfIndex;
  2797. PICB pIcb;
  2798. PMIB_BEST_IF pBestIf;
  2799. TraceEnter("AccessBestIf");
  2800. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2801. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_BEST_IF))
  2802. {
  2803. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_BEST_IF);
  2804. TraceLeave("AccessBestIf");
  2805. return ERROR_INSUFFICIENT_BUFFER;
  2806. }
  2807. if((dwNumIndices < 1) or
  2808. (dwQueryType isnot ACCESS_GET))
  2809. {
  2810. TraceLeave("AccessBestIf");
  2811. return ERROR_INVALID_PARAMETER;
  2812. }
  2813. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_BEST_IF);
  2814. dwResult = GetBestInterfaceFromStack(pInEntry->rgdwVarIndex[0],
  2815. &dwIfIndex);
  2816. if(dwResult is NO_ERROR)
  2817. {
  2818. #if DBG
  2819. ENTER_READER(ICB_LIST);
  2820. pIcb = InterfaceLookupByIfIndex(dwIfIndex);
  2821. if(pIcb is NULL)
  2822. {
  2823. Trace2(ERR,
  2824. "AccessBestIf: Couldnt find i/f for Index %d for dest %d.%d.%d.%d\n",
  2825. dwIfIndex,
  2826. PRINT_IPADDR(pInEntry->rgdwVarIndex[0]));
  2827. }
  2828. EXIT_LOCK(ICB_LIST);
  2829. #endif
  2830. pBestIf = (PMIB_BEST_IF)(pOutEntry->rgbyData);
  2831. pOutEntry->dwId = BEST_IF;
  2832. pBestIf->dwDestAddr = pInEntry->rgdwVarIndex[0];
  2833. pBestIf->dwIfIndex = dwIfIndex;
  2834. }
  2835. TraceLeave("AccessBestIf");
  2836. return dwResult;
  2837. }
  2838. DWORD
  2839. AccessBestRoute(
  2840. DWORD dwQueryType,
  2841. DWORD dwInEntrySize,
  2842. PMIB_OPAQUE_QUERY pInEntry,
  2843. PDWORD pOutEntrySize,
  2844. PMIB_OPAQUE_INFO pOutEntry,
  2845. PBOOL pbCache
  2846. )
  2847. /*++
  2848. Routine Description
  2849. This function services the BEST_IF var id
  2850. Locks
  2851. Takes the ICB_LIST as READER to map from adapter to interface index
  2852. Arguments
  2853. dwQueryType Can only be ACCESS_GET
  2854. pInEntry Destination address filled in the rgdwVarIndex field.
  2855. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_BEST_IF)
  2856. Return Value
  2857. None
  2858. --*/
  2859. {
  2860. DWORD dwNumIndices, dwResult;
  2861. PICB pIcb;
  2862. RTM_NET_ADDRESS rnaDest;
  2863. RTM_DEST_INFO rdiInfo;
  2864. PRTM_ROUTE_INFO prriInfo;
  2865. RTM_NEXTHOP_INFO rniInfo;
  2866. RTM_ENTITY_INFO reiInfo;
  2867. PINTERFACE_ROUTE_INFO pRoute;
  2868. TraceEnter("AccessBestRoute");
  2869. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  2870. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(INTERFACE_ROUTE_INFO))
  2871. {
  2872. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(INTERFACE_ROUTE_INFO);
  2873. TraceLeave("AccessBestRoute");
  2874. return ERROR_INSUFFICIENT_BUFFER;
  2875. }
  2876. if((dwNumIndices < 2) or
  2877. (dwQueryType isnot ACCESS_GET))
  2878. {
  2879. TraceLeave("AccessBestRoute");
  2880. return ERROR_INVALID_PARAMETER;
  2881. }
  2882. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(INTERFACE_ROUTE_INFO);
  2883. pRoute = (PINTERFACE_ROUTE_INFO)(pOutEntry->rgbyData);
  2884. // Get the best route from RTM instead of the stack (chaitk)
  2885. // dwResult = GetBestRouteFromStack(pInEntry->rgdwVarIndex[0],
  2886. // pInEntry->rgdwVarIndex[0],
  2887. // pRoute);
  2888. RTM_IPV4_MAKE_NET_ADDRESS(&rnaDest, pInEntry->rgdwVarIndex[0], 32);
  2889. dwResult = RtmGetMostSpecificDestination(g_hLocalRoute,
  2890. &rnaDest,
  2891. RTM_BEST_PROTOCOL,
  2892. RTM_VIEW_MASK_UCAST,
  2893. &rdiInfo);
  2894. if(dwResult is NO_ERROR)
  2895. {
  2896. ASSERT(rdiInfo.ViewInfo[0].ViewId is RTM_VIEW_ID_UCAST);
  2897. prriInfo = HeapAlloc(
  2898. IPRouterHeap,
  2899. 0,
  2900. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  2901. );
  2902. if ( prriInfo != NULL)
  2903. {
  2904. dwResult = RtmGetRouteInfo(g_hLocalRoute,
  2905. rdiInfo.ViewInfo[0].Route,
  2906. prriInfo,
  2907. NULL);
  2908. if (dwResult is NO_ERROR)
  2909. {
  2910. dwResult = RtmGetEntityInfo(g_hLocalRoute,
  2911. prriInfo->RouteOwner,
  2912. &reiInfo);
  2913. if (dwResult is NO_ERROR)
  2914. {
  2915. // We are working on the first nexthop only
  2916. ASSERT(prriInfo->NextHopsList.NumNextHops > 0);
  2917. dwResult = RtmGetNextHopInfo(g_hLocalRoute,
  2918. prriInfo->NextHopsList.NextHops[0],
  2919. &rniInfo);
  2920. if (dwResult is NO_ERROR)
  2921. {
  2922. ConvertRtmToRouteInfo(reiInfo.EntityId.EntityProtocolId,
  2923. &rdiInfo.DestAddress,
  2924. prriInfo,
  2925. &rniInfo,
  2926. pRoute);
  2927. RtmReleaseNextHopInfo(g_hLocalRoute, &rniInfo);
  2928. }
  2929. }
  2930. RtmReleaseRouteInfo(g_hLocalRoute, prriInfo);
  2931. }
  2932. HeapFree(IPRouterHeap, 0, prriInfo);
  2933. }
  2934. else
  2935. {
  2936. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  2937. }
  2938. RtmReleaseDestInfo(g_hLocalRoute, &rdiInfo);
  2939. }
  2940. if(dwResult is NO_ERROR)
  2941. {
  2942. #if DBG
  2943. ENTER_READER(ICB_LIST);
  2944. pIcb = InterfaceLookupByIfIndex(pRoute->dwRtInfoIfIndex);
  2945. if(pIcb is NULL)
  2946. {
  2947. Trace2(ERR,
  2948. "AccessBestRoute: Couldnt find i/f for index %d for dest %d.%d.%d.%d\n",
  2949. pRoute->dwRtInfoIfIndex,
  2950. PRINT_IPADDR(pInEntry->rgdwVarIndex[0]));
  2951. }
  2952. EXIT_LOCK(ICB_LIST);
  2953. #endif // DBG
  2954. //
  2955. // Not need to map since the indices are the same
  2956. //
  2957. // pRoute->dwRtInfoIfIndex = dwIfIndex;
  2958. }
  2959. TraceLeave("AccessBestRoute");
  2960. return dwResult;
  2961. }
  2962. DWORD
  2963. AccessProxyArp(
  2964. DWORD dwQueryType,
  2965. DWORD dwInEntrySize,
  2966. PMIB_OPAQUE_QUERY pInEntry,
  2967. PDWORD pOutEntrySize,
  2968. PMIB_OPAQUE_INFO pOutEntry,
  2969. PBOOL pbCache
  2970. )
  2971. /*++
  2972. Routine Description
  2973. This function services the PROXY_ARP id
  2974. Locks
  2975. Takes the ICB_LIST as READER to map from interface to adapter index
  2976. Arguments
  2977. dwQueryType Can only be ACCESS_CREATE_ENTRY or ACCESS_DELETE_ENTRY
  2978. pInEntry Destination address filled in the rgdwVarIndex field.
  2979. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_BEST_IF)
  2980. Return Value
  2981. None
  2982. --*/
  2983. {
  2984. MIB_PROXYARP mpEntry;
  2985. PMIB_PROXYARP pProxyEntry;
  2986. PADAPTER_INFO pBinding;
  2987. BOOL bAdd;
  2988. DWORD dwResult;
  2989. TraceEnter("AccessProxyArp");
  2990. if(dwQueryType is ACCESS_DELETE_ENTRY)
  2991. {
  2992. mpEntry.dwAddress = pInEntry->rgdwVarIndex[0];
  2993. mpEntry.dwMask = pInEntry->rgdwVarIndex[1];
  2994. mpEntry.dwIfIndex = pInEntry->rgdwVarIndex[2];
  2995. pProxyEntry = &mpEntry;
  2996. bAdd = FALSE;
  2997. }
  2998. else
  2999. {
  3000. if(dwQueryType is ACCESS_CREATE_ENTRY)
  3001. {
  3002. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_PROXYARP))
  3003. {
  3004. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_PROXYARP);
  3005. TraceLeave("AccessProxyArp");
  3006. return ERROR_INSUFFICIENT_BUFFER;
  3007. }
  3008. pProxyEntry = (PMIB_PROXYARP)(pOutEntry->rgbyData);
  3009. bAdd = TRUE;
  3010. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_PROXYARP);
  3011. pOutEntry->dwId = PROXY_ARP;
  3012. }
  3013. else
  3014. {
  3015. TraceLeave("AccessProxyArp");
  3016. return ERROR_INVALID_PARAMETER;
  3017. }
  3018. }
  3019. ENTER_READER(BINDING_LIST);
  3020. pBinding = GetInterfaceBinding(pProxyEntry->dwIfIndex);
  3021. if(pBinding is NULL)
  3022. {
  3023. Trace1(ERR,
  3024. "AccessProxyArp: Cant find binding for i/f %d",
  3025. pProxyEntry->dwIfIndex);
  3026. EXIT_LOCK(BINDING_LIST);
  3027. TraceLeave("AccessProxyArp");
  3028. return ERROR_INVALID_INDEX;
  3029. }
  3030. if(!pBinding->bBound)
  3031. {
  3032. Trace1(ERR,
  3033. "AccessProxyArp: I/f %d is not bound",
  3034. pProxyEntry->dwIfIndex);
  3035. EXIT_LOCK(BINDING_LIST);
  3036. TraceLeave("AccessProxyArp");
  3037. return ERROR_NOT_READY;
  3038. }
  3039. EXIT_LOCK(BINDING_LIST);
  3040. dwResult = SetProxyArpEntryToStack(pProxyEntry->dwAddress,
  3041. pProxyEntry->dwMask,
  3042. pProxyEntry->dwIfIndex,
  3043. bAdd,
  3044. TRUE);
  3045. TraceLeave("AccessProxyArp");
  3046. return dwResult;
  3047. }
  3048. DWORD
  3049. AccessIfStatus(
  3050. DWORD dwQueryType,
  3051. DWORD dwInEntrySize,
  3052. PMIB_OPAQUE_QUERY pInEntry,
  3053. PDWORD pOutEntrySize,
  3054. PMIB_OPAQUE_INFO pOutEntry,
  3055. PBOOL pbCache
  3056. )
  3057. /*++
  3058. Routine Description
  3059. This function services the BEST_IF var id
  3060. Locks
  3061. Takes the ICB_LIST as READER to map from adapter to interface index
  3062. Arguments
  3063. dwQueryType Can be ACCESS_GET, ACCESS_GET_FIRST or ACCESS_GET_NEXT
  3064. pInEntry Destination address filled in the rgdwVarIndex field.
  3065. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_BEST_IF)
  3066. Return Value
  3067. None
  3068. --*/
  3069. {
  3070. DWORD dwNumIndices, dwResult;
  3071. DWORD dwIfIndex;
  3072. PICB picb;
  3073. PMIB_IFSTATUS pIfStatus;
  3074. SYSTEMTIME stSysTime;
  3075. ULARGE_INTEGER uliTime;
  3076. TraceEnter("AccessIfStatus");
  3077. if(dwQueryType > ACCESS_GET_NEXT)
  3078. {
  3079. TraceLeave("AccessIfStatus");
  3080. return ERROR_INVALID_PARAMETER;
  3081. }
  3082. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3083. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IFSTATUS))
  3084. {
  3085. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFSTATUS);
  3086. TraceLeave("AccessIfStatus");
  3087. return ERROR_INSUFFICIENT_BUFFER;
  3088. }
  3089. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IFSTATUS);
  3090. pIfStatus = (PMIB_IFSTATUS)(pOutEntry->rgbyData);
  3091. ENTER_READER(ICB_LIST);
  3092. dwResult = LocateIfRow(dwQueryType,
  3093. dwNumIndices,
  3094. pInEntry->rgdwVarIndex,
  3095. &picb,
  3096. FALSE);
  3097. if(dwResult is NO_ERROR)
  3098. {
  3099. pIfStatus->dwIfIndex = picb->dwIfIndex;
  3100. pIfStatus->dwAdminStatus = picb->dwAdminState;
  3101. pIfStatus->dwOperationalStatus = picb->dwOperationalState;
  3102. pIfStatus->bMHbeatActive = picb->mhcHeartbeatInfo.bActive;
  3103. if(pIfStatus->bMHbeatActive)
  3104. {
  3105. GetSystemTime(&stSysTime);
  3106. SystemTimeToFileTime(&stSysTime,
  3107. (PFILETIME)&uliTime);
  3108. //
  3109. // Its alive if the currenttime - lastheard < deadinterval
  3110. //
  3111. pIfStatus->bMHbeatAlive =
  3112. (uliTime.QuadPart - picb->mhcHeartbeatInfo.ullLastHeard < picb->mhcHeartbeatInfo.ullDeadInterval);
  3113. }
  3114. EXIT_LOCK(ICB_LIST);
  3115. }
  3116. TraceLeave("AccessIfStatus");
  3117. return dwResult;
  3118. }
  3119. DWORD
  3120. AccessSetRouteState(
  3121. DWORD dwQueryType,
  3122. DWORD dwInEntrySize,
  3123. PMIB_OPAQUE_QUERY pInEntry,
  3124. PDWORD pOutEntrySize,
  3125. PMIB_OPAQUE_INFO pOutEntry,
  3126. PBOOL pbCache
  3127. )
  3128. /*++
  3129. Routine Description
  3130. This function services ROUTE_STATE id
  3131. Locks
  3132. Takes the g_csFwdState lock
  3133. Arguments
  3134. dwQueryType Can be ACCESS_GET only
  3135. pInEntry Destination address filled in the rgdwVarIndex field.
  3136. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_ROUTESTATE)
  3137. Return Value
  3138. None
  3139. --*/
  3140. {
  3141. DWORD dwResult;
  3142. PMIB_ROUTESTATE pState;
  3143. if(dwQueryType isnot ACCESS_GET)
  3144. {
  3145. TraceLeave("AccessSetRouteState");
  3146. return ERROR_INVALID_PARAMETER;
  3147. }
  3148. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_ROUTESTATE))
  3149. {
  3150. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_ROUTESTATE);
  3151. TraceLeave("AccessSetRouteState");
  3152. return ERROR_INSUFFICIENT_BUFFER;
  3153. }
  3154. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_ROUTESTATE);
  3155. pOutEntry->dwId = ROUTE_STATE;
  3156. pState = (PMIB_ROUTESTATE)(pOutEntry->rgbyData);
  3157. EnterCriticalSection(&g_csFwdState);
  3158. pState->bRoutesSetToStack = g_bSetRoutesToStack;
  3159. LeaveCriticalSection(&g_csFwdState);
  3160. TraceLeave("AccessSetRouteState");
  3161. return NO_ERROR;
  3162. }
  3163. DWORD
  3164. AddDestinationRows(
  3165. IN PRTM_DEST_INFO pRdi,
  3166. IN RTM_VIEW_SET dwViews,
  3167. OUT DWORD *pdwCount,
  3168. IN DWORD dwSpaceCount,
  3169. OUT PMIB_IPDESTTABLE pDestTable
  3170. )
  3171. {
  3172. DWORD dwFinalResult, dwResult, i, j, k;
  3173. PRTM_ROUTE_INFO pri;
  3174. RTM_NEXTHOP_INFO nhi;
  3175. PMIB_IPDESTROW pRow;
  3176. pri = HeapAlloc(
  3177. IPRouterHeap,
  3178. 0,
  3179. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  3180. );
  3181. if ( pri == NULL)
  3182. {
  3183. return ERROR_NOT_ENOUGH_MEMORY;
  3184. }
  3185. // XXX how do I walk all next hops which get added to the stack???
  3186. // For now, let's assume only one route per view.
  3187. dwFinalResult = NO_ERROR;
  3188. for (i = 0; i < pRdi->NumberOfViews; i++)
  3189. {
  3190. if (pRdi->ViewInfo[i].Route == NULL)
  3191. {
  3192. continue;
  3193. }
  3194. // Skip if we have seen this route already
  3195. for (k = 0; k < i; k++)
  3196. {
  3197. if (pRdi->ViewInfo[k].Route == pRdi->ViewInfo[i].Route)
  3198. {
  3199. break;
  3200. }
  3201. }
  3202. if (k < i)
  3203. {
  3204. continue;
  3205. }
  3206. dwResult = RtmGetRouteInfo( g_hLocalRoute,
  3207. pRdi->ViewInfo[i].Route,
  3208. pri,
  3209. NULL );
  3210. if (dwResult isnot NO_ERROR)
  3211. {
  3212. dwFinalResult = dwResult;
  3213. continue;
  3214. }
  3215. *pdwCount += pri->NextHopsList.NumNextHops;
  3216. if (dwSpaceCount >= *pdwCount)
  3217. {
  3218. ULARGE_INTEGER now, then;
  3219. ULONG age;
  3220. RTM_ENTITY_INFO rei;
  3221. RtmGetEntityInfo( g_hLocalRoute,
  3222. pri->RouteOwner,
  3223. &rei );
  3224. GetSystemTimeAsFileTime( (LPFILETIME)&now );
  3225. //
  3226. // Explicit copy reqd as '&pRdi->LastChanged'
  3227. // might not be 64-bit aligned (its FILETIME)
  3228. //
  3229. (*(FILETIME *)&then) = *(&pRdi->LastChanged);
  3230. age = (ULONG)((now.QuadPart - then.QuadPart) / 10000000);
  3231. for (j=0; j<pri->NextHopsList.NumNextHops; j++)
  3232. {
  3233. if (RtmGetNextHopInfo( g_hLocalRoute,
  3234. pri->NextHopsList.NextHops[j],
  3235. &nhi ) is NO_ERROR )
  3236. {
  3237. pRow = &pDestTable->table[pDestTable->dwNumEntries++];
  3238. RTM_IPV4_GET_ADDR_AND_MASK( pRow->dwForwardDest,
  3239. pRow->dwForwardMask,
  3240. (&pRdi->DestAddress) );
  3241. pRow->dwForwardPolicy = 0;
  3242. pRow->dwForwardNextHop
  3243. = *((ULONG*)nhi.NextHopAddress.AddrBits);
  3244. pRow->dwForwardIfIndex = nhi.InterfaceIndex;
  3245. pRow->dwForwardType
  3246. = (pri->RouteOwner == g_hLocalRoute)?3:4;
  3247. pRow->dwForwardProto
  3248. = PROTO_FROM_PROTO_ID(rei.EntityId.EntityProtocolId);
  3249. pRow->dwForwardAge = age;
  3250. pRow->dwForwardNextHopAS= 0; // XXX
  3251. pRow->dwForwardPreference = pri->PrefInfo.Preference;
  3252. pRow->dwForwardMetric1 = pri->PrefInfo.Metric;
  3253. pRow->dwForwardMetric2 = 0;
  3254. pRow->dwForwardMetric3 = 0;
  3255. pRow->dwForwardMetric4 = 0;
  3256. pRow->dwForwardMetric5 = 0;
  3257. pRow->dwForwardViewSet = pri->BelongsToViews;
  3258. RtmReleaseNextHopInfo( g_hLocalRoute, &nhi );
  3259. }
  3260. }
  3261. }
  3262. RtmReleaseRouteInfo( g_hLocalRoute, pri );
  3263. }
  3264. HeapFree(IPRouterHeap, 0, pri);
  3265. return dwFinalResult;
  3266. }
  3267. DWORD
  3268. AccessDestMatching(
  3269. DWORD dwQueryType,
  3270. DWORD dwInEntrySize,
  3271. PMIB_OPAQUE_QUERY pInEntry,
  3272. PDWORD pOutEntrySize,
  3273. PMIB_OPAQUE_INFO pOutEntry,
  3274. PBOOL pbCache
  3275. )
  3276. /*++
  3277. Routine Description
  3278. Retrieves all destinations matching a given criteria
  3279. Locks
  3280. XXX
  3281. Arguments
  3282. dwQueryType ACCESS_GET
  3283. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPDESTTABLE)
  3284. Return Value
  3285. NO_ERROR
  3286. --*/
  3287. {
  3288. PMIB_IPDESTTABLE pDestTable;
  3289. DWORD count, i;
  3290. DWORD dwNumDests, dwResult, dwNumIndices, dwSpaceCount;
  3291. RTM_NET_ADDRESS naDest;
  3292. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3293. PRTM_DEST_INFO prdi;
  3294. TraceEnter("AccessDestMatching");
  3295. count = dwSpaceCount = 0;
  3296. pDestTable = NULL;
  3297. if (*pOutEntrySize > dwOffset)
  3298. {
  3299. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3300. / sizeof(MIB_IPDESTROW);
  3301. pDestTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3302. pDestTable->dwNumEntries = 0;
  3303. }
  3304. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3305. if ((dwNumIndices < 4) or
  3306. (dwQueryType isnot ACCESS_GET))
  3307. {
  3308. TraceLeave("AccessDestMatching");
  3309. return ERROR_INVALID_PARAMETER;
  3310. }
  3311. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3312. pInEntry->rgdwVarIndex[0], // Addr
  3313. pInEntry->rgdwVarIndex[1]); // Mask
  3314. prdi = HeapAlloc(
  3315. IPRouterHeap,
  3316. 0,
  3317. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3318. );
  3319. if (prdi != NULL)
  3320. {
  3321. dwResult = RtmGetExactMatchDestination( g_hLocalRoute,
  3322. &naDest,
  3323. pInEntry->rgdwVarIndex[3], // Proto
  3324. pInEntry->rgdwVarIndex[2], // Views
  3325. prdi );
  3326. if (dwResult is ERROR_NOT_FOUND)
  3327. {
  3328. dwResult = NO_ERROR;
  3329. }
  3330. else
  3331. if (dwResult is NO_ERROR)
  3332. {
  3333. AddDestinationRows( prdi,
  3334. pInEntry->rgdwVarIndex[2],
  3335. &count,
  3336. dwSpaceCount,
  3337. pDestTable );
  3338. RtmReleaseDestInfo( g_hLocalRoute, prdi );
  3339. }
  3340. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3341. if (dwSpaceCount < count)
  3342. {
  3343. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3344. }
  3345. HeapFree(IPRouterHeap, 0, prdi);
  3346. }
  3347. else
  3348. {
  3349. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  3350. }
  3351. TraceLeave("AccessDestMatching");
  3352. return dwResult;
  3353. }
  3354. DWORD
  3355. AccessDestShorter(
  3356. DWORD dwQueryType,
  3357. DWORD dwInEntrySize,
  3358. PMIB_OPAQUE_QUERY pInEntry,
  3359. PDWORD pOutEntrySize,
  3360. PMIB_OPAQUE_INFO pOutEntry,
  3361. PBOOL pbCache
  3362. )
  3363. {
  3364. PMIB_IPDESTTABLE pDestTable;
  3365. DWORD count, i;
  3366. DWORD dwNumDests, dwResult, dwNumIndices, dwSpaceCount;
  3367. RTM_NET_ADDRESS naDest;
  3368. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3369. PRTM_DEST_INFO prdi1, prdi2;
  3370. TraceEnter("AccessDestShorter");
  3371. count = dwSpaceCount = 0;
  3372. pDestTable = NULL;
  3373. if (*pOutEntrySize > dwOffset)
  3374. {
  3375. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3376. / sizeof(MIB_IPDESTROW);
  3377. pDestTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3378. pDestTable->dwNumEntries = 0;
  3379. }
  3380. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3381. if ((dwNumIndices < 4) or
  3382. (dwQueryType isnot ACCESS_GET))
  3383. {
  3384. TraceLeave("AccessDestShorter");
  3385. return ERROR_INVALID_PARAMETER;
  3386. }
  3387. prdi1 = HeapAlloc(
  3388. IPRouterHeap,
  3389. 0,
  3390. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3391. );
  3392. if ( prdi1 == NULL)
  3393. {
  3394. TraceLeave("AccessDestShorter");
  3395. return ERROR_NOT_ENOUGH_MEMORY;
  3396. }
  3397. prdi2 = HeapAlloc(
  3398. IPRouterHeap,
  3399. 0,
  3400. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3401. );
  3402. if ( prdi2 == NULL)
  3403. {
  3404. TraceLeave("AccessDestShorter");
  3405. HeapFree(IPRouterHeap, 0, prdi1);
  3406. return ERROR_NOT_ENOUGH_MEMORY;
  3407. }
  3408. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3409. pInEntry->rgdwVarIndex[0], // Addr
  3410. pInEntry->rgdwVarIndex[1]); // Mask
  3411. dwResult = RtmGetMostSpecificDestination( g_hLocalRoute,
  3412. &naDest,
  3413. pInEntry->rgdwVarIndex[3],//Proto
  3414. pInEntry->rgdwVarIndex[2],//Views
  3415. prdi1 );
  3416. while (dwResult is NO_ERROR)
  3417. {
  3418. AddDestinationRows( prdi1,
  3419. pInEntry->rgdwVarIndex[2],
  3420. &count,
  3421. dwSpaceCount,
  3422. pDestTable );
  3423. dwResult = RtmGetLessSpecificDestination( g_hLocalRoute,
  3424. prdi1->DestHandle,
  3425. pInEntry->rgdwVarIndex[3],
  3426. pInEntry->rgdwVarIndex[2],
  3427. prdi2);
  3428. RtmReleaseDestInfo( g_hLocalRoute, prdi1 );
  3429. if (dwResult != NO_ERROR)
  3430. {
  3431. break;
  3432. }
  3433. AddDestinationRows( prdi2,
  3434. pInEntry->rgdwVarIndex[2],
  3435. &count,
  3436. dwSpaceCount,
  3437. pDestTable );
  3438. dwResult = RtmGetLessSpecificDestination( g_hLocalRoute,
  3439. prdi2->DestHandle,
  3440. pInEntry->rgdwVarIndex[3],
  3441. pInEntry->rgdwVarIndex[2],
  3442. prdi1);
  3443. RtmReleaseDestInfo( g_hLocalRoute, prdi2 );
  3444. if (dwResult != NO_ERROR)
  3445. {
  3446. break;
  3447. }
  3448. }
  3449. if (dwResult is ERROR_NOT_FOUND)
  3450. {
  3451. dwResult = NO_ERROR;
  3452. }
  3453. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3454. if (dwSpaceCount < count)
  3455. {
  3456. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3457. }
  3458. HeapFree(IPRouterHeap, 0, prdi1);
  3459. HeapFree(IPRouterHeap, 0, prdi2);
  3460. TraceLeave("AccessDestShorter");
  3461. return dwResult;
  3462. }
  3463. DWORD
  3464. AccessDestLonger(
  3465. DWORD dwQueryType,
  3466. DWORD dwInEntrySize,
  3467. PMIB_OPAQUE_QUERY pInEntry,
  3468. PDWORD pOutEntrySize,
  3469. PMIB_OPAQUE_INFO pOutEntry,
  3470. PBOOL pbCache
  3471. )
  3472. {
  3473. PMIB_IPDESTTABLE pDestTable;
  3474. DWORD count, i;
  3475. DWORD dwNumDests, dwResult, dwNumIndices, dwSpaceCount;
  3476. DWORD dwViews;
  3477. RTM_NET_ADDRESS naDest;
  3478. ULONG ulNumViews, ulNumInfos, ulDestInfoSize;
  3479. RTM_DEST_HANDLE hDest;
  3480. RTM_ENUM_HANDLE hEnum;
  3481. PRTM_DEST_INFO pDestInfos, pRdi;
  3482. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3483. TraceEnter("AccessDestLonger");
  3484. count = dwSpaceCount = 0;
  3485. pDestTable = NULL;
  3486. if (*pOutEntrySize > dwOffset)
  3487. {
  3488. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3489. / sizeof(MIB_IPDESTROW);
  3490. pDestTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3491. pDestTable->dwNumEntries = 0;
  3492. }
  3493. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3494. if ((dwNumIndices < 4) or
  3495. (dwQueryType isnot ACCESS_GET))
  3496. {
  3497. TraceLeave("AccessDestLonger");
  3498. return ERROR_INVALID_PARAMETER;
  3499. }
  3500. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3501. pInEntry->rgdwVarIndex[0], // Addr
  3502. pInEntry->rgdwVarIndex[1]); // Mask
  3503. dwResult = RtmCreateDestEnum( g_hLocalRoute,
  3504. pInEntry->rgdwVarIndex[2], // Views
  3505. RTM_ENUM_RANGE,
  3506. &naDest,
  3507. pInEntry->rgdwVarIndex[3], // Proto
  3508. &hEnum );
  3509. if (dwResult is NO_ERROR)
  3510. {
  3511. //
  3512. // Count the number of views as we have list of dests in buffer
  3513. //
  3514. dwViews = pInEntry->rgdwVarIndex[2];
  3515. ulNumViews = 0;
  3516. while (dwViews)
  3517. {
  3518. dwViews &= (dwViews - 1);
  3519. ulNumViews++;
  3520. }
  3521. ulDestInfoSize = RTM_SIZE_OF_DEST_INFO(ulNumViews);
  3522. pDestInfos = (PRTM_DEST_INFO) HeapAlloc(
  3523. IPRouterHeap,
  3524. 0,
  3525. ulDestInfoSize *
  3526. g_rtmProfile.MaxHandlesInEnum
  3527. );
  3528. if ( pDestInfos != NULL)
  3529. {
  3530. do
  3531. {
  3532. ulNumInfos = g_rtmProfile.MaxHandlesInEnum;
  3533. dwResult = RtmGetEnumDests( g_hLocalRoute,
  3534. hEnum,
  3535. &ulNumInfos,
  3536. pDestInfos );
  3537. for (i=0; i<ulNumInfos; i++)
  3538. {
  3539. pRdi=(PRTM_DEST_INFO)(((PUCHAR)pDestInfos)+(i*ulDestInfoSize));
  3540. AddDestinationRows( pRdi,
  3541. pInEntry->rgdwVarIndex[2],
  3542. &count,
  3543. dwSpaceCount,
  3544. pDestTable );
  3545. }
  3546. RtmReleaseDests( g_hLocalRoute,
  3547. ulNumInfos,
  3548. pDestInfos );
  3549. } while (dwResult is NO_ERROR);
  3550. HeapFree(IPRouterHeap, 0, pDestInfos);
  3551. }
  3552. else
  3553. {
  3554. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  3555. }
  3556. RtmDeleteEnumHandle( g_hLocalRoute, hEnum );
  3557. }
  3558. if (dwResult is ERROR_NO_MORE_ITEMS)
  3559. {
  3560. dwResult = NO_ERROR;
  3561. }
  3562. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3563. if (dwSpaceCount < count)
  3564. {
  3565. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3566. }
  3567. TraceLeave("AccessDestLonger");
  3568. return dwResult;
  3569. }
  3570. DWORD
  3571. AddRouteRows(
  3572. IN PRTM_ROUTE_HANDLE hRoute,
  3573. IN DWORD dwProtocolId,
  3574. OUT DWORD *pdwCount,
  3575. IN DWORD dwSpaceCount,
  3576. OUT PMIB_IPDESTTABLE pRouteTable
  3577. )
  3578. {
  3579. DWORD dwResult, dwRouteProto, j;
  3580. PRTM_ROUTE_INFO pri;
  3581. RTM_NEXTHOP_INFO nhi;
  3582. PMIB_IPDESTROW pRow;
  3583. RTM_NET_ADDRESS naDest;
  3584. RTM_ENTITY_INFO rei;
  3585. pri = HeapAlloc(
  3586. IPRouterHeap,
  3587. 0,
  3588. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  3589. );
  3590. if ( pri == NULL)
  3591. {
  3592. return ERROR_NOT_ENOUGH_MEMORY;
  3593. }
  3594. dwResult = RtmGetRouteInfo( g_hLocalRoute,
  3595. hRoute,
  3596. pri,
  3597. &naDest );
  3598. if (dwResult is NO_ERROR)
  3599. {
  3600. RtmGetEntityInfo( g_hLocalRoute,
  3601. pri->RouteOwner,
  3602. &rei );
  3603. dwRouteProto = PROTO_FROM_PROTO_ID(rei.EntityId.EntityProtocolId);
  3604. if ((dwProtocolId is 0)
  3605. || (dwRouteProto is dwProtocolId))
  3606. {
  3607. *pdwCount += pri->NextHopsList.NumNextHops;
  3608. if (dwSpaceCount >= *pdwCount)
  3609. {
  3610. for (j=0; j<pri->NextHopsList.NumNextHops; j++)
  3611. {
  3612. if (RtmGetNextHopInfo( g_hLocalRoute,
  3613. pri->NextHopsList.NextHops[j],
  3614. &nhi ) is NO_ERROR )
  3615. {
  3616. pRow= &pRouteTable->table[pRouteTable->dwNumEntries++];
  3617. RTM_IPV4_GET_ADDR_AND_MASK( pRow->dwForwardDest,
  3618. pRow->dwForwardMask,
  3619. &naDest );
  3620. pRow->dwForwardPolicy = 0;
  3621. pRow->dwForwardNextHop
  3622. = *((ULONG*)nhi.NextHopAddress.AddrBits);
  3623. pRow->dwForwardIfIndex = nhi.InterfaceIndex;
  3624. pRow->dwForwardType
  3625. = (pri->RouteOwner == g_hLocalRoute)?3:4;
  3626. pRow->dwForwardProto = dwRouteProto;
  3627. pRow->dwForwardAge = 0;
  3628. pRow->dwForwardNextHopAS= 0; // XXX
  3629. pRow->dwForwardPreference = pri->PrefInfo.Preference;
  3630. pRow->dwForwardMetric1 = pri->PrefInfo.Metric;
  3631. pRow->dwForwardMetric2 = 0;
  3632. pRow->dwForwardMetric3 = 0;
  3633. pRow->dwForwardMetric4 = 0;
  3634. pRow->dwForwardMetric5 = 0;
  3635. pRow->dwForwardViewSet = pri->BelongsToViews;
  3636. RtmReleaseNextHopInfo( g_hLocalRoute, &nhi );
  3637. }
  3638. }
  3639. }
  3640. }
  3641. RtmReleaseRouteInfo( g_hLocalRoute, pri );
  3642. }
  3643. HeapFree(IPRouterHeap, 0, pri);
  3644. return dwResult;
  3645. }
  3646. DWORD
  3647. AddRouteRowsOnDest(
  3648. IN PRTM_DEST_INFO prdi,
  3649. IN PMIB_OPAQUE_QUERY pInEntry,
  3650. OUT DWORD *pdwCount,
  3651. IN DWORD dwSpaceCount,
  3652. OUT PMIB_IPDESTTABLE pRouteTable
  3653. )
  3654. {
  3655. DWORD count, i;
  3656. PHANDLE RouteHandles;
  3657. ULONG ulNumHandles;
  3658. RTM_ENUM_HANDLE hEnum;
  3659. DWORD dwResult;
  3660. RouteHandles = HeapAlloc(
  3661. IPRouterHeap,
  3662. 0,
  3663. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  3664. );
  3665. if ( RouteHandles == NULL)
  3666. {
  3667. return ERROR_NOT_ENOUGH_MEMORY;
  3668. }
  3669. dwResult = RtmCreateRouteEnum( g_hLocalRoute,
  3670. prdi->DestHandle,
  3671. pInEntry->rgdwVarIndex[2], // Views
  3672. RTM_ENUM_ALL_ROUTES,
  3673. NULL,
  3674. RTM_MATCH_NONE,
  3675. NULL,
  3676. 0,
  3677. &hEnum );
  3678. if (dwResult is NO_ERROR)
  3679. {
  3680. do
  3681. {
  3682. ulNumHandles = g_rtmProfile.MaxHandlesInEnum;
  3683. dwResult = RtmGetEnumRoutes( g_hLocalRoute,
  3684. hEnum,
  3685. &ulNumHandles,
  3686. RouteHandles );
  3687. for (i=0; i<ulNumHandles; i++)
  3688. {
  3689. AddRouteRows( RouteHandles[i],
  3690. pInEntry->rgdwVarIndex[3],//Proto
  3691. pdwCount,
  3692. dwSpaceCount,
  3693. pRouteTable );
  3694. }
  3695. RtmReleaseRoutes( g_hLocalRoute,
  3696. ulNumHandles,
  3697. RouteHandles );
  3698. } while (dwResult is NO_ERROR);
  3699. if (dwResult is ERROR_NO_MORE_ITEMS)
  3700. {
  3701. dwResult = NO_ERROR;
  3702. }
  3703. RtmDeleteEnumHandle( g_hLocalRoute, hEnum );
  3704. }
  3705. HeapFree(IPRouterHeap, 0, RouteHandles);
  3706. return dwResult;
  3707. }
  3708. DWORD
  3709. AccessRouteMatching(
  3710. DWORD dwQueryType,
  3711. DWORD dwInEntrySize,
  3712. PMIB_OPAQUE_QUERY pInEntry,
  3713. PDWORD pOutEntrySize,
  3714. PMIB_OPAQUE_INFO pOutEntry,
  3715. PBOOL pbCache
  3716. )
  3717. {
  3718. PMIB_IPDESTTABLE pRouteTable;
  3719. DWORD dwResult, dwNumIndices, dwSpaceCount;
  3720. DWORD count;
  3721. RTM_NET_ADDRESS naDest;
  3722. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3723. PRTM_DEST_INFO prdi;
  3724. TraceEnter("AccessRouteMatching");
  3725. count = dwSpaceCount = 0;
  3726. pRouteTable = NULL;
  3727. if (*pOutEntrySize > dwOffset)
  3728. {
  3729. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3730. / sizeof(MIB_IPDESTROW);
  3731. pRouteTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3732. pRouteTable->dwNumEntries = 0;
  3733. }
  3734. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3735. if ((dwNumIndices < 4) or
  3736. (dwQueryType isnot ACCESS_GET))
  3737. {
  3738. TraceLeave("AccessRouteMatching");
  3739. return ERROR_INVALID_PARAMETER;
  3740. }
  3741. prdi = HeapAlloc(
  3742. IPRouterHeap,
  3743. 0,
  3744. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3745. );
  3746. if ( prdi == NULL)
  3747. {
  3748. TraceLeave("AccessRouteMatching");
  3749. return ERROR_NOT_ENOUGH_MEMORY;
  3750. }
  3751. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3752. pInEntry->rgdwVarIndex[0], // Addr
  3753. pInEntry->rgdwVarIndex[1]); // Mask
  3754. dwResult = RtmGetExactMatchDestination( g_hLocalRoute,
  3755. &naDest,
  3756. pInEntry->rgdwVarIndex[3],
  3757. pInEntry->rgdwVarIndex[2],
  3758. prdi );
  3759. if (dwResult is ERROR_NOT_FOUND)
  3760. {
  3761. dwResult = NO_ERROR;
  3762. }
  3763. else
  3764. if (dwResult is NO_ERROR)
  3765. {
  3766. dwResult = AddRouteRowsOnDest( prdi,
  3767. pInEntry,
  3768. &count,
  3769. dwSpaceCount,
  3770. pRouteTable );
  3771. }
  3772. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3773. if (dwSpaceCount < count)
  3774. {
  3775. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3776. }
  3777. HeapFree(IPRouterHeap, 0, prdi);
  3778. TraceLeave("AccessRouteMatching");
  3779. return dwResult;
  3780. }
  3781. DWORD
  3782. AccessRouteShorter(
  3783. DWORD dwQueryType,
  3784. DWORD dwInEntrySize,
  3785. PMIB_OPAQUE_QUERY pInEntry,
  3786. PDWORD pOutEntrySize,
  3787. PMIB_OPAQUE_INFO pOutEntry,
  3788. PBOOL pbCache
  3789. )
  3790. {
  3791. PMIB_IPDESTTABLE pRouteTable;
  3792. DWORD dwResult, dwNumIndices, dwSpaceCount;
  3793. DWORD count;
  3794. RTM_NET_ADDRESS naDest;
  3795. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3796. PRTM_DEST_INFO prdi1, prdi2;
  3797. TraceEnter("AccessRouteShorter");
  3798. count = dwSpaceCount = 0;
  3799. pRouteTable = NULL;
  3800. if (*pOutEntrySize > dwOffset)
  3801. {
  3802. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3803. / sizeof(MIB_IPDESTROW);
  3804. pRouteTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3805. pRouteTable->dwNumEntries = 0;
  3806. }
  3807. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3808. if ((dwNumIndices < 4) or
  3809. (dwQueryType isnot ACCESS_GET))
  3810. {
  3811. TraceLeave("AccessRouteShorter");
  3812. return ERROR_INVALID_PARAMETER;
  3813. }
  3814. prdi1 = HeapAlloc(
  3815. IPRouterHeap,
  3816. 0,
  3817. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3818. );
  3819. if ( prdi1 == NULL)
  3820. {
  3821. TraceLeave("AccessRouteShorter");
  3822. return ERROR_NOT_ENOUGH_MEMORY;
  3823. }
  3824. prdi2 = HeapAlloc(
  3825. IPRouterHeap,
  3826. 0,
  3827. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  3828. );
  3829. if ( prdi2 == NULL)
  3830. {
  3831. TraceLeave("AccessRouteShorter");
  3832. HeapFree(IPRouterHeap, 0, prdi1);
  3833. return ERROR_NOT_ENOUGH_MEMORY;
  3834. }
  3835. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3836. pInEntry->rgdwVarIndex[0], // Addr
  3837. pInEntry->rgdwVarIndex[1]); // Mask
  3838. dwResult = RtmGetMostSpecificDestination( g_hLocalRoute,
  3839. &naDest,
  3840. pInEntry->rgdwVarIndex[3],//Proto
  3841. pInEntry->rgdwVarIndex[2],//Views
  3842. prdi1 );
  3843. while (dwResult is NO_ERROR)
  3844. {
  3845. AddRouteRowsOnDest( prdi1,
  3846. pInEntry,
  3847. &count,
  3848. dwSpaceCount,
  3849. pRouteTable );
  3850. dwResult = RtmGetLessSpecificDestination( g_hLocalRoute,
  3851. prdi1->DestHandle,
  3852. pInEntry->rgdwVarIndex[3],
  3853. pInEntry->rgdwVarIndex[2],
  3854. prdi2);
  3855. RtmReleaseDestInfo( g_hLocalRoute, prdi1 );
  3856. if (dwResult != NO_ERROR)
  3857. {
  3858. break;
  3859. }
  3860. AddRouteRowsOnDest( prdi2,
  3861. pInEntry,
  3862. &count,
  3863. dwSpaceCount,
  3864. pRouteTable );
  3865. dwResult = RtmGetLessSpecificDestination( g_hLocalRoute,
  3866. prdi2->DestHandle,
  3867. pInEntry->rgdwVarIndex[3],
  3868. pInEntry->rgdwVarIndex[2],
  3869. prdi1);
  3870. RtmReleaseDestInfo( g_hLocalRoute, prdi2 );
  3871. if (dwResult != NO_ERROR)
  3872. {
  3873. break;
  3874. }
  3875. }
  3876. if (dwResult is ERROR_NOT_FOUND)
  3877. {
  3878. dwResult = NO_ERROR;
  3879. }
  3880. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3881. if (dwSpaceCount < count)
  3882. {
  3883. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3884. }
  3885. HeapFree(IPRouterHeap, 0, prdi1);
  3886. HeapFree(IPRouterHeap, 0, prdi2);
  3887. TraceLeave("AccessRouteShorter");
  3888. return dwResult;
  3889. }
  3890. DWORD
  3891. AccessRouteLonger(
  3892. DWORD dwQueryType,
  3893. DWORD dwInEntrySize,
  3894. PMIB_OPAQUE_QUERY pInEntry,
  3895. PDWORD pOutEntrySize,
  3896. PMIB_OPAQUE_INFO pOutEntry,
  3897. PBOOL pbCache
  3898. )
  3899. {
  3900. PMIB_IPDESTTABLE pRouteTable;
  3901. DWORD count, i;
  3902. DWORD dwResult, dwNumIndices, dwSpaceCount;
  3903. RTM_NET_ADDRESS naDest;
  3904. ULONG ulNumHandles;
  3905. RTM_ENUM_HANDLE hEnum;
  3906. PHANDLE RouteHandles;
  3907. DWORD dwOffset = MAX_MIB_OFFSET + sizeof(DWORD);
  3908. TraceEnter("AccessRouteLonger");
  3909. count = dwSpaceCount = 0;
  3910. pRouteTable = NULL;
  3911. if (*pOutEntrySize > dwOffset)
  3912. {
  3913. dwSpaceCount = (*pOutEntrySize - dwOffset)
  3914. / sizeof(MIB_IPDESTROW);
  3915. pRouteTable = (PMIB_IPDESTTABLE)(pOutEntry->rgbyData);
  3916. pRouteTable->dwNumEntries = 0;
  3917. }
  3918. dwNumIndices = dwInEntrySize/sizeof(DWORD) - 1;
  3919. if ((dwNumIndices < 4) or
  3920. (dwQueryType isnot ACCESS_GET))
  3921. {
  3922. TraceLeave("AccessRouteLonger");
  3923. return ERROR_INVALID_PARAMETER;
  3924. }
  3925. RouteHandles = HeapAlloc(
  3926. IPRouterHeap,
  3927. 0,
  3928. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  3929. );
  3930. if ( RouteHandles == NULL)
  3931. {
  3932. TraceLeave("AccessRouteLonger");
  3933. return ERROR_NOT_ENOUGH_MEMORY;
  3934. }
  3935. RTM_IPV4_SET_ADDR_AND_MASK(&naDest,
  3936. pInEntry->rgdwVarIndex[0], // Addr
  3937. pInEntry->rgdwVarIndex[1]); // Mask
  3938. dwResult = RtmCreateRouteEnum( g_hLocalRoute,
  3939. NULL,
  3940. pInEntry->rgdwVarIndex[2], // Views
  3941. RTM_ENUM_RANGE,
  3942. &naDest,
  3943. RTM_MATCH_NONE,
  3944. NULL,
  3945. 0,
  3946. &hEnum );
  3947. if (dwResult is NO_ERROR)
  3948. {
  3949. do
  3950. {
  3951. ulNumHandles = g_rtmProfile.MaxHandlesInEnum;
  3952. dwResult = RtmGetEnumRoutes( g_hLocalRoute,
  3953. hEnum,
  3954. &ulNumHandles,
  3955. RouteHandles );
  3956. for (i=0; i<ulNumHandles; i++)
  3957. {
  3958. AddRouteRows( RouteHandles[i],
  3959. pInEntry->rgdwVarIndex[3], // Proto
  3960. &count,
  3961. dwSpaceCount,
  3962. pRouteTable );
  3963. }
  3964. RtmReleaseRoutes( g_hLocalRoute,
  3965. ulNumHandles,
  3966. RouteHandles );
  3967. } while (dwResult is NO_ERROR);
  3968. RtmDeleteEnumHandle( g_hLocalRoute, hEnum );
  3969. }
  3970. if (dwResult is ERROR_NO_MORE_ITEMS)
  3971. {
  3972. dwResult = NO_ERROR;
  3973. }
  3974. *pOutEntrySize = dwOffset + count * sizeof(MIB_IPDESTROW);
  3975. if (dwSpaceCount < count)
  3976. {
  3977. dwResult = ERROR_INSUFFICIENT_BUFFER;
  3978. }
  3979. HeapFree(IPRouterHeap, 0, RouteHandles);
  3980. TraceLeave("AccessRouteLonger");
  3981. return dwResult;
  3982. }
  3983. PINTERFACE_ROUTE_INFO
  3984. ConvertDestRowToRouteInfo(
  3985. IN PMIB_IPDESTROW pMibRow
  3986. )
  3987. {
  3988. PINTERFACE_ROUTE_INFO pRouteInfo = (PINTERFACE_ROUTE_INFO)pMibRow;
  3989. //
  3990. // Note that it is important to note that here
  3991. // the source and dest buffers are the same
  3992. //
  3993. pRouteInfo->dwRtInfoPreference = pMibRow->dwForwardPreference;
  3994. pRouteInfo->dwRtInfoViewSet = pMibRow->dwForwardViewSet;
  3995. #if 0
  3996. // Removed this since metric=0 is legal for routes to the loopback
  3997. // interface.
  3998. // Make sure Metric1 isn't 0
  3999. if (pRouteInfo->dwForwardMetric1 is 0)
  4000. {
  4001. pRouteInfo->dwForwardMetric1 = 1;
  4002. }
  4003. #endif
  4004. return pRouteInfo;
  4005. }
  4006. DWORD
  4007. AccessIpMatchingRoute(
  4008. DWORD dwQueryType,
  4009. DWORD dwInEntrySize,
  4010. PMIB_OPAQUE_QUERY pInEntry,
  4011. PDWORD pOutEntrySize,
  4012. PMIB_OPAQUE_INFO pOutEntry,
  4013. PBOOL pbCache
  4014. )
  4015. /*++
  4016. Routine Description:
  4017. Function used to add, delete or set a route (IP Dest Row)
  4018. Arguments
  4019. dwQueryType Create, Set, Delete permitted
  4020. pInEntry Dest, Mask, IfIndex, and NextHop for the row filled in the
  4021. rgdwVarIndex field.
  4022. pOutEntrySize MAX_MIB_OFFSET + sizeof(MIB_IPDESTROW). For Sets the
  4023. OutBuffer has the row to set
  4024. Return Value:
  4025. NO_ERROR or some error code defined in iprtrmib
  4026. --*/
  4027. {
  4028. PMIB_IPDESTROW pIpRouteRow;
  4029. DWORD dwMask, i;
  4030. DWORD dwResult;
  4031. HANDLE hRtmHandle;
  4032. TraceEnter("AccessIpMatchingRoute");
  4033. pIpRouteRow = (PMIB_IPDESTROW)(pOutEntry->rgbyData);
  4034. if (dwQueryType != ACCESS_DELETE_ENTRY)
  4035. {
  4036. // Make sure we have a buffer of the right size
  4037. if(*pOutEntrySize < MAX_MIB_OFFSET + sizeof(MIB_IPDESTROW))
  4038. {
  4039. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPDESTROW);
  4040. TraceLeave("AccessIpMatchingRoute");
  4041. return ERROR_INSUFFICIENT_BUFFER;
  4042. }
  4043. *pOutEntrySize = MAX_MIB_OFFSET + sizeof(MIB_IPDESTROW);
  4044. pOutEntry->dwId = ROUTE_MATCHING;
  4045. }
  4046. else
  4047. {
  4048. MIB_IPDESTROW IpRouteRow;
  4049. pIpRouteRow = &IpRouteRow;
  4050. // Do you need to check the input buffer size here ?
  4051. pIpRouteRow->dwForwardDest = pInEntry->rgdwVarIndex[0];
  4052. pIpRouteRow->dwForwardMask = pInEntry->rgdwVarIndex[1];
  4053. pIpRouteRow->dwForwardIfIndex = pInEntry->rgdwVarIndex[2];
  4054. pIpRouteRow->dwForwardNextHop = pInEntry->rgdwVarIndex[3];
  4055. pIpRouteRow->dwForwardProto = pInEntry->rgdwVarIndex[4];
  4056. }
  4057. //
  4058. // Do validation before adding or deleting the route
  4059. //
  4060. if((pIpRouteRow->dwForwardDest & pIpRouteRow->dwForwardMask) isnot
  4061. pIpRouteRow->dwForwardDest)
  4062. {
  4063. Trace2(ERR,
  4064. "AccessIpMatchingRoute: Dest %d.%d.%d.%d and Mask %d.%d.%d.%d wrong",
  4065. PRINT_IPADDR(pIpRouteRow->dwForwardDest),
  4066. PRINT_IPADDR(pIpRouteRow->dwForwardMask));
  4067. TraceLeave("AccessIpMatchingRoute");
  4068. return ERROR_INVALID_PARAMETER;
  4069. }
  4070. //
  4071. // Get the RTM handle used to add or delete the route
  4072. //
  4073. hRtmHandle = NULL;
  4074. for(i = 0;
  4075. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  4076. i++)
  4077. {
  4078. if(pIpRouteRow->dwForwardProto is g_rgRtmHandles[i].dwProtoId)
  4079. {
  4080. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  4081. break;
  4082. }
  4083. }
  4084. if(hRtmHandle is NULL)
  4085. {
  4086. Trace1(ERR,
  4087. "AccessIpMatchingRoute: Protocol %d not valid",
  4088. pIpRouteRow->dwForwardProto);
  4089. return ERROR_INVALID_PARAMETER;
  4090. }
  4091. switch (dwQueryType)
  4092. {
  4093. case ACCESS_CREATE_ENTRY:
  4094. case ACCESS_SET:
  4095. //
  4096. // Add the RTM route from the ip row entry
  4097. //
  4098. ENTER_READER(ICB_LIST);
  4099. dwMask = GetBestNextHopMaskGivenIndex(pIpRouteRow->dwForwardIfIndex,
  4100. pIpRouteRow->dwForwardNextHop);
  4101. EXIT_LOCK(ICB_LIST);
  4102. //
  4103. // Convert input to INTERFACE_ROUTE_INFO and add
  4104. //
  4105. dwResult = AddRtmRoute(hRtmHandle,
  4106. ConvertDestRowToRouteInfo(pIpRouteRow),
  4107. IP_VALID_ROUTE | IP_STACK_ROUTE,
  4108. dwMask,
  4109. pIpRouteRow->dwForwardAge,
  4110. NULL);
  4111. if(dwResult isnot NO_ERROR)
  4112. {
  4113. Trace1(MIB,
  4114. "AccessIpMatchingRoute: Could not set route to RTM: Dest %x\n",
  4115. pIpRouteRow->dwForwardDest);
  4116. }
  4117. break;
  4118. case ACCESS_DELETE_ENTRY:
  4119. dwResult = DeleteRtmRoute(hRtmHandle,
  4120. ConvertDestRowToRouteInfo(pIpRouteRow));
  4121. break;
  4122. default:
  4123. dwResult = ERROR_INVALID_FUNCTION;
  4124. }
  4125. TraceLeave("AccessIpMatchingRoute");
  4126. return dwResult;
  4127. }