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.

1653 lines
37 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\ip\rtrmgr\nat.c
  5. Abstract:
  6. Based on filter.c
  7. Abstracts out the NAT functionality
  8. Revision History:
  9. --*/
  10. #include "allinc.h"
  11. DWORD
  12. StartNat(
  13. PIP_NAT_GLOBAL_INFO pNatGlobalInfo
  14. )
  15. {
  16. #if 1
  17. return 0;
  18. #else
  19. PLIST_ENTRY pleNode;
  20. PICB picb;
  21. DWORD dwResult;
  22. NTSTATUS ntStatus;
  23. IO_STATUS_BLOCK IoStatusBlock;
  24. TraceEnter("StartNat");
  25. if(!g_bNatRunning)
  26. {
  27. if(StartDriverAndOpenHandle(IP_NAT_SERVICE_NAME,
  28. DD_IP_NAT_DEVICE_NAME,
  29. &g_hNatDevice) isnot NO_ERROR)
  30. {
  31. Trace0(ERR,
  32. "StartNat: Couldnt open driver");
  33. TraceLeave("StartNat");
  34. return ERROR_OPEN_FAILED;
  35. }
  36. //
  37. // At this point NAT is running
  38. //
  39. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  40. NULL,
  41. NULL,
  42. NULL,
  43. &IoStatusBlock,
  44. IOCTL_IP_NAT_SET_GLOBAL_INFO,
  45. (PVOID)pNatGlobalInfo,
  46. sizeof(IP_NAT_GLOBAL_INFO),
  47. NULL,
  48. 0);
  49. if(ntStatus isnot STATUS_SUCCESS)
  50. {
  51. Trace1(ERR,
  52. "StartNat: Status %X setting global info",
  53. ntStatus);
  54. StopDriverAndCloseHandle(IP_NAT_SERVICE_NAME,
  55. g_hNatDevice);
  56. g_hNatDevice = NULL;
  57. TraceLeave("StartNat");
  58. return ERROR_OPEN_FAILED;
  59. }
  60. g_bNatRunning = TRUE;
  61. //
  62. // Just queue a worker to add the nat info and contexts
  63. //
  64. dwResult = QueueAsyncFunction(RestoreNatInfo,
  65. NULL,
  66. FALSE);
  67. if(dwResult isnot NO_ERROR)
  68. {
  69. Trace1(ERR,
  70. "StartNat: Error %d firing worker function to set nat info",
  71. dwResult);
  72. }
  73. }
  74. TraceLeave("StartNat");
  75. return NO_ERROR;
  76. #endif
  77. }
  78. DWORD
  79. StopNat(
  80. VOID
  81. )
  82. {
  83. #if 1
  84. return 0;
  85. #else
  86. PLIST_ENTRY pleNode;
  87. PICB picb;
  88. DWORD dwResult;
  89. TraceEnter("StopNat");
  90. if(g_bNatRunning)
  91. {
  92. g_bNatRunning = FALSE;
  93. //
  94. // Set the NAT context in the ICBs to INVALID
  95. //
  96. for (pleNode = ICBList.Flink;
  97. pleNode != &ICBList;
  98. pleNode = pleNode->Flink)
  99. {
  100. picb = CONTAINING_RECORD (pleNode, ICB, leIfLink);
  101. if((picb->ritType is ROUTER_IF_TYPE_INTERNAL) or
  102. (picb->ritType is ROUTER_IF_TYPE_LOOPBACK) or
  103. (picb->ritType is ROUTER_IF_TYPE_CLIENT))
  104. {
  105. //
  106. // The above types are not added to the NAT
  107. // or to the IP stack
  108. //
  109. continue;
  110. }
  111. if(picb->dwOperationalState >= MIB_IF_OPER_STATUS_CONNECTED)
  112. {
  113. IpRtAssert(picb->bBound);
  114. UnbindNatInterface(picb);
  115. }
  116. dwResult = DeleteInterfaceFromNat(picb);
  117. if(dwResult isnot NO_ERROR)
  118. {
  119. Trace2(ERR,
  120. "StopNat: NtStatus %x deleting %S from NAT",
  121. dwResult,
  122. picb->pwszName);
  123. }
  124. }
  125. StopDriverAndCloseHandle(IP_NAT_SERVICE_NAME,
  126. g_hNatDevice);
  127. }
  128. TraceLeave("StopNat");
  129. return NO_ERROR;
  130. #endif
  131. }
  132. DWORD
  133. SetGlobalNatInfo(
  134. PRTR_INFO_BLOCK_HEADER pRtrGlobalInfo
  135. )
  136. {
  137. #if 1
  138. return 0;
  139. #else
  140. PRTR_TOC_ENTRY pToc;
  141. PIP_NAT_GLOBAL_INFO pNatGlobalInfo;
  142. NTSTATUS ntStatus;
  143. IO_STATUS_BLOCK IoStatusBlock;
  144. DWORD dwResult;
  145. TraceEnter("SetGlobalNatInfo");
  146. pNatGlobalInfo = NULL;
  147. pToc = GetPointerToTocEntry(IP_NAT_INFO,
  148. pRtrGlobalInfo);
  149. if(pToc)
  150. {
  151. pNatGlobalInfo = GetInfoFromTocEntry(pRtrGlobalInfo,
  152. pToc);
  153. if((pToc->InfoSize is 0) or (pNatGlobalInfo is NULL))
  154. {
  155. //
  156. // Means remove NAT
  157. //
  158. dwResult = StopNat();
  159. if(dwResult isnot NO_ERROR)
  160. {
  161. Trace1(ERR,
  162. "SetGlobalNatInfo: Error %d stopping NAT (no info)",
  163. dwResult);
  164. }
  165. TraceLeave("SetGlobalNatInfo");
  166. return dwResult;
  167. }
  168. }
  169. else
  170. {
  171. Trace0(IF,
  172. "SetGlobalNatInfo: No NAT info, so leaving");
  173. TraceLeave("SetGlobalNatInfo");
  174. return NO_ERROR;
  175. }
  176. EnterCriticalSection(&g_csNatInfo);
  177. if(g_pNatGlobalInfo is NULL)
  178. {
  179. g_pNatGlobalInfo = HeapAlloc(IPRouterHeap,
  180. 0,
  181. sizeof(IP_NAT_GLOBAL_INFO));
  182. if(g_pNatGlobalInfo is NULL)
  183. {
  184. Trace1(ERR,
  185. "SetGlobalNatInfo: Error %d allocating memory for NAT info",
  186. GetLastError());
  187. LeaveCriticalSection(&g_csNatInfo);
  188. return ERROR_NOT_ENOUGH_MEMORY;
  189. }
  190. }
  191. //
  192. // Save a copy
  193. //
  194. CopyMemory(g_pNatGlobalInfo,
  195. pNatGlobalInfo,
  196. sizeof(IP_NAT_GLOBAL_INFO));
  197. if(g_bNatRunning)
  198. {
  199. //
  200. // NAT is running, if the user is asking us to stop it,
  201. // do so now an return
  202. //
  203. if(pNatGlobalInfo->NATEnabled is FALSE)
  204. {
  205. dwResult = StopNat();
  206. LeaveCriticalSection(&g_csNatInfo);
  207. if(dwResult isnot NO_ERROR)
  208. {
  209. Trace1(ERR,
  210. "SetGlobalNatInfo: Error %d stopping NAT",
  211. dwResult);
  212. }
  213. TraceLeave("SetGlobalNatInfo");
  214. return dwResult;
  215. }
  216. }
  217. else
  218. {
  219. if(pNatGlobalInfo->NATEnabled is TRUE)
  220. {
  221. dwResult = StartNat(pNatGlobalInfo);
  222. LeaveCriticalSection(&g_csNatInfo);
  223. if(dwResult isnot NO_ERROR)
  224. {
  225. Trace1(ERR,
  226. "SetGlobalNatInfo: Error %d starting NAT",
  227. dwResult);
  228. }
  229. TraceLeave("SetGlobalNatInfo");
  230. //
  231. // Starting NAT causes us to also set the global info
  232. // so we can return from here
  233. //
  234. return dwResult;
  235. }
  236. }
  237. //
  238. // This is the case where NAT is already started and only its info is
  239. // being changed
  240. //
  241. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  242. NULL,
  243. NULL,
  244. NULL,
  245. &IoStatusBlock,
  246. IOCTL_IP_NAT_SET_GLOBAL_INFO,
  247. (PVOID)pNatGlobalInfo,
  248. sizeof(IP_NAT_GLOBAL_INFO),
  249. NULL,
  250. 0);
  251. if (!NT_SUCCESS(ntStatus))
  252. {
  253. Trace1(ERR,
  254. "SetGlobalNatInfo: NtStatus %x setting NAT info",
  255. ntStatus);
  256. TraceLeave("SetGlobalNatInfo");
  257. LeaveCriticalSection(&g_csNatInfo);
  258. return ERROR_CAN_NOT_COMPLETE;
  259. }
  260. LeaveCriticalSection(&g_csNatInfo);
  261. TraceLeave("SetGlobalNatInfo");
  262. return NO_ERROR;
  263. #endif
  264. }
  265. DWORD
  266. AddInterfaceToNat(
  267. PICB picb
  268. )
  269. /*++
  270. Routine Description
  271. Adds an interface to the nat driver and stores the context returned by
  272. the driver
  273. Can only be called if NAT is running
  274. Locks
  275. Arguments
  276. picb
  277. Return Value
  278. --*/
  279. {
  280. #if 1
  281. return 0;
  282. #else
  283. NTSTATUS ntStatus;
  284. IO_STATUS_BLOCK IoStatusBlock;
  285. IP_NAT_CREATE_INTERFACE inBuffer;
  286. DWORD dwInBufLen;
  287. TraceEnter("AddInterfaceToNat");
  288. IpRtAssert((picb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  289. (picb->ritType isnot ROUTER_IF_TYPE_LOOPBACK) and
  290. (picb->ritType isnot ROUTER_IF_TYPE_CLIENT));
  291. inBuffer.RtrMgrIndex = picb->dwIfIndex;
  292. inBuffer.RtrMgrContext = picb;
  293. inBuffer.NatInterfaceContext = NULL;
  294. dwInBufLen = sizeof(IP_NAT_CREATE_INTERFACE);
  295. picb->pvNatContext = NULL;
  296. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  297. NULL,
  298. NULL,
  299. NULL,
  300. &IoStatusBlock,
  301. IOCTL_IP_NAT_CREATE_INTERFACE,
  302. (PVOID)&inBuffer,
  303. dwInBufLen,
  304. (PVOID)&inBuffer,
  305. dwInBufLen);
  306. if(!NT_SUCCESS(ntStatus))
  307. {
  308. Trace2(ERR,
  309. "AddInterfaceToNat: NtStatus %x adding %S to NAT",
  310. ntStatus,
  311. picb->pwszName);
  312. TraceLeave("AddInterfaceToNat");
  313. return ntStatus;
  314. }
  315. picb->pvNatContext = inBuffer.NatInterfaceContext;
  316. TraceLeave("AddInterfaceToNat");
  317. return NO_ERROR;
  318. #endif
  319. }
  320. DWORD
  321. SetNatInterfaceInfo(
  322. PICB picb,
  323. PRTR_INFO_BLOCK_HEADER pInterfaceInfo
  324. )
  325. {
  326. #if 1
  327. return 0;
  328. #else
  329. NTSTATUS ntStatus;
  330. IO_STATUS_BLOCK IoStatusBlock;
  331. DWORD i,dwInBufLen,dwResult;
  332. PRTR_TOC_ENTRY pToc;
  333. PIP_NAT_INTERFACE_INFO pNatInfo;
  334. if((picb->ritType is ROUTER_IF_TYPE_INTERNAL) or
  335. (picb->ritType is ROUTER_IF_TYPE_LOOPBACK) or
  336. (picb->ritType is ROUTER_IF_TYPE_CLIENT))
  337. {
  338. return NO_ERROR;
  339. }
  340. if(!g_bNatRunning)
  341. {
  342. return NO_ERROR;
  343. }
  344. TraceEnter("SetNatInterfaceInfo");
  345. pToc = GetPointerToTocEntry(IP_NAT_INFO,
  346. pInterfaceInfo);
  347. if(pToc is NULL)
  348. {
  349. //
  350. // NULL means we dont need to change anything
  351. //
  352. Trace1(IF,
  353. "SetNatInterfaceInfo: Nat info is NULL for %S, so leaving",
  354. picb->pwszName);
  355. TraceLeave("SetNatInterfaceInfo");
  356. return NO_ERROR;
  357. }
  358. if(pToc->InfoSize is 0)
  359. {
  360. //
  361. // TOC present, but no info
  362. // This means, delete the interface
  363. //
  364. dwResult = UnbindNatInterface(picb);
  365. if(dwResult isnot NO_ERROR)
  366. {
  367. Trace2(ERR,
  368. "SetNatInterfaceInfo: Error %d unbinding %S",
  369. dwResult,
  370. picb->pwszName);
  371. }
  372. dwResult = DeleteInterfaceFromNat(picb);
  373. if(dwResult isnot NO_ERROR)
  374. {
  375. Trace2(ERR,
  376. "SetNatInterfaceInfo: Error %d deleting interface %S",
  377. dwResult,
  378. picb->pwszName);
  379. }
  380. TraceLeave("SetNatInterfaceInfo");
  381. return dwResult;
  382. }
  383. //
  384. // So we have NAT info
  385. //
  386. if(picb->pvNatContext is NULL)
  387. {
  388. //
  389. // Looks like this interface does not have NAT
  390. //
  391. Trace1(IF,
  392. "SetNatInterfaceInfo: No context, assuming interface %S not added to NAT",
  393. picb->pwszName);
  394. //
  395. // Add the interface to NAT
  396. //
  397. dwResult = AddInterfaceToNat(picb);
  398. if(dwResult isnot NO_ERROR)
  399. {
  400. Trace2(ERR,
  401. "SetNatInterfaceInfo: Error %d adding interface %S",
  402. dwResult,
  403. picb->pwszName);
  404. TraceLeave("SetNatInterfaceInfo");
  405. return dwResult;
  406. }
  407. }
  408. if(picb->pvNatInfo)
  409. {
  410. //
  411. // If we are LAN and UP, then this info has been added for
  412. // proxy ARP. Remove it
  413. // An optimization would be to only remove those addresses that will
  414. // be going away by this set, and then only set those addresses
  415. // that will be coming new due to this set.
  416. // But like I said, that is an _optimization_
  417. //
  418. DeleteNatRangeFromProxyArp(picb);
  419. IpRtAssert(picb->ulNatInfoSize isnot 0);
  420. HeapFree(IPRouterHeap,
  421. 0,
  422. picb->pvNatInfo);
  423. }
  424. picb->ulNatInfoSize = 0;
  425. dwInBufLen = pToc->InfoSize;
  426. pNatInfo = (PIP_NAT_INTERFACE_INFO)GetInfoFromTocEntry(pInterfaceInfo,
  427. pToc);
  428. //
  429. // Allocate space for nat info
  430. //
  431. picb->pvNatInfo = HeapAlloc(IPRouterHeap,
  432. 0,
  433. dwInBufLen);
  434. if(picb->pvNatInfo is NULL)
  435. {
  436. Trace2(ERR,
  437. "SetNatInterfaceInfo: Error %d allocating memory for %S",
  438. GetLastError(),
  439. picb->pwszName);
  440. TraceLeave("SetNatInterfaceInfo");
  441. return ERROR_NOT_ENOUGH_MEMORY;
  442. }
  443. //
  444. // Save a copy of the info
  445. //
  446. CopyMemory(picb->pvNatInfo,
  447. pNatInfo,
  448. dwInBufLen);
  449. picb->ulNatInfoSize = dwInBufLen;
  450. //
  451. // Fill in the context since that will not be in the info that is
  452. // passed to us
  453. //
  454. pNatInfo->NatInterfaceContext = picb->pvNatContext;
  455. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  456. NULL,
  457. NULL,
  458. NULL,
  459. &IoStatusBlock,
  460. IOCTL_IP_NAT_SET_INTERFACE_INFO,
  461. (PVOID)pNatInfo,
  462. dwInBufLen,
  463. NULL,
  464. 0);
  465. if (!NT_SUCCESS(ntStatus))
  466. {
  467. Trace2(ERR,
  468. "SetNatInterfaceInfo: NtStatus %x adding NAT info for %S",
  469. ntStatus,
  470. picb->pwszName);
  471. TraceLeave("SetNatInterfaceInfo");
  472. return ERROR_CAN_NOT_COMPLETE;
  473. }
  474. TraceLeave("SetNatInterfaceInfo");
  475. return NO_ERROR;
  476. #endif
  477. }
  478. DWORD
  479. GetInterfaceNatInfo(
  480. PICB picb,
  481. PRTR_TOC_ENTRY pToc,
  482. PBYTE pbDataPtr,
  483. PRTR_INFO_BLOCK_HEADER pInfoHdrAndBuffer,
  484. PDWORD pdwSize
  485. )
  486. /*++
  487. Routine Description
  488. This function copies out the saved NAT info to the buffer
  489. Can only be called if NAT is running
  490. Locks
  491. ICB_LIST lock held as READER
  492. Arguments
  493. picb
  494. pToc
  495. pbDataPtr
  496. pInfoHdrAndBuffer
  497. pdwSize
  498. Return Value
  499. None
  500. --*/
  501. {
  502. #if 1
  503. return 0;
  504. #else
  505. TraceEnter("GetInterfaceNatInfo");
  506. if(*pdwSize < picb->ulNatInfoSize)
  507. {
  508. *pdwSize = picb->ulNatInfoSize;
  509. TraceLeave("GetInterfaceNatInfo");
  510. return ERROR_INSUFFICIENT_BUFFER;
  511. }
  512. if(picb->pvNatInfo is NULL)
  513. {
  514. IpRtAssert(picb->ulNatInfoSize is 0);
  515. //
  516. // No data
  517. //
  518. *pdwSize = 0;
  519. TraceLeave("GetInterfaceNatInfo");
  520. return ERROR_NO_DATA;
  521. }
  522. IpRtAssert(picb->pvNatContext);
  523. pToc->InfoType = IP_NAT_INFO;
  524. pToc->Count = 1;
  525. pToc->InfoSize = picb->ulNatInfoSize;
  526. pToc->Offset = pbDataPtr - (PBYTE)pInfoHdrAndBuffer;
  527. CopyMemory(pbDataPtr,
  528. picb->pvNatInfo,
  529. picb->ulNatInfoSize);
  530. *pdwSize = picb->ulNatInfoSize;
  531. TraceLeave("GetInterfaceNatInfo");
  532. return NO_ERROR;
  533. #endif
  534. }
  535. DWORD
  536. BindNatInterface(
  537. PICB picb
  538. )
  539. {
  540. #if 1
  541. return 0;
  542. #else
  543. PIP_NAT_BIND_INTERFACE pnbiBindInfo;
  544. NTSTATUS ntStatus;
  545. IO_STATUS_BLOCK IoStatusBlock;
  546. DWORD i, dwInBufLen, dwResult;
  547. PIP_ADAPTER_BINDING_INFO pBinding;
  548. if((picb->ritType is ROUTER_IF_TYPE_INTERNAL) or
  549. (picb->ritType is ROUTER_IF_TYPE_LOOPBACK) or
  550. (picb->ritType is ROUTER_IF_TYPE_CLIENT))
  551. {
  552. return NO_ERROR;
  553. }
  554. if(!g_bNatRunning)
  555. {
  556. return NO_ERROR;
  557. }
  558. TraceEnter("BindNatInterface");
  559. if(picb->pvNatContext is NULL)
  560. {
  561. Trace1(IF,
  562. "BindNatInterface: No context, assuming interface %S not added to NAT",
  563. picb->pwszName);
  564. TraceLeave("SetAddressFromNat");
  565. return NO_ERROR;
  566. }
  567. //
  568. // Try and set the address to NAT
  569. //
  570. if(picb->dwNumAddresses > 0)
  571. {
  572. dwInBufLen = FIELD_OFFSET(IP_NAT_BIND_INTERFACE, BindingInfo[0]) +
  573. SIZEOF_IP_BINDING(picb->dwNumAddresses);
  574. pnbiBindInfo = HeapAlloc(IPRouterHeap,
  575. HEAP_ZERO_MEMORY,
  576. dwInBufLen);
  577. if(pnbiBindInfo is NULL)
  578. {
  579. dwResult = GetLastError();
  580. Trace2(ERR,
  581. "BindNatInterface: Unable to allocate memory for binding for %S",
  582. dwResult,
  583. picb->pwszName);
  584. TraceLeave("BindNatInterface");
  585. return dwResult;
  586. }
  587. pnbiBindInfo->NatInterfaceContext = picb->pvNatContext;
  588. pBinding = (PIP_ADAPTER_BINDING_INFO)pnbiBindInfo->BindingInfo;
  589. pBinding->NumAddresses = picb->dwNumAddresses;
  590. pBinding->RemoteAddress = picb->dwRemoteAddress;
  591. for(i = 0; i < picb->dwNumAddresses; i++)
  592. {
  593. pBinding->Address[i].IPAddress = picb->pibBindings[i].dwAddress;
  594. pBinding->Address[i].Mask = picb->pibBindings[i].dwMask;
  595. }
  596. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  597. NULL,
  598. NULL,
  599. NULL,
  600. &IoStatusBlock,
  601. IOCTL_IP_NAT_BIND_INTERFACE,
  602. (PVOID)pnbiBindInfo,
  603. dwInBufLen,
  604. NULL,
  605. 0);
  606. if(!NT_SUCCESS(ntStatus))
  607. {
  608. Trace2(ERR,
  609. "BindNatInterface: NtStatus %x setting binding for %S",
  610. ntStatus,
  611. picb->pwszName);
  612. }
  613. }
  614. //
  615. // Set the proxy arp range
  616. // This requires that the NAT info already be part of the ICB
  617. //
  618. SetNatRangeForProxyArp(picb);
  619. //
  620. // Set the context to IP stack
  621. //
  622. dwResult = SetNatContextToIpStack(picb);
  623. if(dwResult isnot NO_ERROR)
  624. {
  625. Trace2(ERR,
  626. "BindNatInterface: Error %d setting context for %S",
  627. dwResult,
  628. picb->pwszName);
  629. }
  630. TraceLeave("BindNatInterface");
  631. return ntStatus;
  632. #endif
  633. }
  634. DWORD
  635. UnbindNatInterface(
  636. PICB picb
  637. )
  638. /*++
  639. Routine Description
  640. Locks
  641. Arguments
  642. Return Value
  643. NO_ERROR
  644. --*/
  645. {
  646. #if 1
  647. return 0;
  648. #else
  649. IP_NAT_UNBIND_INTERFACE ubiUnbindInfo;
  650. NTSTATUS ntStatus;
  651. IO_STATUS_BLOCK IoStatusBlock;
  652. DWORD dwResult;
  653. if((picb->ritType is ROUTER_IF_TYPE_INTERNAL) and
  654. (picb->ritType is ROUTER_IF_TYPE_LOOPBACK) and
  655. (picb->ritType is ROUTER_IF_TYPE_CLIENT))
  656. {
  657. return NO_ERROR;
  658. }
  659. if(!g_bNatRunning)
  660. {
  661. return NO_ERROR;
  662. }
  663. TraceEnter("UnbindNatInterface");
  664. if(picb->pvNatContext is NULL)
  665. {
  666. Trace1(IF,
  667. "ClearAddressToNat: No context, assuming interface %S not added to NAT",
  668. picb->pwszName);
  669. TraceLeave("UnbindNatInterface");
  670. return NO_ERROR;
  671. }
  672. ubiUnbindInfo.NatInterfaceContext = picb->pvNatContext;
  673. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  674. NULL,
  675. NULL,
  676. NULL,
  677. &IoStatusBlock,
  678. IOCTL_IP_NAT_UNBIND_INTERFACE,
  679. (PVOID)&ubiUnbindInfo,
  680. sizeof(IP_NAT_UNBIND_INTERFACE),
  681. NULL,
  682. 0);
  683. if(!NT_SUCCESS(ntStatus))
  684. {
  685. Trace2(ERR,
  686. "UnbindNatInterface: NtStatus %x setting binding for %S",
  687. ntStatus,
  688. picb->pwszName);
  689. }
  690. //
  691. // Blow away the proxy arp stuff
  692. //
  693. DeleteNatRangeFromProxyArp(picb);
  694. dwResult = DeleteNatContextFromIpStack(picb);
  695. if(dwResult isnot NO_ERROR)
  696. {
  697. Trace2(ERR,
  698. "UnbindNatInterface: Error %d removing context for %S",
  699. dwResult,
  700. picb->pwszName);
  701. }
  702. TraceLeave("UnbindNatInterface");
  703. return ntStatus;
  704. #endif
  705. }
  706. DWORD
  707. DeleteInterfaceFromNat(
  708. PICB picb
  709. )
  710. {
  711. #if 1
  712. return 0;
  713. #else
  714. IP_NAT_DELETE_INTERFACE DeleteInfo;
  715. NTSTATUS ntStatus;
  716. IO_STATUS_BLOCK IoStatusBlock;
  717. DWORD dwResult;
  718. TraceEnter("DeleteInterfaceFromNat");
  719. IpRtAssert((picb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  720. (picb->ritType isnot ROUTER_IF_TYPE_LOOPBACK) and
  721. (picb->ritType isnot ROUTER_IF_TYPE_CLIENT));
  722. if(picb->pvNatContext is NULL)
  723. {
  724. Trace1(IF,
  725. "DeleteInterfaceFromNat: No context, assuming interface %S not added to NAT",
  726. picb->pwszName);
  727. TraceLeave("DeleteInterfaceFromNat");
  728. return NO_ERROR;
  729. }
  730. //
  731. // Non NULL pvContext means NAT must be running
  732. //
  733. IpRtAssert(g_bNatRunning);
  734. IpRtAssert(g_hNatDevice);
  735. //
  736. // Blow away any saved info
  737. //
  738. if(picb->pvNatInfo)
  739. {
  740. IpRtAssert(picb->ulNatInfoSize isnot 0);
  741. HeapFree(IPRouterHeap,
  742. 0,
  743. picb->pvNatInfo);
  744. picb->pvNatInfo = NULL;
  745. }
  746. picb->ulNatInfoSize = 0;
  747. DeleteInfo.NatInterfaceContext = picb->pvNatContext;
  748. dwResult = NO_ERROR;
  749. ntStatus = NtDeviceIoControlFile(g_hNatDevice,
  750. NULL,
  751. NULL,
  752. NULL,
  753. &IoStatusBlock,
  754. IOCTL_IP_NAT_DELETE_INTERFACE,
  755. (PVOID)&DeleteInfo,
  756. sizeof(IP_NAT_DELETE_INTERFACE),
  757. NULL,
  758. 0);
  759. if(!NT_SUCCESS(ntStatus))
  760. {
  761. Trace2(ERR,
  762. "DeleteInterfaceFromNat: NtStatus %x deleting %S",
  763. ntStatus,
  764. picb->pwszName);
  765. dwResult = ERROR_CAN_NOT_COMPLETE;
  766. }
  767. picb->pvNatContext = NULL;
  768. TraceLeave("DeleteInterfaceFromNat");
  769. return dwResult;
  770. #endif
  771. }
  772. DWORD
  773. SetNatContextToIpStack(
  774. PICB picb
  775. )
  776. /*++
  777. Routine Description
  778. Sets the NAT context as the FIREWALL context in IP
  779. Can only be called if NAT is running
  780. Locks
  781. The ICB list should be held atleast as READER
  782. Arguments
  783. picb ICB for the interface
  784. Return Value
  785. NO_ERROR
  786. --*/
  787. {
  788. #if 1
  789. return 0;
  790. #else
  791. NTSTATUS ntStatus;
  792. IO_STATUS_BLOCK IoStatusBlock;
  793. DWORD dwResult;
  794. IP_SET_IF_CONTEXT_INFO info;
  795. TraceEnter("SetNatContextToIpStack");
  796. IpRtAssert((picb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  797. (picb->ritType isnot ROUTER_IF_TYPE_LOOPBACK) and
  798. (picb->ritType isnot ROUTER_IF_TYPE_CLIENT));
  799. if(picb->pvNatContext is NULL)
  800. {
  801. Trace1(IF,
  802. "SetNatContextToIpStack: No context, assuming interface %S not added to NAT",
  803. picb->pwszName);
  804. return NO_ERROR;
  805. }
  806. if(picb->bBound is FALSE)
  807. {
  808. Trace1(IF,
  809. "SetNatContextToIpStack: Not setting context for %S since it is not bound",
  810. picb->pwszName);
  811. TraceLeave("SetNatContextToIpStack");
  812. return NO_ERROR;
  813. }
  814. info.Index = picb->dwAdapterId;
  815. info.Context = picb->pvNatContext;
  816. ntStatus = NtDeviceIoControlFile(g_hIpDevice,
  817. NULL,
  818. NULL,
  819. NULL,
  820. &IoStatusBlock,
  821. IOCTL_IP_SET_FIREWALL_IF,
  822. (PVOID)&info,
  823. sizeof(IP_SET_IF_CONTEXT_INFO),
  824. NULL,
  825. 0);
  826. if(!NT_SUCCESS(ntStatus))
  827. {
  828. Trace2(ERR,
  829. "SetNatContextToIpStack: NtStatus %x while setting context for %S",
  830. ntStatus,
  831. picb->pwszName);
  832. TraceLeave("SetNatContextToIpStack");
  833. return ntStatus;
  834. }
  835. TraceLeave("SetNatContextToIpStack");
  836. return NO_ERROR;
  837. #endif
  838. }
  839. DWORD
  840. DeleteNatContextFromIpStack(
  841. PICB picb
  842. )
  843. /*++
  844. Routine Description
  845. Deletes the the NAT context as the FIREWALL context in IP by setting it
  846. to NULL
  847. Can only be called if NAT is running
  848. Locks
  849. The ICB list should be held as WRITER
  850. Arguments
  851. picb ICB for the interface
  852. Return Value
  853. NO_ERROR
  854. --*/
  855. {
  856. #if 1
  857. return 0;
  858. #else
  859. NTSTATUS ntStatus;
  860. IO_STATUS_BLOCK IoStatusBlock;
  861. DWORD dwResult;
  862. IP_SET_IF_CONTEXT_INFO info;
  863. TraceEnter("DeleteNatContextFromIpStack");
  864. IpRtAssert((picb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  865. (picb->ritType isnot ROUTER_IF_TYPE_LOOPBACK) and
  866. (picb->ritType isnot ROUTER_IF_TYPE_CLIENT));
  867. if(picb->pvNatContext is NULL)
  868. {
  869. Trace1(IF,
  870. "DeleteNatContextFromIpStack: No context, assuming interface %S not added to NAT",
  871. picb->pwszName);
  872. return NO_ERROR;
  873. }
  874. if(picb->bBound is FALSE)
  875. {
  876. Trace1(IF,
  877. "DeleteNatContextFromIpStack: Not deleting context for %S since it is not bound",
  878. picb->pwszName);
  879. TraceLeave("DeleteNatContextFromIpStack");
  880. return NO_ERROR;
  881. }
  882. info.Index = picb->dwAdapterId;
  883. info.Context = NULL;
  884. ntStatus = NtDeviceIoControlFile(g_hIpDevice,
  885. NULL,
  886. NULL,
  887. NULL,
  888. &IoStatusBlock,
  889. IOCTL_IP_SET_FIREWALL_IF,
  890. (PVOID)&info,
  891. sizeof(IP_SET_IF_CONTEXT_INFO),
  892. NULL,
  893. 0);
  894. if(!NT_SUCCESS(ntStatus))
  895. {
  896. Trace2(ERR,
  897. "DeleteNatContextFromIpStack: NtStatus %x while deleting context for %S",
  898. ntStatus,
  899. picb->pwszName);
  900. TraceLeave("DeleteNatContextFromIpStack");
  901. return ntStatus;
  902. }
  903. TraceLeave("DeleteNatContextFromIpStack");
  904. return NO_ERROR;
  905. #endif
  906. }
  907. VOID
  908. SetNatRangeForProxyArp(
  909. PICB picb
  910. )
  911. /*++
  912. Routine Description
  913. This functions adds any address ranges in the NAT info as Proxy Arp
  914. addresses
  915. Locks
  916. ICB_LIST locked as writer
  917. Arguments
  918. picb ICB of the interface whose nat info is being added
  919. Return Value
  920. NONE we log the errors, there isnt much to do with an error code
  921. --*/
  922. {
  923. #if 1
  924. return;
  925. #else
  926. DWORD dwResult, dwAddr, dwStartAddr, dwEndAddr, i;
  927. PIP_NAT_INTERFACE_INFO pNatInfo;
  928. PIP_NAT_ADDRESS_RANGE pRange;
  929. //
  930. // Only do this if we have a valid adapter index and this is a LAN
  931. // interface
  932. //
  933. if((picb->dwOperationalState < MIB_IF_OPER_STATUS_CONNECTED) or
  934. (picb->ritType isnot ROUTER_IF_TYPE_DEDICATED))
  935. {
  936. return;
  937. }
  938. IpRtAssert(picb->bBound);
  939. IpRtAssert(picb->dwAdapterId isnot INVALID_ADAPTER_ID);
  940. pNatInfo = picb->pvNatInfo;
  941. //
  942. // Now, if we have ranges, we need to set the proxy arp addresses on them
  943. //
  944. for(i = 0; i < pNatInfo->Header.TocEntriesCount; i++)
  945. {
  946. if(pNatInfo->Header.TocEntry[i].InfoType isnot IP_NAT_ADDRESS_RANGE_TYPE)
  947. {
  948. continue;
  949. }
  950. if(pNatInfo->Header.TocEntry[i].InfoSize is 0)
  951. {
  952. continue;
  953. }
  954. //
  955. // Here we are adding potentially duplicate PARP entries.
  956. // Hopefully, IP knows how to handle it
  957. //
  958. pRange = GetInfoFromTocEntry(&(pNatInfo->Header),
  959. &(pNatInfo->Header.TocEntry[i]));
  960. //
  961. // Convert to little endian
  962. //
  963. dwStartAddr = ntohl(pRange->StartAddress);
  964. dwEndAddr = ntohl(pRange->EndAddress);
  965. for(dwAddr = dwStartAddr;
  966. dwAddr <= dwEndAddr;
  967. dwAddr++)
  968. {
  969. DWORD dwNetAddr, dwClassMask;
  970. dwNetAddr = htonl(dwAddr);
  971. //
  972. // Throw away useless addresses and then set proxy arp entries
  973. //
  974. dwClassMask = GetClassMask(dwNetAddr);
  975. if(((dwNetAddr & ~pRange->SubnetMask) is 0) or
  976. (dwNetAddr is (dwNetAddr & ~pRange->SubnetMask)) or
  977. ((dwNetAddr & ~dwClassMask) is 0) or
  978. (dwNetAddr is (dwNetAddr & ~dwClassMask)))
  979. {
  980. continue;
  981. }
  982. dwResult = SetProxyArpEntryToStack(dwNetAddr,
  983. 0xFFFFFFFF,
  984. picb->dwAdapterId,
  985. TRUE,
  986. FALSE);
  987. if(dwResult isnot NO_ERROR)
  988. {
  989. Trace4(ERR,
  990. "SetProxy: Error %x setting %d.%d.%d.%d over adapter %d (%S)",
  991. dwResult,
  992. PRINT_IPADDR(dwNetAddr),
  993. picb->dwAdapterId,
  994. picb->pwszName);
  995. }
  996. }
  997. }
  998. #endif
  999. }
  1000. VOID
  1001. DeleteNatRangeFromProxyArp(
  1002. PICB picb
  1003. )
  1004. /*++
  1005. Routine Description
  1006. This removes the previously added proxy arp addresses
  1007. Locks
  1008. ICB_LIST lock taken as writer
  1009. Arguments
  1010. picb The icb of the interface whose addr range info needs to be removed
  1011. Return Value
  1012. NONE
  1013. --*/
  1014. {
  1015. #if 1
  1016. return;
  1017. #else
  1018. DWORD dwResult, dwAddr, dwStartAddr, dwEndAddr, i;
  1019. PIP_NAT_INTERFACE_INFO pNatInfo;
  1020. PIP_NAT_ADDRESS_RANGE pRange;
  1021. //
  1022. // Only do this if we have a valid adapter index and this is a LAN
  1023. // interface
  1024. //
  1025. if((picb->dwOperationalState < MIB_IF_OPER_STATUS_CONNECTED) or
  1026. (picb->ritType isnot ROUTER_IF_TYPE_DEDICATED))
  1027. {
  1028. return;
  1029. }
  1030. IpRtAssert(picb->bBound);
  1031. pNatInfo = picb->pvNatInfo;
  1032. for(i = 0; i < pNatInfo->Header.TocEntriesCount; i++)
  1033. {
  1034. if(pNatInfo->Header.TocEntry[i].InfoType isnot IP_NAT_ADDRESS_RANGE_TYPE)
  1035. {
  1036. continue;
  1037. }
  1038. if(pNatInfo->Header.TocEntry[i].InfoSize is 0)
  1039. {
  1040. continue;
  1041. }
  1042. //
  1043. // Here we are adding potentially duplicate PARP entries.
  1044. // Hopefully, IP knows how to handle it
  1045. //
  1046. pRange = GetInfoFromTocEntry(&(pNatInfo->Header),
  1047. &(pNatInfo->Header.TocEntry[i]));
  1048. dwStartAddr = ntohl(pRange->StartAddress);
  1049. dwEndAddr = ntohl(pRange->EndAddress);
  1050. for(dwAddr = dwStartAddr;
  1051. dwAddr <= dwEndAddr;
  1052. dwAddr++)
  1053. {
  1054. DWORD dwNetAddr, dwClassMask;
  1055. dwNetAddr = htonl(dwAddr);
  1056. //
  1057. // Throw away useless addresses and then set proxy arp entries
  1058. //
  1059. dwClassMask = GetClassMask(dwNetAddr);
  1060. if(((dwNetAddr & ~pRange->SubnetMask) is 0) or
  1061. (dwNetAddr is (dwNetAddr & ~pRange->SubnetMask)) or
  1062. ((dwNetAddr & ~dwClassMask) is 0) or
  1063. (dwNetAddr is (dwNetAddr & ~dwClassMask)))
  1064. {
  1065. continue;
  1066. }
  1067. dwResult = SetProxyArpEntryToStack(dwNetAddr,
  1068. 0xFFFFFFFF,
  1069. picb->dwAdapterId,
  1070. FALSE,
  1071. FALSE);
  1072. if(dwResult isnot NO_ERROR)
  1073. {
  1074. Trace4(ERR,
  1075. "DeleteProxy: Error %x removing %d.%d.%d.%d over adapter %d (%S)",
  1076. dwResult,
  1077. PRINT_IPADDR(dwNetAddr),
  1078. picb->dwAdapterId,
  1079. picb->pwszName);
  1080. }
  1081. }
  1082. }
  1083. #endif
  1084. }
  1085. DWORD
  1086. GetNumNatMappings(
  1087. PICB picb,
  1088. PULONG pulNatMappings
  1089. )
  1090. /*++
  1091. Routine Description
  1092. This function queries the NAT with a minimum sized buffer to figure out
  1093. the number of mappings
  1094. Can only be called if NAT is running
  1095. Locks
  1096. ICB_LIST lock held as READER
  1097. Arguments
  1098. picb, ICB of interface whose map count needs to be queried
  1099. pulNatMappings Number of mappings
  1100. Return Value
  1101. NO_ERROR
  1102. --*/
  1103. {
  1104. #if 1
  1105. return 0;
  1106. #else
  1107. DWORD dwResult;
  1108. IP_NAT_INTERFACE_STATISTICS stats;
  1109. *pulNatMappings = 0;
  1110. dwResult = GetNatStatistics(picb,
  1111. &stats);
  1112. if(dwResult is NO_ERROR)
  1113. {
  1114. *pulNatMappings = stats.TotalMappings;
  1115. }
  1116. return dwResult;
  1117. #endif
  1118. }
  1119. DWORD
  1120. GetNatMappings(
  1121. PICB picb,
  1122. PIP_NAT_ENUMERATE_SESSION_MAPPINGS pBuffer,
  1123. DWORD dwSize
  1124. )
  1125. /*++
  1126. Routine Description
  1127. This function gets the mappings on the interface
  1128. Can only be called if NAT is running
  1129. Locks
  1130. ICB_LIST held as READER
  1131. Arguments
  1132. picb
  1133. pBuffer
  1134. pdwSize
  1135. Return Value
  1136. None
  1137. --*/
  1138. {
  1139. #if 1
  1140. return 0;
  1141. #else
  1142. IO_STATUS_BLOCK IoStatusBlock;
  1143. NTSTATUS nStatus;
  1144. if(picb->pvNatContext is NULL)
  1145. {
  1146. return ERROR_SERVICE_NOT_ACTIVE;
  1147. }
  1148. IpRtAssert(dwSize >= sizeof(IP_NAT_ENUMERATE_SESSION_MAPPINGS));
  1149. //
  1150. // Zero out the context and stuff
  1151. //
  1152. ZeroMemory(pBuffer,
  1153. sizeof(IP_NAT_ENUMERATE_SESSION_MAPPINGS));
  1154. pBuffer->NatInterfaceContext = picb->pvNatContext;
  1155. nStatus = NtDeviceIoControlFile(g_hNatDevice,
  1156. NULL,
  1157. NULL,
  1158. NULL,
  1159. &IoStatusBlock,
  1160. IOCTL_IP_NAT_ENUMERATE_SESSION_MAPPINGS,
  1161. (PVOID)pBuffer,
  1162. dwSize,
  1163. (PVOID)pBuffer,
  1164. dwSize);
  1165. if(!NT_SUCCESS(nStatus))
  1166. {
  1167. Trace1(ERR,
  1168. "GetNumNatMappings: NtStatus %x",
  1169. nStatus);
  1170. return ERROR_CAN_NOT_COMPLETE;
  1171. }
  1172. return NO_ERROR;
  1173. #endif
  1174. }
  1175. DWORD
  1176. GetNatStatistics(
  1177. PICB picb,
  1178. PIP_NAT_INTERFACE_STATISTICS pBuffer
  1179. )
  1180. /*++
  1181. Routine Description
  1182. This function retrieves the nat interface statistics into the supplied
  1183. buffer
  1184. Locks
  1185. ICB_LIST lock held as READER
  1186. Arguments
  1187. picb
  1188. pBuffer
  1189. Return Value
  1190. None
  1191. --*/
  1192. {
  1193. #if 1
  1194. return 0;
  1195. #else
  1196. IO_STATUS_BLOCK IoStatusBlock;
  1197. NTSTATUS nStatus;
  1198. if(picb->pvNatContext is NULL)
  1199. {
  1200. return ERROR_SERVICE_NOT_ACTIVE;
  1201. }
  1202. pBuffer->NatInterfaceContext = picb->pvNatContext;
  1203. nStatus = NtDeviceIoControlFile(g_hNatDevice,
  1204. NULL,
  1205. NULL,
  1206. NULL,
  1207. &IoStatusBlock,
  1208. IOCTL_IP_NAT_GET_INTERFACE_STATISTICS,
  1209. (PVOID)pBuffer,
  1210. sizeof(IP_NAT_INTERFACE_STATISTICS),
  1211. (PVOID)pBuffer,
  1212. sizeof(IP_NAT_INTERFACE_STATISTICS));
  1213. if(!NT_SUCCESS(nStatus))
  1214. {
  1215. Trace1(ERR,
  1216. "GetNatStatistics: NtStatus %x",
  1217. nStatus);
  1218. return ERROR_CAN_NOT_COMPLETE;
  1219. }
  1220. return NO_ERROR;
  1221. #endif
  1222. }