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.

945 lines
28 KiB

  1. /*++
  2. Copyright(c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. brdgtdi.c
  5. Abstract:
  6. Ethernet MAC level bridge.
  7. Tdi registration for address notifications.
  8. Author:
  9. Salahuddin J. Khan (sjkhan)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. March 2002 - Original version
  14. --*/
  15. #define NDIS_MINIPORT_DRIVER
  16. #define NDIS50_MINIPORT 1
  17. #define NDIS_WDM 1
  18. #pragma warning( push, 3 )
  19. #include <ndis.h>
  20. #include <tdikrnl.h>
  21. #include <ntstatus.h>
  22. #include <wchar.h>
  23. #pragma warning( pop )
  24. #include "bridge.h"
  25. #include "brdgtdi.h"
  26. #include "brdgsta.h"
  27. #include "brdgmini.h"
  28. #include "brdgprot.h"
  29. #include "brdgbuf.h"
  30. #include "brdgfwd.h"
  31. #include "brdgtbl.h"
  32. #include "brdgctl.h"
  33. #include "brdggpo.h"
  34. // ===========================================================================
  35. //
  36. // GLOBALS
  37. //
  38. // ===========================================================================
  39. BRDG_TDI_GLOBALS g_BrdgTdiGlobals;
  40. // ===========================================================================
  41. //
  42. // CONSTANTS
  43. //
  44. // ===========================================================================
  45. #define MAX_GUID_LEN 39
  46. #define MAX_IP4_STRING_LEN 17
  47. const WCHAR TcpipAdaptersKey[] = {L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters"};
  48. // ===========================================================================
  49. //
  50. // PRIVATE PROTOTYPES
  51. //
  52. // ===========================================================================
  53. NTSTATUS
  54. BrdgTdiPnpPowerHandler(
  55. IN PUNICODE_STRING DeviceName,
  56. IN PNET_PNP_EVENT PowerEvent,
  57. IN PTDI_PNP_CONTEXT Context1,
  58. IN PTDI_PNP_CONTEXT Context2
  59. );
  60. VOID
  61. BrdgTdiBindingHandler(
  62. IN TDI_PNP_OPCODE PnPOpcode,
  63. IN PUNICODE_STRING DeviceName,
  64. IN PWSTR MultiSZBindList
  65. );
  66. VOID
  67. BrdgTdiAddAddressHandler(
  68. IN PTA_ADDRESS Address,
  69. IN PUNICODE_STRING DeviceName,
  70. IN PTDI_PNP_CONTEXT Context
  71. );
  72. VOID
  73. BrdgTdiDelAddressHandler(
  74. IN PTA_ADDRESS Address,
  75. IN PUNICODE_STRING DeviceName,
  76. IN PTDI_PNP_CONTEXT Context
  77. );
  78. VOID
  79. TSPrintTaAddress(PTA_ADDRESS pTaAddress);
  80. // ===========================================================================
  81. //
  82. // INLINE FUNCTIONS
  83. //
  84. // ===========================================================================
  85. __forceinline
  86. BOOLEAN
  87. IsLower(WCHAR c)
  88. {
  89. return (BOOLEAN)((c >= L'a') && (c <= 'z'));
  90. }
  91. __forceinline
  92. BOOLEAN
  93. IsDigit(WCHAR c)
  94. {
  95. return (BOOLEAN)((c >= L'0') && (c <= '9'));
  96. }
  97. __forceinline
  98. BOOLEAN
  99. IsXDigit(WCHAR c)
  100. {
  101. return (BOOLEAN)( ((c >= L'0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')) );
  102. }
  103. // ===========================================================================
  104. //
  105. // BRIDGE TDI IMPLEMENTATION
  106. //
  107. // ===========================================================================
  108. VOID
  109. BrdgTdiInitializeClientInterface(
  110. IN PTDI_CLIENT_INTERFACE_INFO ClientInterfaceInfo,
  111. IN PUNICODE_STRING ClientName
  112. )
  113. {
  114. DBGPRINT(TDI, ("BrdgTdiInitializeClientInterface\r\n"));
  115. ClientInterfaceInfo->MajorTdiVersion = TDI_CURRENT_MAJOR_VERSION;
  116. ClientInterfaceInfo->MinorTdiVersion = TDI_CURRENT_MINOR_VERSION;
  117. ClientInterfaceInfo->ClientName = ClientName;
  118. ClientInterfaceInfo->PnPPowerHandler = BrdgTdiPnpPowerHandler;
  119. ClientInterfaceInfo->BindingHandler = BrdgTdiBindingHandler;
  120. ClientInterfaceInfo->AddAddressHandlerV2 = BrdgTdiAddAddressHandler;
  121. ClientInterfaceInfo->DelAddressHandlerV2 = BrdgTdiDelAddressHandler;
  122. }
  123. NTSTATUS
  124. BrdgTdiDriverInit()
  125. /*++
  126. Routine Description:
  127. Driver load-time initialization
  128. Return Value:
  129. Status of initialization
  130. Locking Constraints:
  131. Top-level function. Assumes no locks are held by caller.
  132. --*/
  133. {
  134. NTSTATUS status;
  135. DBGPRINT(TDI, ("BrdgTdiDriverInit\r\n"));
  136. RtlInitUnicodeString(&g_BrdgTdiGlobals.ClientName, L"Bridge");
  137. RtlZeroMemory(&g_BrdgTdiGlobals.ciiBridge, sizeof(TDI_CLIENT_INTERFACE_INFO));
  138. BrdgTdiInitializeClientInterface(&g_BrdgTdiGlobals.ciiBridge, &g_BrdgTdiGlobals.ClientName);
  139. status = BrdgGpoDriverInit();
  140. if (!NT_SUCCESS(status))
  141. {
  142. BrdgTdiCleanup();
  143. }
  144. else
  145. {
  146. status = TdiRegisterPnPHandlers(&g_BrdgTdiGlobals.ciiBridge,
  147. sizeof(TDI_CLIENT_INTERFACE_INFO),
  148. &g_BrdgTdiGlobals.hBindingHandle);
  149. }
  150. return status;
  151. }
  152. VOID
  153. BrdgTdiCleanup()
  154. /*++
  155. Routine Description:
  156. Driver shutdown cleanup
  157. Return Value:
  158. None
  159. Locking Constraints:
  160. Top-level function. Assumes no locks are held by caller.
  161. --*/
  162. {
  163. NTSTATUS status;
  164. status = TdiDeregisterPnPHandlers(g_BrdgTdiGlobals.hBindingHandle);
  165. SAFEASSERT(NT_SUCCESS(status));
  166. BrdgGpoCleanup();
  167. }
  168. NTSTATUS
  169. BrdgTdiPnpPowerHandler(
  170. IN PUNICODE_STRING DeviceName,
  171. IN PNET_PNP_EVENT PowerEvent,
  172. IN PTDI_PNP_CONTEXT Context1,
  173. IN PTDI_PNP_CONTEXT Context2
  174. )
  175. {
  176. DBGPRINT(TDI, ("BrdgTdiPnpPowerHandler\r\n"));
  177. return STATUS_SUCCESS;
  178. }
  179. VOID
  180. BrdgTdiBindingHandler(
  181. IN TDI_PNP_OPCODE PnPOpcode,
  182. IN PUNICODE_STRING DeviceName,
  183. IN PWSTR MultiSZBindList
  184. )
  185. {
  186. DBGPRINT(TDI, ("BrdgTdiBindingHandler\r\n"));
  187. }
  188. VOID
  189. BrdgTdiAddAddressHandler(
  190. IN PTA_ADDRESS Address,
  191. IN PUNICODE_STRING DeviceName,
  192. IN PTDI_PNP_CONTEXT Context
  193. )
  194. /*++
  195. Routine Description:
  196. Called if a new address is added.
  197. Arguments:
  198. Address - New address that has been added.
  199. DeviceName - The device that this is changing for.
  200. Context - Not something we're interested in for now.
  201. Return Value:
  202. None.
  203. --*/
  204. {
  205. DBGPRINT(TDI, ("BrdgTdiAddAddressHandler\r\n"));
  206. if ((Address->AddressType == TDI_ADDRESS_TYPE_IP))
  207. {
  208. if (NULL != DeviceName->Buffer)
  209. {
  210. //
  211. // Find the start of the GUID
  212. //
  213. PWCHAR DeviceId = wcsrchr(DeviceName->Buffer, L'{');
  214. if (NULL != DeviceId)
  215. {
  216. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  217. LPWSTR AdapterPath;
  218. AdapterPath = ExAllocatePoolWithTag(PagedPool,
  219. (wcslen(TcpipAdaptersKey) + 1 + wcslen(DeviceId) + 1) * sizeof(WCHAR),
  220. 'gdrB');
  221. if (AdapterPath)
  222. {
  223. OBJECT_ATTRIBUTES ObAttr;
  224. UNICODE_STRING Adapter;
  225. HANDLE hKey;
  226. wcscpy(AdapterPath, TcpipAdaptersKey);
  227. wcscat(AdapterPath, L"\\");
  228. wcscat(AdapterPath, DeviceId);
  229. RtlInitUnicodeString(&Adapter, AdapterPath);
  230. InitializeObjectAttributes( &ObAttr,
  231. &Adapter,
  232. OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
  233. NULL,
  234. NULL);
  235. status = ZwOpenKey(&hKey,
  236. KEY_READ,
  237. &ObAttr);
  238. if (NT_SUCCESS(status))
  239. {
  240. ZwClose(hKey);
  241. //
  242. // This is a valid adapter on this machine. Otherwise it could be an NdisAdapter etc and
  243. // we don't pay attention to these for group policies.
  244. //
  245. BrdgGpoNewAddressNotification(DeviceId);
  246. }
  247. ExFreePool(AdapterPath);
  248. }
  249. }
  250. }
  251. #if DBG
  252. TSPrintTaAddress(Address);
  253. #endif
  254. }
  255. }
  256. VOID
  257. BrdgTdiDelAddressHandler(
  258. IN PTA_ADDRESS Address,
  259. IN PUNICODE_STRING DeviceName,
  260. IN PTDI_PNP_CONTEXT Context
  261. )
  262. {
  263. DBGPRINT(TDI, ("BrdgTdiDelAddressHandler\r\n"));
  264. //
  265. // We don't delete the current list of networks that we have since we need them to make
  266. // an accurate assessment on whether to follow the GPO. Instead, the AddAddressHandler
  267. // will simply update the existing network address for the ID's and if this results in
  268. // a different network then we'll change the bridge mode.
  269. //
  270. }
  271. VOID
  272. TSPrintTaAddress(PTA_ADDRESS pTaAddress)
  273. {
  274. BOOLEAN fShowAddress = TRUE;
  275. DbgPrint("AddressType = TDI_ADDRESS_TYPE_");
  276. switch (pTaAddress->AddressType)
  277. {
  278. case TDI_ADDRESS_TYPE_UNSPEC:
  279. DbgPrint("UNSPEC\n");
  280. break;
  281. case TDI_ADDRESS_TYPE_UNIX:
  282. DbgPrint("UNIX\n");
  283. break;
  284. case TDI_ADDRESS_TYPE_IP:
  285. DbgPrint("IP\n");
  286. fShowAddress = FALSE;
  287. {
  288. PTDI_ADDRESS_IP pTdiAddressIp = (PTDI_ADDRESS_IP)pTaAddress->Address;
  289. PUCHAR pucTemp = (PUCHAR)&pTdiAddressIp->in_addr;
  290. DbgPrint("sin_port = 0x%04x\n"
  291. "in_addr = %u.%u.%u.%u\n",
  292. pTdiAddressIp->sin_port,
  293. pucTemp[0], pucTemp[1],
  294. pucTemp[2], pucTemp[3]);
  295. }
  296. break;
  297. case TDI_ADDRESS_TYPE_IMPLINK:
  298. DbgPrint("IMPLINK\n");
  299. break;
  300. case TDI_ADDRESS_TYPE_PUP:
  301. DbgPrint("PUP\n");
  302. break;
  303. case TDI_ADDRESS_TYPE_CHAOS:
  304. DbgPrint("CHAOS\n");
  305. break;
  306. case TDI_ADDRESS_TYPE_IPX:
  307. DbgPrint("IPX\n");
  308. fShowAddress = FALSE;
  309. {
  310. PTDI_ADDRESS_IPX pTdiAddressIpx = (PTDI_ADDRESS_IPX)pTaAddress->Address;
  311. DbgPrint("NetworkAddress = 0x%08x\n"
  312. "NodeAddress = %u.%u.%u.%u.%u.%u\n"
  313. "Socket = 0x%04x\n",
  314. pTdiAddressIpx->NetworkAddress,
  315. pTdiAddressIpx->NodeAddress[0],
  316. pTdiAddressIpx->NodeAddress[1],
  317. pTdiAddressIpx->NodeAddress[2],
  318. pTdiAddressIpx->NodeAddress[3],
  319. pTdiAddressIpx->NodeAddress[4],
  320. pTdiAddressIpx->NodeAddress[5],
  321. pTdiAddressIpx->Socket);
  322. }
  323. break;
  324. case TDI_ADDRESS_TYPE_NBS:
  325. DbgPrint("NBS\n");
  326. break;
  327. case TDI_ADDRESS_TYPE_ECMA:
  328. DbgPrint("ECMA\n");
  329. break;
  330. case TDI_ADDRESS_TYPE_DATAKIT:
  331. DbgPrint("DATAKIT\n");
  332. break;
  333. case TDI_ADDRESS_TYPE_CCITT:
  334. DbgPrint("CCITT\n");
  335. break;
  336. case TDI_ADDRESS_TYPE_SNA:
  337. DbgPrint("SNA\n");
  338. break;
  339. case TDI_ADDRESS_TYPE_DECnet:
  340. DbgPrint("DECnet\n");
  341. break;
  342. case TDI_ADDRESS_TYPE_DLI:
  343. DbgPrint("DLI\n");
  344. break;
  345. case TDI_ADDRESS_TYPE_LAT:
  346. DbgPrint("LAT\n");
  347. break;
  348. case TDI_ADDRESS_TYPE_HYLINK:
  349. DbgPrint("HYLINK\n");
  350. break;
  351. case TDI_ADDRESS_TYPE_APPLETALK:
  352. DbgPrint("APPLETALK\n");
  353. fShowAddress = FALSE;
  354. {
  355. PTDI_ADDRESS_APPLETALK pTdiAddressAppleTalk = (PTDI_ADDRESS_APPLETALK)pTaAddress->Address;
  356. DbgPrint("Network = 0x%04x\n"
  357. "Node = 0x%02x\n"
  358. "Socket = 0x%02x\n",
  359. pTdiAddressAppleTalk->Network,
  360. pTdiAddressAppleTalk->Node,
  361. pTdiAddressAppleTalk->Socket);
  362. }
  363. break;
  364. case TDI_ADDRESS_TYPE_NETBIOS:
  365. DbgPrint("NETBIOS\n");
  366. fShowAddress = FALSE;
  367. {
  368. PTDI_ADDRESS_NETBIOS pTdiAddressNetbios = (PTDI_ADDRESS_NETBIOS)pTaAddress->Address;
  369. UCHAR pucName[17];
  370. //
  371. // make sure we have a zero-terminated name to print...
  372. //
  373. RtlCopyMemory(pucName, pTdiAddressNetbios->NetbiosName, 16);
  374. pucName[16] = 0;
  375. DbgPrint("NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_");
  376. switch (pTdiAddressNetbios->NetbiosNameType)
  377. {
  378. case TDI_ADDRESS_NETBIOS_TYPE_UNIQUE:
  379. DbgPrint("UNIQUE\n");
  380. break;
  381. case TDI_ADDRESS_NETBIOS_TYPE_GROUP:
  382. DbgPrint("GROUP\n");
  383. break;
  384. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE:
  385. DbgPrint("QUICK_UNIQUE\n");
  386. break;
  387. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP:
  388. DbgPrint("QUICK_GROUP\n");
  389. break;
  390. default:
  391. DbgPrint("INVALID [0x%04x]\n",
  392. pTdiAddressNetbios->NetbiosNameType);
  393. break;
  394. }
  395. DbgPrint("NetbiosName = %s\n", pucName);
  396. }
  397. break;
  398. case TDI_ADDRESS_TYPE_8022:
  399. DbgPrint("8022\n");
  400. fShowAddress = FALSE;
  401. {
  402. PTDI_ADDRESS_8022 pTdiAddress8022 = (PTDI_ADDRESS_8022)pTaAddress->Address;
  403. DbgPrint("Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
  404. pTdiAddress8022->MACAddress[0],
  405. pTdiAddress8022->MACAddress[1],
  406. pTdiAddress8022->MACAddress[2],
  407. pTdiAddress8022->MACAddress[3],
  408. pTdiAddress8022->MACAddress[4],
  409. pTdiAddress8022->MACAddress[5]);
  410. }
  411. break;
  412. case TDI_ADDRESS_TYPE_OSI_TSAP:
  413. DbgPrint("OSI_TSAP\n");
  414. fShowAddress = FALSE;
  415. {
  416. PTDI_ADDRESS_OSI_TSAP pTdiAddressOsiTsap = (PTDI_ADDRESS_OSI_TSAP)pTaAddress->Address;
  417. ULONG ulSelectorLength;
  418. ULONG ulAddressLength;
  419. PUCHAR pucTemp = pTdiAddressOsiTsap->tp_addr;
  420. DbgPrint("TpAddrType = ISO_");
  421. switch (pTdiAddressOsiTsap->tp_addr_type)
  422. {
  423. case ISO_HIERARCHICAL:
  424. DbgPrint("HIERARCHICAL\n");
  425. ulSelectorLength = pTdiAddressOsiTsap->tp_tsel_len;
  426. ulAddressLength = pTdiAddressOsiTsap->tp_taddr_len;
  427. break;
  428. case ISO_NON_HIERARCHICAL:
  429. DbgPrint("NON_HIERARCHICAL\n");
  430. ulSelectorLength = 0;
  431. ulAddressLength = pTdiAddressOsiTsap->tp_taddr_len;
  432. break;
  433. default:
  434. DbgPrint("INVALID [0x%04x]\n",
  435. pTdiAddressOsiTsap->tp_addr_type);
  436. ulSelectorLength = 0;
  437. ulAddressLength = 0;
  438. break;
  439. }
  440. if (ulSelectorLength)
  441. {
  442. ULONG ulCount;
  443. DbgPrint("TransportSelector: ");
  444. for (ulCount = 0; ulCount < ulSelectorLength; ulCount++)
  445. {
  446. DbgPrint("%02x ", *pucTemp);
  447. ++pucTemp;
  448. }
  449. DbgPrint("\n");
  450. }
  451. if (ulAddressLength)
  452. {
  453. ULONG ulCount;
  454. DbgPrint("TransportAddress: ");
  455. for (ulCount = 0; ulCount < ulAddressLength; ulCount++)
  456. {
  457. DbgPrint("%02x ", *pucTemp);
  458. ++pucTemp;
  459. }
  460. DbgPrint("\n");
  461. }
  462. }
  463. break;
  464. case TDI_ADDRESS_TYPE_NETONE:
  465. DbgPrint("NETONE\n");
  466. fShowAddress = FALSE;
  467. {
  468. PTDI_ADDRESS_NETONE pTdiAddressNetone = (PTDI_ADDRESS_NETONE)pTaAddress->Address;
  469. UCHAR pucName[21];
  470. //
  471. // make sure have 0-terminated name
  472. //
  473. RtlCopyMemory(pucName,
  474. pTdiAddressNetone->NetoneName,
  475. 20);
  476. pucName[20] = 0;
  477. DbgPrint("NetoneNameType = TDI_ADDRESS_NETONE_TYPE_");
  478. switch (pTdiAddressNetone->NetoneNameType)
  479. {
  480. case TDI_ADDRESS_NETONE_TYPE_UNIQUE:
  481. DbgPrint("UNIQUE\n");
  482. break;
  483. case TDI_ADDRESS_NETONE_TYPE_ROTORED:
  484. DbgPrint("ROTORED\n");
  485. break;
  486. default:
  487. DbgPrint("INVALID [0x%04x]\n",
  488. pTdiAddressNetone->NetoneNameType);
  489. break;
  490. }
  491. DbgPrint("NetoneName = %s\n",
  492. pucName);
  493. }
  494. break;
  495. case TDI_ADDRESS_TYPE_VNS:
  496. DbgPrint("VNS\n");
  497. fShowAddress = FALSE;
  498. {
  499. PTDI_ADDRESS_VNS pTdiAddressVns = (PTDI_ADDRESS_VNS)pTaAddress->Address;
  500. DbgPrint("NetAddress: %02x-%02x-%02x-%02x\n",
  501. pTdiAddressVns->net_address[0],
  502. pTdiAddressVns->net_address[1],
  503. pTdiAddressVns->net_address[2],
  504. pTdiAddressVns->net_address[3]);
  505. DbgPrint("SubnetAddr: %02x-%02x\n"
  506. "Port: %02x-%02x\n"
  507. "Hops: %u\n",
  508. pTdiAddressVns->subnet_addr[0],
  509. pTdiAddressVns->subnet_addr[1],
  510. pTdiAddressVns->port[0],
  511. pTdiAddressVns->port[1],
  512. pTdiAddressVns->hops);
  513. }
  514. break;
  515. case TDI_ADDRESS_TYPE_NETBIOS_EX:
  516. DbgPrint("NETBIOS_EX\n");
  517. fShowAddress = FALSE;
  518. {
  519. PTDI_ADDRESS_NETBIOS_EX pTdiAddressNetbiosEx = (PTDI_ADDRESS_NETBIOS_EX)pTaAddress->Address;
  520. UCHAR pucEndpointName[17];
  521. UCHAR pucNetbiosName[17];
  522. //
  523. // make sure we have zero-terminated names to print...
  524. //
  525. RtlCopyMemory(pucEndpointName,
  526. pTdiAddressNetbiosEx->EndpointName,
  527. 16);
  528. pucEndpointName[16] = 0;
  529. RtlCopyMemory(pucNetbiosName,
  530. pTdiAddressNetbiosEx->NetbiosAddress.NetbiosName,
  531. 16);
  532. pucNetbiosName[16] = 0;
  533. DbgPrint("EndpointName = %s\n"
  534. "NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_",
  535. pucEndpointName);
  536. switch (pTdiAddressNetbiosEx->NetbiosAddress.NetbiosNameType)
  537. {
  538. case TDI_ADDRESS_NETBIOS_TYPE_UNIQUE:
  539. DbgPrint("UNIQUE\n");
  540. break;
  541. case TDI_ADDRESS_NETBIOS_TYPE_GROUP:
  542. DbgPrint("GROUP\n");
  543. break;
  544. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE:
  545. DbgPrint("QUICK_UNIQUE\n");
  546. break;
  547. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP:
  548. DbgPrint("QUICK_GROUP\n");
  549. break;
  550. default:
  551. DbgPrint("INVALID [0x%04x]\n",
  552. pTdiAddressNetbiosEx->NetbiosAddress.NetbiosNameType);
  553. break;
  554. }
  555. DbgPrint("NetbiosName = %s\n", pucNetbiosName);
  556. }
  557. break;
  558. case TDI_ADDRESS_TYPE_IP6:
  559. DbgPrint("IPv6\n");
  560. fShowAddress = FALSE;
  561. {
  562. PTDI_ADDRESS_IP6 pTdiAddressIp6 = (PTDI_ADDRESS_IP6)pTaAddress->Address;
  563. PUCHAR pucTemp = (PUCHAR)&pTdiAddressIp6->sin6_addr;
  564. DbgPrint("SinPort6 = 0x%04x\n"
  565. "FlowInfo = 0x%08x\n"
  566. "ScopeId = 0x%08x\n",
  567. pTdiAddressIp6->sin6_port,
  568. pTdiAddressIp6->sin6_flowinfo,
  569. pTdiAddressIp6->sin6_scope_id);
  570. DbgPrint("In6_addr = %x%02x:%x%02x:%x%02x:%x%02x:",
  571. pucTemp[0], pucTemp[1],
  572. pucTemp[2], pucTemp[3],
  573. pucTemp[4], pucTemp[5],
  574. pucTemp[6], pucTemp[7]);
  575. DbgPrint("%x%02x:%x%02x:%x%02x:%x%02x\n",
  576. pucTemp[8], pucTemp[9],
  577. pucTemp[10], pucTemp[11],
  578. pucTemp[12], pucTemp[13],
  579. pucTemp[14], pucTemp[15]);
  580. }
  581. break;
  582. default:
  583. DbgPrint("UNKNOWN [0x%08x]\n", pTaAddress->AddressType);
  584. break;
  585. }
  586. if (fShowAddress)
  587. {
  588. PUCHAR pucTemp = pTaAddress->Address;
  589. ULONG ulCount;
  590. DbgPrint("AddressLength = %d\n"
  591. "Address = ",
  592. pTaAddress->AddressLength);
  593. for (ulCount = 0; ulCount < pTaAddress->AddressLength; ulCount++)
  594. {
  595. DbgPrint("%02x ", *pucTemp);
  596. pucTemp++;
  597. }
  598. DbgPrint("\n");
  599. }
  600. }
  601. NTSTATUS
  602. BrdgTdiIpv4StringToAddress(
  603. IN LPWSTR String,
  604. IN BOOLEAN Strict,
  605. OUT LPWSTR *Terminator,
  606. OUT in_addr *Addr)
  607. /*++
  608. Routine Description:
  609. This function interprets the character string specified by the cp
  610. parameter. This string represents a numeric Internet address
  611. expressed in the Internet standard ".'' notation. The value
  612. returned is a number suitable for use as an Internet address. All
  613. Internet addresses are returned in network order (bytes ordered from
  614. left to right).
  615. Internet Addresses
  616. Values specified using the "." notation take one of the following
  617. forms:
  618. a.b.c.d a.b.c a.b a
  619. When four parts are specified, each is interpreted as a byte of data
  620. and assigned, from left to right, to the four bytes of an Internet
  621. address. Note that when an Internet address is viewed as a 32-bit
  622. integer quantity on the Intel architecture, the bytes referred to
  623. above appear as "d.c.b.a''. That is, the bytes on an Intel
  624. processor are ordered from right to left.
  625. Note: The following notations are only used by Berkeley, and nowhere
  626. else on the Internet. In the interests of compatibility with their
  627. software, they are supported as specified.
  628. When a three part address is specified, the last part is interpreted
  629. as a 16-bit quantity and placed in the right most two bytes of the
  630. network address. This makes the three part address format
  631. convenient for specifying Class B network addresses as
  632. "128.net.host''.
  633. When a two part address is specified, the last part is interpreted
  634. as a 24-bit quantity and placed in the right most three bytes of the
  635. network address. This makes the two part address format convenient
  636. for specifying Class A network addresses as "net.host''.
  637. When only one part is given, the value is stored directly in the
  638. network address without any byte rearrangement.
  639. Arguments:
  640. String - A character string representing a number expressed in the
  641. Internet standard "." notation.
  642. Terminator - Receives a pointer to the character that terminated
  643. the conversion.
  644. Addr - Receives a pointer to the structure to fill in with
  645. a suitable binary representation of the Internet address given.
  646. Return Value:
  647. TRUE if parsing was successful. FALSE otherwise.
  648. --*/
  649. {
  650. ULONG val, n;
  651. LONG base;
  652. WCHAR c;
  653. ULONG parts[4], *pp = parts;
  654. BOOLEAN sawDigit;
  655. again:
  656. //
  657. // We must see at least one digit for address to be valid.
  658. //
  659. sawDigit = FALSE;
  660. //
  661. // Collect number up to ``.''.
  662. // Values are specified as for C:
  663. // 0x=hex, 0=octal, other=decimal.
  664. //
  665. val = 0; base = 10;
  666. if (*String == L'0')
  667. {
  668. String++;
  669. if (IsDigit(*String))
  670. {
  671. base = 8;
  672. } else if (*String == L'x' || *String == L'X')
  673. {
  674. base = 16;
  675. String++;
  676. } else
  677. {
  678. //
  679. // It is still decimal but we saw the digit
  680. // and it was 0.
  681. //
  682. sawDigit = TRUE;
  683. }
  684. }
  685. if (Strict && (base != 10))
  686. {
  687. *Terminator = String;
  688. return STATUS_INVALID_PARAMETER;
  689. }
  690. do
  691. {
  692. ULONG newVal;
  693. c = *String;
  694. if (IsDigit(c) && ((c - L'0') < base)) {
  695. newVal = (val * base) + (c - L'0');
  696. } else if ((base == 16) && IsXDigit(c)) {
  697. newVal = (val << 4) + (c + 10 - (IsLower(c) ? L'a' : L'A'));
  698. } else {
  699. break;
  700. }
  701. //
  702. // Protect from overflow
  703. //
  704. if (newVal < val) {
  705. *Terminator = String;
  706. return STATUS_INVALID_PARAMETER;
  707. }
  708. String++;
  709. sawDigit = TRUE;
  710. val = newVal;
  711. } while (c != L'\0');
  712. if (*String == L'.')
  713. {
  714. //
  715. // Internet format:
  716. // a.b.c.d
  717. // a.b.c (with c treated as 16-bits)
  718. // a.b (with b treated as 24 bits)
  719. //
  720. if (pp >= parts + 3)
  721. {
  722. *Terminator = String;
  723. return STATUS_INVALID_PARAMETER;
  724. }
  725. *pp++ = val, String++;
  726. //
  727. // Check if we saw at least one digit.
  728. //
  729. if (!sawDigit) {
  730. *Terminator = String;
  731. return STATUS_INVALID_PARAMETER;
  732. }
  733. goto again;
  734. } while (c != L'\0');
  735. //
  736. // Check if we saw at least one digit.
  737. //
  738. if (!sawDigit) {
  739. *Terminator = String;
  740. return STATUS_INVALID_PARAMETER;
  741. }
  742. *pp++ = val;
  743. //
  744. // Concoct the address according to
  745. // the number of parts specified.
  746. //
  747. n = (ULONG)(pp - parts);
  748. if (Strict && (n != 4)) {
  749. *Terminator = String;
  750. return STATUS_INVALID_PARAMETER;
  751. }
  752. switch ((int) n) {
  753. case 1: /* a -- 32 bits */
  754. val = parts[0];
  755. break;
  756. case 2: /* a.b -- 8.24 bits */
  757. if ((parts[0] > 0xff) || (parts[1] > 0xffffff)) {
  758. *Terminator = String;
  759. return STATUS_INVALID_PARAMETER;
  760. }
  761. val = (parts[0] << 24) | (parts[1] & 0xffffff);
  762. break;
  763. case 3: /* a.b.c -- 8.8.16 bits */
  764. if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
  765. (parts[2] > 0xffff)) {
  766. *Terminator = String;
  767. return STATUS_INVALID_PARAMETER;
  768. }
  769. val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
  770. (parts[2] & 0xffff);
  771. break;
  772. case 4: /* a.b.c.d -- 8.8.8.8 bits */
  773. if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
  774. (parts[2] > 0xff) || (parts[3] > 0xff)) {
  775. *Terminator = String;
  776. return STATUS_INVALID_PARAMETER;
  777. }
  778. val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
  779. ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
  780. break;
  781. default:
  782. *Terminator = String;
  783. return STATUS_INVALID_PARAMETER;
  784. }
  785. val = RtlUlongByteSwap(val);
  786. *Terminator = String;
  787. Addr->s_addr = val;
  788. return STATUS_SUCCESS;
  789. }