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.

1516 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. ntpnp.c
  5. Abstract:
  6. Plug & Play
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "ntpnp.tmh"
  13. #define TL_INSTANCE 0
  14. ULONG
  15. SmbGetInterfaceIndex(
  16. IN PUNICODE_STRING ucName
  17. );
  18. ULONG
  19. SmbGetInterfaceIndexV4(
  20. IN PUNICODE_STRING ucName
  21. );
  22. ULONG
  23. SmbGetInterfaceIndexV6(
  24. IN PUNICODE_STRING ucName
  25. );
  26. NTSTATUS
  27. SmbBatchedSetBindingInfo(
  28. PSMB_DEVICE Device,
  29. ULONG RequestType,
  30. PWSTR MultiSZBindList
  31. );
  32. #pragma alloc_text(PAGE, SmbBindHandler)
  33. #pragma alloc_text(PAGE, SmbGetInterfaceIndex)
  34. #pragma alloc_text(PAGE, SmbGetInterfaceIndexV6)
  35. #pragma alloc_text(PAGE, SmbGetInterfaceIndexV4)
  36. NTSTATUS
  37. SmbDeviceAdd(
  38. PUNICODE_STRING pDeviceName
  39. );
  40. NTSTATUS
  41. SmbDeviceDel(
  42. PUNICODE_STRING pDeviceName
  43. );
  44. NTSTATUS
  45. SmbUpcaseUnicodeStringNP(
  46. IN OUT PUNICODE_STRING dest,
  47. IN PUNICODE_STRING src
  48. )
  49. {
  50. NTSTATUS status;
  51. dest->MaximumLength = src->MaximumLength;
  52. dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, dest->MaximumLength, SMB_TCP_DEVICE_POOL_TAG);
  53. if (NULL == dest->Buffer) {
  54. return (STATUS_INSUFFICIENT_RESOURCES);
  55. }
  56. status = RtlUpcaseUnicodeString(dest, src, FALSE);
  57. if (STATUS_SUCCESS != status) {
  58. ExFreePool(dest->Buffer);
  59. dest->Buffer = NULL;
  60. }
  61. return status;
  62. }
  63. PSMB_TCP_DEVICE
  64. SmbFindAndReferenceInterface(
  65. PUNICODE_STRING Name
  66. )
  67. /*++
  68. Routine Description:
  69. Find the IPv6 interfaces in IPDeviceList
  70. SpinLock should be held while calling this function.
  71. Arguments:
  72. Name the device name
  73. the buffer should be non-paged
  74. Return Value:
  75. NULL if we cannot find it
  76. non-NULL otherwise
  77. --*/
  78. {
  79. PSMB_TCP_DEVICE pIf = NULL;
  80. PLIST_ENTRY Entry = NULL;
  81. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  82. SmbPrint(SMB_TRACE_PNP, ("SmbFindDevice: looking for %Z\n", Name));
  83. Entry = SmbCfg.IPDeviceList.Flink;
  84. while(Entry != &SmbCfg.IPDeviceList) {
  85. pIf = CONTAINING_RECORD(Entry, SMB_TCP_DEVICE, Linkage);
  86. //
  87. // We can safely call RtlEqualMemory since both buffers are non-paged and resident.
  88. //
  89. SmbPrint(SMB_TRACE_PNP, ("SmbFindDevice: compare with %Z\n", &pIf->AdapterName));
  90. if (pIf->AdapterName.Length == Name->Length &&
  91. RtlEqualMemory(pIf->AdapterName.Buffer, Name->Buffer, Name->Length)) {
  92. SmbReferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  93. return pIf;
  94. }
  95. Entry = Entry->Flink;
  96. }
  97. return NULL;
  98. }
  99. VOID
  100. SmbIp6AddressArrival(
  101. PTDI_ADDRESS_IP6 Addr,
  102. PUNICODE_STRING pDeviceName,
  103. PTDI_PNP_CONTEXT Context
  104. )
  105. {
  106. UNICODE_STRING ucName;
  107. NTSTATUS status;
  108. PSMB_TCP_DEVICE pIf;
  109. KIRQL Irql;
  110. BOOL NotifyClient = FALSE;
  111. PAGED_CODE();
  112. SmbTrace(SMB_TRACE_PNP, ("%!IPV6ADDR! for %Z", (PVOID)&(Addr->sin6_addr), pDeviceName));
  113. SmbInitTCP6(&SmbCfg.SmbDeviceObject->Tcp6, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  114. status = SmbUpcaseUnicodeStringNP(&ucName, pDeviceName);
  115. BAIL_OUT_ON_ERROR(status);
  116. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  117. pIf = SmbFindAndReferenceInterface(&ucName);
  118. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  119. if (NULL == pIf) {
  120. goto cleanup;
  121. }
  122. if (!pIf->AddressPlumbed) {
  123. pIf->PrimaryIpAddress.sin_family = SMB_AF_INET6;
  124. RtlCopyMemory(pIf->PrimaryIpAddress.ip6.sin6_addr,
  125. Addr->sin6_addr,
  126. sizeof(pIf->PrimaryIpAddress.ip6.sin6_addr));
  127. pIf->PrimaryIpAddress.ip6.sin6_scope_id = Addr->sin6_scope_id;
  128. pIf->AddressPlumbed = TRUE;
  129. NotifyClient = (0 == SmbCfg.IPAddressNumber);
  130. SmbCfg.IPAddressNumber++;
  131. SmbCfg.IPv6AddressNumber++;
  132. //
  133. // Don't use SmbPrint to print a WSTR at DISPATCH_LEVEL. Only SmbTrace is usable
  134. //
  135. SmbTrace(SMB_TRACE_PNP, ("New IPv6 address %!IPV6ADDR! for %Z", (PVOID)&(Addr->sin6_addr), &ucName));
  136. }
  137. pIf->InterfaceIndex = SmbGetInterfaceIndex(&pIf->AdapterName);
  138. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  139. //
  140. // Query the loopback interface index if it hasn't been done
  141. //
  142. if (SmbCfg.SmbDeviceObject->Tcp6.LoopbackInterfaceIndex == INVALID_INTERFACE_INDEX) {
  143. if (SmbCfg.SmbDeviceObject->Tcp6.FastQuery) {
  144. SMB_IP6_ADDRESS loopback;
  145. ULONG IfIndex, Metric;
  146. ip6addr_getloopback(&loopback);
  147. hton_ip6addr(&loopback);
  148. status = ((PIP6FASTQUERY)(SmbCfg.SmbDeviceObject->Tcp6.FastQuery))(&loopback, &IfIndex, &Metric);
  149. if (status == STATUS_SUCCESS) {
  150. SmbCfg.SmbDeviceObject->Tcp6.LoopbackInterfaceIndex = IfIndex;
  151. SmbPrint(SMB_TRACE_TCP, ("Loopback Interface Index = %d\n", IfIndex));
  152. SmbTrace(SMB_TRACE_TCP, ("Loopback Interface Index = %d", IfIndex));
  153. } else {
  154. SmbPrint(SMB_TRACE_TCP, ("Query loopback Interface Index returns 0x%08lx\n", status));
  155. SmbTrace(SMB_TRACE_TCP, ("Query loopback Interface Index returns %!status!", status));
  156. }
  157. }
  158. }
  159. if (NotifyClient) {
  160. SmbPrint(SMB_TRACE_PNP, ("Registraion: Notify Client\n"));
  161. SmbTdiRegister(SmbCfg.SmbDeviceObject);
  162. }
  163. cleanup:
  164. if (ucName.Buffer) {
  165. ExFreePool(ucName.Buffer);
  166. }
  167. }
  168. VOID
  169. SmbIp6AddressDeletion(
  170. PTDI_ADDRESS_IP6 Addr,
  171. PUNICODE_STRING pDeviceName,
  172. PTDI_PNP_CONTEXT Context
  173. )
  174. {
  175. UNICODE_STRING ucName;
  176. NTSTATUS status;
  177. PSMB_TCP_DEVICE pIf;
  178. KIRQL Irql;
  179. BOOL NotifyClient = FALSE;
  180. PAGED_CODE();
  181. SmbTrace(SMB_TRACE_PNP, ("%!IPV6ADDR! for %Z", (PVOID)&(Addr->sin6_addr), pDeviceName));
  182. status = SmbUpcaseUnicodeStringNP(&ucName, pDeviceName);
  183. BAIL_OUT_ON_ERROR(status);
  184. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  185. pIf = SmbFindAndReferenceInterface(&ucName);
  186. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  187. if (NULL == pIf) {
  188. goto cleanup;
  189. }
  190. if (pIf->AddressPlumbed &&
  191. RtlEqualMemory(pIf->PrimaryIpAddress.ip6.sin6_addr,
  192. Addr->sin6_addr,
  193. sizeof(pIf->PrimaryIpAddress.ip6.sin6_addr))) {
  194. pIf->AddressPlumbed = FALSE;
  195. SmbCfg.IPAddressNumber--;
  196. SmbCfg.IPv6AddressNumber--;
  197. NotifyClient = (0 == SmbCfg.IPAddressNumber);
  198. //
  199. // Don't use SmbPrint to print a WSTR at DISPATCH_LEVEL. Only SmbTrace is usable
  200. //
  201. SmbTrace(SMB_TRACE_PNP, ("Delete IPv6 address %!IPV6ADDR! for %Z", (PVOID)&(Addr->sin6_addr), &ucName));
  202. }
  203. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  204. if (NotifyClient) {
  205. SmbPrint(SMB_TRACE_PNP, ("Deregistraion: Notify Client\n"));
  206. SmbTdiDeregister(SmbCfg.SmbDeviceObject);
  207. }
  208. cleanup:
  209. if (ucName.Buffer) {
  210. ExFreePool(ucName.Buffer);
  211. }
  212. }
  213. VOID
  214. SmbIp4AddressArrival(
  215. PTDI_ADDRESS_IP Addr,
  216. PUNICODE_STRING pDeviceName,
  217. PTDI_PNP_CONTEXT Context
  218. )
  219. {
  220. UNICODE_STRING ucName;
  221. NTSTATUS status;
  222. PSMB_TCP_DEVICE pIf;
  223. KIRQL Irql;
  224. BOOL NotifyClient = FALSE;
  225. CHAR Buffer[16];
  226. Inet_ntoa_nb(Addr->in_addr, Buffer);
  227. Buffer[15] =0;
  228. SmbPrint(SMB_TRACE_PNP, ("SmbIp4AddressArrival: %s %Z\n", Buffer, pDeviceName));
  229. SmbTrace(SMB_TRACE_PNP, ("%!ipaddr! %Z", Addr->in_addr, pDeviceName));
  230. SmbInitTCP4(&SmbCfg.SmbDeviceObject->Tcp4, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  231. if (INADDR_NONE == Addr->in_addr) {
  232. return;
  233. }
  234. status = SmbUpcaseUnicodeStringNP(&ucName, pDeviceName);
  235. BAIL_OUT_ON_ERROR(status);
  236. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  237. pIf = SmbFindAndReferenceInterface(&ucName);
  238. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  239. if (NULL == pIf) {
  240. goto cleanup;
  241. }
  242. if (!pIf->AddressPlumbed) {
  243. pIf->PrimaryIpAddress.sin_family = SMB_AF_INET;
  244. pIf->PrimaryIpAddress.ip4.sin4_addr = Addr->in_addr;
  245. pIf->AddressPlumbed = TRUE;
  246. NotifyClient = (0 == SmbCfg.IPAddressNumber);
  247. SmbCfg.IPAddressNumber++;
  248. SmbCfg.IPv4AddressNumber++;
  249. //
  250. // Don't use SmbPrint to print a WSTR at DISPATCH_LEVEL. Only SmbTrace is usable
  251. //
  252. SmbTrace(SMB_TRACE_PNP, ("New IPv4 address %s for %Z", Buffer, &ucName));
  253. }
  254. pIf->InterfaceIndex = SmbGetInterfaceIndex(&pIf->AdapterName);
  255. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  256. //
  257. // Query the loopback interface index if it hasn't been done
  258. //
  259. if (SmbCfg.SmbDeviceObject->Tcp4.LoopbackInterfaceIndex == INVALID_INTERFACE_INDEX) {
  260. if (SmbCfg.SmbDeviceObject->Tcp4.FastQuery) {
  261. ULONG IfIndex, Metric;
  262. status = ((PIP4FASTQUERY)(SmbCfg.SmbDeviceObject->Tcp4.FastQuery))(
  263. ntohl(INADDR_LOOPBACK), &IfIndex, &Metric);
  264. if (status == STATUS_SUCCESS) {
  265. SmbCfg.SmbDeviceObject->Tcp4.LoopbackInterfaceIndex = IfIndex;
  266. SmbPrint(SMB_TRACE_TCP, ("Loopback Interface Index = %d\n", IfIndex));
  267. SmbTrace(SMB_TRACE_TCP, ("Loopback Interface Index = %d", IfIndex));
  268. } else {
  269. SmbPrint(SMB_TRACE_TCP, ("Query loopback Interface Index returns 0x%08lx\n", status));
  270. SmbTrace(SMB_TRACE_TCP, ("Query loopback Interface Index returns %!status!", status));
  271. }
  272. }
  273. }
  274. if (NotifyClient) {
  275. SmbPrint(SMB_TRACE_PNP, ("Registraion: Notify Client\n"));
  276. SmbTdiRegister(SmbCfg.SmbDeviceObject);
  277. }
  278. cleanup:
  279. if (ucName.Buffer) {
  280. ExFreePool(ucName.Buffer);
  281. }
  282. }
  283. VOID
  284. SmbIp4AddressDeletion(
  285. PTDI_ADDRESS_IP Addr,
  286. PUNICODE_STRING pDeviceName,
  287. PTDI_PNP_CONTEXT Context
  288. )
  289. {
  290. UNICODE_STRING ucName;
  291. NTSTATUS status;
  292. PSMB_TCP_DEVICE pIf;
  293. KIRQL Irql;
  294. BOOL NotifyClient = FALSE;
  295. CHAR Buffer[16];
  296. Inet_ntoa_nb(Addr->in_addr, Buffer);
  297. Buffer[15] =0;
  298. SmbPrint(SMB_TRACE_PNP, ("SmbIp4AddressDeletion: %s %Z\n", Buffer, pDeviceName));
  299. SmbTrace(SMB_TRACE_PNP, ("%!ipaddr! %Z", Addr->in_addr, pDeviceName));
  300. if (INADDR_NONE == Addr->in_addr) {
  301. return;
  302. }
  303. status = SmbUpcaseUnicodeStringNP(&ucName, pDeviceName);
  304. BAIL_OUT_ON_ERROR(status);
  305. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  306. pIf = SmbFindAndReferenceInterface(&ucName);
  307. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  308. if (NULL == pIf) {
  309. goto cleanup;
  310. }
  311. if (pIf->AddressPlumbed && pIf->PrimaryIpAddress.ip4.sin4_addr == Addr->in_addr) {
  312. pIf->AddressPlumbed = FALSE;
  313. SmbCfg.IPAddressNumber--;
  314. SmbCfg.IPv4AddressNumber--;
  315. NotifyClient = (0 == SmbCfg.IPAddressNumber);
  316. //
  317. // Don't use SmbPrint to print a WSTR at DISPATCH_LEVEL. Only SmbTrace is usable
  318. //
  319. SmbTrace(SMB_TRACE_PNP, ("Delete IPv4 address %s for %Z", Buffer, &ucName));
  320. }
  321. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  322. if (NotifyClient) {
  323. SmbPrint(SMB_TRACE_PNP, ("Deregistraion: Notify Client\n"));
  324. SmbTdiDeregister(SmbCfg.SmbDeviceObject);
  325. }
  326. cleanup:
  327. if (ucName.Buffer) {
  328. ExFreePool(ucName.Buffer);
  329. }
  330. }
  331. VOID
  332. SmbAddressArrival(
  333. PTA_ADDRESS Addr,
  334. PUNICODE_STRING pDeviceName,
  335. PTDI_PNP_CONTEXT Context
  336. )
  337. {
  338. PAGED_CODE();
  339. switch (Addr->AddressType) {
  340. case TDI_ADDRESS_TYPE_IP6:
  341. SmbIp6AddressArrival ((PTDI_ADDRESS_IP6)Addr->Address, pDeviceName, Context);
  342. break;
  343. case TDI_ADDRESS_TYPE_IP:
  344. SmbIp4AddressArrival ((PTDI_ADDRESS_IP)Addr->Address, pDeviceName, Context);
  345. break;
  346. default:
  347. goto cleanup;
  348. }
  349. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  350. //
  351. // Change the binding
  352. //
  353. KeEnterCriticalRegion ();
  354. ExAcquireResourceExclusiveLite (&SmbCfg.Resource, TRUE);
  355. SmbBatchedSetBindingInfo (SmbCfg.SmbDeviceObject, SMB_CLIENT, SmbCfg.SmbDeviceObject->ClientBinding);
  356. SmbBatchedSetBindingInfo (SmbCfg.SmbDeviceObject, SMB_SERVER, SmbCfg.SmbDeviceObject->ServerBinding);
  357. ExReleaseResourceLite (&SmbCfg.Resource);
  358. KeLeaveCriticalRegion ();
  359. cleanup:
  360. return;
  361. }
  362. VOID
  363. SmbAddressDeletion(
  364. PTA_ADDRESS Addr,
  365. PUNICODE_STRING pDeviceName,
  366. PTDI_PNP_CONTEXT Context
  367. )
  368. {
  369. PAGED_CODE();
  370. switch (Addr->AddressType) {
  371. case TDI_ADDRESS_TYPE_IP6:
  372. SmbIp6AddressDeletion ((PTDI_ADDRESS_IP6)Addr->Address, pDeviceName, Context);
  373. break;
  374. case TDI_ADDRESS_TYPE_IP:
  375. SmbIp4AddressDeletion ((PTDI_ADDRESS_IP)Addr->Address, pDeviceName, Context);
  376. break;
  377. default:
  378. goto cleanup;
  379. }
  380. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  381. //
  382. // Change the binding
  383. //
  384. KeEnterCriticalRegion ();
  385. ExAcquireResourceExclusiveLite (&SmbCfg.Resource, TRUE);
  386. SmbBatchedSetBindingInfo (SmbCfg.SmbDeviceObject, SMB_CLIENT, SmbCfg.SmbDeviceObject->ClientBinding);
  387. SmbBatchedSetBindingInfo (SmbCfg.SmbDeviceObject, SMB_SERVER, SmbCfg.SmbDeviceObject->ServerBinding);
  388. ExReleaseResourceLite (&SmbCfg.Resource);
  389. KeLeaveCriticalRegion ();
  390. cleanup:
  391. return;
  392. }
  393. VOID
  394. SmbBindHandler(
  395. TDI_PNP_OPCODE PnPOpCode,
  396. PUNICODE_STRING pDeviceName,
  397. PWSTR MultiSZBindList
  398. )
  399. {
  400. NTSTATUS status;
  401. UNICODE_STRING ucIPDevice;
  402. PAGED_CODE();
  403. if (SmbCfg.Unloading) {
  404. return;
  405. }
  406. switch(PnPOpCode) {
  407. case TDI_PNP_OP_ADD:
  408. status = SmbDeviceAdd(pDeviceName);
  409. SmbTrace(SMB_TRACE_PNP, ("return %!status! for %Z", status, pDeviceName));
  410. SmbPrint(SMB_TRACE_PNP, ("SmbDeviceAdd return 0x%08lx for %Z\n", status, pDeviceName));
  411. break;
  412. case TDI_PNP_OP_DEL:
  413. status = SmbDeviceDel(pDeviceName);
  414. SmbTrace(SMB_TRACE_PNP, ("SmbDeviceDel return %!status! for %Z", status, pDeviceName));
  415. SmbPrint(SMB_TRACE_PNP, ("SmbDeviceDel return 0x%08lx for %Z\n", status, pDeviceName));
  416. break;
  417. case TDI_PNP_OP_PROVIDERREADY:
  418. SmbTrace(SMB_TRACE_PNP, ("Provider %Z is ready", pDeviceName));
  419. SmbPrint(SMB_TRACE_PNP, ("Provider %Z is ready\n", pDeviceName));
  420. RtlInitUnicodeString(&ucIPDevice, DD_IPV6_DEVICE_NAME);
  421. if (RtlEqualUnicodeString(pDeviceName, &ucIPDevice, TRUE)) {
  422. SmbInitTCP6(&SmbCfg.SmbDeviceObject->Tcp6, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  423. if (!SmbCfg.ProviderReady++) {
  424. TdiProviderReady(SmbCfg.TdiProviderHandle);
  425. }
  426. } else {
  427. RtlInitUnicodeString(&ucIPDevice, DD_IP_DEVICE_NAME);
  428. if (RtlEqualUnicodeString(pDeviceName, &ucIPDevice, TRUE)) {
  429. SmbInitTCP4(&SmbCfg.SmbDeviceObject->Tcp4, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  430. if (!SmbCfg.ProviderReady++) {
  431. TdiProviderReady(SmbCfg.TdiProviderHandle);
  432. }
  433. }
  434. }
  435. break;
  436. case TDI_PNP_OP_UPDATE:
  437. case TDI_PNP_OP_NETREADY:
  438. /* Nothing to do */
  439. break;
  440. default:
  441. ASSERT(0);
  442. }
  443. }
  444. VOID
  445. SmbShutdownPnP(
  446. VOID
  447. )
  448. {
  449. PLIST_ENTRY entry;
  450. PSMB_TCP_DEVICE pIf;
  451. PAGED_CODE();
  452. ASSERT(SmbCfg.Unloading);
  453. while(!IsListEmpty(&SmbCfg.IPDeviceList)) {
  454. entry = RemoveHeadList(&SmbCfg.IPDeviceList);
  455. InsertTailList(&SmbCfg.PendingDeleteIPDeviceList, entry);
  456. pIf = CONTAINING_RECORD(entry, SMB_TCP_DEVICE, Linkage);
  457. ASSERT(pIf->RefCount == 1);
  458. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_CREATE);
  459. }
  460. ASSERT(IsListEmpty(&SmbCfg.PendingDeleteIPDeviceList));
  461. }
  462. NTSTATUS
  463. CheckRegistryBinding(
  464. PUNICODE_STRING pDeviceName
  465. )
  466. /*++
  467. Routine Description:
  468. This routine read in the HKLM\System\CCS\Services\SMB6\Linkage\Bind and check if pDeviceName is in the
  469. binding list.
  470. Arguments:
  471. Return Value:
  472. STATUS_SUCCESS if pDeviceName is in the binding list
  473. STATUS_UNSUCCESSFUL otherwise
  474. --*/
  475. {
  476. NTSTATUS status;
  477. DWORD length;
  478. DWORD type;
  479. WCHAR *pBindingList = NULL;
  480. WCHAR *pStart = NULL;
  481. WCHAR *pEnd;
  482. UNICODE_STRING ucName;
  483. PAGED_CODE();
  484. length = 0;
  485. type = REG_MULTI_SZ;
  486. pBindingList = NULL;
  487. status = SmbReadRegistry(
  488. SmbCfg.LinkageKey,
  489. L"Bind",
  490. &type,
  491. &length,
  492. &pBindingList
  493. );
  494. BAIL_OUT_ON_ERROR(status);
  495. pStart = pBindingList;
  496. pEnd = (WCHAR*)(((PUCHAR)pBindingList) + length);
  497. while (*pBindingList && pBindingList < pEnd) {
  498. RtlInitUnicodeString(&ucName, pBindingList);
  499. if (RtlEqualUnicodeString(&ucName, pDeviceName, TRUE)) {
  500. ExFreePool(pStart);
  501. return STATUS_SUCCESS;
  502. }
  503. pBindingList += (ucName.Length / sizeof(WCHAR)) + 1;
  504. }
  505. cleanup:
  506. if (pStart) {
  507. ExFreePool(pStart);
  508. }
  509. return STATUS_UNSUCCESSFUL;
  510. }
  511. ULONG
  512. SmbGetInterfaceIndexV4(
  513. IN PUNICODE_STRING ucName
  514. )
  515. {
  516. PIP_INTERFACE_INFO IpInfo;
  517. ULONG Size;
  518. ULONG Index;
  519. LONG Entries;
  520. LONG i;
  521. NTSTATUS status;
  522. UNICODE_STRING ucIpDeviceName;
  523. PAGED_CODE();
  524. Entries = SmbCfg.IPDeviceNumber;
  525. do {
  526. Size = Entries * sizeof(IP_ADAPTER_INDEX_MAP) + sizeof(ULONG);
  527. IpInfo = (PIP_INTERFACE_INFO)ExAllocatePoolWithTag(NonPagedPool, Size, '6BMS');
  528. if (NULL == IpInfo) {
  529. SmbTrace(SMB_TRACE_TCP, ("out of memory"));
  530. return INVALID_INTERFACE_INDEX;
  531. }
  532. status = SmbSendIoctl(
  533. SmbCfg.SmbDeviceObject->Tcp4.IPControlFileObject,
  534. IOCTL_IP_INTERFACE_INFO,
  535. NULL,
  536. 0,
  537. IpInfo,
  538. &Size
  539. );
  540. if (STATUS_BUFFER_OVERFLOW != status) {
  541. break;
  542. }
  543. ExFreePool(IpInfo);
  544. IpInfo = NULL;
  545. Entries += 2;
  546. } while(Entries < 128);
  547. if (!NT_SUCCESS(status)) {
  548. ExFreePool(IpInfo);
  549. IpInfo = NULL;
  550. return INVALID_INTERFACE_INDEX;
  551. }
  552. Index = INVALID_INTERFACE_INDEX;
  553. for (i = 0; i < IpInfo->NumAdapters; i++) {
  554. RtlInitUnicodeString(&ucIpDeviceName, IpInfo->Adapter[i].Name);
  555. if (RtlEqualUnicodeString(ucName, &ucIpDeviceName, TRUE)) {
  556. Index = IpInfo->Adapter[i].Index;
  557. break;
  558. }
  559. }
  560. ExFreePool(IpInfo);
  561. IpInfo = NULL;
  562. return Index;
  563. }
  564. ULONG
  565. SmbGetInterfaceIndexV6(
  566. IN PUNICODE_STRING ucName
  567. )
  568. {
  569. PAGED_CODE();
  570. return INVALID_INTERFACE_INDEX;
  571. }
  572. ULONG
  573. SmbGetInterfaceIndex(
  574. IN PUNICODE_STRING ucName
  575. )
  576. {
  577. ULONG Index;
  578. PAGED_CODE();
  579. #if 0
  580. Index = SmbGetInterfaceIndexV4(ucName);
  581. SmbPrint(SMB_TRACE_TCP, ("IPV4: returns InterfaceIndex 0x%04lx for %Z\n", Index, ucName));
  582. SmbTrace(SMB_TRACE_TCP, ("IPV4: returns InterfaceIndex 0x%04lx for %Z", Index, ucName));
  583. if (Index != INVALID_INTERFACE_INDEX) {
  584. return Index;
  585. }
  586. Index = SmbGetInterfaceIndexV6(ucName);
  587. SmbPrint(SMB_TRACE_TCP, ("IPV6: returns InterfaceIndex 0x%04lx for %Z\n", Index, ucName));
  588. SmbTrace(SMB_TRACE_TCP, ("IPV6: returns InterfaceIndex 0x%04lx for %Z", Index, ucName));
  589. #else
  590. //
  591. // we have to use the following logic due to a compiler bug
  592. // Hack!!!
  593. //
  594. if (ucName->Length >= 28 && ucName->Buffer[13] == L'6') {
  595. Index = SmbGetInterfaceIndexV6(ucName);
  596. SmbPrint(SMB_TRACE_TCP, ("IPV6: returns InterfaceIndex 0x%04lx for %Z\n", Index, ucName));
  597. SmbTrace(SMB_TRACE_TCP, ("IPV6: returns InterfaceIndex 0x%04lx for %Z", Index, ucName));
  598. } else {
  599. Index = SmbGetInterfaceIndexV4(ucName);
  600. SmbPrint(SMB_TRACE_TCP, ("IPV4: returns InterfaceIndex 0x%04lx for %Z\n", Index, ucName));
  601. SmbTrace(SMB_TRACE_TCP, ("IPV4: returns InterfaceIndex 0x%04lx for %Z", Index, ucName));
  602. }
  603. #endif
  604. return Index;
  605. }
  606. VOID
  607. SmbDeleteTcpDevice(PSMB_TCP_DEVICE pIf)
  608. {
  609. KIRQL Irql;
  610. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  611. ASSERT(EntryIsInList(&SmbCfg.PendingDeleteIPDeviceList, &pIf->Linkage));
  612. RemoveEntryList(&pIf->Linkage);
  613. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  614. ExFreePool(pIf);
  615. SmbPrint(SMB_TRACE_CALL, ("SmbDeleteTcpDevice: free tcp device %p\n", pIf));
  616. }
  617. NTSTATUS
  618. SmbDeviceAdd(
  619. PUNICODE_STRING pDeviceName
  620. )
  621. {
  622. KIRQL Irql;
  623. PLIST_ENTRY Entry = NULL;
  624. PSMB_TCP_DEVICE pIf = NULL;
  625. PSMB_TCP_DEVICE pNewIf = NULL;
  626. DWORD Size;
  627. NTSTATUS status = STATUS_SUCCESS;
  628. pNewIf = NULL;
  629. SmbPrint(SMB_TRACE_PNP, ("SmbDeviceAdd: %Z\n", pDeviceName));
  630. SmbTrace(SMB_TRACE_PNP, ("%Z", pDeviceName));
  631. /*
  632. No need to check it since TDI has already done it before calling us
  633. status = CheckRegistryBinding(pDeviceName);
  634. BAIL_OUT_ON_ERROR(status);
  635. */
  636. Size = ALIGN(sizeof(SMB_TCP_DEVICE)) + pDeviceName->MaximumLength;
  637. pNewIf = ExAllocatePoolWithTag(NonPagedPool, Size, SMB_TCP_DEVICE_POOL_TAG);
  638. if (pNewIf == NULL) {
  639. return STATUS_NO_MEMORY;
  640. }
  641. RtlZeroMemory(pNewIf, Size);
  642. SmbInitializeObject((PSMB_OBJECT)pNewIf, TAG_TCP_DEVICE, (PSMB_OBJECT_CLEANUP)SmbDeleteTcpDevice);
  643. pNewIf->AdapterName.Length = 0;
  644. pNewIf->AdapterName.MaximumLength = pDeviceName->MaximumLength;
  645. pNewIf->AdapterName.Buffer = (WCHAR*)((PUCHAR)pNewIf + ALIGN(sizeof(SMB_TCP_DEVICE)));
  646. InitializeListHead(&pNewIf->Linkage);
  647. status = RtlUpcaseUnicodeString(&pNewIf->AdapterName, pDeviceName, FALSE);
  648. BAIL_OUT_ON_ERROR(status);
  649. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  650. Entry = SmbCfg.IPDeviceList.Flink;
  651. while(Entry != &SmbCfg.IPDeviceList) {
  652. pIf = CONTAINING_RECORD(Entry, SMB_TCP_DEVICE, Linkage);
  653. //
  654. // We can safely call RtlEqualMemory since both buffers are non-paged and resident.
  655. //
  656. if (pIf->AdapterName.Length == pNewIf->AdapterName.Length &&
  657. RtlEqualMemory(pIf->AdapterName.Buffer, pNewIf->AdapterName.Buffer, pNewIf->AdapterName.Length)) {
  658. ExFreePool(pNewIf);
  659. pNewIf = NULL;
  660. break;
  661. }
  662. Entry = Entry->Flink;
  663. }
  664. if (pNewIf) {
  665. SmbCfg.IPDeviceNumber++;
  666. InsertTailList(&SmbCfg.IPDeviceList, &pNewIf->Linkage);
  667. SmbTrace(SMB_TRACE_PNP, ("Add device %Z", &pNewIf->AdapterName));
  668. SmbPrint(SMB_TRACE_PNP, ("SmbDeviceAdd: Add %Z\n", &pNewIf->AdapterName));
  669. }
  670. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  671. SmbInitTCP4(&SmbCfg.SmbDeviceObject->Tcp4, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  672. SmbInitTCP6(&SmbCfg.SmbDeviceObject->Tcp6, SmbCfg.SmbDeviceObject->Port, SmbCfg.SmbDeviceObject);
  673. return STATUS_SUCCESS;
  674. cleanup:
  675. if (pNewIf) {
  676. ExFreePool(pNewIf);
  677. }
  678. return STATUS_UNSUCCESSFUL;
  679. }
  680. NTSTATUS
  681. SmbDeviceDel(
  682. PUNICODE_STRING pDeviceName
  683. )
  684. {
  685. KIRQL Irql;
  686. UNICODE_STRING ucName = { 0 };
  687. NTSTATUS status = STATUS_SUCCESS;
  688. PSMB_TCP_DEVICE pIf = NULL;
  689. SmbPrint(SMB_TRACE_PNP, ("SmbDeviceDel: %Z\n", pDeviceName));
  690. SmbTrace(SMB_TRACE_PNP, ("%Z", pDeviceName));
  691. ucName.MaximumLength = pDeviceName->MaximumLength;
  692. ucName.Buffer = ExAllocatePoolWithTag(NonPagedPool, ucName.MaximumLength, SMB_TCP_DEVICE_POOL_TAG);
  693. if (NULL == ucName.Buffer) {
  694. return STATUS_INSUFFICIENT_RESOURCES;
  695. }
  696. status = RtlUpcaseUnicodeString(&ucName, pDeviceName, FALSE);
  697. BAIL_OUT_ON_ERROR(status);
  698. KeAcquireSpinLock(&SmbCfg.Lock, &Irql);
  699. pIf = SmbFindAndReferenceInterface(&ucName);
  700. KeReleaseSpinLock(&SmbCfg.Lock, Irql);
  701. if (NULL == pIf) {
  702. status = STATUS_NOT_FOUND;
  703. goto cleanup;
  704. }
  705. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  706. SmbCfg.IPDeviceNumber--;
  707. RemoveEntryList(&pIf->Linkage);
  708. InsertTailList(&SmbCfg.PendingDeleteIPDeviceList, &pIf->Linkage);
  709. SmbPrint(SMB_TRACE_PNP, ("Delete device %Z\n", &ucName));
  710. SmbTrace(SMB_TRACE_PNP, ("Delete %Z", &ucName));
  711. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_CREATE);
  712. cleanup:
  713. if (ucName.Buffer) {
  714. ExFreePool(ucName.Buffer);
  715. }
  716. return status;
  717. }
  718. NTSTATUS
  719. SmbTdiRegister(
  720. IN PSMB_DEVICE DeviceObject
  721. )
  722. {
  723. UNICODE_STRING ExportName = { 0 };
  724. NTSTATUS status = STATUS_SUCCESS;
  725. PAGED_CODE();
  726. status = STATUS_SUCCESS;
  727. if (NULL == DeviceObject->DeviceRegistrationHandle) {
  728. RtlInitUnicodeString(&ExportName, DD_SMB6_EXPORT_NAME);
  729. status = TdiRegisterDeviceObject(&ExportName, &DeviceObject->DeviceRegistrationHandle);
  730. SmbTrace(SMB_TRACE_PNP, ("TdiRegisterDeviceObject returns %!status!", status));
  731. SmbPrint(SMB_TRACE_PNP, ("TdiRegisterDeviceObject returns 0x%08lx\n", status));
  732. //
  733. // Don't use SmbWakeupWorkerThread. This should be handled synchronously
  734. //
  735. if (SmbCfg.Tcp6Available) {
  736. SmbReadTCPConf(SmbCfg.ParametersKey, &DeviceObject->Tcp6);
  737. status = SmbSynchConnCache(&DeviceObject->Tcp6, FALSE);
  738. SmbTrace(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP6) returns %!status!", status));
  739. SmbPrint(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP6) returns 0x%08lx\n", status));
  740. }
  741. if (SmbCfg.Tcp4Available) {
  742. SmbReadTCPConf(SmbCfg.ParametersKey, &DeviceObject->Tcp4);
  743. status = SmbSynchConnCache(&DeviceObject->Tcp4, FALSE);
  744. SmbTrace(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP4) returns %!status!", status));
  745. SmbPrint(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP4) returns 0x%08lx\n", status));
  746. }
  747. }
  748. return status;
  749. }
  750. NTSTATUS
  751. SmbTdiDeregister(
  752. IN PSMB_DEVICE DeviceObject
  753. )
  754. {
  755. HANDLE RegHandle;
  756. NTSTATUS status;
  757. PAGED_CODE();
  758. RegHandle = InterlockedExchangePointer(&DeviceObject->DeviceRegistrationHandle, NULL);
  759. SmbPrint(SMB_TRACE_PNP, ("SmbTdiDeregister: RegHandle = %p\n", RegHandle));
  760. status = STATUS_SUCCESS;
  761. if (RegHandle) {
  762. status = TdiDeregisterDeviceObject(RegHandle);
  763. SmbTrace(SMB_TRACE_PNP, ("TdiDeregisterDeviceObject returns %!status!", status));
  764. SmbPrint(SMB_TRACE_PNP, ("TdiDeregisterDeviceObject returns 0x%08lx\n", status));
  765. //
  766. // Don't use SmbWakeupWorkerThread. This should be handled synchronously
  767. //
  768. if (SmbCfg.Tcp6Available) {
  769. status = SmbSynchConnCache(&DeviceObject->Tcp6, TRUE);
  770. SmbTrace(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP6) returns %!status!", status));
  771. SmbPrint(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP6) returns 0x%08lx\n", status));
  772. }
  773. if (SmbCfg.Tcp4Available) {
  774. status = SmbSynchConnCache(&DeviceObject->Tcp4, TRUE);
  775. SmbTrace(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP4) returns %!status!", status));
  776. SmbPrint(SMB_TRACE_PNP, ("SmbSynchConnCache (TCP4) returns 0x%08lx\n", status));
  777. }
  778. }
  779. return status;
  780. }
  781. VOID
  782. GetMultiSZInfo(
  783. WCHAR *str,
  784. LONG *cnt_ret,
  785. LONG *size_ret
  786. )
  787. {
  788. LONG cnt, size, len;
  789. WCHAR *p;
  790. cnt = 0;
  791. size = 0;
  792. p = str;
  793. while (*p) {
  794. cnt ++;
  795. SmbPrint(SMB_TRACE_PNP, ("%d. %ws\n", cnt, p));
  796. SmbTrace(SMB_TRACE_PNP, ("%d. %ws", cnt, p));
  797. len = wcslen(p) + 1;
  798. p += len;
  799. size += len;
  800. }
  801. size++;
  802. SmbPrint(SMB_TRACE_PNP, ("Total number=%d, Total Length=%d\n", cnt, size));
  803. SmbTrace(SMB_TRACE_PNP, ("Total number=%d, Total Length=%d", cnt, size));
  804. if (NULL != cnt_ret) {
  805. *cnt_ret = cnt;
  806. }
  807. if (NULL != size_ret) {
  808. *size_ret = size;
  809. }
  810. }
  811. PWSTR
  812. DuplicateMultiSZString(
  813. IN PWSTR str
  814. )
  815. {
  816. LONG size;
  817. PVOID buffer;
  818. GetMultiSZInfo(str, NULL, &size);
  819. if (0 == size) {
  820. SmbPrint(SMB_TRACE_PNP, ("GetMultiSZInfo return error!!!\n"));
  821. return NULL;
  822. }
  823. size *= sizeof(WCHAR);
  824. buffer = ExAllocatePoolWithTag(NonPagedPool, size, '2BMS');
  825. if (NULL == buffer) {
  826. SmbPrint(SMB_TRACE_PNP, ("Cannot allocate %d bytes memory from NonPagedPool\n", size));
  827. return NULL;
  828. }
  829. RtlCopyMemory(buffer, str, size);
  830. return buffer;
  831. }
  832. PUNICODE_STRING
  833. SeparateMultiSZ(
  834. WCHAR *str,
  835. LONG *num
  836. )
  837. {
  838. PUNICODE_STRING uc_strs;
  839. LONG i, cnt, size, len;
  840. WCHAR *p;
  841. PVOID *buffer;
  842. UNICODE_STRING ucName;
  843. PAGED_CODE();
  844. GetMultiSZInfo(str, &cnt, &len);
  845. if (cnt == 0 || len == 0) {
  846. SmbPrint(SMB_TRACE_PNP, ("GetMultiSZInfo return error!!!\n"));
  847. return NULL;
  848. }
  849. size = len * sizeof(WCHAR) + cnt * sizeof (UNICODE_STRING);
  850. uc_strs = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, size, '1BMS');
  851. if (NULL == uc_strs) {
  852. SmbPrint(SMB_TRACE_PNP, ("Cannot allocate %d bytes memory from NonPagedPool\n", size));
  853. return NULL;
  854. }
  855. //
  856. // Make a uppercase copy of str
  857. //
  858. p = (WCHAR*)(uc_strs + cnt);
  859. for (i = 0; i < len; i++) {
  860. p[i] = RtlUpcaseUnicodeChar(str[i]);
  861. }
  862. p = (WCHAR*)(uc_strs + cnt);
  863. for (i = 0; (i < cnt) && (*p); i++) {
  864. RtlInitUnicodeString(&ucName, p);
  865. p += (ucName.Length/sizeof(WCHAR)) + 1;
  866. uc_strs[i] = ucName;
  867. }
  868. ASSERT (i == cnt);
  869. if (NULL != num) {
  870. *num = cnt;
  871. }
  872. return uc_strs;
  873. }
  874. NTSTATUS
  875. SmbSetTcpInfo(
  876. IN PFILE_OBJECT FileObject,
  877. IN ULONG Entity,
  878. IN ULONG Class,
  879. IN ULONG ToiId,
  880. IN ULONG ToiType,
  881. IN ULONG InfoBufferValue
  882. )
  883. {
  884. NTSTATUS status;
  885. ULONG BufferLength;
  886. PTCP_REQUEST_SET_INFORMATION_EX TcpInfo;
  887. TCPSocketOption *SockOption;
  888. PAGED_CODE();
  889. BufferLength = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(TCPSocketOption);
  890. TcpInfo = (PTCP_REQUEST_SET_INFORMATION_EX)ExAllocatePoolWithTag(NonPagedPool, BufferLength, '2BMS');
  891. if (NULL == TcpInfo) {
  892. return (STATUS_INSUFFICIENT_RESOURCES);
  893. }
  894. RtlZeroMemory(TcpInfo, BufferLength);
  895. SockOption = (TCPSocketOption *) (&TcpInfo->Buffer[0]);
  896. TcpInfo->ID.toi_entity.tei_entity = Entity;
  897. TcpInfo->ID.toi_entity.tei_instance = TL_INSTANCE;
  898. TcpInfo->ID.toi_class = Class;
  899. TcpInfo->BufferSize = sizeof (TCPSocketOption);
  900. //
  901. // Set the Configured values
  902. //
  903. TcpInfo->ID.toi_id = ToiId;
  904. TcpInfo->ID.toi_type = ToiType;
  905. SockOption->tso_value = InfoBufferValue;
  906. status = SmbSendIoctl(
  907. FileObject,
  908. IOCTL_TCP_SET_INFORMATION_EX,
  909. TcpInfo,
  910. BufferLength,
  911. NULL,
  912. NULL
  913. );
  914. if (!NT_SUCCESS(status)) {
  915. SmbPrint(SMB_TRACE_TCP, ("SmbSetTcpInfo: SetTcpInfo FAILed <0x%x>, Id=<0x%x>, Type=<0x%x>, Value=<0x%x>\n",
  916. status, ToiId, ToiType, InfoBufferValue));
  917. SmbTrace(SMB_TRACE_TCP, ("FAILed %!status!, Id=<0x%x>, Type=<0x%x>, Value=<0x%x>\n",
  918. status, ToiId, ToiType, InfoBufferValue));
  919. }
  920. ExFreePool (TcpInfo);
  921. return status;
  922. }
  923. #ifdef STANDALONE_SMB
  924. #define NETBT_PREFIX L"\\DEVICE\\SMB_"
  925. #else
  926. #define NETBT_PREFIX L"\\DEVICE\\NETBT_"
  927. #endif
  928. #define DEVICE_PREFIX L"\\DEVICE\\"
  929. NTSTATUS
  930. SmbSetDeviceBindingInfo(
  931. PSMB_DEVICE Device,
  932. PNETBT_SMB_BIND_REQUEST SmbRequest
  933. )
  934. /*++
  935. Routine Description:
  936. Set the binding information for one IPv4 device
  937. Arguments:
  938. Return Value:
  939. --*/
  940. {
  941. UNICODE_STRING ucName;
  942. PSMB_TCP_DEVICE pIf;
  943. KIRQL Irql;
  944. ULONG Operation;
  945. NTSTATUS status;
  946. SHORT NbtPrefixSize, DevPrefixSize;
  947. if (NULL == SmbRequest->pDeviceName) {
  948. return STATUS_UNSUCCESSFUL;
  949. }
  950. if (SmbRequest->PnPOpCode != TDI_PNP_OP_ADD && SmbRequest->PnPOpCode != TDI_PNP_OP_DEL) {
  951. return STATUS_UNSUCCESSFUL;
  952. }
  953. status = SmbUpcaseUnicodeStringNP(&ucName, SmbRequest->pDeviceName);
  954. if (STATUS_SUCCESS != status) {
  955. return STATUS_UNSUCCESSFUL;
  956. }
  957. //
  958. // Remove the NetBT prefix
  959. //
  960. NbtPrefixSize = wcslen(NETBT_PREFIX) * sizeof(WCHAR);
  961. DevPrefixSize = wcslen(DEVICE_PREFIX) * sizeof(WCHAR);
  962. ASSERT(DevPrefixSize < NbtPrefixSize);
  963. if (RtlEqualMemory(ucName.Buffer, NETBT_PREFIX, NbtPrefixSize)) {
  964. RtlMoveMemory((BYTE*)(ucName.Buffer) + DevPrefixSize,
  965. (BYTE*)(ucName.Buffer) + NbtPrefixSize,
  966. ucName.MaximumLength - NbtPrefixSize
  967. );
  968. ucName.Length -= NbtPrefixSize - DevPrefixSize;
  969. }
  970. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  971. pIf = SmbFindAndReferenceInterface(&ucName);
  972. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  973. ExFreePool(ucName.Buffer);
  974. if (NULL == pIf) {
  975. return STATUS_UNSUCCESSFUL;
  976. }
  977. if (SmbRequest->RequestType == SMB_CLIENT) {
  978. pIf->EnableOutbound = (SmbRequest->PnPOpCode == TDI_PNP_OP_ADD);
  979. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  980. return STATUS_SUCCESS;
  981. }
  982. //
  983. // Inbound
  984. //
  985. if (SmbRequest->PnPOpCode == TDI_PNP_OP_ADD) {
  986. pIf->EnableInbound = TRUE;
  987. Operation = AO_OPTION_ADD_IFLIST;
  988. } else {
  989. pIf->EnableInbound = FALSE;
  990. Operation = AO_OPTION_DEL_IFLIST;
  991. }
  992. if (pIf->PrimaryIpAddress.sin_family == SMB_AF_INET &&
  993. pIf->PrimaryIpAddress.ip4.sin4_addr != 0 &&
  994. pIf->InterfaceIndex != INVALID_INTERFACE_INDEX) {
  995. status = SmbSetTcpInfo (
  996. Device->Tcp4.InboundAddressObject.AddressObject,
  997. CO_TL_ENTITY,
  998. INFO_CLASS_PROTOCOL,
  999. Operation,
  1000. INFO_TYPE_ADDRESS_OBJECT,
  1001. pIf->InterfaceIndex
  1002. );
  1003. SmbPrint(SMB_TRACE_PNP, ("SmbSetTcpInfo return 0x%08lx for %Z\n", status, &pIf->AdapterName));
  1004. SmbTrace(SMB_TRACE_PNP, ("SmbSetTcpInfo return %!status! for %Z", status, &pIf->AdapterName));
  1005. }
  1006. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  1007. return STATUS_SUCCESS;
  1008. }
  1009. NTSTATUS
  1010. SmbBatchedSetBindingInfo(
  1011. PSMB_DEVICE Device,
  1012. ULONG RequestType,
  1013. PWSTR MultiSZBindList
  1014. )
  1015. /*++
  1016. Routine Description:
  1017. Set binding info for a set of IPv4 device
  1018. Note: the input is a list of IPv4 device which SMB device should be bound to.
  1019. The implication is that SMB should be unbound from the device which
  1020. is not in the input list!!!
  1021. We got to support this in order to maintain compatibility
  1022. Arguments:
  1023. Return Value:
  1024. --*/
  1025. {
  1026. LONG i, j, cnt, ip4device_cnt;
  1027. SHORT NbtPrefixSize, DevPrefixSize;
  1028. PUNICODE_STRING uc_strs;
  1029. KIRQL Irql;
  1030. PLIST_ENTRY entry;
  1031. PSMB_TCP_DEVICE pIf, *pIfSnapshot;
  1032. NTSTATUS status;
  1033. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  1034. if (NULL == MultiSZBindList) {
  1035. return STATUS_UNSUCCESSFUL;
  1036. }
  1037. //
  1038. // Separate the MutiSZ string
  1039. //
  1040. uc_strs = SeparateMultiSZ(MultiSZBindList, &cnt);
  1041. if (NULL == uc_strs) {
  1042. return STATUS_INSUFFICIENT_RESOURCES;
  1043. }
  1044. //
  1045. // Remove the NetBT prefix
  1046. //
  1047. NbtPrefixSize = wcslen(NETBT_PREFIX) * sizeof(WCHAR);
  1048. DevPrefixSize = wcslen(DEVICE_PREFIX) * sizeof(WCHAR);
  1049. ASSERT(DevPrefixSize < NbtPrefixSize);
  1050. SmbTrace(SMB_TRACE_PNP, ("Number of bindings: %d", cnt));
  1051. SmbPrint(SMB_TRACE_PNP, ("Number of bindings: %d\n", cnt));
  1052. for (i = 0; i < cnt; i++) {
  1053. if (RtlEqualMemory(uc_strs[i].Buffer, NETBT_PREFIX, NbtPrefixSize)) {
  1054. RtlMoveMemory((BYTE*)(uc_strs[i].Buffer) + DevPrefixSize,
  1055. (BYTE*)(uc_strs[i].Buffer) + NbtPrefixSize,
  1056. uc_strs[i].MaximumLength - NbtPrefixSize
  1057. );
  1058. uc_strs[i].Length -= NbtPrefixSize - DevPrefixSize;
  1059. }
  1060. SmbTrace(SMB_TRACE_PNP, ("\t%d. bind to %Z", i + 1, uc_strs + i));
  1061. SmbPrint(SMB_TRACE_PNP, ("\t%d. bind to %Z\n", i + 1, uc_strs + i));
  1062. }
  1063. //
  1064. // Handle the SMB_CLIENT request
  1065. //
  1066. if (RequestType == SMB_CLIENT) {
  1067. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  1068. entry = SmbCfg.IPDeviceList.Flink;
  1069. while(entry != &SmbCfg.IPDeviceList) {
  1070. pIf = CONTAINING_RECORD(entry, SMB_TCP_DEVICE, Linkage);
  1071. entry = entry->Flink;
  1072. pIf->EnableOutbound = FALSE;
  1073. for (i = 0; i < cnt; i++) {
  1074. if (pIf->AdapterName.Length == uc_strs[i].Length &&
  1075. RtlEqualMemory(pIf->AdapterName.Buffer, uc_strs[i].Buffer, uc_strs[i].Length)) {
  1076. pIf->EnableOutbound = TRUE;
  1077. SmbTrace(SMB_TRACE_PNP, ("Enable outbound on %Z", &pIf->AdapterName));
  1078. }
  1079. }
  1080. }
  1081. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  1082. ExFreePool(uc_strs);
  1083. return STATUS_SUCCESS;
  1084. }
  1085. ASSERT(RequestType == SMB_SERVER);
  1086. //
  1087. // A little bit more complex for server
  1088. // The linked list could be modified while calling into TCP because
  1089. // we cannot hold lock while calling other components.
  1090. //
  1091. //
  1092. // Make a snapshot and reference them
  1093. //
  1094. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  1095. ip4device_cnt = SmbCfg.IPAddressNumber;
  1096. if (ip4device_cnt == 0) {
  1097. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  1098. ExFreePool(uc_strs);
  1099. return STATUS_UNSUCCESSFUL;
  1100. }
  1101. pIfSnapshot = (PSMB_TCP_DEVICE*)ExAllocatePoolWithTag(
  1102. NonPagedPool,
  1103. sizeof(PSMB_TCP_DEVICE)*ip4device_cnt,
  1104. SMB_TCP_DEVICE_POOL_TAG
  1105. );
  1106. if (NULL == pIfSnapshot) {
  1107. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  1108. ExFreePool(uc_strs);
  1109. return STATUS_INSUFFICIENT_RESOURCES;
  1110. }
  1111. for (i = 0, entry = SmbCfg.IPDeviceList.Flink;
  1112. (i < ip4device_cnt) && entry != &SmbCfg.IPDeviceList;
  1113. entry = entry->Flink
  1114. ) {
  1115. pIf = CONTAINING_RECORD(entry, SMB_TCP_DEVICE, Linkage);
  1116. if (pIf->PrimaryIpAddress.sin_family == SMB_AF_INET &&
  1117. pIf->PrimaryIpAddress.ip4.sin4_addr != 0 &&
  1118. pIf->InterfaceIndex != INVALID_INTERFACE_INDEX) {
  1119. SmbReferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  1120. pIfSnapshot[i] = pIf;
  1121. i++;
  1122. }
  1123. }
  1124. ASSERT (i <= ip4device_cnt);
  1125. ip4device_cnt = i;
  1126. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  1127. for (i = 0; i < ip4device_cnt; i++) {
  1128. pIf = pIfSnapshot[i];
  1129. pIf->EnableInbound = FALSE;
  1130. for (j = 0; j < cnt; j++) {
  1131. if (pIf->AdapterName.Length == uc_strs[j].Length &&
  1132. RtlEqualMemory(pIf->AdapterName.Buffer, uc_strs[j].Buffer, uc_strs[j].Length)) {
  1133. pIf->EnableInbound = TRUE;
  1134. SmbTrace(SMB_TRACE_PNP, ("Enable inbound on %Z", &pIf->AdapterName));
  1135. }
  1136. }
  1137. status = SmbSetTcpInfo (
  1138. Device->Tcp4.InboundAddressObject.AddressObject,
  1139. CO_TL_ENTITY,
  1140. INFO_CLASS_PROTOCOL,
  1141. pIf->EnableInbound? AO_OPTION_ADD_IFLIST: AO_OPTION_DEL_IFLIST,
  1142. INFO_TYPE_ADDRESS_OBJECT,
  1143. pIf->InterfaceIndex
  1144. );
  1145. SmbPrint(SMB_TRACE_PNP, ("SmbSetTcpInfo return 0x%08lx for %Z\n", status, &pIf->AdapterName));
  1146. SmbTrace(SMB_TRACE_PNP, ("SmbSetTcpInfo return %!status! for %Z", status, &pIf->AdapterName));
  1147. SmbDereferenceObject((PSMB_OBJECT)pIf, SMB_REF_FIND);
  1148. }
  1149. ExFreePool(uc_strs);
  1150. ExFreePool(pIfSnapshot);
  1151. return STATUS_SUCCESS;
  1152. }
  1153. NTSTATUS
  1154. SmbSetBindingInfo(
  1155. PSMB_DEVICE Device,
  1156. PIRP Irp
  1157. )
  1158. {
  1159. PIO_STACK_LOCATION IrpSp;
  1160. PNETBT_SMB_BIND_REQUEST SmbRequest;
  1161. NTSTATUS status;
  1162. PWSTR MultiSZBindList;
  1163. PAGED_CODE();
  1164. if (Irp->RequestorMode != KernelMode) {
  1165. return STATUS_ACCESS_DENIED;
  1166. }
  1167. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  1168. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(NETBT_SMB_BIND_REQUEST)) {
  1169. return STATUS_UNSUCCESSFUL;
  1170. }
  1171. SmbRequest = (PNETBT_SMB_BIND_REQUEST)Irp->AssociatedIrp.SystemBuffer;
  1172. if (SmbRequest->RequestType != SMB_CLIENT && SmbRequest->RequestType != SMB_SERVER) {
  1173. return STATUS_INVALID_PARAMETER;
  1174. }
  1175. if (NULL == SmbRequest->MultiSZBindList) {
  1176. return SmbSetDeviceBindingInfo(Device, SmbRequest);
  1177. }
  1178. KeEnterCriticalRegion();
  1179. ExAcquireResourceExclusiveLite(&SmbCfg.Resource, TRUE);
  1180. MultiSZBindList = DuplicateMultiSZString(SmbRequest->MultiSZBindList);
  1181. if (NULL != MultiSZBindList) {
  1182. //
  1183. // Update the binding list
  1184. //
  1185. if (SMB_CLIENT == SmbRequest->RequestType) {
  1186. if (Device->ClientBinding) {
  1187. ExFreePool(Device->ClientBinding);
  1188. }
  1189. Device->ClientBinding = MultiSZBindList;
  1190. } else if (SMB_SERVER == SmbRequest->RequestType) {
  1191. if (Device->ServerBinding) {
  1192. ExFreePool(Device->ServerBinding);
  1193. }
  1194. Device->ServerBinding = MultiSZBindList;
  1195. }
  1196. } else {
  1197. //
  1198. // Out of resource is not severe error. Simply ignore it.
  1199. //
  1200. }
  1201. status = SmbBatchedSetBindingInfo(Device, SmbRequest->RequestType, SmbRequest->MultiSZBindList);
  1202. ExReleaseResourceLite(&SmbCfg.Resource);
  1203. KeLeaveCriticalRegion();
  1204. return status;
  1205. }
  1206. NTSTATUS
  1207. SmbSetInboundIPv6Protection(
  1208. IN PSMB_DEVICE pDeviceObject
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. This routine set the TCP/IPv6 listening protection level
  1213. IPv6 stack support 3 level of protection:
  1214. PROTECTION_LEVEL_RESTRICTED: intranet scenario
  1215. allow connection requests from local address only
  1216. PROTECTION_LEVEL_DEFAULT: default level
  1217. PROTECTION_LEVEL_UNRESTRICTED: for peer to peer connection
  1218. Arguments:
  1219. Return Value:
  1220. --*/
  1221. {
  1222. KIRQL Irql = 0;
  1223. PFILE_OBJECT pIPv6AO = NULL;
  1224. NTSTATUS ntStatus = STATUS_SUCCESS;
  1225. ULONG uIPv6ProtectionLevel = 0;
  1226. SMB_ACQUIRE_SPINLOCK(pDeviceObject, Irql);
  1227. pIPv6AO = pDeviceObject->Tcp6.InboundAddressObject.AddressObject;
  1228. if (pIPv6AO == NULL) {
  1229. SMB_RELEASE_SPINLOCK(pDeviceObject, Irql);
  1230. goto error;
  1231. }
  1232. ObReferenceObject(pIPv6AO);
  1233. SMB_RELEASE_SPINLOCK(pDeviceObject, Irql);
  1234. uIPv6ProtectionLevel = SmbCfg.uIPv6Protection;
  1235. ntStatus = SmbSetTcpInfo (
  1236. pIPv6AO,
  1237. CL_TL_ENTITY,
  1238. INFO_CLASS_PROTOCOL,
  1239. AO_OPTION_PROTECT,
  1240. INFO_TYPE_ADDRESS_OBJECT,
  1241. uIPv6ProtectionLevel
  1242. );
  1243. ObDereferenceObject(pIPv6AO);
  1244. SmbTrace(SMB_TRACE_PNP, ("IPv6Protection Level = %d: %!status!", uIPv6ProtectionLevel, ntStatus));
  1245. error:
  1246. return ntStatus;
  1247. }