Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3951 lines
113 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. ntip.c
  5. Abstract:
  6. NT specific routines for loading and configuring the IP driver.
  7. Author:
  8. Mike Massa (mikemas) Aug 13, 1993
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 08-13-93 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #include "iproute.h"
  17. #include "lookup.h"
  18. #include "iprtdef.h"
  19. #include "internaldef.h"
  20. #include "tcp.h"
  21. #include "tcpipbuf.h"
  22. #include "mdlpool.h"
  23. //
  24. // definitions needed by inet_addr.
  25. //
  26. #define INADDR_NONE 0xffffffff
  27. #define INADDR_ANY 0
  28. #define htonl(x) net_long(x)
  29. //
  30. // Other local constants
  31. //
  32. #define WORK_BUFFER_SIZE 256
  33. // size of nte context value in string form
  34. #define NTE_CONTEXT_SIZE (sizeof(uint)*2+2) // 0xAABBCCDD
  35. //
  36. // Configuration defaults
  37. //
  38. #define DEFAULT_IGMP_LEVEL 2
  39. #define DEFAULT_IP_NETS 8
  40. #if MILLEN
  41. // On Win9x, this will help boot time and resume time.
  42. #define DEFAULT_ARPRETRY_COUNT 1
  43. #else // MILLEN
  44. #define DEFAULT_ARPRETRY_COUNT 3
  45. #endif // !MILLEN
  46. //
  47. // Local types
  48. //
  49. typedef struct _PerNetConfigInfo {
  50. uint UseZeroBroadcast;
  51. uint Mtu;
  52. uint NumberOfGateways;
  53. uint MaxForwardPending; // max routing packets pending
  54. } PER_NET_CONFIG_INFO, *PPER_NET_CONFIG_INFO;
  55. //
  56. // Global variables.
  57. //
  58. PDRIVER_OBJECT IPDriverObject;
  59. PDEVICE_OBJECT IPDeviceObject;
  60. HANDLE IPProviderHandle = NULL;
  61. #if IPMCAST
  62. PDEVICE_OBJECT IpMcastDeviceObject;
  63. NTSTATUS
  64. InitializeIpMcast(
  65. IN PDRIVER_OBJECT DriverObject,
  66. IN PUNICODE_STRING RegistryPath,
  67. OUT PDEVICE_OBJECT * ppIpMcastDevice
  68. );
  69. VOID
  70. DeinitializeIpMcast(
  71. IN PDEVICE_OBJECT DeviceObject
  72. );
  73. #endif // IPMCAST
  74. IPConfigInfo *IPConfiguration;
  75. uint ArpUseEtherSnap = FALSE;
  76. uint ArpAlwaysSourceRoute = FALSE;
  77. uint IPAlwaysSourceRoute = TRUE;
  78. extern uint DisableIPSourceRouting;
  79. uint ArpCacheLife = DEFAULT_ARP_CACHE_LIFE;
  80. uint ArpRetryCount = DEFAULT_ARPRETRY_COUNT;
  81. uint ArpMinValidCacheLife = DEFAULT_ARP_MIN_VALID_CACHE_LIFE;
  82. uint DisableMediaSense = 0;
  83. uint DisableMediaSenseEventLog;
  84. uint EnableBcastArpReply = TRUE;
  85. #if MILLEN
  86. // Millennium does not support task offload.
  87. uint DisableTaskOffload = TRUE;
  88. #else // MILLEN
  89. uint DisableTaskOffload = FALSE;
  90. #endif // !MILLEN
  91. uint DisableUserTOS = TRUE;
  92. extern uint MaxRH;
  93. extern uint NET_TABLE_SIZE;
  94. extern uint DampingInterval;
  95. extern uint ConnectDampingInterval;
  96. // Used in the conversion of 100ns times to milliseconds.
  97. static LARGE_INTEGER Magic10000 =
  98. {0xe219652c, 0xd1b71758};
  99. //
  100. // External variables
  101. //
  102. extern LIST_ENTRY PendingEchoList; // def needed for initialization
  103. extern LIST_ENTRY PendingIPSetNTEAddrList; // def needed for initialization
  104. extern LIST_ENTRY PendingIPEventList; // def needed for initialization
  105. extern LIST_ENTRY PendingEnableRouterList; // def needed for initialization
  106. extern LIST_ENTRY PendingArpSendList; // def needed for initialization
  107. extern LIST_ENTRY PendingMediaSenseRequestList;
  108. CTEBlockStruc TcpipUnloadBlock; // Structure for blocking at time of unload
  109. extern CACHE_LINE_KSPIN_LOCK ArpInterfaceListLock;
  110. BOOLEAN fRouteTimerStopping = FALSE;
  111. extern CTETimer IPRouteTimer;
  112. extern LIST_ENTRY ArpInterfaceList;
  113. extern HANDLE IpHeaderPool;
  114. DEFINE_LOCK_STRUCTURE(ArpModuleLock)
  115. extern void FreeFirewallQ(void);
  116. extern VOID TCPUnload(IN PDRIVER_OBJECT DriverObject);
  117. extern uint EnableICMPRedirects;
  118. extern NDIS_HANDLE NdisPacketPool;
  119. extern NDIS_HANDLE TDPacketPool;
  120. extern NDIS_HANDLE TDBufferPool;
  121. extern TDIEntityID* IPEntityList;
  122. extern uint IPEntityCount;
  123. extern PWSTR IPBindList;
  124. KMUTEX NTEContextMutex;
  125. int ARPInit();
  126. //
  127. // Macros
  128. //
  129. //++
  130. //
  131. // LARGE_INTEGER
  132. // CTEConvertMillisecondsTo100ns(
  133. // IN LARGE_INTEGER MsTime
  134. // );
  135. //
  136. // Routine Description:
  137. //
  138. // Converts time expressed in hundreds of nanoseconds to milliseconds.
  139. //
  140. // Arguments:
  141. //
  142. // MsTime - Time in milliseconds.
  143. //
  144. // Return Value:
  145. //
  146. // Time in hundreds of nanoseconds.
  147. //
  148. //--
  149. #define CTEConvertMillisecondsTo100ns(MsTime) \
  150. RtlExtendedIntegerMultiply(MsTime, 10000)
  151. //++
  152. //
  153. // LARGE_INTEGER
  154. // CTEConvert100nsToMilliseconds(
  155. // IN LARGE_INTEGER HnsTime
  156. // );
  157. //
  158. // Routine Description:
  159. //
  160. // Converts time expressed in hundreds of nanoseconds to milliseconds.
  161. //
  162. // Arguments:
  163. //
  164. // HnsTime - Time in hundreds of nanoseconds.
  165. //
  166. // Return Value:
  167. //
  168. // Time in milliseconds.
  169. //
  170. //--
  171. #define SHIFT10000 13
  172. extern LARGE_INTEGER Magic10000;
  173. #define CTEConvert100nsToMilliseconds(HnsTime) \
  174. RtlExtendedMagicDivide((HnsTime), Magic10000, SHIFT10000)
  175. //
  176. // External function prototypes
  177. //
  178. extern int
  179. IPInit(
  180. void
  181. );
  182. long
  183. IPSetInfo(
  184. TDIObjectID * ID,
  185. void *Buffer,
  186. uint Size
  187. );
  188. NTSTATUS
  189. IPDispatch(
  190. IN PDEVICE_OBJECT DeviceObject,
  191. IN PIRP Irp
  192. );
  193. NTSTATUS
  194. OpenRegKey(
  195. PHANDLE HandlePtr,
  196. PWCHAR KeyName
  197. );
  198. NTSTATUS
  199. GetRegDWORDValue(
  200. HANDLE KeyHandle,
  201. PWCHAR ValueName,
  202. PULONG ValueData
  203. );
  204. NTSTATUS
  205. GetRegLARGEINTValue(
  206. HANDLE KeyHandle,
  207. PWCHAR ValueName,
  208. PLARGE_INTEGER ValueData
  209. );
  210. NTSTATUS
  211. SetRegDWORDValue(
  212. HANDLE KeyHandle,
  213. PWCHAR ValueName,
  214. PULONG ValueData
  215. );
  216. NTSTATUS
  217. GetRegSZValue(
  218. HANDLE KeyHandle,
  219. PWCHAR ValueName,
  220. PUNICODE_STRING ValueData,
  221. PULONG ValueType
  222. );
  223. NTSTATUS
  224. GetRegMultiSZValue(
  225. HANDLE KeyHandle,
  226. PWCHAR ValueName,
  227. PUNICODE_STRING ValueData
  228. );
  229. NTSTATUS
  230. GetRegMultiSZValueNew(
  231. HANDLE KeyHandle,
  232. PWCHAR ValueName,
  233. PUNICODE_STRING_NEW ValueData
  234. );
  235. NTSTATUS
  236. InitRegDWORDParameter(
  237. HANDLE RegKey,
  238. PWCHAR ValueName,
  239. ULONG * Value,
  240. ULONG DefaultValue
  241. );
  242. uint
  243. RTReadNext(
  244. void *Context,
  245. void *Buffer
  246. );
  247. uint
  248. RTValidateContext(
  249. void *Context,
  250. uint * Valid
  251. );
  252. extern NTSTATUS
  253. SetRegMultiSZValue(
  254. HANDLE KeyHandle,
  255. PWCHAR ValueName,
  256. PUNICODE_STRING ValueData
  257. );
  258. extern NTSTATUS
  259. SetRegMultiSZValueNew(
  260. HANDLE KeyHandle,
  261. PWCHAR ValueName,
  262. PUNICODE_STRING_NEW ValueData
  263. );
  264. //
  265. // Local funcion prototypes
  266. //
  267. NTSTATUS
  268. IPDriverEntry(
  269. IN PDRIVER_OBJECT DriverObject,
  270. IN PUNICODE_STRING RegistryPath
  271. );
  272. NTSTATUS
  273. IPProcessConfiguration(
  274. VOID
  275. );
  276. NTSTATUS
  277. IPProcessAdapterSection(
  278. WCHAR * DeviceName,
  279. WCHAR * AdapterName
  280. );
  281. uint
  282. GetGeneralIFConfig(
  283. IFGeneralConfig * ConfigInfo,
  284. NDIS_HANDLE Handle,
  285. PNDIS_STRING ConfigName
  286. );
  287. int
  288. IsLLInterfaceValueNull(
  289. NDIS_HANDLE Handle
  290. );
  291. NTSTATUS
  292. GetLLInterfaceValue(
  293. NDIS_HANDLE Handle,
  294. PNDIS_STRING valueString
  295. );
  296. IFAddrList *
  297. GetIFAddrList(
  298. UINT * NumAddr,
  299. NDIS_HANDLE Handle,
  300. UINT * EnableDhcp,
  301. BOOLEAN PppIf,
  302. PNDIS_STRING ConfigName
  303. );
  304. UINT
  305. OpenIFConfig(
  306. PNDIS_STRING ConfigName,
  307. NDIS_HANDLE * Handle
  308. );
  309. VOID
  310. CloseIFConfig(
  311. NDIS_HANDLE Handle
  312. );
  313. IPConfigInfo *
  314. IPGetConfig(
  315. void
  316. );
  317. void
  318. IPFreeConfig(
  319. IPConfigInfo * ConfigInfo
  320. );
  321. ulong
  322. GetGMTDelta(
  323. void
  324. );
  325. ulong
  326. GetTime(
  327. void
  328. );
  329. BOOLEAN
  330. IPConvertStringToAddress(
  331. IN PWCHAR AddressString,
  332. OUT PULONG IpAddress
  333. );
  334. uint
  335. UseEtherSNAP(
  336. PNDIS_STRING Name
  337. );
  338. void
  339. GetAlwaysSourceRoute(
  340. uint * pArpAlwaysSourceRoute,
  341. uint * pIPAlwaysSourceRoute
  342. );
  343. uint
  344. GetArpCacheLife(
  345. void
  346. );
  347. uint
  348. GetArpRetryCount(
  349. void
  350. );
  351. ULONG
  352. RouteMatch(
  353. IN WCHAR * RouteString,
  354. IN IPAddr Address,
  355. IN IPMask Mask,
  356. OUT IPAddr * DestVal,
  357. OUT IPMask * DestMask,
  358. OUT IPAddr * GateVal,
  359. OUT ULONG * Metric
  360. );
  361. VOID
  362. SetPersistentRoutesForNTE(
  363. IPAddr Address,
  364. IPMask Mask,
  365. ULONG IFIndex
  366. );
  367. BOOLEAN
  368. GetTempDHCPAddr(
  369. NDIS_HANDLE Handle,
  370. IPAddr * Tempdhcpaddr,
  371. IPAddr * TempMask,
  372. IPAddr * TempGWAddr,
  373. PNDIS_STRING ConfigName
  374. );
  375. #ifdef ALLOC_PRAGMA
  376. #if !MILLEN
  377. #pragma alloc_text(INIT, IPDriverEntry)
  378. #endif // !MILLEN
  379. #pragma alloc_text(INIT, IPProcessConfiguration)
  380. #pragma alloc_text(INIT, IPProcessAdapterSection)
  381. #pragma alloc_text(INIT, IPGetConfig)
  382. #pragma alloc_text(INIT, IPFreeConfig)
  383. #pragma alloc_text(INIT, GetGMTDelta)
  384. #pragma alloc_text(PAGE, GetGeneralIFConfig)
  385. #pragma alloc_text(PAGE, IsLLInterfaceValueNull)
  386. #pragma alloc_text(PAGE, GetLLInterfaceValue)
  387. #pragma alloc_text(PAGE, GetIFAddrList)
  388. #pragma alloc_text(PAGE, UseEtherSNAP)
  389. #pragma alloc_text(PAGE, GetAlwaysSourceRoute)
  390. #pragma alloc_text(PAGE, GetArpCacheLife)
  391. #pragma alloc_text(PAGE, GetArpRetryCount)
  392. #if !MILLEN
  393. #pragma alloc_text(PAGE, OpenIFConfig)
  394. #pragma alloc_text(PAGE, CloseIFConfig)
  395. #pragma alloc_text(PAGE, RouteMatch)
  396. #pragma alloc_text(PAGE, IPConvertStringToAddress)
  397. #endif // !MILLEN
  398. #endif // ALLOC_PRAGMA
  399. //
  400. // Function definitions
  401. //
  402. NTSTATUS
  403. IPDriverEntry(
  404. IN PDRIVER_OBJECT DriverObject,
  405. IN PUNICODE_STRING RegistryPath
  406. )
  407. /*++
  408. Routine Description:
  409. Initialization routine for the IP driver.
  410. Arguments:
  411. DriverObject - Pointer to the IP driver object created by the system.
  412. DeviceDescription - The name of IP's node in the registry.
  413. Return Value:
  414. The final status from the initialization operation.
  415. --*/
  416. {
  417. NTSTATUS status;
  418. UNICODE_STRING deviceName;
  419. UNICODE_STRING SymbolicDeviceName;
  420. DEBUGMSG(DBG_TRACE && DBG_INIT,
  421. (DTEXT("+IPDriverEntry(%x, %x)\n"),
  422. DriverObject, RegistryPath));
  423. IPDriverObject = DriverObject;
  424. //
  425. // Create the device object. IoCreateDevice zeroes the memory
  426. // occupied by the object.
  427. //
  428. RtlInitUnicodeString(&deviceName, DD_IP_DEVICE_NAME);
  429. RtlInitUnicodeString(&SymbolicDeviceName, DD_IP_SYMBOLIC_DEVICE_NAME);
  430. status = IoCreateDevice(
  431. DriverObject,
  432. 0,
  433. &deviceName,
  434. FILE_DEVICE_NETWORK,
  435. FILE_DEVICE_SECURE_OPEN,
  436. FALSE,
  437. &IPDeviceObject
  438. );
  439. if (!NT_SUCCESS(status)) {
  440. CTELogEvent(
  441. DriverObject,
  442. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  443. 1,
  444. 1,
  445. &deviceName.Buffer,
  446. 0,
  447. NULL
  448. );
  449. DEBUGMSG(DBG_ERROR && DBG_INIT,
  450. (DTEXT("IP init failed. Failure %x to create device object %ws\n"),
  451. status, DD_IP_DEVICE_NAME));
  452. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  453. return (status);
  454. }
  455. status = IoCreateSymbolicLink(&SymbolicDeviceName, &deviceName);
  456. if (!NT_SUCCESS(status)) {
  457. CTELogEvent(
  458. DriverObject,
  459. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  460. 1,
  461. 1,
  462. &deviceName.Buffer,
  463. 0,
  464. NULL
  465. );
  466. DEBUGMSG(DBG_ERROR && DBG_INIT,
  467. (DTEXT("IP init failed. Failure %x to create symbolic device name %ws\n"),
  468. status, DD_IP_SYMBOLIC_DEVICE_NAME));
  469. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  470. return (status);
  471. }
  472. status = TdiRegisterProvider(&deviceName, &IPProviderHandle);
  473. if (!NT_SUCCESS(status)) {
  474. IoDeleteDevice(IPDeviceObject);
  475. DEBUGMSG(DBG_ERROR && DBG_INIT,
  476. (DTEXT("IP init failed. Failure %x to register provider\n"),
  477. status));
  478. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  479. return (status);
  480. }
  481. //
  482. // Intialize the device object.
  483. //
  484. IPDeviceObject->Flags |= DO_DIRECT_IO;
  485. //
  486. // Initialize the list of pending echo request IRPs.
  487. //
  488. InitializeListHead(&PendingEchoList);
  489. InitializeListHead(&PendingArpSendList);
  490. //
  491. // Initialize the list of pending SetAddr request IRPs.
  492. //
  493. InitializeListHead(&PendingIPSetNTEAddrList);
  494. //
  495. // Initialize the list of pending media sense event.
  496. //
  497. InitializeListHead(&PendingIPEventList);
  498. //
  499. // Initialize the list of pending enable-router requests.
  500. //
  501. InitializeListHead(&PendingEnableRouterList);
  502. //
  503. // Initialize the ARP interface list; used in ArpUnload to walk the
  504. // list of ARP IFs so UnBinds can be issued on these.
  505. //
  506. InitializeListHead(&ArpInterfaceList);
  507. //
  508. // Init the lock to protect this list
  509. //
  510. CTEInitLock(&ArpInterfaceListLock.Lock);
  511. //
  512. // Initialize the list of ARP modules
  513. //
  514. InitializeListHead(&ArpModuleList);
  515. CTEInitLock(&ArpModuleLock);
  516. // Initialize media sense request list
  517. InitializeListHead(&PendingMediaSenseRequestList);
  518. //
  519. // Initialize the NTE context-list mutex.
  520. //
  521. KeInitializeMutex(&NTEContextMutex, 0);
  522. //
  523. // Finally, read our configuration parameters from the registry.
  524. //
  525. status = IPProcessConfiguration();
  526. if (status != STATUS_SUCCESS) {
  527. if (IPProviderHandle) {
  528. TdiDeregisterProvider(IPProviderHandle);
  529. }
  530. IoDeleteDevice(IPDeviceObject);
  531. DEBUGMSG(DBG_ERROR && DBG_INIT,
  532. (DTEXT("IPDriverEntry: IPProcessConfiguration failure %x\n"), status));
  533. #if IPMCAST
  534. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  535. return status;
  536. #endif // IPMCAST
  537. }
  538. #if IPMCAST
  539. //
  540. // IP initialized successfully
  541. //
  542. IpMcastDeviceObject = NULL;
  543. status = InitializeIpMcast(DriverObject,
  544. RegistryPath,
  545. &IpMcastDeviceObject);
  546. if (status != STATUS_SUCCESS) {
  547. TCPTRACE(("IP initialization failed: Unable to initialize multicast. Status %x",
  548. status));
  549. /*
  550. CTELogEvent(DriverObject,
  551. EVENT_IPMCAST_INIT_FAILED,
  552. 1,
  553. 1,
  554. &deviceName.Buffer,
  555. 0,
  556. NULL);*/
  557. }
  558. //
  559. // Mcast init failures is not treated as fatal
  560. //
  561. status = STATUS_SUCCESS;
  562. #endif // IPMCAST
  563. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  564. return status;
  565. }
  566. //
  567. // Function definitions
  568. //
  569. NTSTATUS
  570. IPPostDriverEntry(
  571. IN PDRIVER_OBJECT DriverObject,
  572. IN PUNICODE_STRING RegistryPath
  573. )
  574. /*++
  575. Routine Description:
  576. Initialization routine for the IP driver.
  577. Arguments:
  578. DriverObject - Pointer to the IP driver object created by the system.
  579. DeviceDescription - The name of IP's node in the registry.
  580. Return Value:
  581. The final status from the initialization operation.
  582. --*/
  583. {
  584. UNREFERENCED_PARAMETER(DriverObject);
  585. UNREFERENCED_PARAMETER(RegistryPath);
  586. DEBUGMSG(DBG_TRACE && DBG_INIT,
  587. (DTEXT("+IPPostDriverEntry(%x, %x)\n"), DriverObject, RegistryPath));
  588. if (!ARPInit()) {
  589. DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("IPPostDriverEntry: ARPInit failure.\n")));
  590. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPPostDriverEntry [FAILURE]\n")));
  591. return IP_INIT_FAILURE; // Couldn't initialize ARP.
  592. }
  593. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPPostDriverEntry [SUCCESS]\n")));
  594. return IP_SUCCESS;
  595. }
  596. NTSTATUS
  597. IPProcessConfiguration(
  598. VOID
  599. )
  600. /*++
  601. Routine Description:
  602. Reads the IP configuration information from the registry and constructs
  603. the configuration structure expected by the IP driver.
  604. Arguments:
  605. None.
  606. Return Value:
  607. STATUS_SUCCESS or an error status if an operation fails.
  608. --*/
  609. {
  610. NTSTATUS status;
  611. HANDLE myRegKey = NULL;
  612. UNICODE_STRING bindString;
  613. WCHAR IPParametersRegistryKey[] =
  614. #if MILLEN
  615. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP";
  616. #else // MILLEN
  617. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters";
  618. WCHAR IPLinkageRegistryKey[] =
  619. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Linkage";
  620. #endif // !MILLEN
  621. uint ArpTRSingleRoute;
  622. MM_SYSTEMSIZE systemSize;
  623. ULONG ulongValue;
  624. const ULONG DefaultMaxNormLookupMem[] =
  625. {
  626. DEFAULT_MAX_NORM_LOOKUP_MEM_SMALL,
  627. DEFAULT_MAX_NORM_LOOKUP_MEM_MEDIUM,
  628. DEFAULT_MAX_NORM_LOOKUP_MEM_LARGE
  629. };
  630. const ULONG DefaultMaxFastLookupMem[] =
  631. {
  632. DEFAULT_MAX_FAST_LOOKUP_MEM_SMALL,
  633. DEFAULT_MAX_FAST_LOOKUP_MEM_MEDIUM,
  634. DEFAULT_MAX_FAST_LOOKUP_MEM_LARGE
  635. };
  636. const ULONG DefaultFastLookupLevels[] =
  637. {
  638. DEFAULT_EXPN_LEVELS_SMALL,
  639. DEFAULT_EXPN_LEVELS_MEDIUM,
  640. DEFAULT_EXPN_LEVELS_LARGE
  641. };
  642. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("+IPProcessConfiguration()\n")));
  643. bindString.Buffer = NULL;
  644. IPConfiguration = CTEAllocMemBoot(sizeof(IPConfigInfo));
  645. if (IPConfiguration == NULL) {
  646. CTELogEvent(
  647. IPDriverObject,
  648. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  649. 1,
  650. 0,
  651. NULL,
  652. 0,
  653. NULL
  654. );
  655. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPProcessConfiguration [NO_RESOURCES]\n")));
  656. return (STATUS_INSUFFICIENT_RESOURCES);
  657. }
  658. RtlZeroMemory(IPConfiguration, sizeof(IPConfigInfo));
  659. //
  660. // Process the Ip\Parameters section of the registry
  661. //
  662. status = OpenRegKey(&myRegKey, IPParametersRegistryKey);
  663. if (NT_SUCCESS(status)) {
  664. DEBUGMSG(DBG_INFO && DBG_INIT,
  665. (DTEXT("IPProcessConfiguration: Opened registry path %ws, initializing variables.\n"),
  666. IPParametersRegistryKey));
  667. //
  668. // Expected configuration values. We use reasonable defaults if they
  669. // aren't available for some reason.
  670. //
  671. status = GetRegDWORDValue(
  672. myRegKey,
  673. L"IpEnableRouter",
  674. (PULONG) &(IPConfiguration->ici_gateway)
  675. );
  676. #if MILLEN
  677. //
  678. // Backwards compatibility. If 'IpEnableRouter' key is not present, then
  679. // try to read legacy 'EnableRouting' key.
  680. //
  681. if (!NT_SUCCESS(status)) {
  682. status = GetRegDWORDValue(
  683. myRegKey,
  684. L"EnableRouting",
  685. &(IPConfiguration->ici_gateway)
  686. );
  687. }
  688. #endif // MILLEN
  689. if (!NT_SUCCESS(status)) {
  690. TCPTRACE((
  691. "IP: Unable to read IpEnableRouter value from the registry.\n"
  692. " Routing will be disabled.\n"
  693. ));
  694. IPConfiguration->ici_gateway = 0;
  695. }
  696. (VOID) InitRegDWORDParameter(
  697. myRegKey,
  698. L"EnableAddrMaskReply",
  699. (PULONG) &(IPConfiguration->ici_addrmaskreply),
  700. FALSE
  701. );
  702. //
  703. // Optional (hidden) values
  704. //
  705. status = InitRegDWORDParameter(
  706. myRegKey,
  707. L"ForwardBufferMemory",
  708. (PULONG) &(IPConfiguration->ici_fwbufsize),
  709. DEFAULT_FW_BUFSIZE
  710. );
  711. #if MILLEN
  712. //
  713. // Backwards compatibility. If the 'ForwardBufferMemory' value is not
  714. // present, then attempt to read legacy 'RoutingBufSize' value.
  715. //
  716. if (!NT_SUCCESS(status)) {
  717. InitRegDWORDParameter(
  718. myRegKey,
  719. L"RoutingBufSize",
  720. &(IPConfiguration->ici_fwbufsize),
  721. DEFAULT_FW_BUFSIZE
  722. );
  723. }
  724. #endif // MILLEN
  725. status = InitRegDWORDParameter(
  726. myRegKey,
  727. L"MaxForwardBufferMemory",
  728. (PULONG) &(IPConfiguration->ici_maxfwbufsize),
  729. DEFAULT_MAX_FW_BUFSIZE
  730. );
  731. #if MILLEN
  732. //
  733. // Backwards compatibility. If the 'MaxForwardBufferMemory' value is not
  734. // present, then attempt to read legacy 'MaxRoutingBufSize' value.
  735. //
  736. if (!NT_SUCCESS(status)) {
  737. InitRegDWORDParameter(
  738. myRegKey,
  739. L"MaxRoutingBufSize",
  740. &(IPConfiguration->ici_maxfwbufsize),
  741. DEFAULT_MAX_FW_BUFSIZE
  742. );
  743. }
  744. #endif // MILLEN
  745. (VOID) InitRegDWORDParameter(
  746. myRegKey,
  747. L"ForwardBroadcasts",
  748. (PULONG) &(IPConfiguration->ici_fwbcast),
  749. FALSE
  750. );
  751. status = InitRegDWORDParameter(
  752. myRegKey,
  753. L"NumForwardPackets",
  754. (PULONG) &(IPConfiguration->ici_fwpackets),
  755. DEFAULT_FW_PACKETS
  756. );
  757. #if MILLEN
  758. //
  759. // Backwards compatibility. If the 'NumForwardPackets' value is not
  760. // present, then attempt to read legacy 'RoutingPackets' value.
  761. //
  762. if (!NT_SUCCESS(status)) {
  763. InitRegDWORDParameter(
  764. myRegKey,
  765. L"RoutingPackets",
  766. &(IPConfiguration->ici_fwpackets),
  767. DEFAULT_FW_PACKETS
  768. );
  769. }
  770. #endif // MILLEN
  771. status = InitRegDWORDParameter(
  772. myRegKey,
  773. L"MaxNumForwardPackets",
  774. (PULONG) &(IPConfiguration->ici_maxfwpackets),
  775. DEFAULT_MAX_FW_PACKETS
  776. );
  777. #if MILLEN
  778. //
  779. // Backwards compatibility. If the 'MaxNumForwardPackets' value is not
  780. // present, then attempt to read legacy 'MaxRoutingPackets' value.
  781. //
  782. if (!NT_SUCCESS(status)) {
  783. InitRegDWORDParameter(
  784. myRegKey,
  785. L"MaxRoutingPackets",
  786. &(IPConfiguration->ici_maxfwpackets),
  787. DEFAULT_MAX_FW_PACKETS
  788. );
  789. }
  790. #endif // MILLEN
  791. (VOID) InitRegDWORDParameter(
  792. myRegKey,
  793. L"IGMPLevel",
  794. (PULONG) &(IPConfiguration->ici_igmplevel),
  795. DEFAULT_IGMP_LEVEL
  796. );
  797. status = InitRegDWORDParameter(
  798. myRegKey,
  799. L"EnableDeadGWDetect",
  800. (PULONG) &(IPConfiguration->ici_deadgwdetect),
  801. TRUE
  802. );
  803. #if MILLEN
  804. //
  805. // Backwards compatibility. If EnableDeadGWDetect key did not exist, then
  806. // check for the DeadGWDetect key. Same default value.
  807. //
  808. if (!NT_SUCCESS(status)) {
  809. InitRegDWORDParameter(
  810. myRegKey,
  811. L"DeadGWDetect",
  812. &(IPConfiguration->ici_deadgwdetect),
  813. TRUE
  814. );
  815. }
  816. #endif // MILLEN
  817. (VOID) InitRegDWORDParameter(
  818. myRegKey,
  819. L"EnablePMTUDiscovery",
  820. (PULONG) &(IPConfiguration->ici_pmtudiscovery),
  821. TRUE
  822. );
  823. (VOID) InitRegDWORDParameter(
  824. myRegKey,
  825. L"DefaultTTL",
  826. (PULONG) &(IPConfiguration->ici_ttl),
  827. DEFAULT_TTL
  828. );
  829. if (IPConfiguration->ici_ttl == 0) {
  830. IPConfiguration->ici_ttl = DEFAULT_TTL;
  831. }
  832. status = InitRegDWORDParameter(
  833. myRegKey,
  834. L"DefaultTOSValue",
  835. (PULONG) &(IPConfiguration->ici_tos),
  836. DEFAULT_TOS
  837. );
  838. #if MILLEN
  839. //
  840. // Backwards compatibility. Read 'DefaultTOS' if 'DefaultTOSValue' is
  841. // not present.
  842. //
  843. if (!NT_SUCCESS(status)) {
  844. InitRegDWORDParameter(
  845. myRegKey,
  846. L"DefaultTOS",
  847. &(IPConfiguration->ici_tos),
  848. DEFAULT_TOS
  849. );
  850. }
  851. #endif // MILLEN
  852. (VOID) InitRegDWORDParameter(
  853. myRegKey,
  854. L"DisableUserTOSSetting",
  855. (PULONG) &DisableUserTOS,
  856. TRUE
  857. );
  858. (VOID) InitRegDWORDParameter(
  859. myRegKey,
  860. L"EnableICMPRedirect",
  861. (PULONG) &EnableICMPRedirects,
  862. TRUE
  863. );
  864. // Get the system size - SMALL, MEDIUM, LARGE
  865. systemSize = MmQuerySystemSize();
  866. // Get the route lookup memory usage limits
  867. (VOID) InitRegDWORDParameter(
  868. myRegKey,
  869. L"MaxNormLookupMemory",
  870. (PULONG) &(IPConfiguration->ici_maxnormlookupmemory),
  871. DefaultMaxNormLookupMem[systemSize]
  872. );
  873. if (IPConfiguration->ici_maxnormlookupmemory
  874. < MINIMUM_MAX_NORM_LOOKUP_MEM) {
  875. IPConfiguration->ici_maxnormlookupmemory
  876. = MINIMUM_MAX_NORM_LOOKUP_MEM;
  877. }
  878. #if MILLEN
  879. IPConfiguration->ici_fastroutelookup = FALSE;
  880. #else // MILLEN
  881. // Are we a gateway ? Is this a medium or large
  882. // server ? If so, is fast routing enabled ?
  883. if (IPConfiguration->ici_gateway
  884. && MmIsThisAnNtAsSystem()
  885. && (systemSize > MmSmallSystem)) {
  886. (VOID) InitRegDWORDParameter(
  887. myRegKey,
  888. L"EnableFastRouteLookup",
  889. (PULONG) &(IPConfiguration->ici_fastroutelookup),
  890. FALSE
  891. );
  892. } else {
  893. IPConfiguration->ici_fastroutelookup = FALSE;
  894. }
  895. #endif // !MILLEN
  896. // If Fast lookup is enabled, get lookup params
  897. if (IPConfiguration->ici_fastroutelookup) {
  898. (VOID) InitRegDWORDParameter(
  899. myRegKey,
  900. L"FastRouteLookupLevels",
  901. (PULONG) &(IPConfiguration->ici_fastlookuplevels),
  902. DefaultFastLookupLevels[systemSize]
  903. );
  904. (VOID) InitRegDWORDParameter(
  905. myRegKey,
  906. L"MaxFastLookupMemory",
  907. (PULONG) &(IPConfiguration->ici_maxfastlookupmemory),
  908. DefaultMaxFastLookupMem[systemSize]
  909. );
  910. if (IPConfiguration->ici_maxfastlookupmemory
  911. < MINIMUM_MAX_FAST_LOOKUP_MEM) {
  912. IPConfiguration->ici_maxfastlookupmemory
  913. = MINIMUM_MAX_FAST_LOOKUP_MEM;
  914. }
  915. }
  916. (VOID) InitRegDWORDParameter(
  917. myRegKey,
  918. L"MaxEqualCostRoutes",
  919. &ulongValue,
  920. DEFAULT_MAX_EQUAL_COST_ROUTES
  921. );
  922. MaxEqualCostRoutes = (USHORT) ulongValue;
  923. if (MaxEqualCostRoutes > MAXIMUM_MAX_EQUAL_COST_ROUTES) {
  924. MaxEqualCostRoutes = DEFAULT_MAX_EQUAL_COST_ROUTES;
  925. }
  926. #if FFP_SUPPORT
  927. (VOID) InitRegDWORDParameter(
  928. myRegKey,
  929. L"FFPFastForwardingCacheSize",
  930. &FFPRegFastForwardingCacheSize,
  931. DEFAULT_FFP_FFWDCACHE_SIZE
  932. );
  933. (VOID) InitRegDWORDParameter(
  934. myRegKey,
  935. L"FFPControlFlags",
  936. &FFPRegControlFlags,
  937. DEFAULT_FFP_CONTROL_FLAGS
  938. );
  939. #endif // FFP_SUPPORT
  940. (VOID) InitRegDWORDParameter(
  941. myRegKey,
  942. L"TrFunctionalMcastAddress",
  943. (PULONG) &(IPConfiguration->ici_TrFunctionalMcst),
  944. TRUE
  945. );
  946. status = InitRegDWORDParameter(
  947. myRegKey,
  948. L"ArpUseEtherSnap",
  949. (PULONG) &ArpUseEtherSnap,
  950. FALSE
  951. );
  952. #if MILLEN
  953. //
  954. // Backwards compatibility. If the 'ArpUseEtherSnap' key does not exist,
  955. // then try to read the 'EtherSNAP' key.
  956. //
  957. if (!NT_SUCCESS(status)) {
  958. InitRegDWORDParameter(
  959. myRegKey,
  960. L"EtherSNAP",
  961. &ArpUseEtherSnap,
  962. FALSE
  963. );
  964. }
  965. #endif // MILLEN
  966. (VOID) InitRegDWORDParameter(
  967. myRegKey,
  968. L"DisableDHCPMediaSense",
  969. (PULONG) &DisableMediaSense,
  970. 0
  971. );
  972. (VOID) InitRegDWORDParameter(
  973. myRegKey,
  974. L"DisableMediaSenseEventLog",
  975. (PULONG) &DisableMediaSenseEventLog,
  976. #if MILLEN
  977. // This mediasense event log causes issues
  978. // on Windows ME. Since there is no
  979. // event log anyways, disable it.
  980. TRUE
  981. #else // MILLEN
  982. FALSE
  983. #endif // !MILLEN
  984. );
  985. //DisableIPSourceRouting == 2 drop it if SR option
  986. // is rcvd, without forwarding.
  987. (VOID) InitRegDWORDParameter(
  988. myRegKey,
  989. L"DisableIPSourceRouting",
  990. (PULONG) &DisableIPSourceRouting,
  991. 1
  992. );
  993. (VOID) InitRegDWORDParameter(
  994. myRegKey,
  995. L"MaximumReassemblyHeaders",
  996. (PULONG) &MaxRH,
  997. 100
  998. );
  999. (VOID) InitRegDWORDParameter(
  1000. myRegKey,
  1001. L"NetHashTableSize",
  1002. (PULONG) &NET_TABLE_SIZE,
  1003. 8
  1004. );
  1005. if (NET_TABLE_SIZE < 8) {
  1006. NET_TABLE_SIZE = 8;
  1007. } else if (NET_TABLE_SIZE > 0xffff) {
  1008. NET_TABLE_SIZE = 512;
  1009. } else {
  1010. NET_TABLE_SIZE = ComputeLargerOrEqualPowerOfTwo(NET_TABLE_SIZE);
  1011. }
  1012. // we check for the return status here because if this parameter was
  1013. // not defined, then we want the default behavior for both arp
  1014. // and ip broadcasts. For arp, the behavior is to not source route
  1015. // and source router alternately. For ip, it is to always source
  1016. // route. If the parameter is defined and is 0, then for arp the
  1017. // behavior does not change. For ip however, we do not source route
  1018. // at all. Ofcourse, when the parameter is set to a non-zero value,
  1019. // we always source route for both.
  1020. //
  1021. status = InitRegDWORDParameter(
  1022. myRegKey,
  1023. L"ArpAlwaysSourceRoute",
  1024. (PULONG) &ArpAlwaysSourceRoute,
  1025. FALSE
  1026. );
  1027. if (NT_SUCCESS(status)) {
  1028. IPAlwaysSourceRoute = ArpAlwaysSourceRoute;
  1029. }
  1030. (VOID) InitRegDWORDParameter(
  1031. myRegKey,
  1032. L"ArpTRSingleRoute",
  1033. (PULONG) &ArpTRSingleRoute,
  1034. FALSE
  1035. );
  1036. if (ArpTRSingleRoute) {
  1037. TrRii = TR_RII_SINGLE;
  1038. } else {
  1039. TrRii = TR_RII_ALL;
  1040. }
  1041. (VOID) InitRegDWORDParameter(
  1042. myRegKey,
  1043. L"ArpCacheLife",
  1044. (PULONG) &ArpCacheLife,
  1045. DEFAULT_ARP_CACHE_LIFE
  1046. );
  1047. (VOID) InitRegDWORDParameter(
  1048. myRegKey,
  1049. L"ArpCacheMinReferencedLife",
  1050. (PULONG) &ArpMinValidCacheLife,
  1051. DEFAULT_ARP_MIN_VALID_CACHE_LIFE
  1052. );
  1053. (VOID) InitRegDWORDParameter(
  1054. myRegKey,
  1055. L"ArpRetryCount",
  1056. (PULONG) &ArpRetryCount,
  1057. DEFAULT_ARPRETRY_COUNT
  1058. );
  1059. if (((int)ArpRetryCount < 0) || (ArpRetryCount > 3)) {
  1060. ArpRetryCount = DEFAULT_ARPRETRY_COUNT;
  1061. }
  1062. (VOID) InitRegDWORDParameter(
  1063. myRegKey,
  1064. L"EnableBcastArpReply",
  1065. (PULONG) &EnableBcastArpReply,
  1066. TRUE
  1067. );
  1068. (VOID) InitRegDWORDParameter(
  1069. myRegKey,
  1070. L"DisableTaskOffload",
  1071. (PULONG) &DisableTaskOffload,
  1072. #if MILLEN
  1073. TRUE
  1074. #else // MILLEN
  1075. FALSE
  1076. #endif // !MILLEN
  1077. );
  1078. (VOID) InitRegDWORDParameter(
  1079. myRegKey,
  1080. L"ConnectDampInterval",
  1081. (PULONG) &ConnectDampingInterval,
  1082. 5
  1083. );
  1084. ConnectDampingInterval = MIN(10, MAX(5, ConnectDampingInterval));
  1085. (VOID) InitRegDWORDParameter(
  1086. myRegKey,
  1087. L"DisconnectDampInterval",
  1088. (PULONG) &DampingInterval,
  1089. 10
  1090. );
  1091. DampingInterval = MIN(10, MAX(5, DampingInterval));
  1092. ZwClose(myRegKey);
  1093. myRegKey = NULL;
  1094. } else {
  1095. //
  1096. // Use reasonable defaults.
  1097. //
  1098. IPConfiguration->ici_fwbcast = 0;
  1099. IPConfiguration->ici_gateway = 0;
  1100. IPConfiguration->ici_addrmaskreply = 0;
  1101. IPConfiguration->ici_fwbufsize = DEFAULT_FW_BUFSIZE;
  1102. IPConfiguration->ici_fwpackets = DEFAULT_FW_PACKETS;
  1103. IPConfiguration->ici_maxfwbufsize = DEFAULT_MAX_FW_BUFSIZE;
  1104. IPConfiguration->ici_maxfwpackets = DEFAULT_MAX_FW_PACKETS;
  1105. IPConfiguration->ici_igmplevel = DEFAULT_IGMP_LEVEL;
  1106. IPConfiguration->ici_deadgwdetect = FALSE;
  1107. IPConfiguration->ici_pmtudiscovery = FALSE;
  1108. IPConfiguration->ici_ttl = DEFAULT_TTL;
  1109. IPConfiguration->ici_tos = DEFAULT_TOS;
  1110. NET_TABLE_SIZE = 8;
  1111. DEBUGMSG(DBG_WARN && DBG_INIT,
  1112. (DTEXT("IPProcessConfiguration: Unable to open registry - using defaults.\n")));
  1113. }
  1114. #if !MILLEN
  1115. //
  1116. // Retrieve and store the binding list from the Linkage key
  1117. //
  1118. status = OpenRegKey(&myRegKey, IPLinkageRegistryKey);
  1119. if (NT_SUCCESS(status)) {
  1120. UNICODE_STRING_NEW BindString;
  1121. BindString.Length = 0;
  1122. BindString.MaximumLength = WORK_BUFFER_SIZE;
  1123. BindString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1124. if (BindString.Buffer) {
  1125. status = GetRegMultiSZValueNew(myRegKey, L"Bind", &BindString);
  1126. if (status == STATUS_SUCCESS) {
  1127. IPBindList = BindString.Buffer;
  1128. } else {
  1129. CTEFreeMem(BindString.Buffer);
  1130. }
  1131. }
  1132. ZwClose(myRegKey);
  1133. myRegKey = NULL;
  1134. }
  1135. #endif
  1136. status = STATUS_SUCCESS;
  1137. if (!IPInit()) {
  1138. CTELogEvent(
  1139. IPDriverObject,
  1140. EVENT_TCPIP_IP_INIT_FAILED,
  1141. 1,
  1142. 0,
  1143. NULL,
  1144. 0,
  1145. NULL
  1146. );
  1147. DEBUGMSG(DBG_ERROR && DBG_INIT,
  1148. (DTEXT("IPProcessConfiguration: IPInit failure.\n")));
  1149. status = STATUS_UNSUCCESSFUL;
  1150. } else {
  1151. status = STATUS_SUCCESS;
  1152. }
  1153. if (myRegKey != NULL) {
  1154. ZwClose(myRegKey);
  1155. }
  1156. if (IPConfiguration != NULL) {
  1157. IPFreeConfig(IPConfiguration);
  1158. }
  1159. return (status);
  1160. }
  1161. uint
  1162. GetDefaultGWList(
  1163. uint * numGW,
  1164. IPAddr * gwList,
  1165. uint * gwMetricList,
  1166. NDIS_HANDLE Handle,
  1167. PNDIS_STRING ConfigName
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. This routine reads the default gateway list from the registry.
  1172. Arguments:
  1173. numberOfGateways - number of gateway entries in the registry.
  1174. gwList - pointer to the gateway list.
  1175. gwMetricList - pointer to the metric for each gateway
  1176. handle - Config handle from OpenIFConfig().
  1177. ConfigName - description string for use in logging failures.
  1178. Return Value:
  1179. TRUE if we got all the required info, FALSE otherwise.
  1180. --*/
  1181. {
  1182. UNICODE_STRING valueString;
  1183. NTSTATUS status;
  1184. ULONG ulAddGateway, ulTemp;
  1185. uint numberOfGateways;
  1186. PAGED_CODE();
  1187. //
  1188. // Process the gateway MultiSZ. The end is signified by a double NULL.
  1189. // This list currently only applies to the first IP address configured
  1190. // on this interface.
  1191. //
  1192. numberOfGateways = 0;
  1193. ulAddGateway = TRUE;
  1194. RtlZeroMemory(gwList, sizeof(IPAddr) * MAX_DEFAULT_GWS);
  1195. RtlZeroMemory(gwMetricList, sizeof(uint) * MAX_DEFAULT_GWS);
  1196. valueString.Length = 0;
  1197. valueString.MaximumLength = WORK_BUFFER_SIZE;
  1198. valueString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1199. if (valueString.Buffer == NULL) {
  1200. return (FALSE);
  1201. }
  1202. ulTemp = 0;
  1203. status = GetRegDWORDValue(Handle,
  1204. L"DontAddDefaultGateway",
  1205. &ulTemp);
  1206. if (NT_SUCCESS(status)) {
  1207. if (ulTemp == 1) {
  1208. ulAddGateway = FALSE;
  1209. }
  1210. }
  1211. if (ulAddGateway) {
  1212. status = GetRegMultiSZValue(
  1213. Handle,
  1214. L"DefaultGateway",
  1215. &valueString
  1216. );
  1217. if (NT_SUCCESS(status)) {
  1218. PWCHAR addressString = valueString.Buffer;
  1219. while (*addressString != UNICODE_NULL) {
  1220. IPAddr addressValue;
  1221. BOOLEAN conversionStatus;
  1222. if (numberOfGateways >= MAX_DEFAULT_GWS) {
  1223. CTELogEvent(
  1224. IPDriverObject,
  1225. EVENT_TCPIP_TOO_MANY_GATEWAYS,
  1226. 1,
  1227. 1,
  1228. &ConfigName->Buffer,
  1229. 0,
  1230. NULL
  1231. );
  1232. break;
  1233. }
  1234. conversionStatus = IPConvertStringToAddress(
  1235. addressString,
  1236. &addressValue
  1237. );
  1238. if (conversionStatus && (addressValue != 0xFFFFFFFF)) {
  1239. if (addressValue != INADDR_ANY) {
  1240. gwList[numberOfGateways++] = addressValue;
  1241. }
  1242. } else {
  1243. PWCHAR stringList[2];
  1244. stringList[0] = addressString;
  1245. stringList[1] = ConfigName->Buffer;
  1246. CTELogEvent(
  1247. IPDriverObject,
  1248. EVENT_TCPIP_INVALID_DEFAULT_GATEWAY,
  1249. 1,
  1250. 2,
  1251. stringList,
  1252. 0,
  1253. NULL
  1254. );
  1255. TCPTRACE((
  1256. "IP: Invalid default gateway address %ws specified for adapter %ws.\n"
  1257. " Remote networks may not be reachable as a result.\n",
  1258. addressString,
  1259. ConfigName->Buffer
  1260. ));
  1261. }
  1262. //
  1263. // Walk over the entry we just processed.
  1264. //
  1265. while (*addressString++ != UNICODE_NULL);
  1266. }
  1267. status = GetRegMultiSZValue(
  1268. Handle,
  1269. L"DefaultGatewayMetric",
  1270. &valueString
  1271. );
  1272. if (NT_SUCCESS(status)) {
  1273. PWCHAR metricBuffer = valueString.Buffer;
  1274. uint metricIndex = 0;
  1275. while (*metricBuffer != UNICODE_NULL) {
  1276. uint metricValue;
  1277. UNICODE_STRING metricString;
  1278. if (metricIndex >= numberOfGateways) {
  1279. break;
  1280. }
  1281. RtlInitUnicodeString(&metricString, metricBuffer);
  1282. status = RtlUnicodeStringToInteger(
  1283. &metricString,
  1284. 10,
  1285. (PULONG) &metricValue
  1286. );
  1287. if (!NT_SUCCESS(status)) {
  1288. break;
  1289. } else {
  1290. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1291. "GetDefaultGWList: read %d\n", metricValue));
  1292. if ((LONG) metricValue < 0) {
  1293. break;
  1294. }
  1295. }
  1296. gwMetricList[metricIndex++] = metricValue;
  1297. //
  1298. // Walk over the entry we just processed.
  1299. //
  1300. while (*metricBuffer++ != UNICODE_NULL);
  1301. }
  1302. }
  1303. } else {
  1304. TCPTRACE((
  1305. "IP: Unable to read DefaultGateway value for adapter %ws.\n"
  1306. " Initialization will continue.\n",
  1307. ConfigName->Buffer
  1308. ));
  1309. }
  1310. }
  1311. *numGW = numberOfGateways;
  1312. if (valueString.Buffer) {
  1313. CTEFreeMem(valueString.Buffer);
  1314. }
  1315. return TRUE;
  1316. }
  1317. void
  1318. GetInterfaceMetric(
  1319. uint * Metric,
  1320. NDIS_HANDLE Handle
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. A routine to retrieve the metric associated with an interface, if any.
  1325. Arguments:
  1326. Metric - receives the metric
  1327. Handle - Config handle from OpenIFConfig().
  1328. Return Value:
  1329. none.
  1330. --*/
  1331. {
  1332. NTSTATUS status;
  1333. status = GetRegDWORDValue(
  1334. Handle,
  1335. L"InterfaceMetric",
  1336. (PULONG) Metric
  1337. );
  1338. if (!NT_SUCCESS(status)) {
  1339. *Metric = 0;
  1340. } else {
  1341. if (*Metric > 9999) {
  1342. *Metric = 9999;
  1343. }
  1344. }
  1345. }
  1346. void
  1347. UpdateTcpParams(
  1348. NDIS_HANDLE Handle,
  1349. Interface *IF
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. A routine to update per-interface specific tcp tuning parametsrs.
  1354. Arguments:
  1355. Handle - Config handle from OpenIFConfig().
  1356. IF - IP Interface which needs to be updated.
  1357. Return Value:
  1358. none.
  1359. --*/
  1360. {
  1361. ULONG ulTemp;
  1362. NTSTATUS status;
  1363. status = GetRegDWORDValue(
  1364. Handle,
  1365. L"TcpWindowSize",
  1366. &ulTemp
  1367. );
  1368. if (NT_SUCCESS(status)) {
  1369. IF->if_TcpWindowSize = ulTemp;
  1370. }
  1371. status = GetRegDWORDValue(
  1372. Handle,
  1373. L"TcpInitialRTT",
  1374. &ulTemp
  1375. );
  1376. if (NT_SUCCESS(status)) {
  1377. IF->if_TcpInitialRTT = ulTemp;
  1378. }
  1379. status = GetRegDWORDValue(
  1380. Handle,
  1381. L"TcpDelAckTicks",
  1382. &ulTemp
  1383. );
  1384. if (NT_SUCCESS(status) && (ulTemp <= MAX_DEL_ACK_TICKS)) {
  1385. IF->if_TcpDelAckTicks = (uchar)ulTemp;
  1386. }
  1387. status = GetRegDWORDValue(
  1388. Handle,
  1389. L"TcpACKFrequency",
  1390. &ulTemp
  1391. );
  1392. if (NT_SUCCESS(status)) {
  1393. IF->if_TcpAckFrequency = (uchar)ulTemp;
  1394. }
  1395. }
  1396. uint
  1397. GetGeneralIFConfig(
  1398. IFGeneralConfig * ConfigInfo,
  1399. NDIS_HANDLE Handle,
  1400. PNDIS_STRING ConfigName
  1401. )
  1402. /*++
  1403. Routine Description:
  1404. A routine to get the general per-interface config info, such as MTU,
  1405. type of broadcast, etc. The caller gives us a structure to be filled in
  1406. and a handle, and we fill in the structure if we can.
  1407. Arguments:
  1408. ConfigInfo - Structure to be filled in.
  1409. Handle - Config handle from OpenIFConfig().
  1410. ConfigName - identification string for logging failures.
  1411. Return Value:
  1412. TRUE if we got all the required info, FALSE otherwise.
  1413. --*/
  1414. {
  1415. NTSTATUS status;
  1416. ULONG ulTemp;
  1417. PAGED_CODE();
  1418. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1419. (DTEXT("+GetGeneralIFConfig(%x, %x)\n"), ConfigInfo, Handle));
  1420. if (!GetDefaultGWList(
  1421. &ConfigInfo->igc_numgws,
  1422. ConfigInfo->igc_gw,
  1423. ConfigInfo->igc_gwmetric,
  1424. Handle,
  1425. ConfigName)) {
  1426. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1427. (DTEXT("GetGeneralIFConfig: GetDefaultGWList failure.\n")));
  1428. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-GetGeneralIFConfig [FALSE]\n")));
  1429. return FALSE;
  1430. }
  1431. //
  1432. // Are we using zeros broadcasts?
  1433. //
  1434. status = GetRegDWORDValue(
  1435. Handle,
  1436. L"UseZeroBroadcast",
  1437. (PULONG) &(ConfigInfo->igc_zerobcast)
  1438. );
  1439. #if MILLEN
  1440. //
  1441. // Backwards compatibility. If 'UseZeroBroadcast' value doesn't exist, then
  1442. // attempt to read legacy value: 'ZeroBroadcast'.
  1443. //
  1444. if (!NT_SUCCESS(status)) {
  1445. status = GetRegDWORDValue(
  1446. Handle,
  1447. L"ZeroBroadcast",
  1448. &(ConfigInfo->igc_zerobcast)
  1449. );
  1450. }
  1451. #endif // MILLEN
  1452. if (!NT_SUCCESS(status)) {
  1453. TCPTRACE((
  1454. "IP: Unable to read UseZeroBroadcast value for adapter %ws.\n"
  1455. " All-nets broadcasts will be addressed to 255.255.255.255.\n",
  1456. ConfigName->Buffer
  1457. ));
  1458. ConfigInfo->igc_zerobcast = FALSE; // default to off
  1459. }
  1460. //
  1461. // Has anyone specified an MTU?
  1462. //
  1463. status = GetRegDWORDValue(
  1464. Handle,
  1465. L"MTU",
  1466. (PULONG) &(ConfigInfo->igc_mtu)
  1467. );
  1468. #if MILLEN
  1469. //
  1470. // Backwards compatibility. If 'MTU' value doesn't exist, then
  1471. // attempt to read legacy value: 'MaxMTU'.
  1472. //
  1473. if (!NT_SUCCESS(status)) {
  1474. status = GetRegDWORDValue(
  1475. Handle,
  1476. L"MaxMTU",
  1477. &(ConfigInfo->igc_mtu)
  1478. );
  1479. }
  1480. #endif // !MILLEN
  1481. if (!NT_SUCCESS(status)) {
  1482. ConfigInfo->igc_mtu = 0xFFFFFFF; // The stack will pick one.
  1483. }
  1484. //
  1485. // Have we been configured for more routing packets?
  1486. //
  1487. status = GetRegDWORDValue(
  1488. Handle,
  1489. L"MaxForwardPending",
  1490. (PULONG) &(ConfigInfo->igc_maxpending)
  1491. );
  1492. #if MILLEN
  1493. //
  1494. // Backwards compatibility. If 'MaxForwardPending' value doesn't exist, then
  1495. // attempt to read legacy value: 'MaxFWPending'.
  1496. //
  1497. if (!NT_SUCCESS(status)) {
  1498. status = GetRegDWORDValue(
  1499. Handle,
  1500. L"MaxFWPending",
  1501. &(ConfigInfo->igc_maxpending)
  1502. );
  1503. }
  1504. #endif // !MILLEN
  1505. if (!NT_SUCCESS(status)) {
  1506. ConfigInfo->igc_maxpending = DEFAULT_MAX_PENDING;
  1507. }
  1508. //
  1509. // Has Router Discovery been configured?
  1510. // We accept three values:
  1511. // 0: disable router-discovery
  1512. // 1: enable router-discovery
  1513. // 2: disable router-discovery, and enable it only if the DHCP server
  1514. // sends the 'Perform Router Discovery' option. In this case,
  1515. // we wait for the DHCP client service to tell us to start
  1516. // doing router-discovery.
  1517. //
  1518. status = GetRegDWORDValue(
  1519. Handle,
  1520. L"PerformRouterDiscovery",
  1521. &ulTemp
  1522. );
  1523. ConfigInfo->igc_rtrdiscovery = (uchar)ulTemp;
  1524. if (!NT_SUCCESS(status)) {
  1525. ConfigInfo->igc_rtrdiscovery = IP_IRDP_DISABLED_USE_DHCP;
  1526. } else if (ConfigInfo->igc_rtrdiscovery != IP_IRDP_DISABLED &&
  1527. ConfigInfo->igc_rtrdiscovery != IP_IRDP_ENABLED &&
  1528. ConfigInfo->igc_rtrdiscovery != IP_IRDP_DISABLED_USE_DHCP) {
  1529. ConfigInfo->igc_rtrdiscovery = IP_IRDP_DISABLED_USE_DHCP;
  1530. }
  1531. //
  1532. // Has Router Discovery Address been configured?
  1533. //
  1534. status = GetRegDWORDValue(
  1535. Handle,
  1536. L"SolicitationAddressBCast",
  1537. &ulTemp
  1538. );
  1539. if (!NT_SUCCESS(status)) {
  1540. ConfigInfo->igc_rtrdiscaddr = ALL_ROUTER_MCAST;
  1541. } else {
  1542. if (ulTemp == 1) {
  1543. ConfigInfo->igc_rtrdiscaddr = 0xffffffff;
  1544. } else {
  1545. ConfigInfo->igc_rtrdiscaddr = ALL_ROUTER_MCAST;
  1546. }
  1547. }
  1548. //
  1549. // Has a DF-bit handling policy been set for encapsulated packets?
  1550. //
  1551. status = GetRegDWORDValue(
  1552. Handle,
  1553. L"IPSecDFEncap",
  1554. &ulTemp
  1555. );
  1556. if (!NT_SUCCESS(status) || ulTemp >= MaxDfEncap) {
  1557. ConfigInfo->igc_dfencap = DefaultDfEncap;
  1558. } else {
  1559. ConfigInfo->igc_dfencap = (uchar)ulTemp;
  1560. }
  1561. ConfigInfo->igc_TcpWindowSize = 0;
  1562. ConfigInfo->igc_TcpInitialRTT = 0;
  1563. ConfigInfo->igc_TcpDelAckTicks = 0;
  1564. ConfigInfo->igc_TcpAckFrequency = 0;
  1565. status = GetRegDWORDValue(
  1566. Handle,
  1567. L"TcpWindowSize",
  1568. &ulTemp
  1569. );
  1570. if (NT_SUCCESS(status)) {
  1571. ConfigInfo->igc_TcpWindowSize = ulTemp;
  1572. }
  1573. status = GetRegDWORDValue(
  1574. Handle,
  1575. L"TcpInitialRTT",
  1576. &ulTemp
  1577. );
  1578. if (NT_SUCCESS(status)) {
  1579. ConfigInfo->igc_TcpInitialRTT = ulTemp;
  1580. }
  1581. status = GetRegDWORDValue(
  1582. Handle,
  1583. L"TcpDelAckTicks",
  1584. &ulTemp
  1585. );
  1586. if (NT_SUCCESS(status) && (ulTemp <= MAX_DEL_ACK_TICKS)) {
  1587. ConfigInfo->igc_TcpDelAckTicks = (uchar)ulTemp;
  1588. }
  1589. status = GetRegDWORDValue(
  1590. Handle,
  1591. L"TcpACKFrequency",
  1592. &ulTemp
  1593. );
  1594. if (NT_SUCCESS(status)) {
  1595. ConfigInfo->igc_TcpAckFrequency = (uchar)ulTemp;
  1596. }
  1597. GetInterfaceMetric(&ConfigInfo->igc_metric, Handle);
  1598. ConfigInfo->igc_iftype = 0; // by default its 0 means both ucast/mcast traffic allowed
  1599. status = GetRegDWORDValue(
  1600. Handle,
  1601. L"TypeofInterface",
  1602. &ulTemp
  1603. );
  1604. if (NT_SUCCESS(status)) {
  1605. ConfigInfo->igc_iftype = (uchar)ulTemp;
  1606. }
  1607. // Use global value by default.
  1608. ConfigInfo->igc_disablemediasense = DisableMediaSense ? TRUE : FALSE;
  1609. #if MILLEN
  1610. // Only Windows ME supports reading the per-interface setting from the
  1611. // registry. The global value is used for Win2000+.
  1612. status = GetRegDWORDValue(
  1613. Handle,
  1614. L"DisableDHCPMediaSense",
  1615. &ulTemp
  1616. );
  1617. if (NT_SUCCESS(status)) {
  1618. ConfigInfo->igc_disablemediasense = ulTemp ? TRUE : FALSE;
  1619. }
  1620. #endif // MILLEN
  1621. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-GetGeneralIFConfig [TRUE]\n")));
  1622. return TRUE;
  1623. }
  1624. NDIS_STATUS
  1625. GetIPConfigValue(
  1626. NDIS_HANDLE Handle,
  1627. PUNICODE_STRING IPConfig
  1628. )
  1629. /*++
  1630. Routine Description:
  1631. Called to get the IPConfig string value
  1632. Arguments:
  1633. Handle - Handle to use for reading config.
  1634. IPConfig - Pointer to Unicode string where IPConfig is stored.
  1635. Return Value:
  1636. Status of the operation.
  1637. --*/
  1638. {
  1639. NTSTATUS status;
  1640. PAGED_CODE();
  1641. IPConfig->MaximumLength = 200;
  1642. IPConfig->Buffer = CTEAllocMemBoot(IPConfig->MaximumLength);
  1643. if (IPConfig->Buffer == NULL) {
  1644. return (STATUS_INSUFFICIENT_RESOURCES);
  1645. }
  1646. status = GetRegMultiSZValue(
  1647. Handle,
  1648. L"IPConfig",
  1649. IPConfig
  1650. );
  1651. return status;
  1652. }
  1653. int
  1654. IsLLInterfaceValueNull(
  1655. NDIS_HANDLE Handle
  1656. )
  1657. /*++
  1658. Routine Description:
  1659. Called to see if the LLInterface value in the registry key for which the
  1660. handle is provided, is NULL or not.
  1661. Arguments:
  1662. Handle - Handle to use for reading config.
  1663. Return Value:
  1664. FALSE if value is not null
  1665. TRUE if it is null
  1666. --*/
  1667. {
  1668. UNICODE_STRING valueString;
  1669. ULONG valueType;
  1670. NTSTATUS status;
  1671. PAGED_CODE();
  1672. valueString.MaximumLength = 200;
  1673. valueString.Buffer = CTEAllocMemBoot(valueString.MaximumLength);
  1674. if (valueString.Buffer == NULL) {
  1675. return (FALSE);
  1676. }
  1677. status = GetRegSZValue(
  1678. Handle,
  1679. L"LLInterface",
  1680. &valueString,
  1681. &valueType
  1682. );
  1683. if (NT_SUCCESS(status) && (*(valueString.Buffer) != UNICODE_NULL)) {
  1684. CTEFreeMem(valueString.Buffer);
  1685. return FALSE;
  1686. } else {
  1687. CTEFreeMem(valueString.Buffer);
  1688. return TRUE;
  1689. }
  1690. }
  1691. NTSTATUS
  1692. GetLLInterfaceValue(
  1693. NDIS_HANDLE Handle,
  1694. PNDIS_STRING pValueString
  1695. )
  1696. /*++
  1697. Routine Description:
  1698. Called to read the LLInterface value in the registry key for which the
  1699. handle is provided.
  1700. Arguments:
  1701. Handle - Handle to use for reading config.
  1702. Return Value:
  1703. value of key
  1704. --*/
  1705. {
  1706. NTSTATUS status;
  1707. ULONG valueType;
  1708. PAGED_CODE();
  1709. status = GetRegSZValue(
  1710. Handle,
  1711. L"LLInterface",
  1712. pValueString,
  1713. &valueType
  1714. );
  1715. return status;
  1716. }
  1717. BOOLEAN
  1718. GetTempDHCPAddr(
  1719. NDIS_HANDLE Handle,
  1720. IPAddr * Tempdhcpaddr,
  1721. IPAddr * TempMask,
  1722. IPAddr * TempGWAddr,
  1723. PNDIS_STRING ConfigName
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. Called to get temp dhcp address if dhcp is enabled
  1728. Arguments:
  1729. Handle - Handle to use for reading config.
  1730. Tempdhcpaddr - temporary addr, mask and gateway
  1731. TempMask
  1732. TempGWAddr
  1733. ConfigName - identifies the interface in logging failures.
  1734. Return Value:
  1735. --*/
  1736. {
  1737. NTSTATUS Status;
  1738. LARGE_INTEGER LeaseTime, systime;
  1739. UNICODE_STRING valueString;
  1740. ULONG valueType;
  1741. BOOLEAN ConversionStatus;
  1742. UNREFERENCED_PARAMETER(ConfigName);
  1743. Status = GetRegLARGEINTValue(
  1744. Handle,
  1745. L"TempLeaseExpirationTime",
  1746. &LeaseTime
  1747. );
  1748. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1749. "LargeInt status %x\n", Status));
  1750. if (Status != STATUS_SUCCESS) {
  1751. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "No Lease time\n"));
  1752. return FALSE;
  1753. }
  1754. valueString.Length = 0;
  1755. valueString.MaximumLength = WORK_BUFFER_SIZE;
  1756. valueString.Buffer = (PWCHAR) CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1757. KeQuerySystemTime(&systime);
  1758. if (RtlLargeIntegerGreaterThan(systime, LeaseTime)) {
  1759. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1760. "Leastime > systime no tempdhcp\n"));
  1761. return FALSE;
  1762. }
  1763. Status = GetRegSZValue(
  1764. Handle,
  1765. L"TempIpAddress",
  1766. &valueString,
  1767. &valueType
  1768. );
  1769. if (!NT_SUCCESS(Status) || (*(valueString.Buffer) == UNICODE_NULL)) {
  1770. return FALSE;
  1771. }
  1772. ConversionStatus = IPConvertStringToAddress(
  1773. (valueString.Buffer),
  1774. Tempdhcpaddr
  1775. );
  1776. if (!ConversionStatus) {
  1777. return FALSE;
  1778. }
  1779. Status = GetRegSZValue(
  1780. Handle,
  1781. L"TempMask",
  1782. &valueString,
  1783. &valueType
  1784. );
  1785. if (!NT_SUCCESS(Status) || (*(valueString.Buffer) == UNICODE_NULL)) {
  1786. return FALSE;
  1787. }
  1788. ConversionStatus = IPConvertStringToAddress(
  1789. (valueString.Buffer),
  1790. TempMask
  1791. );
  1792. if (!ConversionStatus) {
  1793. return FALSE;
  1794. }
  1795. Status = GetRegMultiSZValue(
  1796. Handle,
  1797. L"DhcpDefaultGateway",
  1798. &valueString
  1799. );
  1800. if (NT_SUCCESS(Status) && (*(valueString.Buffer) != UNICODE_NULL)) {
  1801. PWCHAR addressString = valueString.Buffer;
  1802. uint numberOfGateways = 0;
  1803. while (*addressString != UNICODE_NULL) {
  1804. IPAddr addressValue;
  1805. BOOLEAN conversionStatus;
  1806. if (numberOfGateways >= MAX_DEFAULT_GWS) {
  1807. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1808. "Exceeded mac_default_gws %d\n", numberOfGateways));
  1809. break;
  1810. }
  1811. conversionStatus = IPConvertStringToAddress(
  1812. addressString,
  1813. &addressValue
  1814. );
  1815. if (conversionStatus && (addressValue != 0xFFFFFFFF)) {
  1816. if (addressValue != INADDR_ANY) {
  1817. TempGWAddr[numberOfGateways++] = addressValue;
  1818. }
  1819. }
  1820. //
  1821. // Walk over the entry we just processed.
  1822. //
  1823. while (*addressString++ != UNICODE_NULL);
  1824. }
  1825. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1826. "Temp gws - %d\n", numberOfGateways));
  1827. }
  1828. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1829. "tempdhcp: %x %x %x\n", Tempdhcpaddr, TempMask, TempGWAddr));
  1830. return TRUE;
  1831. }
  1832. IFAddrList *
  1833. GetIFAddrList(
  1834. UINT * NumAddr,
  1835. NDIS_HANDLE Handle,
  1836. UINT * EnableDhcp,
  1837. BOOLEAN PppIf,
  1838. PNDIS_STRING ConfigName
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. Called to read the list of IF addresses and masks for an interface.
  1843. We'll get the address pointer first, then walk the list counting
  1844. to find out how many addresses we have. Then we allocate memory for the
  1845. list, and walk down the list converting them. After that we'll get
  1846. the mask list and convert it.
  1847. Arguments:
  1848. NumAddr - Where to return number of address we have.
  1849. Handle - Handle to use for reading config.
  1850. EnableDhcp - Whether or not dhcp is enabled.
  1851. ConfigName - identifies the interface in logging failures.
  1852. Return Value:
  1853. Pointer to IF address list if we get one, or NULL otherwise.
  1854. --*/
  1855. {
  1856. UNICODE_STRING_NEW ValueString;
  1857. NTSTATUS Status;
  1858. UINT AddressCount = 0;
  1859. UINT GoodAddresses = 0;
  1860. PWCHAR CurrentAddress;
  1861. PWCHAR CurrentMask;
  1862. PWCHAR AddressString;
  1863. PWCHAR MaskString;
  1864. IFAddrList *AddressList;
  1865. UINT i;
  1866. BOOLEAN ConversionStatus;
  1867. IPAddr AddressValue;
  1868. IPAddr MaskValue;
  1869. PAGED_CODE();
  1870. UNREFERENCED_PARAMETER(PppIf);
  1871. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1872. (DTEXT("+GetIFAddrList(%x, %x, %x)\n"), NumAddr, Handle, EnableDhcp));
  1873. // First, try to read the EnableDhcp Value.
  1874. Status = GetRegDWORDValue(
  1875. Handle,
  1876. L"EnableDHCP",
  1877. (PULONG) EnableDhcp
  1878. );
  1879. if (!NT_SUCCESS(Status)) {
  1880. *EnableDhcp = FALSE;
  1881. }
  1882. ValueString.Length = 0;
  1883. ValueString.MaximumLength = WORK_BUFFER_SIZE;
  1884. ValueString.Buffer = (PWCHAR) CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1885. if (ValueString.Buffer == NULL) {
  1886. CTELogEvent(
  1887. IPDriverObject,
  1888. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1889. 2,
  1890. 1,
  1891. &ConfigName->Buffer,
  1892. 0,
  1893. NULL
  1894. );
  1895. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1896. (DTEXT("GetIFAddrList: Failure to allocate memory.\n")));
  1897. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1898. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1899. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1900. return NULL;
  1901. }
  1902. // First, try to read the IpAddress string.
  1903. Status = GetRegMultiSZValueNew(
  1904. Handle,
  1905. L"IpAddress",
  1906. &ValueString
  1907. );
  1908. if (!NT_SUCCESS(Status)) {
  1909. CTELogEvent(
  1910. IPDriverObject,
  1911. EVENT_TCPIP_NO_ADDRESS_LIST,
  1912. 1,
  1913. 1,
  1914. &ConfigName->Buffer,
  1915. 0,
  1916. NULL
  1917. );
  1918. ExFreePool(ValueString.Buffer);
  1919. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1920. (DTEXT("GetIFAddrList: unable to read IP address list for adapter %ws.\n"),
  1921. ConfigName->Buffer));
  1922. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1923. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1924. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1925. return NULL;
  1926. }
  1927. AddressString = ExAllocatePoolWithTag(NonPagedPool, ValueString.MaximumLength, 'iPCT');
  1928. if (AddressString == NULL) {
  1929. CTELogEvent(
  1930. IPDriverObject,
  1931. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1932. 2,
  1933. 1,
  1934. &ConfigName->Buffer,
  1935. 0,
  1936. NULL
  1937. );
  1938. ExFreePool(ValueString.Buffer);
  1939. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1940. (DTEXT("GetIFAddrList: unable to allocate memory for IP address list.\n")));
  1941. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1942. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1943. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1944. return NULL;
  1945. }
  1946. RtlCopyMemory(AddressString, ValueString.Buffer, ValueString.MaximumLength);
  1947. Status = GetRegMultiSZValueNew(
  1948. Handle,
  1949. L"Subnetmask",
  1950. &ValueString
  1951. );
  1952. #if MILLEN
  1953. if (!NT_SUCCESS(Status)) {
  1954. Status = GetRegMultiSZValueNew(
  1955. Handle,
  1956. L"IPMask",
  1957. &ValueString
  1958. );
  1959. }
  1960. #endif // MILLEN
  1961. if (!NT_SUCCESS(Status)) {
  1962. CTELogEvent(
  1963. IPDriverObject,
  1964. EVENT_TCPIP_NO_MASK_LIST,
  1965. 1,
  1966. 1,
  1967. &ConfigName->Buffer,
  1968. 0,
  1969. NULL
  1970. );
  1971. TCPTRACE((
  1972. "IP: Unable to read the subnet mask list for adapter %ws.\n"
  1973. " IP will not be operational on this adapter.\n",
  1974. ConfigName->Buffer
  1975. ));
  1976. ExFreePool(AddressString);
  1977. ExFreePool(ValueString.Buffer);
  1978. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1979. (DTEXT("GetIFAddrList: unable to read subnet mask list for adapter %ws.\n"),
  1980. ConfigName->Buffer));
  1981. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1982. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1983. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1984. return NULL;
  1985. }
  1986. MaskString = ExAllocatePoolWithTag(NonPagedPool, ValueString.MaximumLength, 'iPCT');
  1987. if (MaskString == NULL) {
  1988. CTELogEvent(
  1989. IPDriverObject,
  1990. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1991. 3,
  1992. 1,
  1993. &ConfigName->Buffer,
  1994. 0,
  1995. NULL
  1996. );
  1997. ExFreePool(AddressString);
  1998. ExFreePool(ValueString.Buffer);
  1999. DEBUGMSG(DBG_ERROR && DBG_PNP,
  2000. (DTEXT("GetIFAddrList: unable to allocate memory for subnet mask list.\n")));
  2001. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2002. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2003. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2004. return NULL;
  2005. }
  2006. RtlCopyMemory(MaskString, ValueString.Buffer, ValueString.MaximumLength);
  2007. CurrentAddress = AddressString;
  2008. CurrentMask = MaskString;
  2009. while (*CurrentAddress != UNICODE_NULL &&
  2010. *CurrentMask != UNICODE_NULL) {
  2011. // We have a potential IP address.
  2012. AddressCount++;
  2013. // Skip this one.
  2014. while (*CurrentAddress++ != UNICODE_NULL);
  2015. while (*CurrentMask++ != UNICODE_NULL);
  2016. }
  2017. if (AddressCount == 0) {
  2018. ExFreePool(AddressString);
  2019. ExFreePool(MaskString);
  2020. ExFreePool(ValueString.Buffer);
  2021. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2022. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2023. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2024. return NULL;
  2025. }
  2026. // Allocate memory.
  2027. AddressList = CTEAllocMemBoot(sizeof(IFAddrList) * AddressCount);
  2028. if (AddressList == NULL) {
  2029. CTELogEvent(
  2030. IPDriverObject,
  2031. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  2032. 2,
  2033. 1,
  2034. &ConfigName->Buffer,
  2035. 0,
  2036. NULL
  2037. );
  2038. ExFreePool(AddressString);
  2039. ExFreePool(MaskString);
  2040. ExFreePool(ValueString.Buffer);
  2041. DEBUGMSG(DBG_ERROR && DBG_PNP,
  2042. (DTEXT("GetIFAddrList: unable to allocate memory for IP address list.\n")));
  2043. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2044. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2045. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2046. return NULL;
  2047. }
  2048. // Walk the list again, converting each address.
  2049. CurrentAddress = AddressString;
  2050. CurrentMask = MaskString;
  2051. for (i = 0; i < AddressCount; i++) {
  2052. ConversionStatus = IPConvertStringToAddress(
  2053. CurrentAddress,
  2054. &AddressValue
  2055. );
  2056. if (!ConversionStatus || (AddressValue == 0xFFFFFFFF)) {
  2057. PWCHAR stringList[2];
  2058. stringList[0] = CurrentAddress;
  2059. stringList[1] = ConfigName->Buffer;
  2060. CTELogEvent(
  2061. IPDriverObject,
  2062. EVENT_TCPIP_INVALID_ADDRESS,
  2063. 1,
  2064. 2,
  2065. stringList,
  2066. 0,
  2067. NULL
  2068. );
  2069. DEBUGMSG(DBG_WARN && DBG_PNP,
  2070. (DTEXT("IPAddInterface: Invalid IP address %ws specified for \n")
  2071. TEXT("adapter %ws. Interface may not be init.\n"),
  2072. CurrentAddress, ConfigName->Buffer));
  2073. goto nextone;
  2074. }
  2075. // Now do the current mask.
  2076. ConversionStatus = IPConvertStringToAddress(
  2077. CurrentMask,
  2078. &MaskValue
  2079. );
  2080. if (!ConversionStatus) {
  2081. PWCHAR stringList[3];
  2082. stringList[0] = CurrentMask;
  2083. stringList[1] = CurrentAddress;
  2084. stringList[2] = ConfigName->Buffer;
  2085. CTELogEvent(
  2086. IPDriverObject,
  2087. EVENT_TCPIP_INVALID_MASK,
  2088. 1,
  2089. 3,
  2090. stringList,
  2091. 0,
  2092. NULL
  2093. );
  2094. DEBUGMSG(DBG_WARN && DBG_PNP,
  2095. (DTEXT("IPAddInterface: Invalid IP mask %ws specified for \n")
  2096. TEXT("adapter %ws. Interface may not be init.\n"),
  2097. CurrentMask, ConfigName->Buffer));
  2098. } else {
  2099. AddressList[GoodAddresses].ial_addr = AddressValue;
  2100. AddressList[GoodAddresses].ial_mask = MaskValue;
  2101. GoodAddresses++;
  2102. }
  2103. nextone:
  2104. while (*CurrentAddress++ != UNICODE_NULL);
  2105. while (*CurrentMask++ != UNICODE_NULL);
  2106. }
  2107. ExFreePool(AddressString);
  2108. ExFreePool(MaskString);
  2109. ExFreePool(ValueString.Buffer);
  2110. *NumAddr = GoodAddresses;
  2111. if (GoodAddresses == 0) {
  2112. ExFreePool(AddressList);
  2113. AddressList = NULL;
  2114. }
  2115. #if MILLEN
  2116. //
  2117. // So Millennium may not have the EnableDHCP registry key present, but
  2118. // we still may want to detect this. So if EnableDHCP is not set, and
  2119. // there is only one address which is NULL and it is not a PPP interface,
  2120. // then we set EnableDHCP to true.
  2121. //
  2122. if (*EnableDhcp == FALSE &&
  2123. GoodAddresses == 1 &&
  2124. AddressList[0].ial_addr == NULL_IP_ADDR &&
  2125. AddressList[0].ial_mask == NULL_IP_ADDR &&
  2126. PppIf == FALSE
  2127. ) {
  2128. *EnableDhcp = TRUE;
  2129. }
  2130. #endif // MILLEN
  2131. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2132. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2133. AddressList, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2134. return AddressList;
  2135. }
  2136. #if MILLEN
  2137. //* OpenIFConfig - Open our per-IF config. info,
  2138. //
  2139. // Called when we want to open our per-info config info. We do so if we can,
  2140. // otherwise we fail the request.
  2141. //
  2142. // Input: ConfigName - Name of interface to open.
  2143. // Handle - Where to return the handle.
  2144. //
  2145. // Returns: TRUE if we succeed, FALSE if we don't.
  2146. //
  2147. uint
  2148. OpenIFConfig(PNDIS_STRING ConfigName, NDIS_HANDLE * Handle)
  2149. {
  2150. NDIS_STATUS Status; // Status of open attempt.
  2151. HANDLE myRegKey;
  2152. UINT RetStatus = FALSE;
  2153. PWCHAR Config = NULL;
  2154. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2155. (DTEXT("+OpenIFConfig(%x, %x)\n"), ConfigName, Handle));
  2156. *Handle = NULL;
  2157. //
  2158. // We need to ensure that the buffer is NULL terminated since we are passing
  2159. // in just PWCHAR to OpenRegKey.
  2160. //
  2161. Config = ExAllocatePoolWithTag(
  2162. NonPagedPool,
  2163. ConfigName->Length + sizeof(WCHAR),
  2164. 'iPCT');
  2165. if (Config == NULL) {
  2166. goto done;
  2167. }
  2168. // Copy the configuration name into new buffer.
  2169. RtlZeroMemory(Config, ConfigName->Length + sizeof(WCHAR));
  2170. RtlCopyMemory(Config, ConfigName->Buffer, ConfigName->Length);
  2171. Status = OpenRegKey(&myRegKey, Config);
  2172. if (Status == NDIS_STATUS_SUCCESS) {
  2173. *Handle = myRegKey;
  2174. RetStatus = TRUE;
  2175. }
  2176. done:
  2177. if (Config) {
  2178. ExFreePool(Config);
  2179. }
  2180. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-OpenIFConfig [%s] Handle %x\n"),
  2181. RetStatus == TRUE ? TEXT("TRUE") : TEXT("FALSE"), *Handle));
  2182. return RetStatus;
  2183. }
  2184. #else // MILLEN
  2185. UINT
  2186. OpenIFConfig(
  2187. PNDIS_STRING ConfigName,
  2188. NDIS_HANDLE * Handle
  2189. )
  2190. /*++
  2191. Routine Description:
  2192. Called when we want to open our per-info config info. We do so if we can,
  2193. otherwise we fail the request.
  2194. Arguments:
  2195. ConfigName - Name of interface to open.
  2196. Handle - Where to return the handle.
  2197. Return Value:
  2198. TRUE if we succeed, FALSE if we don't.
  2199. --*/
  2200. {
  2201. NTSTATUS status;
  2202. HANDLE myRegKey;
  2203. UNICODE_STRING valueString;
  2204. WCHAR ServicesRegistryKey[] =
  2205. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
  2206. UINT RetStatus = FALSE;
  2207. PAGED_CODE();
  2208. valueString.MaximumLength = (USHORT)
  2209. (ConfigName->MaximumLength +
  2210. (uint) (((wcslen(ServicesRegistryKey) + 2) * sizeof(WCHAR))));
  2211. valueString.Buffer = ExAllocatePoolWithTag(
  2212. NonPagedPool,
  2213. valueString.MaximumLength,
  2214. 'iPCT'
  2215. );
  2216. if (valueString.Buffer == NULL) {
  2217. CTELogEvent(
  2218. IPDriverObject,
  2219. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  2220. 4,
  2221. 1,
  2222. &ConfigName->Buffer,
  2223. 0,
  2224. NULL
  2225. );
  2226. TCPTRACE(("IP: Unable to allocate memory for reg key name\n"));
  2227. return (FALSE);
  2228. }
  2229. RtlZeroMemory(valueString.Buffer,
  2230. valueString.MaximumLength);
  2231. valueString.Length = 0;
  2232. valueString.Buffer[0] = UNICODE_NULL;
  2233. //
  2234. // Build the key name for the tcpip parameters section and open key.
  2235. // Setting Length = 0 and using append is like initializing the string
  2236. //
  2237. status = RtlAppendUnicodeToString(&valueString, ServicesRegistryKey);
  2238. if (!NT_SUCCESS(status)) {
  2239. CTELogEvent(
  2240. IPDriverObject,
  2241. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2242. 1,
  2243. 1,
  2244. &ConfigName->Buffer,
  2245. 0,
  2246. NULL
  2247. );
  2248. TCPTRACE(("IP: Unable to append services name to key string\n"));
  2249. goto done;
  2250. }
  2251. status = RtlAppendUnicodeStringToString(&valueString,
  2252. ConfigName);
  2253. if (!NT_SUCCESS(status)) {
  2254. CTELogEvent(
  2255. IPDriverObject,
  2256. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2257. 2,
  2258. 1,
  2259. &ConfigName->Buffer,
  2260. 0,
  2261. NULL
  2262. );
  2263. TCPTRACE(("IP: Unable to append adapter name to key string\n"));
  2264. goto done;
  2265. }
  2266. status = OpenRegKey(&myRegKey, valueString.Buffer);
  2267. if (!NT_SUCCESS(status)) {
  2268. CTELogEvent(
  2269. IPDriverObject,
  2270. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2271. 4,
  2272. 1,
  2273. &ConfigName->Buffer,
  2274. 0,
  2275. NULL
  2276. );
  2277. TCPTRACE((
  2278. "IP: Unable to open adapter registry key %ws\n",
  2279. valueString.Buffer
  2280. ));
  2281. //ASSERT(FALSE);
  2282. } else {
  2283. RetStatus = TRUE;
  2284. *Handle = myRegKey;
  2285. }
  2286. done:
  2287. ExFreePool(valueString.Buffer);
  2288. return RetStatus;
  2289. }
  2290. #endif // !MILLEN
  2291. VOID
  2292. CloseIFConfig(
  2293. NDIS_HANDLE Handle
  2294. )
  2295. /*++
  2296. Routine Description:
  2297. Close a per-interface config handle opened via OpenIFConfig().
  2298. Arguments:
  2299. Handle - Handle to be closed.
  2300. Return Value:
  2301. --*/
  2302. {
  2303. PAGED_CODE();
  2304. ZwClose(Handle);
  2305. }
  2306. IPConfigInfo *
  2307. IPGetConfig(
  2308. void
  2309. )
  2310. /*++
  2311. Routine Description:
  2312. Provides IP configuration information for the NT environment.
  2313. Arguments:
  2314. None
  2315. Return Value:
  2316. A pointer to a structure containing the configuration information.
  2317. --*/
  2318. {
  2319. return (IPConfiguration);
  2320. }
  2321. void
  2322. IPFreeConfig(
  2323. IPConfigInfo * ConfigInfo
  2324. )
  2325. /*++
  2326. Routine Description:
  2327. Frees the IP configuration structure allocated by IPGetConfig.
  2328. Arguments:
  2329. ConfigInfo - Pointer to the IP configuration information structure to free.
  2330. Return Value:
  2331. None.
  2332. --*/
  2333. {
  2334. UNREFERENCED_PARAMETER(ConfigInfo);
  2335. if (IPConfiguration != NULL) {
  2336. CTEFreeMem(IPConfiguration);
  2337. }
  2338. IPConfiguration = NULL;
  2339. return;
  2340. }
  2341. ulong
  2342. GetGMTDelta(
  2343. void
  2344. )
  2345. /*++
  2346. Routine Description:
  2347. Returns the offset in milliseconds of the time zone of this machine
  2348. from GMT.
  2349. Arguments:
  2350. None.
  2351. Return Value:
  2352. Time in milliseconds between this time zone and GMT.
  2353. --*/
  2354. {
  2355. #if MILLEN
  2356. return (-1); // Error not supported.
  2357. #else // MILLEN
  2358. LARGE_INTEGER localTime, systemTime;
  2359. //
  2360. // Get time zone bias in 100ns.
  2361. //
  2362. localTime.LowPart = 0;
  2363. localTime.HighPart = 0;
  2364. ExLocalTimeToSystemTime(&localTime, &systemTime);
  2365. if ((localTime.LowPart != 0) || (localTime.HighPart != 0)) {
  2366. localTime = CTEConvert100nsToMilliseconds(systemTime);
  2367. }
  2368. ASSERT(localTime.HighPart == 0);
  2369. return (localTime.LowPart);
  2370. #endif // !MILLEN
  2371. }
  2372. ulong
  2373. GetTime(
  2374. void
  2375. )
  2376. /*++
  2377. Routine Description:
  2378. Returns the time in milliseconds since midnight.
  2379. Arguments:
  2380. None.
  2381. Return Value:
  2382. Time in milliseconds since midnight.
  2383. --*/
  2384. {
  2385. LARGE_INTEGER ntTime;
  2386. TIME_FIELDS breakdownTime;
  2387. ulong returnValue;
  2388. KeQuerySystemTime(&ntTime);
  2389. RtlTimeToTimeFields(&ntTime, &breakdownTime);
  2390. returnValue = breakdownTime.Hour * 60;
  2391. returnValue = (returnValue + breakdownTime.Minute) * 60;
  2392. returnValue = (returnValue + breakdownTime.Second) * 1000;
  2393. returnValue = returnValue + breakdownTime.Milliseconds;
  2394. return (returnValue);
  2395. }
  2396. ulong
  2397. GetUnique32BitValue(
  2398. void
  2399. )
  2400. /*++
  2401. Routine Description:
  2402. Returns a reasonably unique 32-bit number based on the system clock.
  2403. In NT, we take the current system time, convert it to milliseconds,
  2404. and return the low 32 bits.
  2405. Arguments:
  2406. None.
  2407. Return Value:
  2408. A reasonably unique 32-bit value.
  2409. --*/
  2410. {
  2411. LARGE_INTEGER ntTime, tmpTime;
  2412. KeQuerySystemTime(&ntTime);
  2413. tmpTime = CTEConvert100nsToMilliseconds(ntTime);
  2414. return (tmpTime.LowPart);
  2415. }
  2416. uint
  2417. UseEtherSNAP(
  2418. PNDIS_STRING Name
  2419. )
  2420. /*++
  2421. Routine Description:
  2422. Determines whether the EtherSNAP protocol should be used on an interface.
  2423. Arguments:
  2424. Name - The device name of the interface in question.
  2425. Return Value:
  2426. Nonzero if SNAP is to be used on the interface. Zero otherwise.
  2427. --*/
  2428. {
  2429. UNREFERENCED_PARAMETER(Name);
  2430. //
  2431. // We currently set this on a global basis.
  2432. //
  2433. return (ArpUseEtherSnap);
  2434. }
  2435. void
  2436. GetAlwaysSourceRoute(
  2437. uint * pArpAlwaysSourceRoute,
  2438. uint * pIPAlwaysSourceRoute
  2439. )
  2440. /*++
  2441. Routine Description:
  2442. Determines whether ARP should always turn on source routing in queries.
  2443. Arguments:
  2444. None.
  2445. Return Value:
  2446. Nonzero if source routing is always to be used. Zero otherwise.
  2447. --*/
  2448. {
  2449. //
  2450. // We currently set this on a global basis.
  2451. //
  2452. *pArpAlwaysSourceRoute = ArpAlwaysSourceRoute;
  2453. *pIPAlwaysSourceRoute = IPAlwaysSourceRoute;
  2454. return;
  2455. }
  2456. uint
  2457. GetArpCacheLife(
  2458. void
  2459. )
  2460. /*++
  2461. Routine Description:
  2462. Get ArpCacheLife in seconds.
  2463. Arguments:
  2464. None.
  2465. Return Value:
  2466. Set to default if not found.
  2467. --*/
  2468. {
  2469. //
  2470. // We currently set this on a global basis.
  2471. //
  2472. return (ArpCacheLife);
  2473. }
  2474. uint
  2475. GetArpRetryCount(
  2476. void
  2477. )
  2478. /*++
  2479. Routine Description:
  2480. Get ArpRetryCount
  2481. Arguments:
  2482. None.
  2483. Return Value:
  2484. Set to default if not found.
  2485. --*/
  2486. {
  2487. //
  2488. // We currently set this on a global basis.
  2489. //
  2490. return (ArpRetryCount);
  2491. }
  2492. #define IP_ADDRESS_STRING_LENGTH (16+2) // +2 for double NULL on MULTI_SZ
  2493. BOOLEAN
  2494. IPConvertStringToAddress(
  2495. IN PWCHAR AddressString,
  2496. OUT PULONG IpAddress
  2497. )
  2498. /*++
  2499. Routine Description
  2500. This function converts an Internet standard 4-octet dotted decimal
  2501. IP address string into a numeric IP address. Unlike inet_addr(), this
  2502. routine does not support address strings of less than 4 octets nor does
  2503. it support octal and hexadecimal octets, and it returns the address
  2504. in host byte order, rather than network byte order.
  2505. Arguments
  2506. AddressString - IP address in dotted decimal notation
  2507. IpAddress - Pointer to a variable to hold the resulting address
  2508. Return Value:
  2509. TRUE if the address string was converted. FALSE otherwise.
  2510. --*/
  2511. {
  2512. #if !MILLEN
  2513. NTSTATUS status;
  2514. PWCHAR endPointer;
  2515. status = RtlIpv4StringToAddressW(AddressString, TRUE, &endPointer,
  2516. (struct in_addr *)IpAddress);
  2517. if (!NT_SUCCESS(status)) {
  2518. return (FALSE);
  2519. }
  2520. *IpAddress = net_long(*IpAddress);
  2521. return ((BOOLEAN) (*endPointer == '\0'));
  2522. #else // MILLEN
  2523. UNICODE_STRING unicodeString;
  2524. STRING aString;
  2525. UCHAR dataBuffer[IP_ADDRESS_STRING_LENGTH];
  2526. NTSTATUS status;
  2527. PUCHAR addressPtr, cp, startPointer, endPointer;
  2528. ULONG digit, multiplier;
  2529. int i;
  2530. PAGED_CODE();
  2531. aString.Length = 0;
  2532. aString.MaximumLength = IP_ADDRESS_STRING_LENGTH;
  2533. aString.Buffer = dataBuffer;
  2534. RtlInitUnicodeString(&unicodeString, AddressString);
  2535. status = RtlUnicodeStringToAnsiString(
  2536. &aString,
  2537. &unicodeString,
  2538. FALSE
  2539. );
  2540. if (!NT_SUCCESS(status)) {
  2541. return (FALSE);
  2542. }
  2543. *IpAddress = 0;
  2544. addressPtr = (PUCHAR) IpAddress;
  2545. startPointer = dataBuffer;
  2546. endPointer = dataBuffer;
  2547. i = 3;
  2548. while (i >= 0) {
  2549. //
  2550. // Collect the characters up to a '.' or the end of the string.
  2551. //
  2552. while ((*endPointer != '.') && (*endPointer != '\0')) {
  2553. endPointer++;
  2554. }
  2555. if (startPointer == endPointer) {
  2556. return (FALSE);
  2557. }
  2558. //
  2559. // Convert the number.
  2560. //
  2561. for (cp = (endPointer - 1), multiplier = 1, digit = 0;
  2562. cp >= startPointer;
  2563. cp--, multiplier *= 10
  2564. ) {
  2565. if ((*cp < '0') || (*cp > '9') || (multiplier > 100)) {
  2566. return (FALSE);
  2567. }
  2568. digit += (multiplier * ((ULONG) (*cp - '0')));
  2569. }
  2570. if (digit > 255) {
  2571. return (FALSE);
  2572. }
  2573. addressPtr[i] = (UCHAR) digit;
  2574. //
  2575. // We are finished if we have found and converted 4 octets and have
  2576. // no other characters left in the string.
  2577. //
  2578. if ((i-- == 0) &&
  2579. ((*endPointer == '\0') || (*endPointer == ' '))
  2580. ) {
  2581. return (TRUE);
  2582. }
  2583. if (*endPointer == '\0') {
  2584. return (FALSE);
  2585. }
  2586. startPointer = ++endPointer;
  2587. }
  2588. return (FALSE);
  2589. #endif // MILLEN
  2590. }
  2591. ULONG
  2592. RouteMatch(
  2593. IN WCHAR * RouteString,
  2594. IN IPAddr Address,
  2595. IN IPMask Mask,
  2596. OUT IPAddr * DestVal,
  2597. OUT IPMask * DestMask,
  2598. OUT IPAddr * GateVal,
  2599. OUT ULONG * Metric
  2600. )
  2601. /*++
  2602. Routine Description
  2603. This function checks if a perisitent route should be assigned to
  2604. a given interface based on the interface address & mask.
  2605. Arguments
  2606. RouteString - A NULL-terminated route laid out as Dest,Mask,Gate.
  2607. Address - The IP address of the interface being processed.
  2608. Mask - The subnet mask of the interface being processed.
  2609. DestVal - A pointer to the decoded destination IP address.
  2610. DestVal - A pointer to the decoded destination subnet mask.
  2611. DestVal - A pointer to the decoded destination first hop gateway.
  2612. Metric - A pointer to the decoded route metric.
  2613. Return Value:
  2614. The route type, IRE_TYPE_DIRECT or IRE_TYPE_INDIRECT, if the route
  2615. should be added to the interface, IRE_TYPE_INVALID otherwise.
  2616. --*/
  2617. {
  2618. #define ROUTE_SEPARATOR L','
  2619. WCHAR *labelPtr;
  2620. WCHAR *indexPtr = RouteString;
  2621. ULONG i;
  2622. UNICODE_STRING ustring;
  2623. NTSTATUS status;
  2624. BOOLEAN noMetric = FALSE;
  2625. PAGED_CODE();
  2626. //
  2627. // The route is laid out in the string as "Dest,Mask,Gateway,Metric".
  2628. // The metric may not be there if this system was upgraded from
  2629. // NT 3.51.
  2630. //
  2631. // Parse the string and convert each label.
  2632. //
  2633. for (i = 0; i < 4; i++) {
  2634. labelPtr = indexPtr;
  2635. for (;;) {
  2636. if (*indexPtr == UNICODE_NULL) {
  2637. if ((i < 2) || (indexPtr == labelPtr)) {
  2638. return (IRE_TYPE_INVALID);
  2639. }
  2640. if (i == 2) {
  2641. //
  2642. // Old route - no metric.
  2643. //
  2644. noMetric = TRUE;
  2645. }
  2646. break;
  2647. }
  2648. if (*indexPtr == ROUTE_SEPARATOR) {
  2649. *indexPtr = UNICODE_NULL;
  2650. break;
  2651. }
  2652. indexPtr++;
  2653. }
  2654. switch (i) {
  2655. case 0:
  2656. if (!IPConvertStringToAddress(labelPtr, DestVal)) {
  2657. return (IRE_TYPE_INVALID);
  2658. }
  2659. break;
  2660. case 1:
  2661. if (!IPConvertStringToAddress(labelPtr, DestMask)) {
  2662. return (IRE_TYPE_INVALID);
  2663. }
  2664. break;
  2665. case 2:
  2666. if (!IPConvertStringToAddress(labelPtr, GateVal)) {
  2667. return (IRE_TYPE_INVALID);
  2668. }
  2669. break;
  2670. case 3:
  2671. RtlInitUnicodeString(&ustring, labelPtr);
  2672. status = RtlUnicodeStringToInteger(
  2673. &ustring,
  2674. 0,
  2675. Metric
  2676. );
  2677. if (!NT_SUCCESS(status)) {
  2678. return (IRE_TYPE_INVALID);
  2679. }
  2680. break;
  2681. default:
  2682. ASSERT(0);
  2683. return (IRE_TYPE_INVALID);
  2684. }
  2685. if (noMetric) {
  2686. //
  2687. // Default to 1.
  2688. //
  2689. *Metric = 1;
  2690. break;
  2691. }
  2692. indexPtr++;
  2693. }
  2694. if (IP_ADDR_EQUAL(*GateVal, Address)) {
  2695. return (IRE_TYPE_DIRECT);
  2696. }
  2697. if (IP_ADDR_EQUAL((*GateVal & Mask), (Address & Mask))) {
  2698. return (IRE_TYPE_INDIRECT);
  2699. }
  2700. return (IRE_TYPE_INVALID);
  2701. }
  2702. VOID
  2703. SetPersistentRoutesForNTE(
  2704. IPAddr Address,
  2705. IPMask Mask,
  2706. ULONG IFIndex
  2707. )
  2708. /*++
  2709. Routine Description
  2710. Adds persistent routes that match an interface. The routes are read
  2711. from a list in the registry.
  2712. Arguments
  2713. Address - The address of the new interface
  2714. Mask - The subnet mask of the new interface.
  2715. IFIndex - The index of the new interface.
  2716. Return Value:
  2717. None.
  2718. --*/
  2719. {
  2720. #define ROUTE_DATA_STRING_SIZE (51 * sizeof(WCHAR))
  2721. #define BASIC_INFO_SIZE (sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + ROUTE_DATA_STRING_SIZE)
  2722. #if !MILLEN
  2723. WCHAR IPRoutesRegistryKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\PersistentRoutes";
  2724. #else // !MILLEN
  2725. WCHAR IPRoutesRegistryKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP\\PersistentRoutes";
  2726. #endif // MILLEN
  2727. UCHAR workbuf[BASIC_INFO_SIZE];
  2728. PKEY_VALUE_BASIC_INFORMATION basicInfo = (PKEY_VALUE_BASIC_INFORMATION) workbuf;
  2729. ULONG resultLength;
  2730. ULONG type;
  2731. HANDLE regKey;
  2732. IPAddr destVal;
  2733. IPMask destMask;
  2734. IPAddr gateVal;
  2735. ULONG metric;
  2736. TDIObjectID id;
  2737. ULONG enumIndex = 0;
  2738. CTELockHandle TableHandle;
  2739. RouteTableEntry *RTE, *TempRTE;
  2740. IPRouteEntry routeEntry;
  2741. NTSTATUS status, setStatus;
  2742. DEBUGMSG(DBG_TRACE && DBG_ROUTE,
  2743. (DTEXT("+SetPersistenRoutesForNTE(%x, %x, %x)\n"),
  2744. Address, Mask, IFIndex));
  2745. //
  2746. // Open the registry key to read list of persistant routes
  2747. //
  2748. status = OpenRegKey(&regKey, IPRoutesRegistryKey);
  2749. DEBUGMSG(DBG_WARN && !NT_SUCCESS(status),
  2750. (DTEXT("SetPersistentRoutesForNTE: failed to open registry key %ls\n"),
  2751. IPRoutesRegistryKey));
  2752. if (NT_SUCCESS(status)) {
  2753. do {
  2754. //
  2755. // Enum each route from the registry list
  2756. //
  2757. status = ZwEnumerateValueKey(
  2758. regKey,
  2759. enumIndex,
  2760. KeyValueBasicInformation,
  2761. basicInfo,
  2762. BASIC_INFO_SIZE - sizeof(WCHAR),
  2763. &resultLength
  2764. );
  2765. if (!NT_SUCCESS(status)) {
  2766. if (status == STATUS_BUFFER_OVERFLOW) {
  2767. continue;
  2768. }
  2769. break;
  2770. }
  2771. #if !MILLEN
  2772. // Millennium seems to return REG_NONE in this case for some reason.
  2773. // Do we really care, since we are just using the name, and not the
  2774. // value?
  2775. if (basicInfo->Type != REG_SZ) {
  2776. DEBUGMSG(DBG_ERROR,
  2777. (DTEXT("SetPersistentRoutesForNTE: !NOT REG_SZ!\n")));
  2778. continue;
  2779. }
  2780. #endif // MILLEN
  2781. DEBUGMSG(DBG_INFO && DBG_ROUTE,
  2782. (DTEXT("SetPersistentRoutesForNTE: read key: %ls\n"),
  2783. basicInfo->Name));
  2784. //
  2785. // Ensure NULL termination
  2786. //
  2787. basicInfo->Name[basicInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
  2788. basicInfo->NameLength += sizeof(WCHAR);
  2789. type = RouteMatch(
  2790. basicInfo->Name,
  2791. Address,
  2792. Mask,
  2793. &destVal,
  2794. &destMask,
  2795. &gateVal,
  2796. &metric
  2797. );
  2798. DEBUGMSG(DBG_WARN && type == IRE_TYPE_INVALID,
  2799. (DTEXT("SetPersistentRoutesForNTE: RouteMatch returned IRE_TYPE_INVALID\n")));
  2800. if (type != IRE_TYPE_INVALID) {
  2801. //
  2802. // Do we already have a route with dest, mask ?
  2803. //
  2804. routeEntry.ire_dest = net_long(destVal);
  2805. routeEntry.ire_mask = net_long(destMask);
  2806. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  2807. RTE = FindMatchingRTE(routeEntry.ire_dest,
  2808. routeEntry.ire_mask,
  2809. 0, 0,
  2810. &TempRTE,
  2811. MATCH_NONE);
  2812. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  2813. DEBUGMSG(DBG_WARN && RTE,
  2814. (DTEXT("SetPersistentRoutesForNTE: route already exists RTE %x\n"),
  2815. RTE));
  2816. if (!RTE) {
  2817. //
  2818. // We do not have a route, so add this one
  2819. //
  2820. id.toi_entity.tei_entity = CL_NL_ENTITY;
  2821. id.toi_entity.tei_instance = 0;
  2822. id.toi_class = INFO_CLASS_PROTOCOL;
  2823. id.toi_type = INFO_TYPE_PROVIDER;
  2824. id.toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  2825. routeEntry.ire_nexthop = net_long(gateVal);
  2826. routeEntry.ire_type = type;
  2827. routeEntry.ire_metric1 = metric;
  2828. routeEntry.ire_index = IFIndex;
  2829. routeEntry.ire_metric2 = (ULONG) - 1;
  2830. routeEntry.ire_metric3 = (ULONG) - 1;
  2831. routeEntry.ire_metric4 = (ULONG) - 1;
  2832. routeEntry.ire_metric5 = (ULONG) - 1;
  2833. routeEntry.ire_proto = IRE_PROTO_NETMGMT;
  2834. routeEntry.ire_age = 0;
  2835. setStatus = IPSetInfo(
  2836. &id,
  2837. &routeEntry,
  2838. sizeof(IPRouteEntry)
  2839. );
  2840. DEBUGMSG(DBG_WARN && setStatus != IP_SUCCESS,
  2841. (DTEXT("SetPersistentRoutesForNTE: faile to add route [%x, %x, %x, %d], status %d\n"),
  2842. destVal, destMask, gateVal, metric, setStatus));
  2843. }
  2844. }
  2845. } while (++enumIndex);
  2846. ZwClose(regKey);
  2847. }
  2848. }
  2849. extern NetTableEntry *LoopNTE;
  2850. VOID
  2851. IPUnload(
  2852. IN PDRIVER_OBJECT DriverObject
  2853. )
  2854. /*++
  2855. Routine Description:
  2856. This routine cleans up the IP layer.
  2857. Arguments:
  2858. DriverObject - Pointer to driver object created by the system.
  2859. Return Value:
  2860. None. When the function returns, the driver is unloaded.
  2861. --*/
  2862. {
  2863. #if IPMCAST
  2864. if(IpMcastDeviceObject != NULL)
  2865. {
  2866. DeinitializeIpMcast(IpMcastDeviceObject);
  2867. }
  2868. #endif // IPMCAST
  2869. //
  2870. // Free up loopback resources
  2871. //
  2872. CTEInitBlockStrucEx(&LoopNTE->nte_timerblock);
  2873. LoopNTE->nte_if->if_flags |= IF_FLAGS_DELETING;
  2874. if ((LoopNTE->nte_flags & NTE_TIMER_STARTED) &&
  2875. !CTEStopTimer(&LoopNTE->nte_timer)) {
  2876. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop loopback timer - waiting on unload event\n"));
  2877. (VOID) CTEBlock(&LoopNTE->nte_timerblock);
  2878. KeClearEvent(&LoopNTE->nte_timerblock.cbs_event);
  2879. }
  2880. CTEFreeMem(LoopNTE);
  2881. //
  2882. // Shut down all timers
  2883. // NTE timers are stopped at DelIF time
  2884. //
  2885. CTEInitBlockStrucEx(&TcpipUnloadBlock);
  2886. fRouteTimerStopping = TRUE;
  2887. if (!CTEStopTimer(&IPRouteTimer)) {
  2888. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop route timer - waiting on unload event\n"));
  2889. #if !MILLEN
  2890. if (KeReadStateEvent(&(TcpipUnloadBlock.cbs_event))) {
  2891. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Event is signaled...\n"));
  2892. }
  2893. #endif // !MILLEN
  2894. (VOID) CTEBlock(&TcpipUnloadBlock);
  2895. KeClearEvent(&TcpipUnloadBlock.cbs_event);
  2896. }
  2897. //
  2898. // Free any residual memory - IP buffer/pkt pools
  2899. //
  2900. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Freeing Header buffer pools...\n"));
  2901. MdpDestroyPool(IpHeaderPool);
  2902. NdisFreePacketPool(NdisPacketPool);
  2903. if (TDBufferPool) {
  2904. NdisFreeBufferPool(TDBufferPool);
  2905. TDBufferPool = NULL;
  2906. }
  2907. if (TDPacketPool) {
  2908. NdisFreePacketPool(TDPacketPool);
  2909. TDPacketPool = NULL;
  2910. }
  2911. if (IPProviderHandle) {
  2912. TdiDeregisterProvider(IPProviderHandle);
  2913. }
  2914. //
  2915. // Free the cached entity-list
  2916. //
  2917. if (IPEntityList) {
  2918. CTEFreeMem(IPEntityList);
  2919. IPEntityList = NULL;
  2920. IPEntityCount = 0;
  2921. }
  2922. //
  2923. // Free the list of bindings
  2924. //
  2925. if (IPBindList) {
  2926. CTEFreeMem(IPBindList);
  2927. IPBindList = NULL;
  2928. }
  2929. //
  2930. // Free firewall-hook resources
  2931. //
  2932. FreeFirewallQ();
  2933. //
  2934. // Call into TCP so it can shut down
  2935. //
  2936. TCPUnload(DriverObject);
  2937. //
  2938. // Delete the IP device
  2939. //
  2940. IoDeleteDevice(IPDeviceObject);
  2941. }
  2942. NTSTATUS
  2943. IPAddNTEContextList(
  2944. HANDLE KeyHandle,
  2945. ushort contextValue,
  2946. uint isPrimary
  2947. )
  2948. /*++
  2949. Routine Description:
  2950. Writes the interface context of the NTE in the registry.
  2951. Arguments:
  2952. KeyHandle - Open handle to the parent key of the value to write.
  2953. contextvalue - The context value of the NTE
  2954. isPrimary -whether or not this is a Primary NTE
  2955. Return Value:
  2956. STATUS_SUCCESS or an appropriate failure code.
  2957. --*/
  2958. {
  2959. UNICODE_STRING_NEW contextString; // buffer holding the nte context list
  2960. NTSTATUS status; // status of this operation
  2961. PWSTR nextContext; // buffer where next context is stored
  2962. int i, nextDigit;
  2963. contextString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
  2964. if (contextString.Buffer == NULL) {
  2965. CTELogEvent(
  2966. IPDriverObject,
  2967. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  2968. 3,
  2969. 0,
  2970. NULL,
  2971. 0,
  2972. NULL
  2973. );
  2974. status = STATUS_INSUFFICIENT_RESOURCES;
  2975. return status;
  2976. }
  2977. RtlZeroMemory(contextString.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
  2978. contextString.Buffer[0] = UNICODE_NULL;
  2979. contextString.Length = 0;
  2980. contextString.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
  2981. KeWaitForMutexObject(&NTEContextMutex, Executive, KernelMode, FALSE, NULL);
  2982. if (!isPrimary) {
  2983. status = GetRegMultiSZValueNew(
  2984. KeyHandle,
  2985. L"NTEContextList",
  2986. &contextString
  2987. );
  2988. if (NT_SUCCESS(status)) {
  2989. ASSERT(contextString.Length > 0);
  2990. if (contextString.MaximumLength >= (contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR))) {
  2991. } else {
  2992. char *newBuf;
  2993. newBuf = CTEAllocMemBoot(contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  2994. if (!newBuf)
  2995. goto Exit;
  2996. RtlCopyMemory(newBuf, contextString.Buffer, contextString.Length);
  2997. RtlZeroMemory(newBuf + contextString.Length, (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  2998. CTEFreeMem(contextString.Buffer);
  2999. contextString.MaximumLength = contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR);
  3000. contextString.Buffer = (PWCHAR) newBuf;
  3001. }
  3002. nextContext = (PWCHAR) ((char *)contextString.Buffer + contextString.Length - 1 * sizeof(WCHAR));
  3003. RtlZeroMemory(nextContext, (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  3004. contextString.Length += 1 * sizeof(WCHAR);
  3005. } else {
  3006. goto Exit;
  3007. }
  3008. } else {
  3009. // this is the first nte of this if.
  3010. // add 2 null chars in the length.
  3011. nextContext = contextString.Buffer;
  3012. contextString.Length += 2 * sizeof(WCHAR);
  3013. }
  3014. for (i = NTE_CONTEXT_SIZE; i >= 2;) {
  3015. nextDigit = contextValue % 16;
  3016. if (nextDigit >= 0 && nextDigit <= 9) {
  3017. nextContext[--i] = (WCHAR) (L'0' + nextDigit);
  3018. } else {
  3019. nextContext[--i] = (WCHAR) (L'A' + nextDigit - 10);
  3020. }
  3021. contextValue /= 16;
  3022. }
  3023. // now prepend 0x
  3024. nextContext[0] = L'0';
  3025. nextContext[1] = L'x';
  3026. contextString.Length += NTE_CONTEXT_SIZE * sizeof(WCHAR);
  3027. status = SetRegMultiSZValueNew(
  3028. KeyHandle,
  3029. L"NTEContextList",
  3030. &contextString
  3031. );
  3032. Exit:
  3033. KeReleaseMutex(&NTEContextMutex, FALSE);
  3034. if (contextString.Buffer) {
  3035. CTEFreeMem(contextString.Buffer);
  3036. }
  3037. return status;
  3038. }
  3039. NTSTATUS
  3040. IPDelNTEContextList(
  3041. HANDLE KeyHandle,
  3042. ushort contextValue
  3043. )
  3044. /*++
  3045. Routine Description:
  3046. Writes the interface context of the NTE in the registry.
  3047. Arguments:
  3048. KeyHandle - Open handle to the parent key of the value to write.
  3049. NTE - The pointer to the NTE
  3050. Return Value:
  3051. STATUS_SUCCESS or an appropriate failure code.
  3052. --*/
  3053. {
  3054. UNICODE_STRING_NEW contextString; // buffer holding the nte context list
  3055. NTSTATUS status; // status of this operation
  3056. PWSTR nextContext; // buffer where next context is stored
  3057. int i, nextDigit;
  3058. WCHAR thisContext[NTE_CONTEXT_SIZE];
  3059. contextString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
  3060. if (contextString.Buffer == NULL) {
  3061. CTELogEvent(
  3062. IPDriverObject,
  3063. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  3064. 3,
  3065. 0,
  3066. NULL,
  3067. 0,
  3068. NULL
  3069. );
  3070. status = STATUS_INSUFFICIENT_RESOURCES;
  3071. return status;
  3072. }
  3073. RtlZeroMemory(contextString.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
  3074. contextString.Buffer[0] = UNICODE_NULL;
  3075. contextString.Length = 0;
  3076. contextString.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
  3077. // first read the ntecontext list.
  3078. KeWaitForMutexObject(&NTEContextMutex, Executive, KernelMode, FALSE, NULL);
  3079. status = GetRegMultiSZValueNew(
  3080. KeyHandle,
  3081. L"NTEContextList",
  3082. &contextString
  3083. );
  3084. if (NT_SUCCESS(status)) {
  3085. ASSERT(contextString.Length > 0);
  3086. // convert this NTE's context into string so that we can do simple mem compare.
  3087. for (i = NTE_CONTEXT_SIZE; i >= 2;) {
  3088. nextDigit = contextValue % 16;
  3089. if (nextDigit >= 0 && nextDigit <= 9) {
  3090. thisContext[--i] = (WCHAR) (L'0' + nextDigit);
  3091. } else {
  3092. thisContext[--i] = (WCHAR) (L'A' + nextDigit - 10);
  3093. }
  3094. contextValue /= 16;
  3095. }
  3096. // now prepend 0x
  3097. thisContext[0] = L'0';
  3098. thisContext[1] = L'x';
  3099. // now find thisContext in the contextlist, remove it off the list
  3100. // and update the contextList in the registry.
  3101. status = STATUS_UNSUCCESSFUL;
  3102. for (i = 0;
  3103. (i + NTE_CONTEXT_SIZE + 1)*sizeof(WCHAR) < contextString.Length &&
  3104. contextString.Buffer[i] != L'\0' &&
  3105. contextString.Buffer[i + NTE_CONTEXT_SIZE] == L'\0';
  3106. i += NTE_CONTEXT_SIZE + 1) {
  3107. nextContext = &contextString.Buffer[i];
  3108. if (RtlEqualMemory(nextContext, thisContext,
  3109. NTE_CONTEXT_SIZE * sizeof(WCHAR))) {
  3110. PWSTR nextNextContext = nextContext + NTE_CONTEXT_SIZE + 1;
  3111. RtlMoveMemory(nextContext,
  3112. nextNextContext,
  3113. contextString.Length -
  3114. ((PSTR)nextNextContext -
  3115. (PSTR)contextString.Buffer));
  3116. contextString.Length -= (NTE_CONTEXT_SIZE + 1) * sizeof(WCHAR);
  3117. status = SetRegMultiSZValueNew(KeyHandle,
  3118. L"NTEContextList",
  3119. &contextString);
  3120. break;
  3121. }
  3122. }
  3123. }
  3124. KeReleaseMutex(&NTEContextMutex, FALSE);
  3125. if (contextString.Buffer) {
  3126. CTEFreeMem(contextString.Buffer);
  3127. }
  3128. return status;
  3129. }
  3130. static const struct {
  3131. IP_STATUS ipStatus;
  3132. NTSTATUS ntStatus;
  3133. } IPStatusMap[] = {
  3134. { IP_SUCCESS, STATUS_SUCCESS },
  3135. { IP_NO_RESOURCES, STATUS_INSUFFICIENT_RESOURCES },
  3136. { IP_DEVICE_DOES_NOT_EXIST, STATUS_DEVICE_DOES_NOT_EXIST },
  3137. { IP_DUPLICATE_ADDRESS, STATUS_DUPLICATE_NAME },
  3138. { IP_PENDING, STATUS_PENDING },
  3139. { IP_DUPLICATE_IPADD, STATUS_DUPLICATE_OBJECTID },
  3140. { IP_GENERAL_FAILURE, STATUS_UNSUCCESSFUL }
  3141. };
  3142. NTSTATUS
  3143. IPStatusToNTStatus(
  3144. IN IP_STATUS ipStatus
  3145. )
  3146. /*++
  3147. Routine Description:
  3148. This routine converts IP_STATUS to NTSTATUS.
  3149. Arguments:
  3150. ipStatus - IP status code.
  3151. Return Value:
  3152. correcponding NTSTATUS
  3153. --*/
  3154. {
  3155. ULONG i;
  3156. for (i = 0; IPStatusMap[i].ipStatus != IP_GENERAL_FAILURE; i++) {
  3157. if (IPStatusMap[i].ipStatus == ipStatus) {
  3158. return IPStatusMap[i].ntStatus;
  3159. }
  3160. }
  3161. return STATUS_UNSUCCESSFUL;
  3162. }