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.

2852 lines
82 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ntinit.c
  5. Abstract:
  6. NT specific routines for loading and configuring the TCP/UDP 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. #if !MILLEN
  17. #include <ipfilter.h>
  18. #include <ipsec.h>
  19. #endif // !MILLEN
  20. #include "tdint.h"
  21. #include "addr.h"
  22. #include "tcp.h"
  23. #include "tcb.h"
  24. #include "udp.h"
  25. #include "raw.h"
  26. #include "tcpconn.h"
  27. #include "mdlpool.h"
  28. #include "pplasl.h"
  29. #include "tcprcv.h"
  30. #include "tcpsend.h"
  31. #include "tlcommon.h"
  32. #include "tcpcfg.h"
  33. #include "secfltr.h"
  34. #include "info.h"
  35. #if GPC
  36. #include <qos.h>
  37. #include <traffic.h>
  38. #include "gpcifc.h"
  39. #include "ntddtc.h"
  40. GPC_HANDLE hGpcClient[GPC_CF_MAX] = {0};
  41. ulong GpcCfCounts[GPC_CF_MAX] = {0};
  42. GPC_EXPORTED_CALLS GpcEntries;
  43. GPC_CLIENT_FUNC_LIST GpcHandlers;
  44. ulong GPCcfInfo = 0;
  45. GPC_STATUS GPCcfInfoAddNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt,
  46. GPC_HANDLE GpcHandle,
  47. PTC_INTERFACE_ID InterfaceInfo,
  48. ULONG CfInfoSize,
  49. PVOID CfInfo,
  50. PGPC_CLIENT_HANDLE pClInfoCxt);
  51. GPC_STATUS GPCcfInfoRemoveNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt,
  52. GPC_CLIENT_HANDLE ClInfoCxt);
  53. GPC_STATUS GPCcfInfoAddNotifyQoS(GPC_CLIENT_HANDLE ClCtxt,
  54. GPC_HANDLE GpcHandle,
  55. PTC_INTERFACE_ID InterfaceInfo,
  56. ULONG CfInfoSize,
  57. PVOID CfInfo,
  58. PGPC_CLIENT_HANDLE pClInfoCxt);
  59. GPC_STATUS GPCcfInfoRemoveNotifyQoS(GPC_CLIENT_HANDLE ClCtxt,
  60. GPC_CLIENT_HANDLE ClInfoCxt);
  61. #endif
  62. ReservedPortListEntry *PortRangeList = NULL;
  63. VOID
  64. GetReservedPortList(
  65. NDIS_HANDLE ConfigHandle
  66. );
  67. //
  68. // Global variables.
  69. //
  70. PDRIVER_OBJECT TCPDriverObject = NULL;
  71. PDEVICE_OBJECT TCPDeviceObject = NULL;
  72. PDEVICE_OBJECT UDPDeviceObject = NULL;
  73. PDEVICE_OBJECT RawIPDeviceObject = NULL;
  74. extern PDEVICE_OBJECT IPDeviceObject;
  75. TCPXSUM_ROUTINE tcpxsum_routine = tcpxsum;
  76. #if ACC
  77. PSECURITY_DESCRIPTOR TcpAdminSecurityDescriptor;
  78. extern uint AllowUserRawAccess;
  79. typedef ULONG SECURITY_INFORMATION;
  80. BOOLEAN
  81. IsRunningOnPersonal (
  82. VOID
  83. );
  84. #endif
  85. extern uint DisableLargeSendOffload;
  86. //
  87. //Place holder for Maximum duplicate acks we would like
  88. //to see before we do fast retransmit
  89. //
  90. extern uint MaxDupAcks;
  91. MM_SYSTEMSIZE systemSize;
  92. extern uint MaxHashTableSize;
  93. extern uint NumTcbTablePartitions;
  94. extern uint PerPartitionSize;
  95. extern uint LogPerPartitionSize;
  96. #define CACHE_LINE_SIZE 64
  97. #define CACHE_ALIGN_MASK (~(CACHE_LINE_SIZE-1))
  98. CTELock *pTWTCBTableLock;
  99. CTELock *pTCBTableLock;
  100. CTELock *pSynTCBTableLock;
  101. extern Queue *TWQueue;
  102. extern Queue *TWTCBTable;
  103. extern TCB **TCBTable;
  104. extern Queue *SYNTCBTable;
  105. extern PTIMER_WHEEL TimerWheel;
  106. PTIMER_WHEEL OrgTimerWheel;
  107. extern TCPConn **ConnTable;
  108. extern uint MaxConnBlocks;
  109. extern uint ConnPerBlock;
  110. extern uint GlobalMaxRcvWin;
  111. extern uint TcpHostOpts;
  112. extern uint TcpHostSendOpts;
  113. HANDLE TCPRegistrationHandle;
  114. HANDLE UDPRegistrationHandle;
  115. HANDLE IPRegistrationHandle;
  116. //SynAttackProtect=0 no syn flood attack protection
  117. //SynAttackProtect !0 syn flood attack protection
  118. //SynAttackProtect !0 syn flood attack protection+forced(non-dynamic)
  119. // delayed connect acceptance
  120. uint SynAttackProtect; // SYN-attack protection checks are made
  121. uint TCPMaxHalfOpen; //Max # of half-open connections allowed
  122. // before we dec. the syn-ack retries
  123. uint TCPMaxHalfOpenRetried; //Max # of half-open conn. that have
  124. // been retried at least 1 time
  125. uint TCPMaxHalfOpenRetriedLW; //Low-watermark of the above. When
  126. // go down to it, we revert to normal
  127. // # of retries for syn-acks
  128. uint TCPHalfOpen; //# of half-open connections
  129. uint TCPHalfOpenRetried; //# of half-open conn. that have been
  130. //retried at least once
  131. PDEVICE_OBJECT IPSECDeviceObject;
  132. PFILE_OBJECT IPSECFileObject;
  133. extern uint Time_Proc;
  134. extern HANDLE TcbPool;
  135. extern HANDLE TimewaitTcbPool;
  136. extern HANDLE SynTcbPool;
  137. extern void ArpUnload(PDRIVER_OBJECT);
  138. extern CTETimer TCBTimer[];
  139. extern BOOLEAN fTCBTimerStopping;
  140. extern CTEBlockStruc TcpipUnloadBlock;
  141. HANDLE AddressChangeHandle;
  142. extern ulong DefaultTOSValue;
  143. extern ulong DisableUserTOSSetting;
  144. extern uint MaxSendSegments;
  145. //
  146. // External function prototypes
  147. //
  148. int
  149. tlinit(
  150. void
  151. );
  152. NTSTATUS
  153. TCPDispatch(
  154. IN PDEVICE_OBJECT DeviceObject,
  155. IN PIRP Irp
  156. );
  157. NTSTATUS
  158. TCPDispatchInternalDeviceControl(
  159. IN PDEVICE_OBJECT DeviceObject,
  160. IN PIRP Irp
  161. );
  162. NTSTATUS
  163. IPDispatch(
  164. IN PDEVICE_OBJECT DeviceObject,
  165. IN PIRP Irp
  166. );
  167. NTSTATUS
  168. IPDriverEntry(
  169. IN PDRIVER_OBJECT DriverObject,
  170. IN PUNICODE_STRING RegistryPath
  171. );
  172. NTSTATUS
  173. IPPostDriverEntry(
  174. IN PDRIVER_OBJECT DriverObject,
  175. IN PUNICODE_STRING RegistryPath
  176. );
  177. NTSTATUS
  178. GetRegMultiSZValue(
  179. HANDLE KeyHandle,
  180. PWCHAR ValueName,
  181. PUNICODE_STRING ValueData
  182. );
  183. PWCHAR
  184. EnumRegMultiSz(
  185. IN PWCHAR MszString,
  186. IN ULONG MszStringLength,
  187. IN ULONG StringIndex
  188. );
  189. uint InitIsnGenerator();
  190. #if !MILLEN
  191. extern ulong g_cRandIsnStore;
  192. #endif // !MILLEN
  193. #if MILLEN
  194. extern VOID InitializeWDebDebug();
  195. #endif // MILLEN
  196. //
  197. // Local funcion prototypes
  198. //
  199. NTSTATUS
  200. DriverEntry(
  201. IN PDRIVER_OBJECT DriverObject,
  202. IN PUNICODE_STRING RegistryPath
  203. );
  204. void *
  205. TLRegisterProtocol(
  206. uchar Protocol,
  207. void *RcvHandler,
  208. void *XmitHandler,
  209. void *StatusHandler,
  210. void *RcvCmpltHandler,
  211. void *PnPHandler,
  212. void *ElistHandler
  213. );
  214. IP_STATUS
  215. TLGetIPInfo(
  216. IPInfo * Buffer,
  217. int Size
  218. );
  219. uchar
  220. TCPGetConfigInfo(
  221. void
  222. );
  223. NTSTATUS
  224. TCPInitializeParameter(
  225. HANDLE KeyHandle,
  226. PWCHAR ValueName,
  227. PULONG Value
  228. );
  229. #if !MILLEN
  230. NTSTATUS
  231. IpsecInitialize(
  232. void
  233. );
  234. NTSTATUS
  235. IpsecDeinitialize(
  236. void
  237. );
  238. #endif
  239. #if !MILLEN
  240. #ifdef i386
  241. NTSTATUS
  242. TCPSetChecksumRoutine(
  243. VOID
  244. );
  245. #endif
  246. #endif // !MILLEN
  247. uint
  248. EnumSecurityFilterValue(
  249. PNDIS_STRING FilterList,
  250. ulong Index,
  251. ulong * FilterValue
  252. );
  253. VOID
  254. TCPAcdBind();
  255. #ifdef ACC
  256. typedef ULONG SECURITY_INFORMATION;
  257. NTSTATUS
  258. TcpBuildDeviceAcl(
  259. OUT PACL * DeviceAcl
  260. );
  261. NTSTATUS
  262. TcpCreateAdminSecurityDescriptor(
  263. VOID
  264. );
  265. NTSTATUS
  266. AddNetConfigOpsAce(IN PACL Dacl,
  267. OUT PACL * DeviceAcl
  268. );
  269. NTSTATUS
  270. CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject
  271. );
  272. #endif // ACC
  273. #ifdef ALLOC_PRAGMA
  274. #pragma alloc_text(INIT, DriverEntry)
  275. #pragma alloc_text(INIT, TLRegisterProtocol)
  276. #pragma alloc_text(INIT, TLGetIPInfo)
  277. #pragma alloc_text(INIT, TCPGetConfigInfo)
  278. #pragma alloc_text(INIT, TCPInitializeParameter)
  279. #if !MILLEN
  280. #pragma alloc_text(INIT, IpsecInitialize)
  281. #endif
  282. #if !MILLEN
  283. #ifdef i386
  284. #pragma alloc_text(INIT, TCPSetChecksumRoutine)
  285. #endif
  286. #endif // !MILLEN
  287. #pragma alloc_text(PAGE, EnumSecurityFilterValue)
  288. #pragma alloc_text(INIT, TCPAcdBind)
  289. #ifdef ACC
  290. #pragma alloc_text(INIT, TcpBuildDeviceAcl)
  291. #pragma alloc_text(INIT, TcpCreateAdminSecurityDescriptor)
  292. #pragma alloc_text(INIT, AddNetConfigOpsAce)
  293. #pragma alloc_text(INIT, CreateDeviceDriverSecurityDescriptor)
  294. #endif // ACC
  295. #endif
  296. //
  297. // Function definitions
  298. //
  299. NTSTATUS
  300. DriverEntry(
  301. IN PDRIVER_OBJECT DriverObject,
  302. IN PUNICODE_STRING RegistryPath
  303. )
  304. /*++
  305. Routine Description:
  306. Initialization routine for the TCP/UDP driver.
  307. Arguments:
  308. DriverObject - Pointer to the TCP driver object created by the system.
  309. DeviceDescription - The name of TCP's node in the registry.
  310. Return Value:
  311. The final status from the initialization operation.
  312. --*/
  313. {
  314. NTSTATUS status;
  315. UNICODE_STRING deviceName;
  316. UNICODE_STRING SymbolicDeviceName;
  317. USHORT i;
  318. int initStatus;
  319. DEBUGMSGINIT();
  320. DEBUGMSG(DBG_TRACE && DBG_INIT,
  321. (DTEXT("+DriverEntry(%x, %x)\n"), DriverObject, RegistryPath));
  322. TdiInitialize();
  323. //
  324. // IP calls the security filter code, so initialize it first.
  325. //
  326. InitializeSecurityFilters();
  327. //
  328. // Initialize IP
  329. //
  330. status = IPDriverEntry(DriverObject, RegistryPath);
  331. if (!NT_SUCCESS(status)) {
  332. DEBUGMSG(DBG_ERROR && DBG_INIT,
  333. (DTEXT("TCPIP: IP Initialization failure %x\n"), status));
  334. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status));
  335. return (status);
  336. }
  337. #if !MILLEN
  338. //
  339. // Initialize IPSEC
  340. //
  341. status = IpsecInitialize();
  342. if (!NT_SUCCESS(status)) {
  343. DEBUGMSG(DBG_ERROR && DBG_INIT,
  344. (DTEXT("TCPIP: IPSEC Initialization failure %x\n"), status));
  345. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status));
  346. goto init_failed;
  347. }
  348. #endif
  349. //
  350. // Initialize TCP, UDP, and RawIP
  351. //
  352. TCPDriverObject = DriverObject;
  353. //
  354. // Create the device objects. IoCreateDevice zeroes the memory
  355. // occupied by the object.
  356. //
  357. RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME);
  358. RtlInitUnicodeString(&SymbolicDeviceName, DD_TCP_SYMBOLIC_DEVICE_NAME);
  359. status = IoCreateDevice(
  360. DriverObject,
  361. 0,
  362. &deviceName,
  363. FILE_DEVICE_NETWORK,
  364. FILE_DEVICE_SECURE_OPEN,
  365. FALSE,
  366. &TCPDeviceObject
  367. );
  368. if (!NT_SUCCESS(status)) {
  369. CTELogEvent(
  370. DriverObject,
  371. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  372. 1,
  373. 1,
  374. &deviceName.Buffer,
  375. 0,
  376. NULL
  377. );
  378. DEBUGMSG(DBG_ERROR && DBG_INIT,
  379. (DTEXT("DriverEntry: failure %x to create TCP device object %ws\n"),
  380. status, DD_TCP_DEVICE_NAME));
  381. goto init_failed;
  382. }
  383. status = IoCreateSymbolicLink(&SymbolicDeviceName, &deviceName);
  384. if (!NT_SUCCESS(status)) {
  385. CTELogEvent(
  386. DriverObject,
  387. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  388. 1,
  389. 1,
  390. &deviceName.Buffer,
  391. 0,
  392. NULL
  393. );
  394. DEBUGMSG(DBG_ERROR && DBG_INIT,
  395. (DTEXT("DriverEntry: failure %x to create TCP symbolic device link %ws\n"),
  396. status, DD_TCP_SYMBOLIC_DEVICE_NAME));
  397. goto init_failed;
  398. }
  399. RtlInitUnicodeString(&deviceName, DD_UDP_DEVICE_NAME);
  400. status = IoCreateDevice(
  401. DriverObject,
  402. 0,
  403. &deviceName,
  404. FILE_DEVICE_NETWORK,
  405. FILE_DEVICE_SECURE_OPEN,
  406. FALSE,
  407. &UDPDeviceObject
  408. );
  409. if (!NT_SUCCESS(status)) {
  410. CTELogEvent(
  411. DriverObject,
  412. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  413. 1,
  414. 1,
  415. &deviceName.Buffer,
  416. 0,
  417. NULL
  418. );
  419. TCPTRACE((
  420. "TCP: Failed to create UDP device object, status %lx\n",
  421. status
  422. ));
  423. goto init_failed;
  424. }
  425. RtlInitUnicodeString(&deviceName, DD_RAW_IP_DEVICE_NAME);
  426. status = IoCreateDevice(
  427. DriverObject,
  428. 0,
  429. &deviceName,
  430. FILE_DEVICE_NETWORK,
  431. FILE_DEVICE_SECURE_OPEN,
  432. FALSE,
  433. &RawIPDeviceObject
  434. );
  435. if (!NT_SUCCESS(status)) {
  436. CTELogEvent(
  437. DriverObject,
  438. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  439. 1,
  440. 1,
  441. &deviceName.Buffer,
  442. 0,
  443. NULL
  444. );
  445. TCPTRACE((
  446. "TCP: Failed to create Raw IP device object, status %lx\n",
  447. status
  448. ));
  449. goto init_failed;
  450. }
  451. //
  452. // Initialize the driver object
  453. //
  454. DriverObject->DriverUnload = ArpUnload;
  455. DriverObject->FastIoDispatch = NULL;
  456. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  457. DriverObject->MajorFunction[i] = TCPDispatch;
  458. }
  459. //
  460. // We special case Internal Device Controls because they are the
  461. // hot path for kernel-mode clients.
  462. //
  463. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  464. TCPDispatchInternalDeviceControl;
  465. //
  466. // Intialize the device objects.
  467. //
  468. TCPDeviceObject->Flags |= DO_DIRECT_IO;
  469. UDPDeviceObject->Flags |= DO_DIRECT_IO;
  470. RawIPDeviceObject->Flags |= DO_DIRECT_IO;
  471. #ifdef ACC
  472. // Change the different devices and Objects to allow access to Network Configuration Operators
  473. if (!IsRunningOnPersonal()) {
  474. status = CreateDeviceDriverSecurityDescriptor(IPDeviceObject);
  475. if (!NT_SUCCESS(status)) {
  476. goto init_failed;
  477. }
  478. status = CreateDeviceDriverSecurityDescriptor(TCPDeviceObject);
  479. if (!NT_SUCCESS(status)) {
  480. goto init_failed;
  481. }
  482. status = CreateDeviceDriverSecurityDescriptor(IPSECDeviceObject);
  483. if (!NT_SUCCESS(status)) {
  484. goto init_failed;
  485. }
  486. }
  487. //
  488. // Create the security descriptor used for raw socket access checks.
  489. //
  490. status = TcpCreateAdminSecurityDescriptor();
  491. if (!NT_SUCCESS(status)) {
  492. goto init_failed;
  493. }
  494. #endif // ACC
  495. #if !MILLEN
  496. #ifdef i386
  497. //
  498. // Set the checksum routine pointer according to the processor available
  499. //
  500. TCPSetChecksumRoutine();
  501. #endif
  502. #endif // !MILLEN
  503. //
  504. // Finally, initialize the stack.
  505. //
  506. initStatus = tlinit();
  507. if (initStatus == TRUE) {
  508. //
  509. // Get the automatic connection driver
  510. // entry points.
  511. //
  512. TCPAcdBind();
  513. RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME);
  514. (void)TdiRegisterDeviceObject(&deviceName, &TCPRegistrationHandle);
  515. RtlInitUnicodeString(&deviceName, DD_UDP_DEVICE_NAME);
  516. (void)TdiRegisterDeviceObject(&deviceName, &UDPRegistrationHandle);
  517. RtlInitUnicodeString(&deviceName, DD_RAW_IP_DEVICE_NAME);
  518. (void)TdiRegisterDeviceObject(&deviceName, &IPRegistrationHandle);
  519. #if GPC
  520. status = GpcInitialize(&GpcEntries);
  521. if (!NT_SUCCESS(status)) {
  522. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GpcInitialize Failed! Status: 0x%x\n", status));
  523. //return status;
  524. } else {
  525. //
  526. // Need to register as GPC client. Try it now.
  527. // we register clients for QOS and IPSEC
  528. //
  529. memset(&GpcHandlers, 0, sizeof(GPC_CLIENT_FUNC_LIST));
  530. GpcHandlers.ClAddCfInfoNotifyHandler = GPCcfInfoAddNotifyQoS;
  531. GpcHandlers.ClRemoveCfInfoNotifyHandler = GPCcfInfoRemoveNotifyQoS;
  532. status = GpcEntries.GpcRegisterClientHandler(
  533. GPC_CF_QOS, // classification family
  534. 0, // flags
  535. 1, // default max priority
  536. &GpcHandlers, // client notification vector - no notifications to TCPIP required
  537. 0, // client context, not needed
  538. &hGpcClient[GPC_CF_QOS]);
  539. if (!NT_SUCCESS(status)) {
  540. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GPC registerclient QOS status %x hGpcClient %p\n",
  541. status, hGpcClient[GPC_CF_QOS]));
  542. hGpcClient[GPC_CF_QOS] = NULL;
  543. }
  544. GpcHandlers.ClAddCfInfoNotifyHandler = GPCcfInfoAddNotifyIpsec;
  545. GpcHandlers.ClRemoveCfInfoNotifyHandler = GPCcfInfoRemoveNotifyIpsec;
  546. status = GpcEntries.GpcRegisterClientHandler(
  547. GPC_CF_IPSEC, // classification family
  548. 0, // flags
  549. GPC_PRIORITY_IPSEC, // default max priority
  550. &GpcHandlers, // client notification vector - no notifications to TCPIP required
  551. 0, // client context, not needed
  552. &hGpcClient[GPC_CF_IPSEC]);
  553. if (!NT_SUCCESS(status)) {
  554. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GPC registerclient IPSEC status %x hGpcClient %p\n",
  555. status, hGpcClient[GPC_CF_IPSEC]));
  556. hGpcClient[GPC_CF_IPSEC] = NULL;
  557. }
  558. }
  559. #endif
  560. if (InitIsnGenerator() == FALSE) {
  561. DEBUGMSG(DBG_ERROR && DBG_INIT,
  562. (DTEXT("InitIsnGenerator failure. TCP/IP failing to start.\n")));
  563. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status));
  564. return (STATUS_UNSUCCESSFUL);
  565. }
  566. // do the ndis register protocol now after all the intialization
  567. // is complete, o/w we get bindadapter even before we r fully
  568. // initialized.
  569. status = IPPostDriverEntry(DriverObject, RegistryPath);
  570. if (!NT_SUCCESS(status)) {
  571. DEBUGMSG(DBG_ERROR && DBG_INIT,
  572. (DTEXT("TCPIP: IP post-init failure %x\n"), status));
  573. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status));
  574. return (status);
  575. }
  576. // Millennium TCPIP has debugger extensions built in!
  577. #if MILLEN
  578. InitializeWDebDebug();
  579. #endif // MILLEN
  580. #if TRACE_EVENT
  581. //
  582. // Register with WMI for Enable/Disable Notification
  583. // of Trace Logging
  584. //
  585. TCPCPHandlerRoutine = NULL;
  586. IoWMIRegistrationControl(
  587. TCPDeviceObject,
  588. WMIREG_ACTION_REGISTER |
  589. WMIREG_FLAG_TRACE_PROVIDER |
  590. WMIREG_NOTIFY_TDI_IO
  591. );
  592. #endif
  593. //
  594. // Initialize the connection callback object. We do not treat its
  595. // failure as fatal, and continue to function even in case of failure.
  596. // We may log it in the future.
  597. //
  598. TcpInitCcb();
  599. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [SUCCESS]\n")));
  600. return (STATUS_SUCCESS);
  601. }
  602. DEBUGMSG(DBG_ERROR && DBG_INIT,
  603. (DTEXT("TCPIP: TCP initialization failed, IP still available.\n")));
  604. CTELogEvent(
  605. DriverObject,
  606. EVENT_TCPIP_TCP_INIT_FAILED,
  607. 1,
  608. 0,
  609. NULL,
  610. 0,
  611. NULL
  612. );
  613. status = STATUS_UNSUCCESSFUL;
  614. init_failed:
  615. DEBUGMSG(DBG_ERROR && DBG_INIT,
  616. (DTEXT("TCPIP DriverEntry initialization failure!\n")));
  617. //
  618. // IP has successfully started, but TCP & UDP failed. Set the
  619. // Dispatch routine to point to IP only, since the TCP and UDP
  620. // devices don't exist.
  621. //
  622. if (TCPDeviceObject != NULL) {
  623. IoDeleteDevice(TCPDeviceObject);
  624. }
  625. if (UDPDeviceObject != NULL) {
  626. IoDeleteDevice(UDPDeviceObject);
  627. }
  628. if (RawIPDeviceObject != NULL) {
  629. IoDeleteDevice(RawIPDeviceObject);
  630. }
  631. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  632. DriverObject->MajorFunction[i] = IPDispatch;
  633. }
  634. #if !MILLEN
  635. if (IPSECFileObject) {
  636. IpsecDeinitialize();
  637. }
  638. #endif
  639. return (status);
  640. }
  641. #if !MILLEN
  642. #ifdef i386
  643. NTSTATUS
  644. TCPSetChecksumRoutine(
  645. VOID
  646. )
  647. /*++
  648. Routine Description:
  649. This routine sets the checksum routine function pointer to the
  650. appropriate routine based on the processor features available
  651. Arguments:
  652. None
  653. Return Value:
  654. STATUS_SUCCESS - if successful
  655. --*/
  656. {
  657. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  658. if (ExIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
  659. tcpxsum_routine = tcpxsum_xmmi;
  660. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip: Loading XMMI Prefetch Checksum\n"));
  661. Status = STATUS_SUCCESS;
  662. }
  663. return Status;
  664. }
  665. #endif
  666. #endif // !MILLEN
  667. IP_STATUS
  668. TLGetIPInfo(
  669. IPInfo * Buffer,
  670. int Size
  671. )
  672. /*++
  673. Routine Description:
  674. Returns information necessary for TCP to call into IP.
  675. Arguments:
  676. Buffer - A pointer to the IP information structure.
  677. Size - The size of Buffer.
  678. Return Value:
  679. The IP status of the operation.
  680. --*/
  681. {
  682. return (IPGetInfo(Buffer, Size));
  683. }
  684. void *
  685. TLRegisterProtocol(
  686. uchar Protocol,
  687. void *RcvHandler,
  688. void *XmitHandler,
  689. void *StatusHandler,
  690. void *RcvCmpltHandler,
  691. void *PnPHandler,
  692. void *ElistHandler
  693. )
  694. /*++
  695. Routine Description:
  696. Calls the IP driver's protocol registration function.
  697. Arguments:
  698. Protocol - The protocol number to register.
  699. RcvHandler - Transport's packet receive handler.
  700. XmitHandler - Transport's packet transmit complete handler.
  701. StatusHandler - Transport's status update handler.
  702. RcvCmpltHandler - Transport's receive complete handler
  703. Return Value:
  704. A context value for the protocol to pass to IP when transmitting.
  705. --*/
  706. {
  707. return (IPRegisterProtocol(
  708. Protocol,
  709. RcvHandler,
  710. XmitHandler,
  711. StatusHandler,
  712. RcvCmpltHandler,
  713. PnPHandler,
  714. ElistHandler));
  715. }
  716. //
  717. // Interval in milliseconds between keepalive transmissions until a
  718. // response is received.
  719. //
  720. #define DEFAULT_KEEPALIVE_INTERVAL 1000
  721. //
  722. // time to first keepalive transmission. 2 hours == 7,200,000 milliseconds
  723. //
  724. #define DEFAULT_KEEPALIVE_TIME 7200000
  725. #define MIN_THRESHOLD_MAX_HO 1
  726. #define MIN_THRESHOLD_MAX_HO_RETRIED 80
  727. uchar
  728. TCPGetConfigInfo(
  729. void
  730. )
  731. /*++
  732. Routine Description:
  733. Initializes TCP global configuration parameters.
  734. Arguments:
  735. None.
  736. Return Value:
  737. Zero on failure, nonzero on success.
  738. --*/
  739. {
  740. HANDLE keyHandle;
  741. NTSTATUS status;
  742. OBJECT_ATTRIBUTES objectAttributes;
  743. UNICODE_STRING UKeyName;
  744. ULONG maxConnectRexmits = 0;
  745. ULONG maxConnectResponseRexmits = 0;
  746. ULONG maxDataRexmits = 0;
  747. ULONG pptpmaxDataRexmits = 0;
  748. ULONG useRFC1122UrgentPointer = 0;
  749. ULONG tcp1323opts = 3; //turning off 1323 options by default
  750. ULONG SackOpts;
  751. ULONG i, j;
  752. DEBUGMSG(DBG_TRACE && DBG_INIT,
  753. (DTEXT("+TCPGetConfigInfo()\n")));
  754. //
  755. // Initialize to the defaults in case an error occurs somewhere.
  756. //
  757. KAInterval = DEFAULT_KEEPALIVE_INTERVAL;
  758. KeepAliveTime = DEFAULT_KEEPALIVE_TIME;
  759. PMTUDiscovery = TRUE;
  760. PMTUBHDetect = FALSE;
  761. DeadGWDetect = TRUE;
  762. DefaultRcvWin = 0; // Automagically pick a reasonable one.
  763. MaxConnections = DEFAULT_MAX_CONNECTIONS;
  764. maxConnectRexmits = MAX_CONNECT_REXMIT_CNT;
  765. maxConnectResponseRexmits = MAX_CONNECT_RESPONSE_REXMIT_CNT;
  766. pptpmaxDataRexmits = maxDataRexmits = MAX_REXMIT_CNT;
  767. BSDUrgent = TRUE;
  768. FinWait2TO = FIN_WAIT2_TO;
  769. NTWMaxConnectCount = NTW_MAX_CONNECT_COUNT;
  770. NTWMaxConnectTime = NTW_MAX_CONNECT_TIME;
  771. MaxUserPort = DEFAULT_MAX_USER_PORT;
  772. // Default number of duplicate acks
  773. MaxDupAcks = 2;
  774. SynAttackProtect = 0; //by default it is always off
  775. #if MILLEN
  776. TCPMaxHalfOpen = 100;
  777. TCPMaxHalfOpenRetried = 80;
  778. #else // MILLEN
  779. if (!MmIsThisAnNtAsSystem()) {
  780. TCPMaxHalfOpen = 100;
  781. TCPMaxHalfOpenRetried = 80;
  782. } else {
  783. TCPMaxHalfOpen = 500;
  784. TCPMaxHalfOpenRetried = 400;
  785. }
  786. #endif // !MILLEN
  787. SecurityFilteringEnabled = FALSE;
  788. #ifdef ACC
  789. AllowUserRawAccess = FALSE;
  790. #endif
  791. //
  792. // Read the TCP optional (hidden) registry parameters.
  793. //
  794. #if !MILLEN
  795. RtlInitUnicodeString(
  796. &UKeyName,
  797. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
  798. );
  799. #else // !MILLEN
  800. RtlInitUnicodeString(
  801. &UKeyName,
  802. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP"
  803. );
  804. #endif // MILLEN
  805. DEBUGMSG(DBG_INFO && DBG_INIT,
  806. (DTEXT("TCPGetConfigInfo: Opening key %ws\n"), UKeyName.Buffer));
  807. memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  808. InitializeObjectAttributes(
  809. &objectAttributes,
  810. &UKeyName,
  811. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  812. NULL,
  813. NULL
  814. );
  815. status = ZwOpenKey(
  816. &keyHandle,
  817. KEY_READ,
  818. &objectAttributes
  819. );
  820. DEBUGMSG(!NT_SUCCESS(status) && DBG_ERROR,
  821. (DTEXT("TCPGetConfigInfo: failed to open TCP registry configuration: %ws\n"),
  822. UKeyName.Buffer));
  823. if (NT_SUCCESS(status)) {
  824. DEBUGMSG(DBG_INFO && DBG_INIT,
  825. (DTEXT("TCPGetConfigInfo: successfully opened registry to read.\n")));
  826. #if !MILLEN
  827. TCPInitializeParameter(
  828. keyHandle,
  829. L"IsnStoreSize",
  830. &g_cRandIsnStore
  831. );
  832. #endif // !MILLEN
  833. TCPInitializeParameter(
  834. keyHandle,
  835. L"KeepAliveInterval",
  836. (PULONG)&KAInterval
  837. );
  838. TCPInitializeParameter(
  839. keyHandle,
  840. L"KeepAliveTime",
  841. (PULONG)&KeepAliveTime
  842. );
  843. status = TCPInitializeParameter(
  844. keyHandle,
  845. L"EnablePMTUBHDetect",
  846. (PULONG)&PMTUBHDetect
  847. );
  848. #if MILLEN
  849. //
  850. // Backwards compatibility. If 'EnablePMTUBHDetect' value does not exist,
  851. // then attempt to read legacy 'PMTUBlackHoleDetect'.
  852. //
  853. if (!NT_SUCCESS(status)) {
  854. TCPInitializeParameter(
  855. keyHandle,
  856. L"PMTUBlackHoleDetect",
  857. &PMTUBHDetect
  858. );
  859. }
  860. #endif // MILLEN
  861. status = TCPInitializeParameter(
  862. keyHandle,
  863. L"TcpWindowSize",
  864. (PULONG)&DefaultRcvWin
  865. );
  866. #if MILLEN
  867. //
  868. // Backwards compatibility. If 'TcpWindowSize' value does not exist,
  869. // then attempt to read legacy 'DefaultRcvWindow'.
  870. //
  871. if (!NT_SUCCESS(status)) {
  872. TCPInitializeParameter(
  873. keyHandle,
  874. L"DefaultRcvWindow",
  875. &DefaultRcvWin
  876. );
  877. }
  878. #endif // MILLEN
  879. // We can not have negative size windows
  880. if ( (LONG) DefaultRcvWin < 0 ) {
  881. DefaultRcvWin = TCP_MAX_SCALED_WIN;
  882. }
  883. status = TCPInitializeParameter(
  884. keyHandle,
  885. L"TcpNumConnections",
  886. (PULONG)&MaxConnections
  887. );
  888. #if MILLEN
  889. //
  890. // Backwards compatibility. If 'TcpNumConnections' value does not exist,
  891. // then attempt to read legacy 'MaxConnections'.
  892. //
  893. if (!NT_SUCCESS(status)) {
  894. TCPInitializeParameter(
  895. keyHandle,
  896. L"MaxConnections",
  897. &MaxConnections
  898. );
  899. }
  900. #endif // MILLEN
  901. status = TCPInitializeParameter(
  902. keyHandle,
  903. L"TcpMaxConnectRetransmissions",
  904. &maxConnectRexmits
  905. );
  906. #if MILLEN
  907. //
  908. // Backwards compatibility. If 'TcpMaxConnectRetransmissions' value does not exist,
  909. // then attempt to read legacty 'MaxConnectRetries'.
  910. //
  911. if (!NT_SUCCESS(status)) {
  912. TCPInitializeParameter(
  913. keyHandle,
  914. L"MaxConnectRetries",
  915. &maxConnectRexmits
  916. );
  917. }
  918. #endif // MILLEN
  919. if (maxConnectRexmits > 255) {
  920. maxConnectRexmits = 255;
  921. }
  922. TCPInitializeParameter(
  923. keyHandle,
  924. L"TcpMaxConnectResponseRetransmissions",
  925. &maxConnectResponseRexmits
  926. );
  927. if (maxConnectResponseRexmits > 255) {
  928. maxConnectResponseRexmits = 255;
  929. }
  930. status = TCPInitializeParameter(
  931. keyHandle,
  932. L"TcpMaxDataRetransmissions",
  933. &maxDataRexmits
  934. );
  935. #if MILLEN
  936. //
  937. // Backwards compatibility. If 'TcpMaxDataRetransmissions' value does not exist,
  938. // then attempt to read legacy 'MaxDataRetries'.
  939. //
  940. if (!NT_SUCCESS(status)) {
  941. TCPInitializeParameter(
  942. keyHandle,
  943. L"MaxDataRetries",
  944. &maxDataRexmits
  945. );
  946. }
  947. #endif // MILLEN
  948. if (maxDataRexmits > 255) {
  949. maxDataRexmits = 255;
  950. }
  951. // Limit the MaxDupAcks to 3
  952. status = TCPInitializeParameter(
  953. keyHandle,
  954. L"TcpMaxDupAcks",
  955. (PULONG)&MaxDupAcks
  956. );
  957. #if MILLEN
  958. //
  959. // Backwards compatibility. If 'TcpMaxDupAcks' value does not exist,
  960. // then attempt to read legacy 'MaxDupAcks'.
  961. //
  962. if (!NT_SUCCESS(status)) {
  963. TCPInitializeParameter(
  964. keyHandle,
  965. L"MaxDupAcks",
  966. &MaxDupAcks
  967. );
  968. }
  969. #endif // MILLEN
  970. if (MaxDupAcks > 3) {
  971. MaxDupAcks = 3;
  972. }
  973. if (MaxDupAcks == 0) {
  974. MaxDupAcks = 1;
  975. }
  976. #if MILLEN
  977. MaxConnBlocks = 16;
  978. #else // MILLEN
  979. systemSize = MmQuerySystemSize();
  980. if (MmIsThisAnNtAsSystem()) {
  981. if (systemSize == MmSmallSystem) {
  982. MaxConnBlocks = 128;
  983. } else if (systemSize == MmMediumSystem) {
  984. MaxConnBlocks = 256;
  985. } else {
  986. #if defined(_WIN64)
  987. MaxConnBlocks = 4096;
  988. #else
  989. MaxConnBlocks = 1024;
  990. #endif
  991. }
  992. } else {
  993. //for workstation, small system limit default number of connections to 4K.
  994. // medium system 8k
  995. // Large system 32k connections
  996. if (systemSize == MmSmallSystem) {
  997. MaxConnBlocks = 16;
  998. } else if (systemSize == MmMediumSystem) {
  999. MaxConnBlocks = 32;
  1000. } else {
  1001. MaxConnBlocks = 128;
  1002. }
  1003. }
  1004. #endif // !MILLEN
  1005. #if MILLEN
  1006. NumTcbTablePartitions = 1;
  1007. #else
  1008. NumTcbTablePartitions = (KeNumberProcessors * KeNumberProcessors);
  1009. #endif
  1010. TCPInitializeParameter(
  1011. keyHandle,
  1012. L"NumTcbTablePartitions",
  1013. (PULONG)&NumTcbTablePartitions
  1014. );
  1015. if (NumTcbTablePartitions > (MAXIMUM_PROCESSORS * MAXIMUM_PROCESSORS)) {
  1016. NumTcbTablePartitions = (MAXIMUM_PROCESSORS * MAXIMUM_PROCESSORS);
  1017. }
  1018. NumTcbTablePartitions = ComputeLargerOrEqualPowerOfTwo(NumTcbTablePartitions);
  1019. // Default to 128 buckets per partition
  1020. MaxHashTableSize = 128 * NumTcbTablePartitions;
  1021. TCPInitializeParameter(
  1022. keyHandle,
  1023. L"MaxHashTableSize",
  1024. (PULONG)&MaxHashTableSize
  1025. );
  1026. if (MaxHashTableSize < 64) {
  1027. MaxHashTableSize = 64;
  1028. } else if (MaxHashTableSize > 0xffff) {
  1029. MaxHashTableSize = 0x10000;
  1030. }
  1031. MaxHashTableSize = ComputeLargerOrEqualPowerOfTwo(MaxHashTableSize);
  1032. if (MaxHashTableSize < NumTcbTablePartitions) {
  1033. MaxHashTableSize = 128 * NumTcbTablePartitions;
  1034. }
  1035. ASSERT(IsPowerOfTwo(MaxHashTableSize));
  1036. //since hash table size is power of 2 and cache line size
  1037. //is power of 2 and number of partion is even,
  1038. //entries per partions will be power of 2 and multiple of
  1039. //cache line size.
  1040. PerPartitionSize = MaxHashTableSize / NumTcbTablePartitions;
  1041. ASSERT(IsPowerOfTwo(PerPartitionSize));
  1042. LogPerPartitionSize =
  1043. ComputeShiftForLargerOrEqualPowerOfTwo(PerPartitionSize);
  1044. status = TCPInitializeParameter(
  1045. keyHandle,
  1046. L"Tcp1323Opts",
  1047. &tcp1323opts
  1048. );
  1049. if (status == STATUS_SUCCESS) {
  1050. // Check if TS and/or WS options
  1051. // are enabled.
  1052. TcpHostOpts = TCP_FLAG_WS | TCP_FLAG_TS;
  1053. if (!(tcp1323opts & TCP_FLAG_TS)) {
  1054. TcpHostOpts &= ~TCP_FLAG_TS;
  1055. }
  1056. if (!(tcp1323opts & TCP_FLAG_WS)) {
  1057. TcpHostOpts &= ~TCP_FLAG_WS;
  1058. }
  1059. TcpHostSendOpts = TcpHostOpts;
  1060. } else {
  1061. TcpHostSendOpts = 0;
  1062. }
  1063. TcpHostOpts |= TCP_FLAG_SACK;
  1064. status = TCPInitializeParameter(
  1065. keyHandle,
  1066. L"SackOpts",
  1067. &SackOpts
  1068. );
  1069. if (status == STATUS_SUCCESS) {
  1070. //Check if Sack option is enabled
  1071. //If so, set it in global options variable
  1072. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Sackopts %x\n", SackOpts));
  1073. if (!SackOpts) {
  1074. TcpHostOpts &= ~TCP_FLAG_SACK;
  1075. }
  1076. }
  1077. TCPInitializeParameter(
  1078. keyHandle,
  1079. L"GlobalMaxTcpWindowSize",
  1080. (PULONG)&GlobalMaxRcvWin
  1081. );
  1082. TCPInitializeParameter(
  1083. keyHandle,
  1084. L"SynAttackProtect",
  1085. (unsigned long *)&SynAttackProtect
  1086. );
  1087. if (SynAttackProtect) {
  1088. TCPInitializeParameter(
  1089. keyHandle,
  1090. L"TCPMaxHalfOpen",
  1091. (PULONG)&TCPMaxHalfOpen
  1092. );
  1093. if (TCPMaxHalfOpen < MIN_THRESHOLD_MAX_HO) {
  1094. TCPMaxHalfOpen = MIN_THRESHOLD_MAX_HO;
  1095. }
  1096. TCPInitializeParameter(
  1097. keyHandle,
  1098. L"TCPMaxHalfOpenRetried",
  1099. (PULONG)&TCPMaxHalfOpenRetried
  1100. );
  1101. if ((TCPMaxHalfOpenRetried > TCPMaxHalfOpen) ||
  1102. (TCPMaxHalfOpenRetried < MIN_THRESHOLD_MAX_HO_RETRIED)) {
  1103. TCPMaxHalfOpenRetried = MIN_THRESHOLD_MAX_HO_RETRIED;
  1104. }
  1105. TCPMaxHalfOpenRetriedLW = (TCPMaxHalfOpenRetried >> 1) +
  1106. (TCPMaxHalfOpenRetried >> 2);
  1107. }
  1108. //
  1109. // If we fail, then set to same value as maxDataRexmit so that the
  1110. // max(pptpmaxDataRexmit,maxDataRexmit) is a decent value
  1111. // Need this since TCPInitializeParameter no longer "initializes"
  1112. // to a default value
  1113. //
  1114. if (TCPInitializeParameter(keyHandle,
  1115. L"PPTPTcpMaxDataRetransmissions",
  1116. &pptpmaxDataRexmits) != STATUS_SUCCESS) {
  1117. pptpmaxDataRexmits = maxDataRexmits;
  1118. }
  1119. if (pptpmaxDataRexmits > 255) {
  1120. pptpmaxDataRexmits = 255;
  1121. }
  1122. status = TCPInitializeParameter(
  1123. keyHandle,
  1124. L"TcpUseRFC1122UrgentPointer",
  1125. &useRFC1122UrgentPointer
  1126. );
  1127. #if MILLEN
  1128. //
  1129. // Backwards compatibility. If TcpUseRFC1122UrgentPointer does not exist,
  1130. // then check for BSDUrgent. These values are logical opposites.
  1131. //
  1132. if (!NT_SUCCESS(status)) {
  1133. ULONG tmpBsdUrgent = TRUE;
  1134. status = TCPInitializeParameter(
  1135. keyHandle,
  1136. L"BSDUrgent",
  1137. &tmpBsdUrgent);
  1138. if (NT_SUCCESS(status)) {
  1139. useRFC1122UrgentPointer = !tmpBsdUrgent;
  1140. }
  1141. }
  1142. #endif
  1143. if (useRFC1122UrgentPointer) {
  1144. BSDUrgent = FALSE;
  1145. }
  1146. TCPInitializeParameter(
  1147. keyHandle,
  1148. L"TcpTimedWaitDelay",
  1149. (PULONG)&FinWait2TO
  1150. );
  1151. if (FinWait2TO > 300) {
  1152. FinWait2TO = 300;
  1153. }
  1154. FinWait2TO = MS_TO_TICKS(FinWait2TO * 1000);
  1155. NTWMaxConnectTime = MS_TO_TICKS(NTWMaxConnectTime * 1000);
  1156. TCPInitializeParameter(
  1157. keyHandle,
  1158. L"MaxUserPort",
  1159. (PULONG)&MaxUserPort
  1160. );
  1161. if (MaxUserPort < 5000) {
  1162. MaxUserPort = 5000;
  1163. }
  1164. if (MaxUserPort > 65534) {
  1165. MaxUserPort = 65534;
  1166. }
  1167. GetReservedPortList(keyHandle);
  1168. //Reserve ports if
  1169. //
  1170. // Read a few IP optional (hidden) registry parameters that TCP
  1171. // cares about.
  1172. //
  1173. status = TCPInitializeParameter(
  1174. keyHandle,
  1175. L"EnablePMTUDiscovery",
  1176. (PULONG)&PMTUDiscovery
  1177. );
  1178. #if MILLEN
  1179. //
  1180. // Backwards compatibility. If 'EnablePMTUDiscovery' value does not exist,
  1181. // then attempt to read legacy 'PMTUDiscovery'.
  1182. //
  1183. if (!NT_SUCCESS(status)) {
  1184. TCPInitializeParameter(
  1185. keyHandle,
  1186. L"PMTUDiscovery",
  1187. &PMTUDiscovery
  1188. );
  1189. }
  1190. #endif // MILLEN
  1191. TCPInitializeParameter(
  1192. keyHandle,
  1193. L"EnableDeadGWDetect",
  1194. (PULONG)&DeadGWDetect
  1195. );
  1196. TCPInitializeParameter(
  1197. keyHandle,
  1198. L"EnableSecurityFilters",
  1199. (PULONG)&SecurityFilteringEnabled
  1200. );
  1201. #ifdef ACC
  1202. TCPInitializeParameter(
  1203. keyHandle,
  1204. L"AllowUserRawAccess",
  1205. (PULONG)&AllowUserRawAccess
  1206. );
  1207. #endif // ACC
  1208. status = TCPInitializeParameter(
  1209. keyHandle,
  1210. L"DefaultTOSValue",
  1211. &DefaultTOSValue
  1212. );
  1213. #if MILLEN
  1214. //
  1215. // Backwards compatibility. Read 'DefaultTOS' if 'DefaultTOSValue' is
  1216. // not present.
  1217. //
  1218. if (!NT_SUCCESS(status)) {
  1219. TCPInitializeParameter(
  1220. keyHandle,
  1221. L"DefaultTOS",
  1222. &DefaultTOSValue
  1223. );
  1224. }
  1225. #endif // MILLEN
  1226. TCPInitializeParameter(
  1227. keyHandle,
  1228. L"DisableUserTOSSetting",
  1229. &DisableUserTOSSetting
  1230. );
  1231. TCPInitializeParameter(
  1232. keyHandle,
  1233. L"MaxSendSegments",
  1234. (PULONG)&MaxSendSegments
  1235. );
  1236. TCPInitializeParameter(
  1237. keyHandle,
  1238. L"DisableLargeSendOffload",
  1239. (PULONG)&DisableLargeSendOffload
  1240. );
  1241. ZwClose(keyHandle);
  1242. }
  1243. MaxConnectRexmitCount = maxConnectRexmits;
  1244. MaxConnectResponseRexmitCount = maxConnectResponseRexmits;
  1245. MaxConnectResponseRexmitCountTmp = MaxConnectResponseRexmitCount;
  1246. //
  1247. // Use the greater of the two, hence both values should be valid
  1248. //
  1249. MaxDataRexmitCount = (maxDataRexmits > pptpmaxDataRexmits ? maxDataRexmits : pptpmaxDataRexmits);
  1250. TWTCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*TWTCBTable));
  1251. if (TWTCBTable == NULL) {
  1252. ZwClose(keyHandle);
  1253. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tw tcb table of size %x\n", MaxHashTableSize));
  1254. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1255. return (0);
  1256. }
  1257. for (i = 0; i < MaxHashTableSize; i++)
  1258. {
  1259. INITQ(&TWTCBTable[i]);
  1260. }
  1261. TCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*TCBTable));
  1262. if (TCBTable == NULL) {
  1263. ExFreePool(TWTCBTable);
  1264. ZwClose(keyHandle);
  1265. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tcb table of size %x\n", MaxHashTableSize));
  1266. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1267. return (0);
  1268. }
  1269. NdisZeroMemory(TCBTable, MaxHashTableSize * sizeof(*TCBTable));
  1270. SYNTCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*SYNTCBTable));
  1271. if (SYNTCBTable == NULL) {
  1272. ExFreePool(TWTCBTable);
  1273. ExFreePool(TCBTable);
  1274. ZwClose(keyHandle);
  1275. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate syn tcb table of size %x\n", MaxHashTableSize));
  1276. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1277. return (0);
  1278. }
  1279. for (i = 0; i < MaxHashTableSize; i++)
  1280. {
  1281. INITQ(&SYNTCBTable[i]);
  1282. }
  1283. pSynTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock));
  1284. if (pSynTCBTableLock == NULL) {
  1285. ExFreePool(TCBTable);
  1286. ExFreePool(TWTCBTable);
  1287. ExFreePool(SYNTCBTable);
  1288. ZwClose(keyHandle);
  1289. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate twtcb lock table \n"));
  1290. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1291. return (0);
  1292. }
  1293. pTWTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock));
  1294. if (pTWTCBTableLock == NULL) {
  1295. ExFreePool(TCBTable);
  1296. ExFreePool(TWTCBTable);
  1297. ExFreePool(SYNTCBTable);
  1298. ExFreePool(pSynTCBTableLock);
  1299. ZwClose(keyHandle);
  1300. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate twtcb lock table \n"));
  1301. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1302. return (0);
  1303. }
  1304. pTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock));
  1305. if (pTCBTableLock == NULL) {
  1306. ExFreePool(TCBTable);
  1307. ExFreePool(TWTCBTable);
  1308. ExFreePool(pTWTCBTableLock);
  1309. ExFreePool(SYNTCBTable);
  1310. ExFreePool(pSynTCBTableLock);
  1311. ZwClose(keyHandle);
  1312. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tcb lock table \n"));
  1313. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1314. return (0);
  1315. }
  1316. TWQueue = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(Queue));
  1317. if (TWQueue == NULL) {
  1318. ExFreePool(TCBTable);
  1319. ExFreePool(TWTCBTable);
  1320. ExFreePool(pTWTCBTableLock);
  1321. ExFreePool(SYNTCBTable);
  1322. ExFreePool(pSynTCBTableLock);
  1323. ExFreePool(pTCBTableLock);
  1324. ZwClose(keyHandle);
  1325. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate Twqueue \n"));
  1326. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1327. return (0);
  1328. }
  1329. TimerWheel = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(TIMER_WHEEL) + CACHE_LINE_SIZE);
  1330. if (TimerWheel == NULL) {
  1331. ExFreePool(TCBTable);
  1332. ExFreePool(TWTCBTable);
  1333. ExFreePool(pTWTCBTableLock);
  1334. ExFreePool(SYNTCBTable);
  1335. ExFreePool(pSynTCBTableLock);
  1336. ExFreePool(pTCBTableLock);
  1337. ExFreePool(TWQueue);
  1338. ZwClose(keyHandle);
  1339. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate Twqueue \n"));
  1340. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1341. return (0);
  1342. }
  1343. OrgTimerWheel = TimerWheel;
  1344. TimerWheel = (PTIMER_WHEEL)(((ULONG_PTR) TimerWheel + CACHE_LINE_SIZE) & CACHE_ALIGN_MASK);
  1345. for (i = 0; i < NumTcbTablePartitions; i++) {
  1346. CTEInitLock(&pTCBTableLock[i]);
  1347. CTEInitLock(&pTWTCBTableLock[i]);
  1348. CTEInitLock(&pSynTCBTableLock[i]);
  1349. INITQ(&TWQueue[i])
  1350. // Init the timer wheel
  1351. CTEInitLock(&TimerWheel[i].tw_lock);
  1352. #ifdef TIMER_TEST
  1353. TimerWheel[i].tw_starttick = 0xfffff000;
  1354. #else
  1355. TimerWheel[i].tw_starttick = 0;
  1356. #endif
  1357. for(j = 0; j < TIMER_WHEEL_SIZE; j++) {
  1358. INITQ(&TimerWheel[i].tw_timerslot[j])
  1359. }
  1360. }
  1361. if (MaxConnections != DEFAULT_MAX_CONNECTIONS) {
  1362. //make it even
  1363. MaxConnBlocks = ((MaxConnections >> 1) << 1);
  1364. //allow minimum of 1k level 1 conn blocks.
  1365. //this gives minimum of 256K connections capability
  1366. if (MaxConnBlocks < 1024) {
  1367. MaxConnBlocks = 1024;
  1368. }
  1369. }
  1370. ConnTable = CTEAllocMemBoot(MaxConnBlocks * sizeof(TCPConnBlock *));
  1371. if (ConnTable == NULL) {
  1372. ExFreePool(OrgTimerWheel);
  1373. ExFreePool(TWQueue);
  1374. ExFreePool(TCBTable);
  1375. ExFreePool(TWTCBTable);
  1376. ExFreePool(pTWTCBTableLock);
  1377. ExFreePool(pTCBTableLock);
  1378. ExFreePool(SYNTCBTable);
  1379. ExFreePool(pSynTCBTableLock);
  1380. ZwClose(keyHandle);
  1381. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate ConnTable \n"));
  1382. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n")));
  1383. return (0);
  1384. }
  1385. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [SUCCESS]\n")));
  1386. return (1);
  1387. }
  1388. #define WORK_BUFFER_SIZE 256
  1389. extern NTSTATUS
  1390. GetRegDWORDValue(
  1391. HANDLE KeyHandle,
  1392. PWCHAR ValueName,
  1393. PULONG ValueData
  1394. );
  1395. NTSTATUS
  1396. TCPInitializeParameter(
  1397. HANDLE KeyHandle,
  1398. PWCHAR ValueName,
  1399. PULONG Value
  1400. )
  1401. /*++
  1402. Routine Description:
  1403. Initializes a ULONG parameter from the registry or to a default
  1404. parameter if accessing the registry value fails.
  1405. Arguments:
  1406. KeyHandle - An open handle to the registry key for the parameter.
  1407. ValueName - The UNICODE name of the registry value to read.
  1408. Value - The ULONG into which to put the data.
  1409. DefaultValue - The default to assign if reading the registry fails.
  1410. Return Value:
  1411. None.
  1412. --*/
  1413. {
  1414. return (GetRegDWORDValue(KeyHandle, ValueName, Value));
  1415. }
  1416. VOID
  1417. GetReservedPortList(
  1418. NDIS_HANDLE ConfigHandle
  1419. )
  1420. {
  1421. UNICODE_STRING PortList;
  1422. PWCHAR nextRange;
  1423. TDI_STATUS status;
  1424. PortList.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
  1425. if (!PortList.Buffer) {
  1426. return;
  1427. }
  1428. PortList.Buffer[0] = UNICODE_NULL;
  1429. PortList.Length = 0;
  1430. PortList.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
  1431. PortRangeList = NULL;
  1432. if (PortList.Buffer) {
  1433. NdisZeroMemory(PortList.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
  1434. status = GetRegMultiSZValue(
  1435. ConfigHandle,
  1436. L"ReservedPorts",
  1437. &PortList
  1438. );
  1439. if (NT_SUCCESS(status)) {
  1440. for (nextRange = PortList.Buffer;
  1441. *nextRange != L'\0';
  1442. nextRange += wcslen(nextRange) + 1) {
  1443. PWCHAR tmps = nextRange;
  1444. USHORT upval = 0, loval = 0, tmpval = 0;
  1445. BOOLEAN error = FALSE;
  1446. ReservedPortListEntry *ListEntry;
  1447. while (*tmps != L'\0') {
  1448. if (*tmps == L'-') {
  1449. tmps++;
  1450. loval = tmpval;
  1451. tmpval = 0;
  1452. }
  1453. if (*tmps >= L'0' && *tmps <= L'9') {
  1454. tmpval = tmpval * 10 + (*tmps - L'0');
  1455. } else {
  1456. error = TRUE;
  1457. break;
  1458. }
  1459. tmps++;
  1460. }
  1461. upval = tmpval;
  1462. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"loval %d upval %d\n", loval, upval));
  1463. if (!error && (loval > 0) && (upval > 0) && (loval <= upval) &&
  1464. (upval <= MaxUserPort) && (loval <= MaxUserPort)) {
  1465. ListEntry = CTEAllocMemBoot(sizeof(ReservedPortListEntry));
  1466. if (ListEntry) {
  1467. //Insert this range.
  1468. //No need to take locks
  1469. //since we are at initialization.
  1470. ListEntry->UpperRange = upval;
  1471. ListEntry->LowerRange = loval;
  1472. ListEntry->next = PortRangeList;
  1473. PortRangeList = ListEntry;
  1474. }
  1475. }
  1476. }
  1477. }
  1478. CTEFreeMem(PortList.Buffer);
  1479. }
  1480. }
  1481. TDI_STATUS
  1482. GetSecurityFilterList(
  1483. NDIS_HANDLE ConfigHandle,
  1484. ulong Protocol,
  1485. PNDIS_STRING FilterList
  1486. )
  1487. {
  1488. PWCHAR parameterName;
  1489. TDI_STATUS status;
  1490. if (Protocol == PROTOCOL_TCP) {
  1491. parameterName = L"TcpAllowedPorts";
  1492. } else if (Protocol == PROTOCOL_UDP) {
  1493. parameterName = L"UdpAllowedPorts";
  1494. } else {
  1495. parameterName = L"RawIpAllowedProtocols";
  1496. }
  1497. status = GetRegMultiSZValue(
  1498. ConfigHandle,
  1499. parameterName,
  1500. FilterList
  1501. );
  1502. if (!NT_SUCCESS(status)) {
  1503. FilterList->Length = 0;
  1504. }
  1505. return (status);
  1506. }
  1507. uint
  1508. EnumSecurityFilterValue(
  1509. PNDIS_STRING FilterList,
  1510. ulong Index,
  1511. ulong * FilterValue
  1512. )
  1513. {
  1514. PWCHAR valueString;
  1515. UNICODE_STRING unicodeString;
  1516. NTSTATUS status;
  1517. PAGED_CODE();
  1518. valueString = EnumRegMultiSz(
  1519. FilterList->Buffer,
  1520. FilterList->Length,
  1521. Index
  1522. );
  1523. if ((valueString == NULL) || (valueString[0] == UNICODE_NULL)) {
  1524. return (FALSE);
  1525. }
  1526. RtlInitUnicodeString(&unicodeString, valueString);
  1527. status = RtlUnicodeStringToInteger(&unicodeString, 0, FilterValue);
  1528. if (!(NT_SUCCESS(status))) {
  1529. TCPTRACE(("TCP: Invalid filter value %ws\n", valueString));
  1530. return (FALSE);
  1531. }
  1532. return (TRUE);
  1533. }
  1534. VOID
  1535. TCPFreeupMemory()
  1536. /*++
  1537. Routine Description:
  1538. This routine frees up the memory at the TCP layer
  1539. Arguments:
  1540. NULL
  1541. Return Value:
  1542. None.
  1543. --*/
  1544. {
  1545. //
  1546. // Walk various lists and free assoc blocks
  1547. //
  1548. // DG header list
  1549. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Freeing DG headers....\n"));
  1550. MdpDestroyPool(DgHeaderPool);
  1551. if (AddrObjTable) {
  1552. CTEFreeMem(AddrObjTable);
  1553. }
  1554. PplDestroyPool(TcbPool);
  1555. PplDestroyPool(SynTcbPool);
  1556. #ifdef ACC
  1557. if (TcpAdminSecurityDescriptor) {
  1558. ExFreePool(TcpAdminSecurityDescriptor);
  1559. }
  1560. #endif
  1561. }
  1562. VOID
  1563. TCPUnload(
  1564. IN PDRIVER_OBJECT DriverObject
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. This routine cleans up the TCP layer.
  1569. Arguments:
  1570. DriverObject - Pointer to driver object created by the system.
  1571. Return Value:
  1572. None. When the function returns, the driver is unloaded.
  1573. --*/
  1574. {
  1575. NTSTATUS status;
  1576. uint i;
  1577. TcpUnInitCcb();
  1578. #if !MILLEN
  1579. //
  1580. // Deinitialize IPSEC first
  1581. //
  1582. status = IpsecDeinitialize();
  1583. #endif
  1584. //
  1585. // Shut down all timers/events
  1586. //
  1587. CTEInitBlockStrucEx(&TcpipUnloadBlock);
  1588. fTCBTimerStopping = TRUE;
  1589. for (i = 0; i < Time_Proc; i++) {
  1590. if (!CTEStopTimer(&TCBTimer[i])) {
  1591. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop TCB timer - waiting on unload event\n"));
  1592. #if !MILLEN
  1593. if (KeReadStateEvent(&(TcpipUnloadBlock.cbs_event))) {
  1594. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Event is signaled...\n"));
  1595. }
  1596. #endif // !MILLEN
  1597. (VOID) CTEBlock(&TcpipUnloadBlock);
  1598. KeClearEvent(&TcpipUnloadBlock.cbs_event);
  1599. }
  1600. }
  1601. #if GPC
  1602. //
  1603. if (hGpcClient[GPC_CF_QOS]) {
  1604. status = GpcEntries.GpcDeregisterClientHandler(hGpcClient[GPC_CF_QOS]);
  1605. hGpcClient[GPC_CF_QOS] = NULL;
  1606. }
  1607. if (hGpcClient[GPC_CF_IPSEC]) {
  1608. status = GpcEntries.GpcDeregisterClientHandler(hGpcClient[GPC_CF_IPSEC]);
  1609. hGpcClient[GPC_CF_IPSEC] = NULL;
  1610. }
  1611. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Deregistering GPC\n"));
  1612. status = GpcDeinitialize(&GpcEntries);
  1613. #endif
  1614. //
  1615. // Clean up all residual memory
  1616. //
  1617. TCPFreeupMemory();
  1618. //
  1619. // Deregister address notifn handler with TDI
  1620. //
  1621. (void)TdiDeregisterPnPHandlers(AddressChangeHandle);
  1622. //
  1623. // Deregister our devices with TDI
  1624. //
  1625. (void)TdiDeregisterDeviceObject(TCPRegistrationHandle);
  1626. (void)TdiDeregisterDeviceObject(UDPRegistrationHandle);
  1627. (void)TdiDeregisterDeviceObject(IPRegistrationHandle);
  1628. #if TRACE_EVENT
  1629. //
  1630. // Deregister with WMI
  1631. //
  1632. IoWMIRegistrationControl(TCPDeviceObject, WMIREG_ACTION_DEREGISTER);
  1633. #endif
  1634. //
  1635. // Delete devices
  1636. //
  1637. IoDeleteDevice(TCPDeviceObject);
  1638. IoDeleteDevice(UDPDeviceObject);
  1639. IoDeleteDevice(RawIPDeviceObject);
  1640. }
  1641. #if GPC
  1642. GPC_STATUS
  1643. GPCcfInfoAddNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt,
  1644. GPC_HANDLE GpcHandle,
  1645. PTC_INTERFACE_ID InterfaceInfo,
  1646. ULONG CfInfoSize,
  1647. PVOID CfInfo,
  1648. PGPC_CLIENT_HANDLE pClInfoCxt)
  1649. {
  1650. InterlockedIncrement((PLONG)&GPCcfInfo);
  1651. IF_TCPDBG(TCP_DEBUG_GPC)
  1652. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GPCcfInfo));
  1653. InterlockedIncrement((PLONG)&GpcCfCounts[GPC_CF_IPSEC]);
  1654. IF_TCPDBG(TCP_DEBUG_GPC)
  1655. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification IPSEC:%x\n", GpcCfCounts[GPC_CF_IPSEC]));
  1656. return (STATUS_SUCCESS);
  1657. }
  1658. GPC_STATUS
  1659. GPCcfInfoRemoveNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt,
  1660. GPC_CLIENT_HANDLE ClInfoCxt)
  1661. {
  1662. InterlockedDecrement((PLONG)&GPCcfInfo);
  1663. IF_TCPDBG(TCP_DEBUG_GPC)
  1664. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo remove notification %x\n", GPCcfInfo));
  1665. InterlockedDecrement((PLONG)&GpcCfCounts[GPC_CF_IPSEC]);
  1666. IF_TCPDBG(TCP_DEBUG_GPC)
  1667. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification IPSEC: %x\n", GpcCfCounts[GPC_CF_IPSEC]));
  1668. return (STATUS_SUCCESS);
  1669. }
  1670. GPC_STATUS
  1671. GPCcfInfoAddNotifyQoS(GPC_CLIENT_HANDLE ClCtxt,
  1672. GPC_HANDLE GpcHandle,
  1673. PTC_INTERFACE_ID InterfaceInfo,
  1674. ULONG CfInfoSize,
  1675. PVOID CfInfo,
  1676. PGPC_CLIENT_HANDLE pClInfoCxt)
  1677. {
  1678. InterlockedIncrement((PLONG)&GPCcfInfo);
  1679. IF_TCPDBG(TCP_DEBUG_GPC)
  1680. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GPCcfInfo));
  1681. InterlockedIncrement((PLONG)&GpcCfCounts[GPC_CF_QOS]);
  1682. IF_TCPDBG(TCP_DEBUG_GPC)
  1683. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification QOS: %x\n", GpcCfCounts[GPC_CF_QOS]));
  1684. return (STATUS_SUCCESS);
  1685. }
  1686. GPC_STATUS
  1687. GPCcfInfoRemoveNotifyQoS(GPC_CLIENT_HANDLE ClCtxt,
  1688. GPC_CLIENT_HANDLE ClInfoCxt)
  1689. {
  1690. InterlockedDecrement((PLONG)&GPCcfInfo);
  1691. IF_TCPDBG(TCP_DEBUG_GPC)
  1692. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo remove notification %x\n", GPCcfInfo));
  1693. InterlockedDecrement((PLONG)&GpcCfCounts[GPC_CF_QOS]);
  1694. IF_TCPDBG(TCP_DEBUG_GPC)
  1695. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GpcCfCounts[GPC_CF_QOS]));
  1696. return (STATUS_SUCCESS);
  1697. }
  1698. #endif
  1699. #if ACC
  1700. NTSTATUS
  1701. TcpBuildDeviceAcl(
  1702. OUT PACL * DeviceAcl
  1703. )
  1704. /*++
  1705. Routine Description:
  1706. (Lifted from AFD - AfdBuildDeviceAcl)
  1707. This routine builds an ACL which gives Administrators and LocalSystem
  1708. principals full access. All other principals have no access.
  1709. Arguments:
  1710. DeviceAcl - Output pointer to the new ACL.
  1711. Return Value:
  1712. STATUS_SUCCESS or an appropriate error code.
  1713. --*/
  1714. {
  1715. PGENERIC_MAPPING GenericMapping;
  1716. PSID AdminsSid;
  1717. PSID SystemSid;
  1718. PSID NetworkSid;
  1719. ULONG AclLength;
  1720. NTSTATUS Status;
  1721. ACCESS_MASK AccessMask = GENERIC_ALL;
  1722. PACL NewAcl;
  1723. //
  1724. // Enable access to all the globally defined SIDs
  1725. //
  1726. GenericMapping = IoGetFileObjectGenericMapping();
  1727. RtlMapGenericMask(&AccessMask, GenericMapping);
  1728. AdminsSid = SeExports->SeAliasAdminsSid;
  1729. SystemSid = SeExports->SeLocalSystemSid;
  1730. NetworkSid = SeExports->SeNetworkServiceSid;
  1731. AclLength = sizeof(ACL) +
  1732. 3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE,SidStart) +
  1733. RtlLengthSid(AdminsSid) +
  1734. RtlLengthSid(SystemSid) +
  1735. RtlLengthSid(NetworkSid);
  1736. NewAcl = CTEAllocMemBoot(AclLength);
  1737. if (NewAcl == NULL) {
  1738. return (STATUS_INSUFFICIENT_RESOURCES);
  1739. }
  1740. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
  1741. if (!NT_SUCCESS(Status)) {
  1742. CTEFreeMem(NewAcl);
  1743. return (Status);
  1744. }
  1745. Status = RtlAddAccessAllowedAce(
  1746. NewAcl,
  1747. ACL_REVISION,
  1748. AccessMask,
  1749. AdminsSid
  1750. );
  1751. ASSERT(NT_SUCCESS(Status));
  1752. Status = RtlAddAccessAllowedAce(
  1753. NewAcl,
  1754. ACL_REVISION,
  1755. AccessMask,
  1756. SystemSid
  1757. );
  1758. ASSERT(NT_SUCCESS(Status));
  1759. // Add acl for NetworkSid!
  1760. Status = RtlAddAccessAllowedAce(
  1761. NewAcl,
  1762. ACL_REVISION,
  1763. AccessMask,
  1764. NetworkSid
  1765. );
  1766. ASSERT(NT_SUCCESS(Status));
  1767. *DeviceAcl = NewAcl;
  1768. return (STATUS_SUCCESS);
  1769. } // TcpBuildDeviceAcl
  1770. NTSTATUS
  1771. TcpCreateAdminSecurityDescriptor(
  1772. VOID
  1773. )
  1774. /*++
  1775. Routine Description:
  1776. (Lifted from AFD - AfdCreateAdminSecurityDescriptor)
  1777. This routine creates a security descriptor which gives access
  1778. only to Administrtors and LocalSystem. This descriptor is used
  1779. to access check raw endpoint opens and exclisive access to transport
  1780. addresses.
  1781. Arguments:
  1782. None.
  1783. Return Value:
  1784. STATUS_SUCCESS or an appropriate error code.
  1785. --*/
  1786. {
  1787. PACL rawAcl = NULL;
  1788. NTSTATUS status;
  1789. BOOLEAN memoryAllocated = FALSE;
  1790. PSECURITY_DESCRIPTOR tcpSecurityDescriptor;
  1791. ULONG tcpSecurityDescriptorLength;
  1792. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  1793. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  1794. (PSECURITY_DESCRIPTOR) & buffer;
  1795. PSECURITY_DESCRIPTOR localTcpAdminSecurityDescriptor;
  1796. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  1797. //
  1798. // Get a pointer to the security descriptor from the TCP device object.
  1799. //
  1800. status = ObGetObjectSecurity(
  1801. TCPDeviceObject,
  1802. &tcpSecurityDescriptor,
  1803. &memoryAllocated
  1804. );
  1805. if (!NT_SUCCESS(status)) {
  1806. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1807. "TCP: Unable to get security descriptor, error: %x\n",
  1808. status
  1809. ));
  1810. ASSERT(memoryAllocated == FALSE);
  1811. return (status);
  1812. }
  1813. //
  1814. // Build a local security descriptor with an ACL giving only
  1815. // administrators and system access.
  1816. //
  1817. status = TcpBuildDeviceAcl(&rawAcl);
  1818. if (!NT_SUCCESS(status)) {
  1819. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: Unable to create Raw ACL, error: %x\n", status));
  1820. goto error_exit;
  1821. }
  1822. (VOID) RtlCreateSecurityDescriptor(
  1823. localSecurityDescriptor,
  1824. SECURITY_DESCRIPTOR_REVISION
  1825. );
  1826. (VOID) RtlSetDaclSecurityDescriptor(
  1827. localSecurityDescriptor,
  1828. TRUE,
  1829. rawAcl,
  1830. FALSE
  1831. );
  1832. //
  1833. // Make a copy of the TCP descriptor. This copy will be the raw descriptor.
  1834. //
  1835. tcpSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  1836. tcpSecurityDescriptor
  1837. );
  1838. localTcpAdminSecurityDescriptor = ExAllocatePool(
  1839. PagedPool,
  1840. tcpSecurityDescriptorLength
  1841. );
  1842. if (localTcpAdminSecurityDescriptor == NULL) {
  1843. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: couldn't allocate security descriptor\n"));
  1844. goto error_exit;
  1845. }
  1846. RtlMoveMemory(
  1847. localTcpAdminSecurityDescriptor,
  1848. tcpSecurityDescriptor,
  1849. tcpSecurityDescriptorLength
  1850. );
  1851. TcpAdminSecurityDescriptor = localTcpAdminSecurityDescriptor;
  1852. //
  1853. // Now apply the local descriptor to the raw descriptor.
  1854. //
  1855. status = SeSetSecurityDescriptorInfo(
  1856. NULL,
  1857. &securityInformation,
  1858. localSecurityDescriptor,
  1859. &TcpAdminSecurityDescriptor,
  1860. PagedPool,
  1861. IoGetFileObjectGenericMapping()
  1862. );
  1863. if (!NT_SUCCESS(status)) {
  1864. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: SeSetSecurity failed, %lx\n", status));
  1865. ASSERT(TcpAdminSecurityDescriptor == localTcpAdminSecurityDescriptor);
  1866. ExFreePool(TcpAdminSecurityDescriptor);
  1867. TcpAdminSecurityDescriptor = NULL;
  1868. goto error_exit;
  1869. }
  1870. if (TcpAdminSecurityDescriptor != localTcpAdminSecurityDescriptor) {
  1871. ExFreePool(localTcpAdminSecurityDescriptor);
  1872. }
  1873. status = STATUS_SUCCESS;
  1874. error_exit:
  1875. ObReleaseObjectSecurity(
  1876. tcpSecurityDescriptor,
  1877. memoryAllocated
  1878. );
  1879. if (rawAcl != NULL) {
  1880. CTEFreeMem(rawAcl);
  1881. }
  1882. return (status);
  1883. }
  1884. #endif // ACC
  1885. #if !MILLEN
  1886. NTSTATUS
  1887. IpsecInitialize(
  1888. void
  1889. )
  1890. /*++
  1891. Routine Description:
  1892. Initialize IPSEC.SYS.
  1893. Arguments:
  1894. None.
  1895. Return Value:
  1896. None.
  1897. --*/
  1898. {
  1899. UNICODE_STRING IPSECDeviceName;
  1900. IPSEC_SET_TCPIP_STATUS SetTcpipStatus;
  1901. PIRP Irp;
  1902. IO_STATUS_BLOCK StatusBlock;
  1903. KEVENT Event;
  1904. NTSTATUS status;
  1905. IPSECDeviceObject = NULL;
  1906. IPSECFileObject = NULL;
  1907. RtlInitUnicodeString(&IPSECDeviceName, DD_IPSEC_DEVICE_NAME);
  1908. //
  1909. // Keep a reference to the IPSec driver so it won't unload before us.
  1910. //
  1911. status = IoGetDeviceObjectPointer( &IPSECDeviceName,
  1912. FILE_ALL_ACCESS,
  1913. &IPSECFileObject,
  1914. &IPSECDeviceObject);
  1915. if (!NT_SUCCESS(status)) {
  1916. IPSECFileObject = NULL;
  1917. return (status);
  1918. }
  1919. SetTcpipStatus.TcpipStatus = TRUE;
  1920. SetTcpipStatus.TcpipFreeBuff = FreeIprBuff;
  1921. SetTcpipStatus.TcpipAllocBuff = IPAllocBuff;
  1922. SetTcpipStatus.TcpipGetInfo = IPGetInfo;
  1923. SetTcpipStatus.TcpipNdisRequest = IPProxyNdisRequest;
  1924. SetTcpipStatus.TcpipSetIPSecStatus = IPSetIPSecStatus;
  1925. SetTcpipStatus.TcpipSetIPSecPtr = SetIPSecPtr;
  1926. SetTcpipStatus.TcpipUnSetIPSecPtr = UnSetIPSecPtr;
  1927. SetTcpipStatus.TcpipUnSetIPSecSendPtr = UnSetIPSecSendPtr;
  1928. SetTcpipStatus.TcpipTCPXsum = tcpxsum;
  1929. SetTcpipStatus.TcpipSendICMPErr = SendICMPErr;
  1930. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  1931. Irp = IoBuildDeviceIoControlRequest( IOCTL_IPSEC_SET_TCPIP_STATUS,
  1932. IPSECDeviceObject,
  1933. &SetTcpipStatus,
  1934. sizeof(IPSEC_SET_TCPIP_STATUS),
  1935. NULL,
  1936. 0,
  1937. FALSE,
  1938. &Event,
  1939. &StatusBlock);
  1940. if (Irp) {
  1941. status = IoCallDriver(IPSECDeviceObject, Irp);
  1942. if (status == STATUS_PENDING) {
  1943. KeWaitForSingleObject( &Event,
  1944. Executive,
  1945. KernelMode,
  1946. FALSE,
  1947. NULL);
  1948. status = StatusBlock.Status;
  1949. }
  1950. } else {
  1951. status = STATUS_INSUFFICIENT_RESOURCES;
  1952. }
  1953. return (status);
  1954. }
  1955. NTSTATUS
  1956. IpsecDeinitialize(
  1957. void
  1958. )
  1959. /*++
  1960. Routine Description:
  1961. Deinitialize IPSEC.SYS.
  1962. Arguments:
  1963. None.
  1964. Return Value:
  1965. None.
  1966. --*/
  1967. {
  1968. IPSEC_SET_TCPIP_STATUS SetTcpipStatus;
  1969. PIRP Irp;
  1970. IO_STATUS_BLOCK StatusBlock;
  1971. KEVENT Event;
  1972. NTSTATUS status;
  1973. if (!IPSECFileObject) {
  1974. return (STATUS_SUCCESS);
  1975. }
  1976. RtlZeroMemory(&SetTcpipStatus, sizeof(IPSEC_SET_TCPIP_STATUS));
  1977. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  1978. Irp = IoBuildDeviceIoControlRequest( IOCTL_IPSEC_SET_TCPIP_STATUS,
  1979. IPSECDeviceObject,
  1980. &SetTcpipStatus,
  1981. sizeof(IPSEC_SET_TCPIP_STATUS),
  1982. NULL,
  1983. 0,
  1984. FALSE,
  1985. &Event,
  1986. &StatusBlock);
  1987. if (Irp) {
  1988. status = IoCallDriver(IPSECDeviceObject, Irp);
  1989. if (status == STATUS_PENDING) {
  1990. KeWaitForSingleObject( &Event,
  1991. Executive,
  1992. KernelMode,
  1993. FALSE,
  1994. NULL);
  1995. status = StatusBlock.Status;
  1996. }
  1997. } else {
  1998. status = STATUS_INSUFFICIENT_RESOURCES;
  1999. }
  2000. ObDereferenceObject(IPSECFileObject);
  2001. IPSECFileObject = NULL;
  2002. return (status);
  2003. }
  2004. NTSTATUS
  2005. AddNetConfigOpsAce(IN PACL Dacl,
  2006. OUT PACL * DeviceAcl
  2007. )
  2008. /*++
  2009. Routine Description:
  2010. This routine builds an ACL which gives adds the Network Configuration Operators group
  2011. to the principals allowed to control the driver.
  2012. Arguments:
  2013. Dacl - Existing DACL.
  2014. DeviceAcl - Output pointer to the new ACL.
  2015. Return Value:
  2016. STATUS_SUCCESS or an appropriate error code.
  2017. --*/
  2018. {
  2019. PGENERIC_MAPPING GenericMapping;
  2020. PSID NetworkSid = NULL;
  2021. PSID NetConfigOpsSid = NULL;
  2022. ULONG AclLength;
  2023. NTSTATUS Status;
  2024. ACCESS_MASK AccessMask = GENERIC_ALL;
  2025. PACL NewAcl = NULL;
  2026. ULONG SidSize;
  2027. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  2028. PACE_HEADER AceTemp;
  2029. int i;
  2030. //
  2031. // Enable access to all the globally defined SIDs
  2032. //
  2033. GenericMapping = IoGetFileObjectGenericMapping();
  2034. RtlMapGenericMask(&AccessMask, GenericMapping);
  2035. NetworkSid = SeExports->SeNetworkServiceSid;
  2036. SidSize = RtlLengthRequiredSid(3);
  2037. NetConfigOpsSid = (PSID)(CTEAllocMemBoot(SidSize));
  2038. if (NULL == NetConfigOpsSid) {
  2039. return STATUS_INSUFFICIENT_RESOURCES;
  2040. }
  2041. Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2);
  2042. if (Status != STATUS_SUCCESS) {
  2043. goto clean_up;
  2044. }
  2045. *RtlSubAuthoritySid(NetConfigOpsSid, 0) =
  2046. SECURITY_BUILTIN_DOMAIN_RID;
  2047. *RtlSubAuthoritySid(NetConfigOpsSid, 1) =
  2048. DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  2049. AclLength = Dacl->AclSize;
  2050. AclLength = Dacl->AclSize +
  2051. 2*FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
  2052. RtlLengthSid(NetConfigOpsSid) +
  2053. RtlLengthSid(NetworkSid);
  2054. NewAcl = CTEAllocMemBoot(AclLength);
  2055. if (NewAcl == NULL) {
  2056. Status = STATUS_INSUFFICIENT_RESOURCES;
  2057. goto clean_up;
  2058. }
  2059. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
  2060. if (!NT_SUCCESS(Status)) {
  2061. goto clean_up;
  2062. }
  2063. for (i = 0; i < Dacl->AceCount; i++) {
  2064. Status = RtlGetAce(Dacl, i, &AceTemp);
  2065. if (NT_SUCCESS(Status)) {
  2066. Status = RtlAddAce(NewAcl, ACL_REVISION, MAXULONG, AceTemp,
  2067. AceTemp->AceSize);
  2068. }
  2069. if (!NT_SUCCESS(Status)) {
  2070. goto clean_up;
  2071. }
  2072. }
  2073. // Add Net Config Operators Ace
  2074. Status = RtlAddAccessAllowedAce(NewAcl,
  2075. ACL_REVISION,
  2076. AccessMask,
  2077. NetConfigOpsSid);
  2078. if (!NT_SUCCESS(Status)) {
  2079. goto clean_up;
  2080. }
  2081. // Add Network Services Ace
  2082. Status = RtlAddAccessAllowedAce(NewAcl,
  2083. ACL_REVISION,
  2084. AccessMask,
  2085. NetworkSid);
  2086. if (!NT_SUCCESS(Status)) {
  2087. goto clean_up;
  2088. }
  2089. *DeviceAcl = NewAcl;
  2090. clean_up:
  2091. if (NetConfigOpsSid) {
  2092. CTEFreeMem(NetConfigOpsSid);
  2093. }
  2094. if (!NT_SUCCESS(Status) && NewAcl) {
  2095. CTEFreeMem(NewAcl);
  2096. }
  2097. return (Status);
  2098. }
  2099. NTSTATUS
  2100. CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject)
  2101. /*++
  2102. Routine Description:
  2103. Creates the SD responsible for giving access to different users.
  2104. Arguments:
  2105. DeviceOrDriverObject - Object to which to assign the Access Rights.
  2106. Return Value:
  2107. STATUS_SUCCESS or an appropriate error code.
  2108. --*/
  2109. {
  2110. NTSTATUS status;
  2111. BOOLEAN memoryAllocated = FALSE;
  2112. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  2113. PACL Dacl = NULL;
  2114. BOOLEAN HasDacl = FALSE;
  2115. BOOLEAN DaclDefaulted = FALSE;
  2116. PACL NewAcl = NULL;
  2117. //
  2118. // Get a pointer to the security descriptor from the driver/device object.
  2119. //
  2120. status = ObGetObjectSecurity(
  2121. DeviceOrDriverObject,
  2122. &SecurityDescriptor,
  2123. &memoryAllocated
  2124. );
  2125. if (!NT_SUCCESS(status)) {
  2126. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  2127. "TCP: Unable to get security descriptor, error: %x\n",
  2128. status
  2129. ));
  2130. ASSERT(memoryAllocated == FALSE);
  2131. return (status);
  2132. }
  2133. status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &HasDacl, &Dacl, &DaclDefaulted);
  2134. if (NT_SUCCESS(status) && HasDacl && Dacl != NULL)
  2135. {
  2136. status = AddNetConfigOpsAce(Dacl, &NewAcl);
  2137. if (NT_SUCCESS(status)) {
  2138. PSECURITY_DESCRIPTOR SecDesc = NULL;
  2139. ULONG SecDescSize = 0;
  2140. PACL AbsDacl = NULL;
  2141. ULONG DaclSize = 0;
  2142. PACL AbsSacl = NULL;
  2143. ULONG ulSacl = 0;
  2144. PSID Owner = NULL;
  2145. ULONG OwnerSize = 0;
  2146. PSID PrimaryGroup = NULL;
  2147. ULONG PrimaryGroupSize = 0;
  2148. BOOLEAN OwnerDefault = FALSE;
  2149. BOOLEAN GroupDefault = FALSE;
  2150. BOOLEAN HasSacl = FALSE;
  2151. BOOLEAN SaclDefaulted = FALSE;
  2152. SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  2153. SecDescSize = sizeof(SecDesc) + NewAcl->AclSize;
  2154. SecDesc = CTEAllocMemBoot(SecDescSize);
  2155. if (SecDesc) {
  2156. DaclSize = NewAcl->AclSize;
  2157. AbsDacl = CTEAllocMemBoot(DaclSize);
  2158. if (AbsDacl) {
  2159. status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &Owner, &OwnerDefault);
  2160. if (NT_SUCCESS(status)) {
  2161. OwnerSize = RtlLengthSid(Owner);
  2162. status = RtlGetGroupSecurityDescriptor(SecurityDescriptor, &PrimaryGroup, &GroupDefault);
  2163. if (NT_SUCCESS(status)) {
  2164. PrimaryGroupSize = RtlLengthSid(PrimaryGroup);
  2165. status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, &HasSacl, &AbsSacl, &SaclDefaulted);
  2166. if (NT_SUCCESS(status)) {
  2167. if (HasSacl) {
  2168. ulSacl = AbsSacl->AclSize;
  2169. secInfo |= SACL_SECURITY_INFORMATION;
  2170. }
  2171. status = RtlSelfRelativeToAbsoluteSD(SecurityDescriptor, SecDesc, &SecDescSize, AbsDacl,
  2172. &DaclSize, AbsSacl, &ulSacl, Owner, &OwnerSize, PrimaryGroup, &PrimaryGroupSize);
  2173. if (NT_SUCCESS(status)) {
  2174. status = RtlSetDaclSecurityDescriptor(SecDesc, TRUE, NewAcl, FALSE);
  2175. if (NT_SUCCESS(status)) {
  2176. status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, SecDesc);
  2177. }
  2178. }
  2179. }
  2180. }
  2181. } else {
  2182. status = STATUS_INSUFFICIENT_RESOURCES;
  2183. }
  2184. } else {
  2185. status = STATUS_INSUFFICIENT_RESOURCES;
  2186. }
  2187. if (SecDesc) {
  2188. // Since this is a Self-Relative security descriptor, freeing it also frees
  2189. // Owner and PrimaryGroup.
  2190. CTEFreeMem(SecDesc);
  2191. }
  2192. if (AbsDacl) {
  2193. CTEFreeMem(AbsDacl);
  2194. }
  2195. }
  2196. if (NewAcl) {
  2197. CTEFreeMem(NewAcl);
  2198. }
  2199. }
  2200. } else {
  2201. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: No Dacl: %x\n", status));
  2202. }
  2203. ObReleaseObjectSecurity(
  2204. SecurityDescriptor,
  2205. memoryAllocated
  2206. );
  2207. return (status);
  2208. }
  2209. //
  2210. // Function: IsRunningOnPersonal
  2211. //
  2212. // Purpose: Determines whether running on Whistler Personal
  2213. //
  2214. // Returns: Returns true if running on Personal - FALSE otherwise
  2215. BOOLEAN
  2216. IsRunningOnPersonal(
  2217. VOID
  2218. )
  2219. {
  2220. OSVERSIONINFOEXW OsVer = {0};
  2221. ULONGLONG ConditionMask = 0;
  2222. BOOLEAN IsPersonal = TRUE;
  2223. OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  2224. OsVer.wSuiteMask = VER_SUITE_PERSONAL;
  2225. OsVer.wProductType = VER_NT_WORKSTATION;
  2226. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  2227. VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
  2228. if (RtlVerifyVersionInfo(&OsVer, VER_PRODUCT_TYPE | VER_SUITENAME,
  2229. ConditionMask) == STATUS_REVISION_MISMATCH) {
  2230. IsPersonal = FALSE;
  2231. }
  2232. return IsPersonal;
  2233. }
  2234. #endif