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

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